diff options
Diffstat (limited to 'tdecore/klocale.cpp')
-rw-r--r-- | tdecore/klocale.cpp | 2474 |
1 files changed, 0 insertions, 2474 deletions
diff --git a/tdecore/klocale.cpp b/tdecore/klocale.cpp deleted file mode 100644 index c4ae52b19..000000000 --- a/tdecore/klocale.cpp +++ /dev/null @@ -1,2474 +0,0 @@ -// -*- c-basic-offset: 2 -*- -/* This file is part of the KDE libraries - Copyright (c) 1997,2001 Stephan Kulow <coolo@kde.org> - Copyright (c) 1999 Preston Brown <pbrown@kde.org> - Copyright (c) 1999-2002 Hans Petter Bieker <bieker@kde.org> - Copyright (c) 2002 Lukas Tinkl <lukas@kde.org> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include <config.h> - -#include <stdlib.h> // getenv - -#include <tqtextcodec.h> -#include <tqfile.h> -#include <tqprinter.h> -#include <tqdatetime.h> -#include <tqfileinfo.h> -#include <tqregexp.h> - -#include "kcatalogue.h" -#include "kglobal.h" -#include "kstandarddirs.h" -#include "ksimpleconfig.h" -#include "kinstance.h" -#include "kconfig.h" -#include "kdebug.h" -#include "kcalendarsystem.h" -#include "kcalendarsystemfactory.h" -#include "klocale.h" - -#ifdef Q_WS_WIN -#include <windows.h> -#endif - -static const char * const SYSTEM_MESSAGES = "tdelibs"; - -static const char *maincatalogue = 0; - -class KLocalePrivate -{ -public: - int weekStartDay; - bool nounDeclension; - bool dateMonthNamePossessive; - TQStringList languageList; - TQStringList catalogNames; // list of all catalogs (regardless of language) - TQValueList<KCatalogue> catalogues; // list of all loaded catalogs, contains one instance per catalog name and language - TQString encoding; - TQTextCodec * codecForEncoding; - KConfig * config; - bool formatInited; - int /*TQPrinter::PageSize*/ pageSize; - KLocale::MeasureSystem measureSystem; - TQStringList langTwoAlpha; - KConfig *languages; - - TQString calendarType; - KCalendarSystem * calendar; - bool utf8FileEncoding; - TQString appName; -#ifdef Q_WS_WIN - char win32SystemEncoding[3+7]; //"cp " + lang ID -#endif - bool useMainCatalogue; -}; - -static KLocale *this_klocale = 0; - -KLocale::KLocale( const TQString & catalog, KConfig * config ) -{ - d = new KLocalePrivate; - d->config = config; - d->languages = 0; - d->calendar = 0; - d->formatInited = false; - - initEncoding(0); - initFileNameEncoding(0); - - KConfig *cfg = d->config; - this_klocale = this; - if (!cfg) cfg = KGlobal::instance()->config(); - this_klocale = 0; - Q_ASSERT( cfg ); - - d->appName = catalog; - initLanguageList( cfg, config == 0); - initMainCatalogues(catalog); -} - -TQString KLocale::_initLanguage(KConfigBase *config) -{ - if (this_klocale) - { - // ### HPB Why this cast?? - this_klocale->initLanguageList((KConfig *) config, true); - // todo: adapt current catalog list: remove unused languages, insert main catalogs, if not already found - return this_klocale->language(); - } - return TQString::null; -} - -void KLocale::initMainCatalogues(const TQString & catalog) -{ - // Use the first non-null string. - TQString mainCatalogue = catalog; - - // don't use main catalogue if we're looking up .desktop translations - if (mainCatalogue.contains("desktop") == 0 || mainCatalogue.contains("kdesktop") == 1) { - if (maincatalogue) { - mainCatalogue = TQString::fromLatin1(maincatalogue); - } - } - - if (mainCatalogue.isEmpty()) { - kdDebug(173) << "KLocale instance created called without valid " - << "catalog! Give an argument or call setMainCatalogue " - << "before init" << endl; - } - else { - // do not use insertCatalogue here, that would already trigger updateCatalogs - d->catalogNames.append( mainCatalogue ); // application catalog - if (mainCatalogue.contains("desktop") == 0 || mainCatalogue.contains("kdesktop") == 1) { //don't bother if we're looking up desktop translations - d->catalogNames.append( SYSTEM_MESSAGES ); // always include tdelibs.mo - d->catalogNames.append( "kio" ); // always include kio.mo - d->catalogNames.append( "xdg-user-dirs" ); - } - updateCatalogues(); // evaluate this for all languages - } -} - -void KLocale::initLanguageList(KConfig * config, bool useEnv) -{ - KConfigGroupSaver saver(config, "Locale"); - - m_country = config->readEntry( "Country" ); - if ( m_country.isEmpty() ) - m_country = defaultCountry(); - - // Reset the list and add the new languages - TQStringList languageList; - if ( useEnv ) - languageList += TQStringList::split - (':', TQFile::decodeName( ::getenv("TDE_LANG") )); - - languageList += config->readListEntry("Language", ':'); - - // same order as setlocale use - if ( useEnv ) - { - // HPB: Only run splitLocale on the environment variables.. - TQStringList langs; - - langs << TQFile::decodeName( ::getenv("LC_ALL") ); - langs << TQFile::decodeName( ::getenv("LC_MESSAGES") ); - langs << TQFile::decodeName( ::getenv("LANG") ); - - for ( TQStringList::Iterator it = langs.begin(); - it != langs.end(); - ++it ) - { - TQString ln, ct, chrset; - splitLocale(*it, ln, ct, chrset); - - if (!ct.isEmpty()) { - langs.insert(it, ln + '_' + ct); - if (!chrset.isEmpty()) - langs.insert(it, ln + '_' + ct + '.' + chrset); - } - - langs.insert(it, ln); - } - - languageList += langs; - } - - // now we have a language list -- let's use the first OK language - setLanguage( languageList ); -} - -void KLocale::initPluralTypes() -{ - for ( TQValueList<KCatalogue>::Iterator it = d->catalogues.begin(); - it != d->catalogues.end(); - ++it ) - { - TQString language = (*it).language(); - int pt = pluralType( language ); - (*it).setPluralType( pt ); - } -} - - -int KLocale::pluralType( const TQString & language ) -{ - for ( TQValueList<KCatalogue>::ConstIterator it = d->catalogues.begin(); - it != d->catalogues.end(); - ++it ) - { - if ( ((*it).name() == SYSTEM_MESSAGES ) && ((*it).language() == language )) { - return pluralType( *it ); - } - } - // tdelibs.mo does not seem to exist for this language - return -1; -} - -int KLocale::pluralType( const KCatalogue& catalog ) -{ - const char* pluralFormString = - I18N_NOOP("_: Dear translator, please do not translate this string " - "in any form, but pick the _right_ value out of " - "NoPlural/TwoForms/French... If not sure what to do mail " - "thd@kde.org and coolo@kde.org, they will tell you. " - "Better leave that out if unsure, the programs will " - "crash!!\nDefinition of PluralForm - to be set by the " - "translator of tdelibs.po"); - TQString pf (catalog.translate( pluralFormString)); - if ( pf.isEmpty() ) { - return -1; - } - else if ( pf == "NoPlural" ) - return 0; - else if ( pf == "TwoForms" ) - return 1; - else if ( pf == "French" ) - return 2; - else if ( pf == "OneTwoRest" ) - return 3; - else if ( pf == "Russian" ) - return 4; - else if ( pf == "Polish" ) - return 5; - else if ( pf == "Slovenian" ) - return 6; - else if ( pf == "Lithuanian" ) - return 7; - else if ( pf == "Czech" ) - return 8; - else if ( pf == "Slovak" ) - return 9; - else if ( pf == "Maltese" ) - return 10; - else if ( pf == "Arabic" ) - return 11; - else if ( pf == "Balcan" ) - return 12; - else if ( pf == "Macedonian" ) - return 13; - else if ( pf == "Gaeilge" ) - return 14; - else { - kdWarning(173) << "Definition of PluralForm is none of " - << "NoPlural/" - << "TwoForms/" - << "French/" - << "OneTwoRest/" - << "Russian/" - << "Polish/" - << "Slovenian/" - << "Lithuanian/" - << "Czech/" - << "Slovak/" - << "Arabic/" - << "Balcan/" - << "Macedonian/" - << "Gaeilge/" - << "Maltese: " << pf << endl; - exit(1); - } -} - -void KLocale::doFormatInit() const -{ - if ( d->formatInited ) return; - - KLocale * that = const_cast<KLocale *>(this); - that->initFormat(); - - d->formatInited = true; -} - -void KLocale::initFormat() -{ - KConfig *config = d->config; - if (!config) config = KGlobal::instance()->config(); - Q_ASSERT( config ); - - kdDebug(173) << "KLocale::initFormat" << endl; - - // make sure the config files are read using the correct locale - // ### Why not add a KConfigBase::setLocale( const KLocale * )? - // ### Then we could remove this hack - KLocale *lsave = KGlobal::_locale; - KGlobal::_locale = this; - - KConfigGroupSaver saver(config, "Locale"); - - KSimpleConfig entry(locate("locale", - TQString::fromLatin1("l10n/%1/entry.desktop") - .arg(m_country)), true); - entry.setGroup("KCM Locale"); - - // Numeric -#define readConfigEntry(key, default, save) \ - save = entry.readEntry(key, TQString::fromLatin1(default)); \ - save = config->readEntry(key, save); - -#define readConfigNumEntry(key, default, save, type) \ - save = (type)entry.readNumEntry(key, default); \ - save = (type)config->readNumEntry(key, save); - -#define readConfigBoolEntry(key, default, save) \ - save = entry.readBoolEntry(key, default); \ - save = config->readBoolEntry(key, save); - - readConfigEntry("DecimalSymbol", ".", m_decimalSymbol); - readConfigEntry("ThousandsSeparator", ",", m_thousandsSeparator); - m_thousandsSeparator.replace( TQString::fromLatin1("$0"), TQString() ); - //kdDebug(173) << "m_thousandsSeparator=" << m_thousandsSeparator << endl; - - readConfigEntry("PositiveSign", "", m_positiveSign); - readConfigEntry("NegativeSign", "-", m_negativeSign); - - // Monetary - readConfigEntry("CurrencySymbol", "$", m_currencySymbol); - readConfigEntry("MonetaryDecimalSymbol", ".", m_monetaryDecimalSymbol); - readConfigEntry("MonetaryThousandsSeparator", ",", - m_monetaryThousandsSeparator); - m_monetaryThousandsSeparator.replace(TQString::fromLatin1("$0"), TQString()); - - readConfigNumEntry("FracDigits", 2, m_fracDigits, int); - readConfigBoolEntry("PositivePrefixCurrencySymbol", true, - m_positivePrefixCurrencySymbol); - readConfigBoolEntry("NegativePrefixCurrencySymbol", true, - m_negativePrefixCurrencySymbol); - readConfigNumEntry("PositiveMonetarySignPosition", (int)BeforeQuantityMoney, - m_positiveMonetarySignPosition, SignPosition); - readConfigNumEntry("NegativeMonetarySignPosition", (int)ParensAround, - m_negativeMonetarySignPosition, SignPosition); - - - // Date and time - readConfigEntry("TimeFormat", "%H:%M:%S", m_timeFormat); - readConfigEntry("DateFormat", "%A %d %B %Y", m_dateFormat); - readConfigEntry("DateFormatShort", "%Y-%m-%d", m_dateFormatShort); - readConfigNumEntry("WeekStartDay", 1, d->weekStartDay, int); - - // other - readConfigNumEntry("PageSize", (int)TQPrinter::A4, d->pageSize, int); - readConfigNumEntry("MeasureSystem", (int)Metric, d->measureSystem, - MeasureSystem); - readConfigEntry("CalendarSystem", "gregorian", d->calendarType); - delete d->calendar; - d->calendar = 0; // ### HPB Is this the correct place? - - //Grammatical - //Precedence here is l10n / i18n / config file - KSimpleConfig language(locate("locale", - TQString::fromLatin1("%1/entry.desktop") - .arg(m_language)), true); - language.setGroup("KCM Locale"); -#define read3ConfigBoolEntry(key, default, save) \ - save = entry.readBoolEntry(key, default); \ - save = language.readBoolEntry(key, save); \ - save = config->readBoolEntry(key, save); - - read3ConfigBoolEntry("NounDeclension", false, d->nounDeclension); - read3ConfigBoolEntry("DateMonthNamePossessive", false, - d->dateMonthNamePossessive); - - // end of hack - KGlobal::_locale = lsave; -} - -bool KLocale::setCountry(const TQString & country) -{ - // Check if the file exists too?? - if ( country.isEmpty() ) - return false; - - m_country = country; - - d->formatInited = false; - - return true; -} - -TQString KLocale::catalogueFileName(const TQString & language, - const KCatalogue & catalog) -{ - TQString path = TQString::fromLatin1("%1/LC_MESSAGES/%2.mo") - .arg( language ) - .arg( catalog.name() ); - - TQString fileName = locate( "locale", path ); - if (fileName.isEmpty()) - fileName = locate( "locale-bundle", path ); - - return fileName; -} - -bool KLocale::setLanguage(const TQString & language) -{ - if ( d->languageList.contains( language ) ) { - d->languageList.remove( language ); - } - d->languageList.prepend( language ); // let us consider this language to be the most important one - - m_language = language; // remember main language for shortcut evaluation - - // important when called from the outside and harmless when called before populating the - // catalog name list - updateCatalogues(); - - d->formatInited = false; - - return true; // Maybe the mo-files for this language are empty, but in principle we can speak all languages -} - -bool KLocale::setLanguage(const TQStringList & languages) -{ - TQStringList languageList( languages ); - // This list might contain - // 1) some empty strings that we have to eliminate - // 2) duplicate entries like in de:fr:de, where we have to keep the first occurrance of a language in order - // to preserve the order of precenence of the user => iterate backwards - // 3) languages into which the application is not translated. For those languages we should not even load tdelibs.mo or kio.po. - // these langugage have to be dropped. Otherwise we get strange side effects, e.g. with Hebrew: - // the right/left switch for languages that write from - // right to left (like Hebrew or Arabic) is set in tdelibs.mo. If you only have tdelibs.mo - // but nothing from appname.mo, you get a mostly English app with layout from right to left. - // That was considered to be a bug by the Hebrew translators. - for( TQStringList::Iterator it = languageList.fromLast(); - it != languageList.begin(); --it ) - { - // kdDebug() << "checking " << (*it) << endl; - bool bIsTranslated = isApplicationTranslatedInto( *it ); - if ( languageList.contains(*it) > 1 || (*it).isEmpty() || (!bIsTranslated) ) { - // kdDebug() << "removing " << (*it) << endl; - it = languageList.remove( it ); - } - } - // now this has left the first element of the list unchecked. - // The question why this is the case is left as an exercise for the reader... - // Besides the list might have been empty all the way, so check that too. - if ( languageList.begin() != languageList.end() ) { - TQStringList::Iterator it = languageList.begin(); // now pointing to the first element - // kdDebug() << "checking " << (*it) << endl; - if( (*it).isEmpty() || !(isApplicationTranslatedInto( *it )) ) { - // kdDebug() << "removing " << (*it) << endl; - languageList.remove( it ); // that's what the iterator was for... - } - } - - if ( languageList.isEmpty() ) { - // user picked no language, so we assume he/she speaks English. - languageList.append( defaultLanguage() ); - } - m_language = languageList.first(); // keep this for shortcut evaluations - - d->languageList = languageList; // keep this new list of languages to use - d->langTwoAlpha.clear(); // Flush cache - - // important when called from the outside and harmless when called before populating the - // catalog name list - updateCatalogues(); - - return true; // we found something. Maybe it's only English, but we found something -} - -bool KLocale::isApplicationTranslatedInto( const TQString & language) -{ - if ( language.isEmpty() ) { - return false; - } - - if ( language == defaultLanguage() ) { - // en_us is always "installed" - return true; - } - - TQString appName = d->appName; - if (maincatalogue) { - appName = TQString::fromLatin1(maincatalogue); - } - // sorry, catalogueFileName requires catalog object,k which we do not have here - // path finding was supposed to be moved completely to KCatalogue. The interface cannot - // be changed that far during deep freeze. So in order to fix the bug now, we have - // duplicated code for file path evaluation. Cleanup will follow later. We could have e.g. - // a static method in KCataloge that can translate between these file names. - // a stat - TQString sFileName = TQString::fromLatin1("%1/LC_MESSAGES/%2.mo") - .arg( language ) - .arg( appName ); - // kdDebug() << "isApplicationTranslatedInto: filename " << sFileName << endl; - - TQString sAbsFileName = locate( "locale", sFileName ); - if (sAbsFileName.isEmpty()) - sAbsFileName = locate( "locale-bundle", sFileName ); - - // kdDebug() << "isApplicationTranslatedInto: absname " << sAbsFileName << endl; - return ! sAbsFileName.isEmpty(); -} - -void KLocale::splitLocale(const TQString & aStr, - TQString & language, - TQString & country, - TQString & chrset) -{ - TQString str = aStr; - - // just in case, there is another language appended - int f = str.find(':'); - if (f >= 0) - str.truncate(f); - - country = TQString::null; - chrset = TQString::null; - language = TQString::null; - - f = str.find('.'); - if (f >= 0) - { - chrset = str.mid(f + 1); - str.truncate(f); - } - - f = str.find('_'); - if (f >= 0) - { - country = str.mid(f + 1); - str.truncate(f); - } - - language = str; -} - -TQString KLocale::language() const -{ - return m_language; -} - -TQString KLocale::country() const -{ - return m_country; -} - -TQString KLocale::monthName(int i, bool shortName) const -{ - if ( shortName ) - switch ( i ) - { - case 1: return translate("January", "Jan"); - case 2: return translate("February", "Feb"); - case 3: return translate("March", "Mar"); - case 4: return translate("April", "Apr"); - case 5: return translate("May short", "May"); - case 6: return translate("June", "Jun"); - case 7: return translate("July", "Jul"); - case 8: return translate("August", "Aug"); - case 9: return translate("September", "Sep"); - case 10: return translate("October", "Oct"); - case 11: return translate("November", "Nov"); - case 12: return translate("December", "Dec"); - } - else - switch (i) - { - case 1: return translate("January"); - case 2: return translate("February"); - case 3: return translate("March"); - case 4: return translate("April"); - case 5: return translate("May long", "May"); - case 6: return translate("June"); - case 7: return translate("July"); - case 8: return translate("August"); - case 9: return translate("September"); - case 10: return translate("October"); - case 11: return translate("November"); - case 12: return translate("December"); - } - - return TQString::null; -} - -TQString KLocale::monthNamePossessive(int i, bool shortName) const -{ - if ( shortName ) - switch ( i ) - { - case 1: return translate("of January", "of Jan"); - case 2: return translate("of February", "of Feb"); - case 3: return translate("of March", "of Mar"); - case 4: return translate("of April", "of Apr"); - case 5: return translate("of May short", "of May"); - case 6: return translate("of June", "of Jun"); - case 7: return translate("of July", "of Jul"); - case 8: return translate("of August", "of Aug"); - case 9: return translate("of September", "of Sep"); - case 10: return translate("of October", "of Oct"); - case 11: return translate("of November", "of Nov"); - case 12: return translate("of December", "of Dec"); - } - else - switch (i) - { - case 1: return translate("of January"); - case 2: return translate("of February"); - case 3: return translate("of March"); - case 4: return translate("of April"); - case 5: return translate("of May long", "of May"); - case 6: return translate("of June"); - case 7: return translate("of July"); - case 8: return translate("of August"); - case 9: return translate("of September"); - case 10: return translate("of October"); - case 11: return translate("of November"); - case 12: return translate("of December"); - } - - return TQString::null; -} - -TQString KLocale::weekDayName (int i, bool shortName) const -{ - return calendar()->weekDayName(i, shortName); -} - -void KLocale::insertCatalogue( const TQString & catalog ) -{ - if ( !d->catalogNames.contains( catalog) ) { - d->catalogNames.append( catalog ); - } - updateCatalogues( ); // evaluate the changed list and generate the neccessary KCatalog objects -} - -void KLocale::updateCatalogues( ) -{ - // some changes have occured. Maybe we have learned or forgotten some languages. - // Maybe the language precedence has changed. - // Maybe we have learned or forgotten some catalog names. - // Now examine the list of KCatalogue objects and change it according to the new circumstances. - - // this could be optimized: try to reuse old KCatalog objects, but remember that the order of - // catalogs might have changed: e.g. in this fashion - // 1) move all catalogs into a temporary list - // 2) iterate over all languages and catalog names - // 3.1) pick the catalog from the saved list, if it already exists - // 3.2) else create a new catalog. - // but we will do this later. - - for ( TQValueList<KCatalogue>::Iterator it = d->catalogues.begin(); - it != d->catalogues.end(); ) - { - it = d->catalogues.remove(it); - } - - // now iterate over all languages and all wanted catalog names and append or create them in the right order - // the sequence must be e.g. nds/appname nds/tdelibs nds/kio de/appname de/tdelibs de/kio etc. - // and not nds/appname de/appname nds/tdelibs de/tdelibs etc. Otherwise we would be in trouble with a language - // sequende nds,en_US, de. In this case en_US must hide everything below in the language list. - for ( TQStringList::ConstIterator itLangs = d->languageList.begin(); - itLangs != d->languageList.end(); ++itLangs) - { - for ( TQStringList::ConstIterator itNames = d->catalogNames.begin(); - itNames != d->catalogNames.end(); ++itNames) - { - KCatalogue cat( *itNames, *itLangs ); // create Catalog for this name and this language - d->catalogues.append( cat ); - } - } - initPluralTypes(); // evaluate the plural type for all languages and remember this in each KCatalogue -} - - - - -void KLocale::removeCatalogue(const TQString &catalog) -{ - if ( d->catalogNames.contains( catalog )) { - d->catalogNames.remove( catalog ); - if (KGlobal::_instance) - updateCatalogues(); // walk through the KCatalogue instances and weed out everything we no longer need - } -} - -void KLocale::setActiveCatalogue(const TQString &catalog) -{ - if ( d->catalogNames.contains( catalog ) ) { - d->catalogNames.remove( catalog ); - d->catalogNames.prepend( catalog ); - updateCatalogues(); // walk through the KCatalogue instances and adapt to the new order - } -} - -KLocale::~KLocale() -{ - delete d->calendar; - delete d->languages; - delete d; - d = 0L; -} - -TQString KLocale::translate_priv(const char *msgid, - const char *fallback, - const char **translated, - int* pluralType ) const -{ - if ( pluralType) { - *pluralType = -1; // unless we find something more precise - } - if (!msgid || !msgid[0]) - { - kdWarning() << "KLocale: trying to look up \"\" in catalog. " - << "Fix the program" << endl; - return TQString::null; - } - - if ( useDefaultLanguage() ) { // shortcut evaluation if en_US is main language: do not consult the catalogs - return TQString::fromUtf8( fallback ); - } - - for ( TQValueList<KCatalogue>::ConstIterator it = d->catalogues.begin(); - it != d->catalogues.end(); - ++it ) - { - // shortcut evaluation: once we have arrived at en_US (default language) we cannot consult - // the catalog as it will not have an assiciated mo-file. For this default language we can - // immediately pick the fallback string. - if ( (*it).language() == defaultLanguage() ) { - return TQString::fromUtf8( fallback ); - } - - const char * text = (*it).translate( msgid ); - - if ( text ) - { - // we found it - if (translated) { - *translated = text; - } - if ( pluralType) { - *pluralType = (*it).pluralType(); // remember the plural type information from the catalog that was used - } - return TQString::fromUtf8( text ); - } - } - - // Always use UTF-8 if the string was not found - return TQString::fromUtf8( fallback ); -} - -TQString KLocale::translate(const char* msgid) const -{ - return translate_priv(msgid, msgid); -} - -TQString KLocale::translate( const char *index, const char *fallback) const -{ - if (!index || !index[0] || !fallback || !fallback[0]) - { - kdDebug(173) << "KLocale: trying to look up \"\" in catalog. " - << "Fix the program" << endl; - return TQString::null; - } - - if ( useDefaultLanguage() ) - return TQString::fromUtf8( fallback ); - - char *newstring = new char[strlen(index) + strlen(fallback) + 5]; - sprintf(newstring, "_: %s\n%s", index, fallback); - // as copying TQString is very fast, it looks slower as it is ;/ - TQString r = translate_priv(newstring, fallback); - delete [] newstring; - - return r; -} - -static TQString put_n_in(const TQString &orig, unsigned long n) -{ - TQString ret = orig; - int index = ret.find("%n"); - if (index == -1) - return ret; - ret.replace(index, 2, TQString::number(n)); - return ret; -} - -#define EXPECT_LENGTH(x) \ - if (forms.count() != x) { \ - kdError() << "translation of \"" << singular << "\" doesn't contain " << x << " different plural forms as expected\n"; \ - return TQString( "BROKEN TRANSLATION %1" ).arg( singular ); } - -TQString KLocale::translate( const char *singular, const char *plural, - unsigned long n ) const -{ - if (!singular || !singular[0] || !plural || !plural[0]) - { - kdWarning() << "KLocale: trying to look up \"\" in catalog. " - << "Fix the program" << endl; - return TQString::null; - } - - char *newstring = new char[strlen(singular) + strlen(plural) + 6]; - sprintf(newstring, "_n: %s\n%s", singular, plural); - // as copying TQString is very fast, it looks slower as it is ;/ - int pluralType = -1; - TQString r = translate_priv(newstring, 0, 0, &pluralType); - delete [] newstring; - - if ( r.isEmpty() || useDefaultLanguage() || pluralType == -1) { - if ( n == 1 ) { - return put_n_in( TQString::fromUtf8( singular ), n ); - } else { - TQString tmp = TQString::fromUtf8( plural ); -#ifndef NDEBUG - if (tmp.find("%n") == -1) { - kdDebug() << "the message for i18n should contain a '%n'! " << plural << endl; - } -#endif - return put_n_in( tmp, n ); - } - } - - TQStringList forms = TQStringList::split( "\n", r, false ); - switch ( pluralType ) { - case 0: // NoPlural - EXPECT_LENGTH( 1 ); - return put_n_in( forms[0], n); - case 1: // TwoForms - EXPECT_LENGTH( 2 ); - if ( n == 1 ) - return put_n_in( forms[0], n); - else - return put_n_in( forms[1], n); - case 2: // French - EXPECT_LENGTH( 2 ); - if ( n == 1 || n == 0 ) - return put_n_in( forms[0], n); - else - return put_n_in( forms[1], n); - case 3: // OneTwoRest - EXPECT_LENGTH( 3 ); - if ( n == 1 ) - return put_n_in( forms[0], n); - else if ( n == 2 ) - return put_n_in( forms[1], n); - else - return put_n_in( forms[2], n); - case 4: // Russian, corrected by mok - EXPECT_LENGTH( 3 ); - if ( n%10 == 1 && n%100 != 11) - return put_n_in( forms[0], n); // odin fail - else if (( n%10 >= 2 && n%10 <=4 ) && (n%100<10 || n%100>20)) - return put_n_in( forms[1], n); // dva faila - else - return put_n_in( forms[2], n); // desyat' failov - case 5: // Polish - EXPECT_LENGTH( 3 ); - if ( n == 1 ) - return put_n_in( forms[0], n); - else if ( n%10 >= 2 && n%10 <=4 && (n%100<10 || n%100>=20) ) - return put_n_in( forms[1], n); - else - return put_n_in( forms[2], n); - case 6: // Slovenian - EXPECT_LENGTH( 4 ); - if ( n%100 == 1 ) - return put_n_in( forms[1], n); // ena datoteka - else if ( n%100 == 2 ) - return put_n_in( forms[2], n); // dve datoteki - else if ( n%100 == 3 || n%100 == 4 ) - return put_n_in( forms[3], n); // tri datoteke - else - return put_n_in( forms[0], n); // sto datotek - case 7: // Lithuanian - EXPECT_LENGTH( 3 ); - if ( n%10 == 0 || (n%100>=11 && n%100<=19) ) - return put_n_in( forms[2], n); - else if ( n%10 == 1 ) - return put_n_in( forms[0], n); - else - return put_n_in( forms[1], n); - case 8: // Czech - use modern form which is equivalent to Slovak - case 9: // Slovak - EXPECT_LENGTH( 3 ); - if ( n == 1 ) - return put_n_in( forms[0], n); - else if (( n >= 2 ) && ( n <= 4 )) - return put_n_in( forms[1], n); - else - return put_n_in( forms[2], n); - case 10: // Maltese - EXPECT_LENGTH( 4 ); - if ( n == 1 ) - return put_n_in( forms[0], n ); - else if ( ( n == 0 ) || ( n%100 > 0 && n%100 <= 10 ) ) - return put_n_in( forms[1], n ); - else if ( n%100 > 10 && n%100 < 20 ) - return put_n_in( forms[2], n ); - else - return put_n_in( forms[3], n ); - case 11: // Arabic - EXPECT_LENGTH( 4 ); - if (n == 1) - return put_n_in(forms[0], n); - else if (n == 2) - return put_n_in(forms[1], n); - else if ( n < 11) - return put_n_in(forms[2], n); - else - return put_n_in(forms[3], n); - case 12: // Balcan - EXPECT_LENGTH( 3 ); - if (n != 11 && n % 10 == 1) - return put_n_in(forms[0], n); - else if (n / 10 != 1 && n % 10 >= 2 && n % 10 <= 4) - return put_n_in(forms[1], n); - else - return put_n_in(forms[2], n); - case 13: // Macedonian - EXPECT_LENGTH(3); - if (n % 10 == 1) - return put_n_in(forms[0], n); - else if (n % 10 == 2) - return put_n_in(forms[1], n); - else - return put_n_in(forms[2], n); - case 14: // Gaeilge - EXPECT_LENGTH(5); - if (n == 1) // "ceann amhain" - return put_n_in(forms[0], n); - else if (n == 2) // "dha cheann" - return put_n_in(forms[1], n); - else if (n < 7) // "%n cinn" - return put_n_in(forms[2], n); - else if (n < 11) // "%n gcinn" - return put_n_in(forms[3], n); - else // "%n ceann" - return put_n_in(forms[4], n); - } - kdFatal() << "The function should have been returned in another way\n"; - - return TQString::null; -} - -TQString KLocale::translateQt( const char *context, const char *source, - const char *message) const -{ - if (!source || !source[0]) { - kdWarning() << "KLocale: trying to look up \"\" in catalog. " - << "Fix the program" << endl; - return TQString::null; - } - - if ( useDefaultLanguage() ) { - return TQString::null; - } - - char *newstring = 0; - const char *translation = 0; - TQString r; - - if ( message && message[0]) { - char *newstring = new char[strlen(source) + strlen(message) + 5]; - sprintf(newstring, "_: %s\n%s", source, message); - const char *translation = 0; - // as copying TQString is very fast, it looks slower as it is ;/ - r = translate_priv(newstring, source, &translation); - delete [] newstring; - if (translation) - return r; - } - - if ( context && context[0] && message && message[0]) { - newstring = new char[strlen(context) + strlen(message) + 5]; - sprintf(newstring, "_: %s\n%s", context, message); - // as copying TQString is very fast, it looks slower as it is ;/ - r = translate_priv(newstring, source, &translation); - delete [] newstring; - if (translation) - return r; - } - - r = translate_priv(source, source, &translation); - if (translation) - return r; - return TQString::null; -} - -bool KLocale::nounDeclension() const -{ - doFormatInit(); - return d->nounDeclension; -} - -bool KLocale::dateMonthNamePossessive() const -{ - doFormatInit(); - return d->dateMonthNamePossessive; -} - -int KLocale::weekStartDay() const -{ - doFormatInit(); - return d->weekStartDay; -} - -bool KLocale::weekStartsMonday() const //deprecated -{ - doFormatInit(); - return (d->weekStartDay==1); -} - -TQString KLocale::decimalSymbol() const -{ - doFormatInit(); - return m_decimalSymbol; -} - -TQString KLocale::thousandsSeparator() const -{ - doFormatInit(); - return m_thousandsSeparator; -} - -TQString KLocale::currencySymbol() const -{ - doFormatInit(); - return m_currencySymbol; -} - -TQString KLocale::monetaryDecimalSymbol() const -{ - doFormatInit(); - return m_monetaryDecimalSymbol; -} - -TQString KLocale::monetaryThousandsSeparator() const -{ - doFormatInit(); - return m_monetaryThousandsSeparator; -} - -TQString KLocale::positiveSign() const -{ - doFormatInit(); - return m_positiveSign; -} - -TQString KLocale::negativeSign() const -{ - doFormatInit(); - return m_negativeSign; -} - -int KLocale::fracDigits() const -{ - doFormatInit(); - return m_fracDigits; -} - -bool KLocale::positivePrefixCurrencySymbol() const -{ - doFormatInit(); - return m_positivePrefixCurrencySymbol; -} - -bool KLocale::negativePrefixCurrencySymbol() const -{ - doFormatInit(); - return m_negativePrefixCurrencySymbol; -} - -KLocale::SignPosition KLocale::positiveMonetarySignPosition() const -{ - doFormatInit(); - return m_positiveMonetarySignPosition; -} - -KLocale::SignPosition KLocale::negativeMonetarySignPosition() const -{ - doFormatInit(); - return m_negativeMonetarySignPosition; -} - -static inline void put_it_in( TQChar *buffer, uint& index, const TQString &s ) -{ - for ( uint l = 0; l < s.length(); l++ ) - buffer[index++] = s.at( l ); -} - -static inline void put_it_in( TQChar *buffer, uint& index, int number ) -{ - buffer[index++] = number / 10 + '0'; - buffer[index++] = number % 10 + '0'; -} - -// insert (thousands)-"separator"s into the non-fractional part of str -static void _insertSeparator(TQString &str, const TQString &separator, - const TQString &decimalSymbol) -{ - // leave fractional part untouched - TQString mainPart = str.section(decimalSymbol, 0, 0); - TQString fracPart = str.section(decimalSymbol, 1, 1, - TQString::SectionIncludeLeadingSep); - - for (int pos = mainPart.length() - 3; pos > 0; pos -= 3) - mainPart.insert(pos, separator); - - str = mainPart + fracPart; -} - -TQString KLocale::formatMoney(double num, - const TQString & symbol, - int precision) const -{ - // some defaults - TQString currency = symbol.isNull() - ? currencySymbol() - : symbol; - if (precision < 0) precision = fracDigits(); - - // the number itself - bool neg = num < 0; - TQString res = TQString::number(neg?-num:num, 'f', precision); - - // Replace dot with locale decimal separator - res.replace(TQChar('.'), monetaryDecimalSymbol()); - - // Insert the thousand separators - _insertSeparator(res, monetaryThousandsSeparator(), monetaryDecimalSymbol()); - - // set some variables we need later - int signpos = neg - ? negativeMonetarySignPosition() - : positiveMonetarySignPosition(); - TQString sign = neg - ? negativeSign() - : positiveSign(); - - switch (signpos) - { - case ParensAround: - res.prepend('('); - res.append (')'); - break; - case BeforeQuantityMoney: - res.prepend(sign); - break; - case AfterQuantityMoney: - res.append(sign); - break; - case BeforeMoney: - currency.prepend(sign); - break; - case AfterMoney: - currency.append(sign); - break; - } - - if (neg?negativePrefixCurrencySymbol(): - positivePrefixCurrencySymbol()) - { - res.prepend(' '); - res.prepend(currency); - } else { - res.append (' '); - res.append (currency); - } - - return res; -} - -TQString KLocale::formatMoney(const TQString &numStr) const -{ - return formatMoney(numStr.toDouble()); -} - -TQString KLocale::formatNumber(double num, int precision) const -{ - if (precision == -1) precision = 2; - // no need to round since TQString::number does this for us - return formatNumber(TQString::number(num, 'f', precision), false, 0); -} - -TQString KLocale::formatLong(long num) const -{ - return formatNumber((double)num, 0); -} - -TQString KLocale::formatNumber(const TQString &numStr) const -{ - return formatNumber(numStr, true, 2); -} - -// increase the digit at 'position' by one -static void _inc_by_one(TQString &str, int position) -{ - for (int i = position; i >= 0; i--) - { - char last_char = str[i].latin1(); - switch(last_char) - { - case '0': - str[i] = (QChar)'1'; - break; - case '1': - str[i] = (QChar)'2'; - break; - case '2': - str[i] = (QChar)'3'; - break; - case '3': - str[i] = (QChar)'4'; - break; - case '4': - str[i] = (QChar)'5'; - break; - case '5': - str[i] = (QChar)'6'; - break; - case '6': - str[i] = (QChar)'7'; - break; - case '7': - str[i] = (QChar)'8'; - break; - case '8': - str[i] = (QChar)'9'; - break; - case '9': - str[i] = (QChar)'0'; - if (i == 0) str.prepend('1'); - continue; - case '.': - continue; - } - break; - } -} - -// Cut off if more digits in fractional part than 'precision' -static void _round(TQString &str, int precision) -{ - int decimalSymbolPos = str.find('.'); - - if (decimalSymbolPos == -1) - if (precision == 0) return; - else if (precision > 0) // add dot if missing (and needed) - { - str.append('.'); - decimalSymbolPos = str.length() - 1; - } - - // fill up with more than enough zeroes (in case fractional part too short) - str.append(TQString().fill('0', precision)); - - // Now decide whether to round up or down - char last_char = str[decimalSymbolPos + precision + 1].latin1(); - switch (last_char) - { - case '0': - case '1': - case '2': - case '3': - case '4': - // nothing to do, rounding down - break; - case '5': - case '6': - case '7': - case '8': - case '9': - _inc_by_one(str, decimalSymbolPos + precision); - break; - default: - break; - } - - decimalSymbolPos = str.find('.'); - str.truncate(decimalSymbolPos + precision + 1); - - // if precision == 0 delete also '.' - if (precision == 0) str = str.section('.', 0, 0); -} - -TQString KLocale::formatNumber(const TQString &numStr, bool round, - int precision) const -{ - TQString tmpString = numStr; - if ((round && precision < 0) || - ! TQRegExp("^[+-]?\\d+(\\.\\d+)*(e[+-]?\\d+)?$").exactMatch(tmpString)) - return numStr; - - - // Skip the sign (for now) - bool neg = (tmpString[0] == (QChar)'-'); - if (neg || tmpString[0] == (QChar)'+') tmpString.remove(0, 1); - - // Split off exponential part (including 'e'-symbol) - TQString mantString = tmpString.section('e', 0, 0, - TQString::SectionCaseInsensitiveSeps); - TQString expString = tmpString.section('e', 1, 1, - TQString::SectionCaseInsensitiveSeps | - TQString::SectionIncludeLeadingSep); - - if (round) _round(mantString, precision); - - // Replace dot with locale decimal separator - mantString.replace(TQChar('.'), decimalSymbol()); - - // Insert the thousand separators - _insertSeparator(mantString, thousandsSeparator(), decimalSymbol()); - - // How can we know where we should put the sign? - mantString.prepend(neg?negativeSign():positiveSign()); - - return mantString + expString; -} - -TQString KLocale::formatDate(const TQDate &pDate, bool shortFormat) const -{ - const TQString rst = shortFormat?dateFormatShort():dateFormat(); - - TQString buffer; - - if ( ! pDate.isValid() ) return buffer; - - bool escape = false; - - int year = calendar()->year(pDate); - int month = calendar()->month(pDate); - - for ( uint format_index = 0; format_index < rst.length(); ++format_index ) - { - if ( !escape ) - { - if ( (TQChar(rst.at( format_index )).unicode()) == '%' ) - escape = true; - else - buffer.append(rst.at(format_index)); - } - else - { - switch ( TQChar(rst.at( format_index )).unicode() ) - { - case '%': - buffer.append('%'); - break; - case 'Y': - buffer.append(calendar()->yearString(pDate, false)); - break; - case 'y': - buffer.append(calendar()->yearString(pDate, true)); - break; - case 'n': - buffer.append(calendar()->monthString(pDate, true)); - break; - case 'e': - buffer.append(calendar()->dayString(pDate, true)); - break; - case 'm': - buffer.append(calendar()->monthString(pDate, false)); - break; - case 'b': - if (d->nounDeclension && d->dateMonthNamePossessive) - buffer.append(calendar()->monthNamePossessive(month, year, true)); - else - buffer.append(calendar()->monthName(month, year, true)); - break; - case 'B': - if (d->nounDeclension && d->dateMonthNamePossessive) - buffer.append(calendar()->monthNamePossessive(month, year, false)); - else - buffer.append(calendar()->monthName(month, year, false)); - break; - case 'd': - buffer.append(calendar()->dayString(pDate, false)); - break; - case 'a': - buffer.append(calendar()->weekDayName(pDate, true)); - break; - case 'A': - buffer.append(calendar()->weekDayName(pDate, false)); - break; - default: - buffer.append(rst.at(format_index)); - break; - } - escape = false; - } - } - return buffer; -} - -void KLocale::setMainCatalogue(const char *catalog) -{ - maincatalogue = catalog; -} - -double KLocale::readNumber(const TQString &_str, bool * ok) const -{ - TQString str = _str.stripWhiteSpace(); - bool neg = str.find(negativeSign()) == 0; - if (neg) - str.remove( 0, negativeSign().length() ); - - /* will hold the scientific notation portion of the number. - Example, with 2.34E+23, exponentialPart == "E+23" - */ - TQString exponentialPart; - int EPos; - - EPos = str.find('E', 0, false); - - if (EPos != -1) - { - exponentialPart = str.mid(EPos); - str = str.left(EPos); - } - - int pos = str.find(decimalSymbol()); - TQString major; - TQString minor; - if ( pos == -1 ) - major = str; - else - { - major = str.left(pos); - minor = str.mid(pos + decimalSymbol().length()); - } - - // Remove thousand separators - int thlen = thousandsSeparator().length(); - int lastpos = 0; - while ( ( pos = major.find( thousandsSeparator() ) ) > 0 ) - { - // e.g. 12,,345,,678,,922 Acceptable positions (from the end) are 5, 10, 15... i.e. (3+thlen)*N - int fromEnd = major.length() - pos; - if ( fromEnd % (3+thlen) != 0 // Needs to be a multiple, otherwise it's an error - || pos - lastpos > 3 // More than 3 digits between two separators -> error - || pos == 0 // Can't start with a separator - || (lastpos>0 && pos-lastpos!=3)) // Must have exactly 3 digits between two separators - { - if (ok) *ok = false; - return 0.0; - } - - lastpos = pos; - major.remove( pos, thlen ); - } - if (lastpos>0 && major.length()-lastpos!=3) // Must have exactly 3 digits after the last separator - { - if (ok) *ok = false; - return 0.0; - } - - TQString tot; - if (neg) tot = (QChar)'-'; - - tot += major + '.' + minor + exponentialPart; - - return tot.toDouble(ok); -} - -double KLocale::readMoney(const TQString &_str, bool * ok) const -{ - TQString str = _str.stripWhiteSpace(); - bool neg = false; - bool currencyFound = false; - TQString symbol = currencySymbol(); - // First try removing currency symbol from either end - int pos = str.find(symbol); - if ( pos == 0 || pos == (int) str.length()-symbol.length() ) - { - str.remove(pos,symbol.length()); - str = str.stripWhiteSpace(); - currencyFound = true; - } - if (str.isEmpty()) - { - if (ok) *ok = false; - return 0; - } - // Then try removing negative sign from either end - // (with a special case for parenthesis) - if (negativeMonetarySignPosition() == ParensAround) - { - if (str[0] == (QChar)'(' && str[str.length()-1] == (QChar)')') - { - neg = true; - str.remove(str.length()-1,1); - str.remove(0,1); - } - } - else - { - int i1 = str.find(negativeSign()); - if ( i1 == 0 || i1 == (int) str.length()-1 ) - { - neg = true; - str.remove(i1,negativeSign().length()); - } - } - if (neg) str = str.stripWhiteSpace(); - - // Finally try again for the currency symbol, if we didn't find - // it already (because of the negative sign being in the way). - if ( !currencyFound ) - { - pos = str.find(symbol); - if ( pos == 0 || pos == (int) str.length()-symbol.length() ) - { - str.remove(pos,symbol.length()); - str = str.stripWhiteSpace(); - } - } - - // And parse the rest as a number - pos = str.find(monetaryDecimalSymbol()); - TQString major; - TQString minior; - if (pos == -1) - major = str; - else - { - major = str.left(pos); - minior = str.mid(pos + monetaryDecimalSymbol().length()); - } - - // Remove thousand separators - int thlen = monetaryThousandsSeparator().length(); - int lastpos = 0; - while ( ( pos = major.find( monetaryThousandsSeparator() ) ) > 0 ) - { - // e.g. 12,,345,,678,,922 Acceptable positions (from the end) are 5, 10, 15... i.e. (3+thlen)*N - int fromEnd = major.length() - pos; - if ( fromEnd % (3+thlen) != 0 // Needs to be a multiple, otherwise it's an error - || pos - lastpos > 3 // More than 3 digits between two separators -> error - || pos == 0 // Can't start with a separator - || (lastpos>0 && pos-lastpos!=3)) // Must have exactly 3 digits between two separators - { - if (ok) *ok = false; - return 0.0; - } - lastpos = pos; - major.remove( pos, thlen ); - } - if (lastpos>0 && major.length()-lastpos!=3) // Must have exactly 3 digits after the last separator - { - if (ok) *ok = false; - return 0.0; - } - - TQString tot; - if (neg) tot = (QChar)'-'; - tot += major + '.' + minior; - return tot.toDouble(ok); -} - -/** - * helper function to read integers - * @param str - * @param pos the position to start at. It will be updated when we parse it. - * @return the integer read in the string, or -1 if no string - */ -static int readInt(const TQString &str, uint &pos) -{ - if (!str.at(pos).isDigit()) return -1; - int result = 0; - for (; str.length() > pos && str.at(pos).isDigit(); pos++) - { - result *= 10; - result += str.at(pos).digitValue(); - } - - return result; -} - -TQDate KLocale::readDate(const TQString &intstr, bool* ok) const -{ - TQDate date; - date = readDate(intstr, ShortFormat, ok); - if (date.isValid()) return date; - return readDate(intstr, NormalFormat, ok); -} - -TQDate KLocale::readDate(const TQString &intstr, ReadDateFlags flags, bool* ok) const -{ - TQString fmt = ((flags & ShortFormat) ? dateFormatShort() : dateFormat()).simplifyWhiteSpace(); - return readDate( intstr, fmt, ok ); -} - -TQDate KLocale::readDate(const TQString &intstr, const TQString &fmt, bool* ok) const -{ - //kdDebug() << "KLocale::readDate intstr=" << intstr << " fmt=" << fmt << endl; - TQString str = intstr.simplifyWhiteSpace().lower(); - int day = -1, month = -1; - // allow the year to be omitted if not in the format - int year = calendar()->year(TQDate::currentDate()); - uint strpos = 0; - uint fmtpos = 0; - - int iLength; // Temporary variable used when reading input - - bool error = false; - - while (fmt.length() > fmtpos && str.length() > strpos && !error) - { - - TQChar c = fmt.at(fmtpos++); - - if (c != (QChar)'%') { - if (c.isSpace() && str.at(strpos).isSpace()) - strpos++; - else if (c != str.at(strpos++)) - error = true; - } - else - { - int j; - // remove space at the beginning - if (str.length() > strpos && str.at(strpos).isSpace()) - strpos++; - - c = fmt.at(fmtpos++); - switch (c) - { - case 'a': - case 'A': - - error = true; - j = 1; - while (error && (j < 8)) { - TQString s = calendar()->weekDayName(j, c == (QChar)'a').lower(); - int len = s.length(); - if (str.mid(strpos, len) == s) - { - strpos += len; - error = false; - } - j++; - } - break; - case 'b': - case 'B': - - error = true; - if (d->nounDeclension && d->dateMonthNamePossessive) { - j = 1; - while (error && (j < 13)) { - TQString s = calendar()->monthNamePossessive(j, year, c == (QChar)'b').lower(); - int len = s.length(); - if (str.mid(strpos, len) == s) { - month = j; - strpos += len; - error = false; - } - j++; - } - } - j = 1; - while (error && (j < 13)) { - TQString s = calendar()->monthName(j, year, c == (QChar)'b').lower(); - int len = s.length(); - if (str.mid(strpos, len) == s) { - month = j; - strpos += len; - error = false; - } - j++; - } - break; - case 'd': - case 'e': - day = calendar()->dayStringToInteger(str.mid(strpos), iLength); - strpos += iLength; - - error = iLength <= 0; - break; - - case 'n': - case 'm': - month = calendar()->monthStringToInteger(str.mid(strpos), iLength); - strpos += iLength; - - error = iLength <= 0; - break; - - case 'Y': - case 'y': - year = calendar()->yearStringToInteger(str.mid(strpos), iLength); - strpos += iLength; - - error = iLength <= 0; - break; - } - } - } - - /* for a match, we should reach the end of both strings, not just one of - them */ - if ( fmt.length() > fmtpos || str.length() > strpos ) - { - error = true; - } - - //kdDebug(173) << "KLocale::readDate day=" << day << " month=" << month << " year=" << year << endl; - if ( year != -1 && month != -1 && day != -1 && !error) - { - if (ok) *ok = true; - - TQDate result; - calendar()->setYMD(result, year, month, day); - - return result; - } - else - { - if (ok) *ok = false; - return TQDate(); // invalid date - } -} - -TQTime KLocale::readTime(const TQString &intstr, bool *ok) const -{ - TQTime _time; - _time = readTime(intstr, WithSeconds, ok); - if (_time.isValid()) return _time; - return readTime(intstr, WithoutSeconds, ok); -} - -TQTime KLocale::readTime(const TQString &intstr, ReadTimeFlags flags, bool *ok) const -{ - TQString str = intstr.simplifyWhiteSpace().lower(); - TQString Format = timeFormat().simplifyWhiteSpace(); - if (flags & WithoutSeconds) - Format.remove(TQRegExp(".%S")); - - int hour = -1, minute = -1; - int second = ( (flags & WithoutSeconds) == 0 ) ? -1 : 0; // don't require seconds - bool g_12h = false; - bool pm = false; - uint strpos = 0; - uint Formatpos = 0; - - while (Format.length() > Formatpos || str.length() > strpos) - { - if ( !(Format.length() > Formatpos && str.length() > strpos) ) goto error; - - TQChar c = Format.at(Formatpos++); - - if (c != (QChar)'%') - { - if (c.isSpace()) - strpos++; - else if (c != str.at(strpos++)) - goto error; - continue; - } - - // remove space at the beginning - if (str.length() > strpos && str.at(strpos).isSpace()) - strpos++; - - c = Format.at(Formatpos++); - switch (c) - { - case 'p': - { - TQString s; - s = translate("pm").lower(); - int len = s.length(); - if (str.mid(strpos, len) == s) - { - pm = true; - strpos += len; - } - else - { - s = translate("am").lower(); - len = s.length(); - if (str.mid(strpos, len) == s) { - pm = false; - strpos += len; - } - else - goto error; - } - } - break; - - case 'k': - case 'H': - g_12h = false; - hour = readInt(str, strpos); - if (hour < 0 || hour > 23) - goto error; - - break; - - case 'l': - case 'I': - g_12h = true; - hour = readInt(str, strpos); - if (hour < 1 || hour > 12) - goto error; - - break; - - case 'M': - minute = readInt(str, strpos); - if (minute < 0 || minute > 59) - goto error; - - break; - - case 'S': - second = readInt(str, strpos); - if (second < 0 || second > 59) - goto error; - - break; - } - } - if (g_12h) { - hour %= 12; - if (pm) hour += 12; - } - - if (ok) *ok = true; - return TQTime(hour, minute, second); - - error: - if (ok) *ok = false; - // ######## KDE4: remove this - return TQTime(-1, -1, -1); // return invalid date if it didn't work -} - -//BIC: merge with below -TQString KLocale::formatTime(const TQTime &pTime, bool includeSecs) const -{ - return formatTime( pTime, includeSecs, false ); -} - -TQString KLocale::formatTime(const TQTime &pTime, bool includeSecs, bool isDuration) const -{ - const TQString rst = timeFormat(); - - // only "pm/am" here can grow, the rest shrinks, but - // I'm rather safe than sorry - TQChar *buffer = new TQChar[rst.length() * 3 / 2 + 30]; - - uint index = 0; - bool escape = false; - int number = 0; - - for ( uint format_index = 0; format_index < rst.length(); format_index++ ) - { - if ( !escape ) - { - if ( (TQChar(rst.at( format_index )).unicode()) == '%' ) - escape = true; - else - buffer[index++] = rst.at( format_index ); - } - else - { - switch ( TQChar(rst.at( format_index )).unicode() ) - { - case '%': - buffer[index++] = (QChar)'%'; - break; - case 'H': - put_it_in( buffer, index, pTime.hour() ); - break; - case 'I': - if ( isDuration ) - put_it_in( buffer, index, pTime.hour() ); - else - put_it_in( buffer, index, ( pTime.hour() + 11) % 12 + 1 ); - break; - case 'M': - put_it_in( buffer, index, pTime.minute() ); - break; - case 'S': - if (includeSecs) - put_it_in( buffer, index, pTime.second() ); - else if ( index > 0 ) - { - // we remove the separator sign before the seconds and - // assume that works everywhere - --index; - break; - } - break; - case 'k': - number = pTime.hour(); - case 'l': - // to share the code - if ( (TQChar(rst.at( format_index )).unicode()) == 'l' ) - number = isDuration ? pTime.hour() : (pTime.hour() + 11) % 12 + 1; - if ( number / 10 ) - buffer[index++] = number / 10 + '0'; - buffer[index++] = number % 10 + '0'; - break; - case 'p': - if ( !isDuration ) - { - TQString s; - if ( pTime.hour() >= 12 ) - put_it_in( buffer, index, translate("pm") ); - else - put_it_in( buffer, index, translate("am") ); - } - break; - default: - buffer[index++] = rst.at( format_index ); - break; - } - escape = false; - } - } - TQString ret( buffer, index ); - delete [] buffer; - if ( isDuration ) // eliminate trailing-space due to " %p" - return ret.stripWhiteSpace(); - else - return ret; -} - -bool KLocale::use12Clock() const -{ - if ((timeFormat().contains(TQString::fromLatin1("%I")) > 0) || - (timeFormat().contains(TQString::fromLatin1("%l")) > 0)) - return true; - else - return false; -} - -TQString KLocale::languages() const -{ - return d->languageList.join( TQString::fromLatin1(":") ); -} - -TQStringList KLocale::languageList() const -{ - return d->languageList; -} - -TQString KLocale::formatDateTime(const TQDateTime &pDateTime, - bool shortFormat, - bool includeSeconds) const -{ - return translate("concatenation of dates and time", "%1 %2") - .arg( formatDate( TQT_TQDATE_OBJECT(pDateTime.date()), shortFormat ) ) - .arg( formatTime( TQT_TQTIME_OBJECT(pDateTime.time()), includeSeconds ) ); -} - -TQString i18n(const char* text) -{ - register KLocale *instance = KGlobal::locale(); - if (instance) - return instance->translate(text); - return TQString::fromUtf8(text); -} - -TQString i18n(const char* index, const char *text) -{ - register KLocale *instance = KGlobal::locale(); - if (instance) - return instance->translate(index, text); - return TQString::fromUtf8(text); -} - -TQString i18n(const char* singular, const char* plural, unsigned long n) -{ - register KLocale *instance = KGlobal::locale(); - if (instance) - return instance->translate(singular, plural, n); - if (n == 1) - return put_n_in(TQString::fromUtf8(singular), n); - else - return put_n_in(TQString::fromUtf8(plural), n); -} - -void KLocale::initInstance() -{ - if (KGlobal::_locale) - return; - - KInstance *app = KGlobal::instance(); - if (app) { - KGlobal::_locale = new KLocale(TQString::fromLatin1(app->instanceName())); - - // only do this for the global instance - TQTextCodec::setCodecForLocale(KGlobal::_locale->codecForEncoding()); - } - else - kdDebug(173) << "no app name available using KLocale - nothing to do\n"; -} - -TQString KLocale::langLookup(const TQString &fname, const char *rtype) -{ - TQStringList search; - - // assemble the local search paths - const TQStringList localDoc = KGlobal::dirs()->resourceDirs(rtype); - - // look up the different languages - for (int id=localDoc.count()-1; id >= 0; --id) - { - TQStringList langs = KGlobal::locale()->languageList(); - langs.append( "en" ); - langs.remove( defaultLanguage() ); - TQStringList::ConstIterator lang; - for (lang = langs.begin(); lang != langs.end(); ++lang) - search.append(TQString("%1%2/%3").arg(localDoc[id]).arg(*lang).arg(fname)); - } - - // try to locate the file - TQStringList::Iterator it; - for (it = search.begin(); it != search.end(); ++it) - { - kdDebug(173) << "Looking for help in: " << *it << endl; - - TQFileInfo info(*it); - if (info.exists() && info.isFile() && info.isReadable()) - return *it; - } - - return TQString::null; -} - -bool KLocale::useDefaultLanguage() const -{ - return language() == defaultLanguage(); -} - -void KLocale::initEncoding(KConfig *) -{ - const int mibDefault = 4; // ISO 8859-1 - - // This all made more sense when we still had the EncodingEnum config key. - setEncoding( TQTextCodec::codecForLocale()->mibEnum() ); - - if ( !d->codecForEncoding ) - { - kdWarning(173) << " Defaulting to ISO 8859-1 encoding." << endl; - setEncoding(mibDefault); - } - - Q_ASSERT( d->codecForEncoding ); -} - -void KLocale::initFileNameEncoding(KConfig *) -{ - // If the following environment variable is set, assume all filenames - // are in UTF-8 regardless of the current C locale. - d->utf8FileEncoding = getenv("TDE_UTF8_FILENAMES") != 0; - if (d->utf8FileEncoding) - { - TQFile::setEncodingFunction(KLocale::encodeFileNameUTF8); - TQFile::setDecodingFunction(KLocale::decodeFileNameUTF8); - } - // Otherwise, stay with QFile's default filename encoding functions - // which, on Unix platforms, use the locale's codec. -} - -#ifdef USE_QT3 -TQCString KLocale::encodeFileNameUTF8( const TQString & fileName ) -#endif // USE_QT3 -#ifdef USE_QT4 -QByteArray KLocale::encodeFileNameUTF8( const QString & fileName ) -#endif // USE_QT4 -{ - return TQString(fileName).utf8(); -} - -#ifdef USE_QT3 -TQString KLocale::decodeFileNameUTF8( const TQCString & localFileName ) -#endif // USE_QT3 -#ifdef USE_QT4 -QString KLocale::decodeFileNameUTF8( const QByteArray & localFileName ) -#endif // USE_QT4 -{ - return TQString::fromUtf8(localFileName); -} - -void KLocale::setDateFormat(const TQString & format) -{ - doFormatInit(); - m_dateFormat = format.stripWhiteSpace(); -} - -void KLocale::setDateFormatShort(const TQString & format) -{ - doFormatInit(); - m_dateFormatShort = format.stripWhiteSpace(); -} - -void KLocale::setDateMonthNamePossessive(bool possessive) -{ - doFormatInit(); - d->dateMonthNamePossessive = possessive; -} - -void KLocale::setTimeFormat(const TQString & format) -{ - doFormatInit(); - m_timeFormat = format.stripWhiteSpace(); -} - -void KLocale::setWeekStartsMonday(bool start) //deprecated -{ - doFormatInit(); - if (start) - d->weekStartDay = 1; - else - d->weekStartDay = 7; -} - -void KLocale::setWeekStartDay(int day) -{ - doFormatInit(); - if (day>7 || day<1) - d->weekStartDay = 1; //Monday is default - else - d->weekStartDay = day; -} - -TQString KLocale::dateFormat() const -{ - doFormatInit(); - return m_dateFormat; -} - -TQString KLocale::dateFormatShort() const -{ - doFormatInit(); - return m_dateFormatShort; -} - -TQString KLocale::timeFormat() const -{ - doFormatInit(); - return m_timeFormat; -} - -void KLocale::setDecimalSymbol(const TQString & symbol) -{ - doFormatInit(); - m_decimalSymbol = symbol.stripWhiteSpace(); -} - -void KLocale::setThousandsSeparator(const TQString & separator) -{ - doFormatInit(); - // allow spaces here - m_thousandsSeparator = separator; -} - -void KLocale::setPositiveSign(const TQString & sign) -{ - doFormatInit(); - m_positiveSign = sign.stripWhiteSpace(); -} - -void KLocale::setNegativeSign(const TQString & sign) -{ - doFormatInit(); - m_negativeSign = sign.stripWhiteSpace(); -} - -void KLocale::setPositiveMonetarySignPosition(SignPosition signpos) -{ - doFormatInit(); - m_positiveMonetarySignPosition = signpos; -} - -void KLocale::setNegativeMonetarySignPosition(SignPosition signpos) -{ - doFormatInit(); - m_negativeMonetarySignPosition = signpos; -} - -void KLocale::setPositivePrefixCurrencySymbol(bool prefix) -{ - doFormatInit(); - m_positivePrefixCurrencySymbol = prefix; -} - -void KLocale::setNegativePrefixCurrencySymbol(bool prefix) -{ - doFormatInit(); - m_negativePrefixCurrencySymbol = prefix; -} - -void KLocale::setFracDigits(int digits) -{ - doFormatInit(); - m_fracDigits = digits; -} - -void KLocale::setMonetaryThousandsSeparator(const TQString & separator) -{ - doFormatInit(); - // allow spaces here - m_monetaryThousandsSeparator = separator; -} - -void KLocale::setMonetaryDecimalSymbol(const TQString & symbol) -{ - doFormatInit(); - m_monetaryDecimalSymbol = symbol.stripWhiteSpace(); -} - -void KLocale::setCurrencySymbol(const TQString & symbol) -{ - doFormatInit(); - m_currencySymbol = symbol.stripWhiteSpace(); -} - -int KLocale::pageSize() const -{ - doFormatInit(); - return d->pageSize; -} - -void KLocale::setPageSize(int pageSize) -{ - // #### check if it's in range?? - doFormatInit(); - d->pageSize = pageSize; -} - -KLocale::MeasureSystem KLocale::measureSystem() const -{ - doFormatInit(); - return d->measureSystem; -} - -void KLocale::setMeasureSystem(MeasureSystem value) -{ - doFormatInit(); - d->measureSystem = value; -} - -TQString KLocale::defaultLanguage() -{ - return TQString::fromLatin1("en_US"); -} - -TQString KLocale::defaultCountry() -{ - return TQString::fromLatin1("C"); -} - -const char * KLocale::encoding() const -{ -#ifdef Q_WS_WIN - if (0==qstrcmp("System", codecForEncoding()->name())) - { - //win32 returns "System" codec name here but KDE apps expect a real name: - strcpy(d->win32SystemEncoding, "cp "); - if (GetLocaleInfoA( MAKELCID(MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), SORT_DEFAULT), - LOCALE_IDEFAULTANSICODEPAGE, d->win32SystemEncoding+3, sizeof(d->win32SystemEncoding)-3-1 )) - { - return d->win32SystemEncoding; - } - } -#endif - return codecForEncoding()->name(); -} - -int KLocale::encodingMib() const -{ - return codecForEncoding()->mibEnum(); -} - -int KLocale::fileEncodingMib() const -{ - if (d->utf8FileEncoding) - return 106; - return codecForEncoding()->mibEnum(); -} - -TQTextCodec * KLocale::codecForEncoding() const -{ - return d->codecForEncoding; -} - -bool KLocale::setEncoding(int mibEnum) -{ - TQTextCodec * codec = TQTextCodec::codecForMib(mibEnum); - if (codec) - d->codecForEncoding = codec; - - return codec != 0; -} - -TQStringList KLocale::languagesTwoAlpha() const -{ - if (d->langTwoAlpha.count()) - return d->langTwoAlpha; - - const TQStringList &origList = languageList(); - - TQStringList result; - - KConfig config(TQString::fromLatin1("language.codes"), true, false); - config.setGroup("TwoLetterCodes"); - - for ( TQStringList::ConstIterator it = origList.begin(); - it != origList.end(); - ++it ) - { - TQString lang = *it; - TQStringList langLst; - if (config.hasKey( lang )) - langLst = config.readListEntry( lang ); - else - { - int i = lang.find('_'); - if (i >= 0) - lang.truncate(i); - langLst << lang; - } - - for ( TQStringList::ConstIterator langIt = langLst.begin(); - langIt != langLst.end(); - ++langIt ) - { - if ( !(*langIt).isEmpty() && !result.contains( *langIt ) ) - result += *langIt; - } - } - d->langTwoAlpha = result; - return result; -} - -TQStringList KLocale::allLanguagesTwoAlpha() const -{ - if (!d->languages) - d->languages = new KConfig("all_languages", true, false, "locale"); - - return d->languages->groupList(); -} - -TQString KLocale::twoAlphaToLanguageName(const TQString &code) const -{ - if (!d->languages) - d->languages = new KConfig("all_languages", true, false, "locale"); - - TQString groupName = code; - const int i = groupName.find('_'); - groupName.replace(0, i, groupName.left(i).lower()); - - d->languages->setGroup(groupName); - return d->languages->readEntry("Name"); -} - -TQStringList KLocale::allCountriesTwoAlpha() const -{ - TQStringList countries; - TQStringList paths = KGlobal::dirs()->findAllResources("locale", "l10n/*/entry.desktop"); - for(TQStringList::ConstIterator it = paths.begin(); - it != paths.end(); ++it) - { - TQString code = (*it).mid((*it).length()-16, 2); - if (code != "/C") - countries.append(code); - } - return countries; -} - -TQString KLocale::twoAlphaToCountryName(const TQString &code) const -{ - KConfig cfg("l10n/"+code.lower()+"/entry.desktop", true, false, "locale"); - cfg.setGroup("KCM Locale"); - return cfg.readEntry("Name"); -} - -void KLocale::setCalendar(const TQString & calType) -{ - doFormatInit(); - - d->calendarType = calType; - - delete d->calendar; - d->calendar = 0; -} - -TQString KLocale::calendarType() const -{ - doFormatInit(); - - return d->calendarType; -} - -const KCalendarSystem * KLocale::calendar() const -{ - doFormatInit(); - - // Check if it's the correct calendar?!? - if ( !d->calendar ) - d->calendar = KCalendarSystemFactory::create( d->calendarType, this ); - - return d->calendar; -} - -KLocale::KLocale(const KLocale & rhs) -{ - d = new KLocalePrivate; - - *this = rhs; -} - -KLocale & KLocale::operator=(const KLocale & rhs) -{ - // Numbers and money - m_decimalSymbol = rhs.m_decimalSymbol; - m_thousandsSeparator = rhs.m_thousandsSeparator; - m_currencySymbol = rhs.m_currencySymbol; - m_monetaryDecimalSymbol = rhs.m_monetaryDecimalSymbol; - m_monetaryThousandsSeparator = rhs.m_monetaryThousandsSeparator; - m_positiveSign = rhs.m_positiveSign; - m_negativeSign = rhs.m_negativeSign; - m_fracDigits = rhs.m_fracDigits; - m_positivePrefixCurrencySymbol = rhs.m_positivePrefixCurrencySymbol; - m_negativePrefixCurrencySymbol = rhs.m_negativePrefixCurrencySymbol; - m_positiveMonetarySignPosition = rhs.m_positiveMonetarySignPosition; - m_negativeMonetarySignPosition = rhs.m_negativeMonetarySignPosition; - - // Date and time - m_timeFormat = rhs.m_timeFormat; - m_dateFormat = rhs.m_dateFormat; - m_dateFormatShort = rhs.m_dateFormatShort; - - m_language = rhs.m_language; - m_country = rhs.m_country; - - // the assignment operator works here - *d = *rhs.d; - d->languages = 0; // Don't copy languages - d->calendar = 0; // Don't copy the calendar - - return *this; -} - -bool KLocale::setCharset(const TQString & ) { return true; } -TQString KLocale::charset() const { return TQString::fromLatin1("UTF-8"); } - -// KDE4: remove -#if 0 -void nothing() { i18n("&Next"); } -#endif |