From d1d8fda63745350804d76b4ed160732086fa9655 Mon Sep 17 00:00:00 2001 From: Oliver Tappe Date: Tue, 19 Oct 2010 21:36:44 +0000 Subject: [PATCH] Next step of Locale Kit refactoring: * BLocale now keeps language and country completely separate and mixes the formatting conventions into the current language's locale when formatting dates and times (needs to be done for number- and currency-formatting, too, since the digits may not be in the preferred language) * optimized fetching of the flag icons such that they are all loaded in one go (by the locale roster) - this alone speeds up the Locale preflet considerably * worked on fixing the language confusion in the Locale preflet * fixed a couple of bugs in the Locale preflet that would lead to illegal characters being displayed in the date-subpart menus git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39013 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/locale/Country.h | 10 +- headers/os/locale/Language.h | 17 +- headers/os/locale/Locale.h | 16 +- headers/os/locale/LocaleRoster.h | 4 + headers/os/locale/TimeZone.h | 4 +- headers/private/locale/CountryPrivate.h | 37 +++ headers/private/locale/LanguagePrivate.h | 37 +++ headers/private/locale/MutableLocaleRoster.h | 4 + headers/private/locale/TimeZonePrivate.h | 4 +- src/apps/aboutsystem/AboutSystem.cpp | 6 +- src/apps/mediaplayer/MainWin.cpp | 2 +- .../readonlybootprompt/BootPromptWindow.cpp | 19 +- src/kits/locale/Country.cpp | 53 ++-- src/kits/locale/DurationFormat.cpp | 2 +- src/kits/locale/Language.cpp | 31 +- src/kits/locale/Locale.cpp | 279 ++++++++++++++---- src/kits/locale/LocaleRoster.cpp | 35 +++ src/kits/locale/MutableLocaleRoster.cpp | 24 +- src/kits/locale/TimeZone.cpp | 80 ++--- src/preferences/locale/FormatSettingsView.cpp | 107 +++---- src/preferences/locale/FormatSettingsView.h | 2 - src/preferences/locale/LanguageListView.cpp | 4 +- src/preferences/locale/LocaleSettings.cpp | 15 +- src/preferences/locale/LocaleWindow.cpp | 73 ++--- 24 files changed, 590 insertions(+), 275 deletions(-) create mode 100644 headers/private/locale/CountryPrivate.h create mode 100644 headers/private/locale/LanguagePrivate.h diff --git a/headers/os/locale/Country.h b/headers/os/locale/Country.h index db88b139ab..02ecaa7070 100644 --- a/headers/os/locale/Country.h +++ b/headers/os/locale/Country.h @@ -13,6 +13,7 @@ class BBitmap; +class BLanguage; class BMessage; namespace icu_44 { @@ -37,7 +38,11 @@ public: BCountry& operator=(const BCountry& other); ~BCountry(); - bool GetName(BString& name) const; + status_t GetNativeName(BString& name) const; + status_t GetName(BString& name, + const BLanguage* displayLanguage = NULL + ) const; + const char* Code() const; status_t GetIcon(BBitmap* result) const; @@ -48,7 +53,10 @@ public: int8 Measurement() const; + class Private; private: + friend class Private; + icu_44::Locale* fICULocale; }; diff --git a/headers/os/locale/Language.h b/headers/os/locale/Language.h index ec03c43886..cf9eb9af6c 100644 --- a/headers/os/locale/Language.h +++ b/headers/os/locale/Language.h @@ -34,12 +34,17 @@ public: BLanguage& operator=(const BLanguage& source); - status_t GetName(BString& name) const; - status_t GetTranslatedName(BString& name) const; + status_t GetNativeName(BString& name) const; + status_t GetName(BString& name, + const BLanguage* displayLanguage = NULL + ) const; - // ISO-639 language code, e.g. "en", "de" const char* Code() const; - const char* Country() const; + // ISO-639-1 + const char* CountryCode() const; + // ISO-3166 + const char* ScriptCode() const; + // ISO-15924 const char* Variant() const; const char* ID() const; @@ -50,10 +55,12 @@ public: status_t SetTo(const char* language); - // see definitions below const char* GetString(uint32 id) const; + class Private; private: + friend class Private; + // BString fStrings[B_NUM_LANGUAGE_STRINGS]; uint8 fDirection; icu_44::Locale* fICULocale; diff --git a/headers/os/locale/Locale.h b/headers/os/locale/Locale.h index 435730632c..e389e06b59 100644 --- a/headers/os/locale/Locale.h +++ b/headers/os/locale/Locale.h @@ -38,8 +38,8 @@ typedef enum { class BLocale { public: - BLocale(const char* languageAndCountryCode - = "en_US"); + BLocale(const BLanguage* language = NULL, + const BCountry* country = NULL); BLocale(const BLocale& other); ~BLocale(); @@ -48,12 +48,12 @@ public: status_t GetCollator(BCollator* collator) const; status_t GetLanguage(BLanguage* language) const; status_t GetCountry(BCountry* country) const; - const char* Code() const; - bool GetName(BString& name) const; void SetCountry(const BCountry& newCountry); void SetCollator(const BCollator& newCollator); - void SetLanguage(const char* languageCode); + void SetLanguage(const BLanguage& newLanguage); + + bool GetName(BString& name) const; // see definitions in LocaleStrings.h const char* GetString(uint32 id) const; @@ -140,17 +140,19 @@ public: void GetSortKey(const char* string, BString* key) const; -protected: +private: + void _UpdateFormats(); + mutable BLocker fLock; BCollator fCollator; BCountry fCountry; BLanguage fLanguage; - icu_44::Locale* fICULocale; BString fLongDateFormat; BString fShortDateFormat; BString fLongTimeFormat; BString fShortTimeFormat; + }; diff --git a/headers/os/locale/LocaleRoster.h b/headers/os/locale/LocaleRoster.h index c6657dce49..5ce7210f5b 100644 --- a/headers/os/locale/LocaleRoster.h +++ b/headers/os/locale/LocaleRoster.h @@ -9,6 +9,7 @@ #include +class BBitmap; class BCatalog; class BCollator; class BCountry; @@ -48,6 +49,9 @@ public: BMessage* message, const char* countryCode) const; + status_t GetFlagIconForCountry(BBitmap* flagIcon, + const char* countryCode); + status_t GetInstalledCatalogs(BMessage* message, const char* sigPattern = NULL, const char* langPattern = NULL, diff --git a/headers/os/locale/TimeZone.h b/headers/os/locale/TimeZone.h index 0f4a26e45e..4fca971d05 100644 --- a/headers/os/locale/TimeZone.h +++ b/headers/os/locale/TimeZone.h @@ -46,8 +46,8 @@ public: private: friend class Private; - icu_44::TimeZone* fIcuTimeZone; - icu_44::Locale* fIcuLocale; + icu_44::TimeZone* fICUTimeZone; + icu_44::Locale* fICULocale; status_t fInitStatus; mutable uint32 fInitializedFields; diff --git a/headers/private/locale/CountryPrivate.h b/headers/private/locale/CountryPrivate.h new file mode 100644 index 0000000000..51b87dc3c9 --- /dev/null +++ b/headers/private/locale/CountryPrivate.h @@ -0,0 +1,37 @@ +/* + * Copyright 2010, Oliver Tappe + * Distributed under the terms of the MIT License. + */ +#ifndef _COUNTRY_PRIVATE_H +#define _COUNTRY_PRIVATE_H + + +#include + + +class BCountry::Private { +public: + Private(const BCountry* country = NULL) + : + fCountry(country) + { + } + + void + SetTo(const BCountry* country) + { + fCountry = country; + } + + icu_44::Locale* + ICULocale() + { + return fCountry->fICULocale; + } + +private: + const BCountry* fCountry; +}; + + +#endif // _COUNTRY_PRIVATE_H diff --git a/headers/private/locale/LanguagePrivate.h b/headers/private/locale/LanguagePrivate.h new file mode 100644 index 0000000000..bea1417755 --- /dev/null +++ b/headers/private/locale/LanguagePrivate.h @@ -0,0 +1,37 @@ +/* + * Copyright 2010, Oliver Tappe + * Distributed under the terms of the MIT License. + */ +#ifndef _LANGUAGE_PRIVATE_H +#define _LANGUAGE_PRIVATE_H + + +#include + + +class BLanguage::Private { +public: + Private(const BLanguage* language = NULL) + : + fLanguage(language) + { + } + + void + SetTo(const BLanguage* language) + { + fLanguage = language; + } + + icu_44::Locale* + ICULocale() + { + return fLanguage->fICULocale; + } + +private: + const BLanguage* fLanguage; +}; + + +#endif // _LANGUAGE_PRIVATE_H diff --git a/headers/private/locale/MutableLocaleRoster.h b/headers/private/locale/MutableLocaleRoster.h index fbd46a8363..bad15aadc1 100644 --- a/headers/private/locale/MutableLocaleRoster.h +++ b/headers/private/locale/MutableLocaleRoster.h @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -113,6 +114,9 @@ struct RosterData { BLocale fDefaultLocale; BTimeZone fDefaultTimeZone; + bool fAreResourcesLoaded; + BResources fResources; + RosterData(); ~RosterData(); diff --git a/headers/private/locale/TimeZonePrivate.h b/headers/private/locale/TimeZonePrivate.h index 490a97ba90..a4ec4eb292 100644 --- a/headers/private/locale/TimeZonePrivate.h +++ b/headers/private/locale/TimeZonePrivate.h @@ -24,9 +24,9 @@ public: } icu_44::TimeZone* - IcuTimeZone() + ICUTimeZone() { - return fTimeZone->fIcuTimeZone; + return fTimeZone->fICUTimeZone; } private: diff --git a/src/apps/aboutsystem/AboutSystem.cpp b/src/apps/aboutsystem/AboutSystem.cpp index dfd1ad3d20..53450073f3 100644 --- a/src/apps/aboutsystem/AboutSystem.cpp +++ b/src/apps/aboutsystem/AboutSystem.cpp @@ -182,7 +182,7 @@ TranslationComparator(const void* left, const void* right) BString leftName; if (be_locale_roster->GetLanguage(leftTranslation->languageCode, &language) == B_OK) { - language->GetTranslatedName(leftName); + language->GetName(leftName); delete language; } else leftName = leftTranslation->languageCode; @@ -190,7 +190,7 @@ TranslationComparator(const void* left, const void* right) BString rightName; if (be_locale_roster->GetLanguage(rightTranslation->languageCode, &language) == B_OK) { - language->GetTranslatedName(rightName); + language->GetName(rightName); delete language; } else rightName = rightTranslation->languageCode; @@ -1101,7 +1101,7 @@ AboutView::_CreateCreditsView() langName.Truncate(0); if (be_locale_roster->GetLanguage(translation.languageCode, &lang) == B_OK) { - lang->GetTranslatedName(langName); + lang->GetName(langName); delete lang; } else { // We failed to get the localized readable name, diff --git a/src/apps/mediaplayer/MainWin.cpp b/src/apps/mediaplayer/MainWin.cpp index 3ee240fe94..2fc82b7768 100644 --- a/src/apps/mediaplayer/MainWin.cpp +++ b/src/apps/mediaplayer/MainWin.cpp @@ -1587,7 +1587,7 @@ MainWin::_SetupTrackMenus(BMenu* audioTrackMenu, BMenu* videoTrackMenu, if (languageString != NULL) { BLanguage language(languageString); BString languageName; - if (language.GetTranslatedName(languageName) == B_OK) + if (language.GetName(languageName) == B_OK) languageString = languageName.String(); snprintf(s, sizeof(s), "%s", languageString); } else diff --git a/src/apps/readonlybootprompt/BootPromptWindow.cpp b/src/apps/readonlybootprompt/BootPromptWindow.cpp index dd82b72ec7..ae2c05fae5 100644 --- a/src/apps/readonlybootprompt/BootPromptWindow.cpp +++ b/src/apps/readonlybootprompt/BootPromptWindow.cpp @@ -260,6 +260,9 @@ BootPromptWindow::_PopulateLanguages() be_locale_roster->GetInstalledCatalogs(&installedCatalogs, "x-vnd.Haiku-ReadOnlyBootPrompt"); + BFont font; + fLanguagesListView->GetFont(&font); + // Try to instantiate a BCatalog for each language, it will only work // for translations of this application. So the list of languages will be // limited to catalogs written for this application, which is on purpose! @@ -270,14 +273,16 @@ BootPromptWindow::_PopulateLanguages() BLanguage* language; if (be_locale_roster->GetLanguage(languageString, &language) == B_OK) { BString name; - language->GetName(name); + language->GetNativeName(name); - // TODO: as long as the app_server doesn't support font overlays, - // use the translated name if problematic characters are used... - const char* string = name.String(); - while (uint32 code = BUnicodeChar::FromUTF8(&string)) { - if (code > 1424) { - language->GetTranslatedName(name); + // TODO: the following block fails to detect a couple of language + // names as containing glyphs we can't render. Why's that? + bool hasGlyphs[name.CountChars()]; + font.GetHasGlyphs(name.String(), name.CountChars(), hasGlyphs); + for (int32 i = 0; i < name.CountChars(); ++i) { + if (!hasGlyphs[i]) { + // replace by name translated to current language + language->GetName(name); break; } } diff --git a/src/kits/locale/Country.cpp b/src/kits/locale/Country.cpp index 5d75ba1521..57f19ec846 100644 --- a/src/kits/locale/Country.cpp +++ b/src/kits/locale/Country.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -68,14 +69,39 @@ BCountry::~BCountry() } -bool -BCountry::GetName(BString& name) const +status_t +BCountry::GetNativeName(BString& name) const { + UnicodeString string; + fICULocale->getDisplayName(*fICULocale, string); + string.toTitle(NULL, *fICULocale); + + name.Truncate(0); + BStringByteSink converter(&name); + string.toUTF8(converter); + + return B_OK; +} + + +status_t +BCountry::GetName(BString& name, const BLanguage* displayLanguage) const +{ + BString appLanguage; + if (displayLanguage == NULL) { + BMessage preferredLanguage; + be_locale_roster->GetPreferredLanguages(&preferredLanguage); + preferredLanguage.FindString("language", 0, &appLanguage); + } else { + appLanguage = displayLanguage->Code(); + } + UnicodeString uString; - fICULocale->getDisplayCountry(uString); + fICULocale->getDisplayName(Locale(appLanguage), uString); BStringByteSink stringConverter(&name); uString.toUTF8(stringConverter); - return true; + + return B_OK; } @@ -89,23 +115,10 @@ BCountry::Code() const status_t BCountry::GetIcon(BBitmap* result) const { - if (result == NULL) - return B_BAD_DATA; - // TODO: a proper way to locate the library being used ? - BResources storage("/boot/system/lib/liblocale.so"); - if (storage.InitCheck() != B_OK) - return B_ERROR; - size_t size; const char* code = fICULocale->getCountry(); - if (code != NULL) { - const void* buffer = storage.LoadResource(B_VECTOR_ICON_TYPE, code, - &size); - if (buffer != NULL && size != 0) { - return BIconUtils::GetVectorIcon(static_cast(buffer), - size, result); - } - } - return B_BAD_DATA; + if (code == NULL) + return B_ERROR; + return be_locale_roster->GetFlagIconForCountry(result, code); } diff --git a/src/kits/locale/DurationFormat.cpp b/src/kits/locale/DurationFormat.cpp index e887b1eac9..316202fc3f 100644 --- a/src/kits/locale/DurationFormat.cpp +++ b/src/kits/locale/DurationFormat.cpp @@ -123,7 +123,7 @@ BDurationFormat::SetTimeZone(const BTimeZone* timeZone) } else zonePrivate.SetTo(timeZone); - TimeZone* icuTimeZone = zonePrivate.IcuTimeZone(); + TimeZone* icuTimeZone = zonePrivate.ICUTimeZone(); if (icuTimeZone != NULL) fCalendar->setTimeZone(*icuTimeZone); diff --git a/src/kits/locale/Language.cpp b/src/kits/locale/Language.cpp index 057d9a4b6e..62e3a9a3e8 100644 --- a/src/kits/locale/Language.cpp +++ b/src/kits/locale/Language.cpp @@ -110,10 +110,11 @@ BLanguage::GetString(uint32 id) const status_t -BLanguage::GetName(BString& name) const +BLanguage::GetNativeName(BString& name) const { UnicodeString string; fICULocale->getDisplayName(*fICULocale, string); + string.toTitle(NULL, *fICULocale); name.Truncate(0); BStringByteSink converter(&name); @@ -124,13 +125,16 @@ BLanguage::GetName(BString& name) const status_t -BLanguage::GetTranslatedName(BString& name) const +BLanguage::GetName(BString& name, const BLanguage* displayLanguage) const { - BMessage preferredLanguage; - be_locale_roster->GetPreferredLanguages(&preferredLanguage); - BString appLanguage; - preferredLanguage.FindString("language", 0, &appLanguage); + if (displayLanguage == NULL) { + BMessage preferredLanguage; + be_locale_roster->GetPreferredLanguages(&preferredLanguage); + preferredLanguage.FindString("language", 0, &appLanguage); + } else { + appLanguage = displayLanguage->Code(); + } UnicodeString string; fICULocale->getDisplayName(Locale(appLanguage), string); @@ -151,7 +155,7 @@ BLanguage::Code() const const char* -BLanguage::Country() const +BLanguage::CountryCode() const { const char* country = fICULocale->getCountry(); if (country == NULL || country[0] == '\0') @@ -161,6 +165,17 @@ BLanguage::Country() const } +const char* +BLanguage::ScriptCode() const +{ + const char* script = fICULocale->getScript(); + if (script == NULL || script[0] == '\0') + return NULL; + + return script; +} + + const char* BLanguage::Variant() const { @@ -182,7 +197,7 @@ BLanguage::ID() const bool BLanguage::IsCountrySpecific() const { - return Country() != NULL; + return CountryCode() != NULL; } diff --git a/src/kits/locale/Locale.cpp b/src/kits/locale/Locale.cpp index 4ca24803cb..425c694acf 100644 --- a/src/kits/locale/Locale.cpp +++ b/src/kits/locale/Locale.cpp @@ -1,6 +1,7 @@ /* -** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. -** Distributed under the terms of the OpenBeOS License. +** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. +** Copyright 2010, Oliver Tappe, zooey@hirschkaefer.de. +** All rights reserved. Distributed under the terms of the OpenBeOS License. */ @@ -8,6 +9,8 @@ #include #include #include +#include +#include #include #include #include @@ -37,14 +40,25 @@ static DateFormat* CreateDateFormat(bool longFormat, const Locale& locale, const BString& format); static DateFormat* CreateTimeFormat(bool longFormat, const Locale& locale, const BString& format); +static void FetchDateFormat(bool longFormat, const Locale& locale, + BString& format); +static void FetchTimeFormat(bool longFormat, const Locale& locale, + BString& format); -BLocale::BLocale(const char* languageAndCountryCode) - : - fCountry(languageAndCountryCode), - fLanguage(languageAndCountryCode), - fICULocale(new ICU_VERSION::Locale(languageAndCountryCode)) +BLocale::BLocale(const BLanguage* language, const BCountry* country) { + if (country != NULL) + fCountry = *country; + else + be_locale->GetCountry(&fCountry); + + if (language != NULL) + fLanguage = *language; + else + be_locale->GetLanguage(&fLanguage); + + _UpdateFormats(); } @@ -52,7 +66,6 @@ BLocale::BLocale(const BLocale& other) : fCountry(other.fCountry), fLanguage(other.fLanguage), - fICULocale(new ICU_VERSION::Locale(*other.fICULocale)), fLongDateFormat(other.fLongDateFormat), fShortDateFormat(other.fShortDateFormat), fLongTimeFormat(other.fLongTimeFormat), @@ -67,8 +80,6 @@ BLocale::operator=(const BLocale& other) if (this == &other) return *this; - *fICULocale = *other.fICULocale; - fLongDateFormat = other.fLongDateFormat; fShortDateFormat = other.fShortDateFormat; fLongTimeFormat = other.fLongTimeFormat; @@ -83,7 +94,6 @@ BLocale::operator=(const BLocale& other) BLocale::~BLocale() { - delete fICULocale; } @@ -140,6 +150,10 @@ BLocale::GetString(uint32 id) const { // Note: this code assumes a certain order of the string bases + BAutolock lock(fLock); + if (!lock.IsLocked()) + return ""; + if (id >= B_OTHER_STRINGS_BASE) { if (id == B_CODESET) return "UTF-8"; @@ -153,41 +167,54 @@ BLocale::GetString(uint32 id) const void BLocale::SetCountry(const BCountry& newCountry) { + BAutolock lock(fLock); + if (!lock.IsLocked()) + return; + fCountry = newCountry; + + _UpdateFormats(); } void BLocale::SetCollator(const BCollator& newCollator) { + BAutolock lock(fLock); + if (!lock.IsLocked()) + return; + fCollator = newCollator; } void -BLocale::SetLanguage(const char* languageCode) +BLocale::SetLanguage(const BLanguage& newLanguage) { - fLanguage.SetTo(languageCode); -} + BAutolock lock(fLock); + if (!lock.IsLocked()) + return; - -const char* -BLocale::Code() const -{ - return fICULocale->getName(); + fLanguage = newLanguage; } bool BLocale::GetName(BString& name) const { + Locale icuLocale = Locale::createCanonical(fCountry.Code()); + if (icuLocale.isBogus()) + return false; + UnicodeString uString; - fICULocale->getDisplayName(uString); + const Locale* countryLocale = BCountry::Private(&fCountry).ICULocale(); + countryLocale->getDisplayName(icuLocale, uString); BStringByteSink stringConverter(&name); uString.toUTF8(stringConverter); return true; } + // #pragma mark - Date @@ -195,8 +222,13 @@ status_t BLocale::FormatDate(char* string, size_t maxSize, time_t time, bool longFormat) const { + BAutolock lock(fLock); + if (!lock.IsLocked()) + return B_ERROR; + ObjectDeleter dateFormatter = CreateDateFormat(longFormat, - *fICULocale, longFormat ? fLongDateFormat : fShortDateFormat); + *BLanguage::Private(&fLanguage).ICULocale(), + longFormat ? fLongDateFormat : fShortDateFormat); if (dateFormatter.Get() == NULL) return B_NO_MEMORY; @@ -204,7 +236,6 @@ BLocale::FormatDate(char* string, size_t maxSize, time_t time, ICUString = dateFormatter->format((UDate)time * 1000, ICUString); CheckedArrayByteSink stringConverter(string, maxSize); - ICUString.toUTF8(stringConverter); if (stringConverter.Overflowed()) @@ -218,12 +249,13 @@ status_t BLocale::FormatDate(BString *string, time_t time, bool longFormat, const BTimeZone* timeZone) const { - string->Truncate(0); - // We make the string empty, this way even in cases where ICU fail we at - // least return something sane - Locale locale(fLanguage.Code()); + BAutolock lock(fLock); + if (!lock.IsLocked()) + return B_ERROR; + ObjectDeleter dateFormatter = CreateDateFormat(longFormat, - locale, longFormat ? fLongDateFormat : fShortDateFormat); + *BLanguage::Private(&fLanguage).ICULocale(), + longFormat ? fLongDateFormat : fShortDateFormat); if (dateFormatter.Get() == NULL) return B_NO_MEMORY; @@ -238,6 +270,7 @@ BLocale::FormatDate(BString *string, time_t time, bool longFormat, UnicodeString ICUString; ICUString = dateFormatter->format((UDate)time * 1000, ICUString); + string->Truncate(0); BStringByteSink stringConverter(string); ICUString.toUTF8(stringConverter); @@ -249,10 +282,13 @@ status_t BLocale::FormatDate(BString* string, int*& fieldPositions, int& fieldCount, time_t time, bool longFormat) const { - string->Truncate(0); + BAutolock lock(fLock); + if (!lock.IsLocked()) + return B_ERROR; ObjectDeleter dateFormatter = CreateDateFormat(longFormat, - *fICULocale, longFormat ? fLongDateFormat : fShortDateFormat); + *BLanguage::Private(&fLanguage).ICULocale(), + longFormat ? fLongDateFormat : fShortDateFormat); if (dateFormatter.Get() == NULL) return B_NO_MEMORY; @@ -280,6 +316,7 @@ BLocale::FormatDate(BString* string, int*& fieldPositions, int& fieldCount, for (int i = 0 ; i < fieldCount ; i++ ) fieldPositions[i] = fieldPosStorage[i]; + string->Truncate(0); BStringByteSink stringConverter(string); ICUString.toUTF8(stringConverter); @@ -291,6 +328,10 @@ BLocale::FormatDate(BString* string, int*& fieldPositions, int& fieldCount, status_t BLocale::GetDateFormat(BString& format, bool longFormat) const { + BAutolock lock(fLock); + if (!lock.IsLocked()) + return B_ERROR; + if (longFormat && fLongDateFormat.Length() > 0) format = fLongDateFormat; else if (!longFormat && fShortDateFormat.Length() > 0) @@ -299,7 +340,7 @@ BLocale::GetDateFormat(BString& format, bool longFormat) const format.Truncate(0); ObjectDeleter dateFormatter = CreateDateFormat(longFormat, - *fICULocale, longFormat ? fLongDateFormat : fShortDateFormat); + *BCountry::Private(&fCountry).ICULocale(), format); if (dateFormatter.Get() == NULL) return B_NO_MEMORY; @@ -321,6 +362,10 @@ BLocale::GetDateFormat(BString& format, bool longFormat) const status_t BLocale::SetDateFormat(const char* formatString, bool longFormat) { + BAutolock lock(fLock); + if (!lock.IsLocked()) + return B_ERROR; + if (longFormat) fLongDateFormat = formatString; else @@ -334,8 +379,13 @@ status_t BLocale::GetDateFields(BDateElement*& fields, int& fieldCount, bool longFormat) const { + BAutolock lock(fLock); + if (!lock.IsLocked()) + return B_ERROR; + ObjectDeleter dateFormatter = CreateDateFormat(longFormat, - *fICULocale, longFormat ? fLongDateFormat : fShortDateFormat); + *BCountry::Private(&fCountry).ICULocale(), + longFormat ? fLongDateFormat : fShortDateFormat); if (dateFormatter.Get() == NULL) return B_NO_MEMORY; @@ -384,8 +434,14 @@ BLocale::GetDateFields(BDateElement*& fields, int& fieldCount, int BLocale::StartOfWeek() const { + BAutolock lock(fLock); + if (!lock.IsLocked()) + return B_ERROR; + UErrorCode err = U_ZERO_ERROR; - Calendar* c = Calendar::createInstance(*fICULocale, err); + Calendar* c + = Calendar::createInstance(*BCountry::Private(&fCountry).ICULocale(), + err); if (err == U_ZERO_ERROR && c->getFirstDayOfWeek(err) == UCAL_SUNDAY) { delete c; @@ -402,13 +458,19 @@ status_t BLocale::FormatDateTime(char* target, size_t maxSize, time_t time, bool longFormat) const { + BAutolock lock(fLock); + if (!lock.IsLocked()) + return B_ERROR; + ObjectDeleter dateFormatter = CreateDateFormat(longFormat, - *fICULocale, longFormat ? fLongDateFormat : fShortDateFormat); + *BLanguage::Private(&fLanguage).ICULocale(), + longFormat ? fLongDateFormat : fShortDateFormat); if (dateFormatter.Get() == NULL) return B_NO_MEMORY; ObjectDeleter timeFormatter = CreateTimeFormat(longFormat, - *fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); + *BLanguage::Private(&fLanguage).ICULocale(), + longFormat ? fLongTimeFormat : fShortTimeFormat); if (timeFormatter.Get() == NULL) return B_NO_MEMORY; @@ -433,13 +495,19 @@ status_t BLocale::FormatDateTime(BString* target, time_t time, bool longFormat, const BTimeZone* timeZone) const { + BAutolock lock(fLock); + if (!lock.IsLocked()) + return B_ERROR; + ObjectDeleter dateFormatter = CreateDateFormat(longFormat, - *fICULocale, longFormat ? fLongDateFormat : fShortDateFormat); + *BLanguage::Private(&fLanguage).ICULocale(), + longFormat ? fLongDateFormat : fShortDateFormat); if (dateFormatter.Get() == NULL) return B_NO_MEMORY; ObjectDeleter timeFormatter = CreateTimeFormat(longFormat, - *fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); + *BLanguage::Private(&fLanguage).ICULocale(), + longFormat ? fLongTimeFormat : fShortTimeFormat); if (timeFormatter.Get() == NULL) return B_NO_MEMORY; @@ -458,6 +526,7 @@ BLocale::FormatDateTime(BString* target, time_t time, bool longFormat, ICUString = timeFormatter->format((UDate)time * 1000, ICUString); + target->Truncate(0); BStringByteSink stringConverter(target); ICUString.toUTF8(stringConverter); @@ -472,8 +541,13 @@ status_t BLocale::FormatTime(char* string, size_t maxSize, time_t time, bool longFormat) const { + BAutolock lock(fLock); + if (!lock.IsLocked()) + return B_ERROR; + ObjectDeleter timeFormatter = CreateTimeFormat(longFormat, - *fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); + *BLanguage::Private(&fLanguage).ICULocale(), + longFormat ? fLongTimeFormat : fShortTimeFormat); if (timeFormatter.Get() == NULL) return B_NO_MEMORY; @@ -495,10 +569,13 @@ status_t BLocale::FormatTime(BString* string, time_t time, bool longFormat, const BTimeZone* timeZone) const { - string->Truncate(0); + BAutolock lock(fLock); + if (!lock.IsLocked()) + return B_ERROR; ObjectDeleter timeFormatter = CreateTimeFormat(longFormat, - *fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); + *BLanguage::Private(&fLanguage).ICULocale(), + longFormat ? fLongTimeFormat : fShortTimeFormat); if (timeFormatter.Get() == NULL) return B_NO_MEMORY; @@ -513,6 +590,7 @@ BLocale::FormatTime(BString* string, time_t time, bool longFormat, UnicodeString ICUString; ICUString = timeFormatter->format((UDate)time * 1000, ICUString); + string->Truncate(0); BStringByteSink stringConverter(string); ICUString.toUTF8(stringConverter); @@ -525,10 +603,13 @@ status_t BLocale::FormatTime(BString* string, int*& fieldPositions, int& fieldCount, time_t time, bool longFormat) const { - string->Truncate(0); + BAutolock lock(fLock); + if (!lock.IsLocked()) + return B_ERROR; ObjectDeleter timeFormatter = CreateTimeFormat(longFormat, - *fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); + *BLanguage::Private(&fLanguage).ICULocale(), + longFormat ? fLongTimeFormat : fShortTimeFormat); if (timeFormatter.Get() == NULL) return B_NO_MEMORY; @@ -556,6 +637,7 @@ BLocale::FormatTime(BString* string, int*& fieldPositions, int& fieldCount, for (int i = 0 ; i < fieldCount ; i++ ) fieldPositions[i] = fieldPosStorage[i]; + string->Truncate(0); BStringByteSink stringConverter(string); ICUString.toUTF8(stringConverter); @@ -568,8 +650,13 @@ status_t BLocale::GetTimeFields(BDateElement*& fields, int& fieldCount, bool longFormat) const { + BAutolock lock(fLock); + if (!lock.IsLocked()) + return B_ERROR; + ObjectDeleter timeFormatter = CreateTimeFormat(longFormat, - *fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); + *BCountry::Private(&fCountry).ICULocale(), + longFormat ? fLongTimeFormat : fShortTimeFormat); if (timeFormatter.Get() == NULL) return B_NO_MEMORY; @@ -624,6 +711,10 @@ BLocale::GetTimeFields(BDateElement*& fields, int& fieldCount, status_t BLocale::SetTimeFormat(const char* formatString, bool longFormat) { + BAutolock lock(fLock); + if (!lock.IsLocked()) + return B_ERROR; + if (longFormat) fLongTimeFormat = formatString; else @@ -636,6 +727,10 @@ BLocale::SetTimeFormat(const char* formatString, bool longFormat) status_t BLocale::GetTimeFormat(BString& format, bool longFormat) const { + BAutolock lock(fLock); + if (!lock.IsLocked()) + return B_ERROR; + if (longFormat && fLongTimeFormat.Length() > 0) format = fLongTimeFormat; else if (!longFormat && fShortTimeFormat.Length() > 0) @@ -644,7 +739,8 @@ BLocale::GetTimeFormat(BString& format, bool longFormat) const format.Truncate(0); ObjectDeleter timeFormatter = CreateTimeFormat(longFormat, - *fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); + *BCountry::Private(&fCountry).ICULocale(), + longFormat ? fLongTimeFormat : fShortTimeFormat); if (timeFormatter.Get() == NULL) return B_NO_MEMORY; @@ -662,6 +758,20 @@ BLocale::GetTimeFormat(BString& format, bool longFormat) const } +void +BLocale::_UpdateFormats() +{ + FetchDateFormat(true, *BCountry::Private(&fCountry).ICULocale(), + this->fLongDateFormat); + FetchDateFormat(false, *BCountry::Private(&fCountry).ICULocale(), + this->fShortDateFormat); + FetchTimeFormat(true, *BCountry::Private(&fCountry).ICULocale(), + this->fLongTimeFormat); + FetchTimeFormat(false, *BCountry::Private(&fCountry).ICULocale(), + this->fShortTimeFormat); +} + + // #pragma mark - Numbers @@ -680,9 +790,14 @@ BLocale::FormatNumber(char* string, size_t maxSize, double value) const status_t BLocale::FormatNumber(BString* string, double value) const { + BAutolock lock(fLock); + if (!lock.IsLocked()) + return B_ERROR; + UErrorCode err = U_ZERO_ERROR; ObjectDeleter numberFormatter = NumberFormat::createInstance( - *fICULocale, NumberFormat::kNumberStyle, err); + *BCountry::Private(&fCountry).ICULocale(), NumberFormat::kNumberStyle, + err); if (numberFormatter.Get() == NULL) return B_NO_MEMORY; @@ -715,9 +830,14 @@ BLocale::FormatNumber(char* string, size_t maxSize, int32 value) const status_t BLocale::FormatNumber(BString* string, int32 value) const { + BAutolock lock(fLock); + if (!lock.IsLocked()) + return B_ERROR; + UErrorCode err = U_ZERO_ERROR; ObjectDeleter numberFormatter = NumberFormat::createInstance( - *fICULocale, NumberFormat::kNumberStyle, err); + *BCountry::Private(&fCountry).ICULocale(), NumberFormat::kNumberStyle, + err); if (numberFormatter.Get() == NULL) return B_NO_MEMORY; @@ -753,9 +873,14 @@ BLocale::FormatMonetary(BString* string, double value) const if (string == NULL) return B_BAD_VALUE; + BAutolock lock(fLock); + if (!lock.IsLocked()) + return B_ERROR; + UErrorCode err; ObjectDeleter numberFormatter - = NumberFormat::createCurrencyInstance(*fICULocale, err); + = NumberFormat::createCurrencyInstance( + *BCountry::Private(&fCountry).ICULocale(), err); if (numberFormatter.Get() == NULL) return B_NO_MEMORY; @@ -777,14 +902,17 @@ status_t BLocale::FormatMonetary(BString* string, int*& fieldPositions, BNumberElement*& fieldTypes, int& fieldCount, double value) const { + BAutolock lock(fLock); + if (!lock.IsLocked()) + return B_ERROR; + UErrorCode err = U_ZERO_ERROR; ObjectDeleter numberFormatter - = NumberFormat::createCurrencyInstance(*fICULocale, err); + = NumberFormat::createCurrencyInstance( + *BCountry::Private(&fCountry).ICULocale(), err); if (U_FAILURE(err)) return B_NO_MEMORY; - string->Truncate(0); - fieldPositions = NULL; fieldTypes = NULL; ICU_VERSION::FieldPositionIterator positionIterator; @@ -827,6 +955,7 @@ BLocale::FormatMonetary(BString* string, int*& fieldPositions, } } + string->Truncate(0); BStringByteSink stringConverter(string); ICUString.toUTF8(stringConverter); @@ -838,9 +967,13 @@ BLocale::FormatMonetary(BString* string, int*& fieldPositions, status_t BLocale::GetCurrencySymbol(BString& result) const { + BAutolock lock(fLock); + if (!lock.IsLocked()) + return B_ERROR; + UErrorCode error = U_ZERO_ERROR; - NumberFormat* format = NumberFormat::createCurrencyInstance(*fICULocale, - error); + NumberFormat* format = NumberFormat::createCurrencyInstance( + *BCountry::Private(&fCountry).ICULocale(), error); if (U_FAILURE(error)) return B_ERROR; @@ -860,11 +993,10 @@ BLocale::GetCurrencySymbol(BString& result) const static DateFormat* -CreateDateFormat(bool longFormat, const Locale& locale, - const BString& format) +CreateDateFormat(bool longFormat, const Locale& locale, const BString& format) { DateFormat* dateFormatter = DateFormat::createDateInstance( - longFormat ? DateFormat::FULL : DateFormat::SHORT, locale); + longFormat ? DateFormat::kFull : DateFormat::kShort, locale); if (format.Length() > 0) { SimpleDateFormat* dateFormatterImpl @@ -879,11 +1011,10 @@ CreateDateFormat(bool longFormat, const Locale& locale, static DateFormat* -CreateTimeFormat(bool longFormat, const Locale& locale, - const BString& format) +CreateTimeFormat(bool longFormat, const Locale& locale, const BString& format) { DateFormat* timeFormatter = DateFormat::createTimeInstance( - longFormat ? DateFormat::MEDIUM : DateFormat::SHORT, locale); + longFormat ? DateFormat::kMedium: DateFormat::kShort, locale); if (format.Length() > 0) { SimpleDateFormat* timeFormatterImpl @@ -895,3 +1026,37 @@ CreateTimeFormat(bool longFormat, const Locale& locale, return timeFormatter; } + + +static void +FetchDateFormat(bool longFormat, const Locale& locale, BString& format) +{ + DateFormat* dateFormatter = DateFormat::createDateInstance( + longFormat ? DateFormat::kFull : DateFormat::kShort, locale); + + SimpleDateFormat* dateFormatterImpl + = static_cast(dateFormatter); + + UnicodeString pattern; + dateFormatterImpl->toPattern(pattern); + format.Truncate(0); + BStringByteSink stringConverter(&format); + pattern.toUTF8(stringConverter); +} + + +static void +FetchTimeFormat(bool longFormat, const Locale& locale, BString& format) +{ + DateFormat* timeFormatter = DateFormat::createTimeInstance( + longFormat ? DateFormat::kMedium : DateFormat::kShort, locale); + + SimpleDateFormat* timeFormatterImpl + = static_cast(timeFormatter); + + UnicodeString pattern; + timeFormatterImpl->toPattern(pattern); + format.Truncate(0); + BStringByteSink stringConverter(&format); + pattern.toUTF8(stringConverter); +} diff --git a/src/kits/locale/LocaleRoster.cpp b/src/kits/locale/LocaleRoster.cpp index 830bd9a866..a638762091 100644 --- a/src/kits/locale/LocaleRoster.cpp +++ b/src/kits/locale/LocaleRoster.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -24,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -227,6 +229,39 @@ BLocaleRoster::GetAvailableTimeZonesForCountry(BMessage* timeZones, } +status_t +BLocaleRoster::GetFlagIconForCountry(BBitmap* flagIcon, const char* countryCode) +{ + if (countryCode == NULL) + return B_BAD_DATA; + + BAutolock lock(gRosterData.fLock); + if (!lock.IsLocked()) + return B_ERROR; + + if (!gRosterData.fAreResourcesLoaded) { + status_t result = gRosterData.fResources.SetToImage(&gRosterData); + if (result != B_OK) + return result; + + result = gRosterData.fResources.PreloadResourceType(); + if (result != B_OK) + return result; + + gRosterData.fAreResourcesLoaded = true; + } + + size_t size; + const void* buffer = gRosterData.fResources.LoadResource(B_VECTOR_ICON_TYPE, + countryCode, &size); + if (buffer == NULL || size == 0) + return B_NAME_NOT_FOUND; + + return BIconUtils::GetVectorIcon(static_cast(buffer), size, + flagIcon); +} + + status_t BLocaleRoster::GetInstalledCatalogs(BMessage* languageList, const char* sigPattern, const char* langPattern, int32 fingerprint) const diff --git a/src/kits/locale/MutableLocaleRoster.cpp b/src/kits/locale/MutableLocaleRoster.cpp index d6629f47fa..7d360bfad6 100644 --- a/src/kits/locale/MutableLocaleRoster.cpp +++ b/src/kits/locale/MutableLocaleRoster.cpp @@ -122,7 +122,7 @@ CatalogAddOnInfo::UnloadIfPossible() } -// #pragma mark - MutableLocaleRoster +// #pragma mark - RosterData RosterData gRosterData; @@ -132,7 +132,8 @@ static const char* kPriorityAttr = "ADDON:priority"; RosterData::RosterData() : - fLock("LocaleRosterData") + fLock("LocaleRosterData"), + fAreResourcesLoaded(false) { openlog_team("liblocale.so", LOG_PID, LOG_USER); #ifndef DEBUG @@ -439,8 +440,10 @@ RosterData::_LoadLocaleSettings() BString codeName; BLocale newDefaultLocale; - if (settings.FindString("country", &codeName) == B_OK) - newDefaultLocale = BLocale(codeName); + if (settings.FindString("country", &codeName) == B_OK) { + BCountry country(codeName); + newDefaultLocale = BLocale(NULL, &country); + } BString timeFormat; if (settings.FindString("shortTimeFormat", &timeFormat) == B_OK) @@ -461,7 +464,8 @@ RosterData::_LoadLocaleSettings() fPreferredLanguages.MakeEmpty(); fPreferredLanguages.AddString("language", "en"); - _SetDefaultLocale("en_US"); + BLanguage defaultLanguage("en_US"); + _SetDefaultLocale(BLocale(&defaultLanguage)); return status; } @@ -574,7 +578,9 @@ RosterData::_SetDefaultLocale(const BLocale& newLocale) fDefaultLocale = newLocale; UErrorCode icuError = U_ZERO_ERROR; - Locale icuLocale = Locale::createCanonical(newLocale.Code()); + BCountry defaultCountry; + newLocale.GetCountry(&defaultCountry); + Locale icuLocale = Locale::createCanonical(defaultCountry.Code()); if (icuLocale.isBogus()) return B_ERROR; @@ -607,7 +613,7 @@ RosterData::_SetPreferredLanguages(const BMessage* languages) if (languages != NULL && languages->FindString("language", &langName) == B_OK) { fDefaultLocale.SetCollator(BCollator(langName.String())); - fDefaultLocale.SetLanguage(langName.String()); + fDefaultLocale.SetLanguage(BLanguage(langName.String())); fPreferredLanguages.RemoveName("language"); for (int i = 0; languages->FindString("language", i, &langName) == B_OK; @@ -627,7 +633,9 @@ RosterData::_SetPreferredLanguages(const BMessage* languages) status_t RosterData::_AddDefaultCountryToMessage(BMessage* message) const { - status_t status = message->AddString("country", fDefaultLocale.Code()); + BCountry defaultCountry; + fDefaultLocale.GetCountry(&defaultCountry); + status_t status = message->AddString("country", defaultCountry.Code()); BString timeFormat; if (status == B_OK) status = fDefaultLocale.GetTimeFormat(timeFormat, false); diff --git a/src/kits/locale/TimeZone.cpp b/src/kits/locale/TimeZone.cpp index 27353429e7..98293bac4a 100644 --- a/src/kits/locale/TimeZone.cpp +++ b/src/kits/locale/TimeZone.cpp @@ -38,8 +38,8 @@ static const uint32 skOffsetFromGMTField = 1U << 8; BTimeZone::BTimeZone(const char* zoneID, const BLanguage* language) : - fIcuTimeZone(NULL), - fIcuLocale(NULL), + fICUTimeZone(NULL), + fICULocale(NULL), fInitStatus(B_NO_INIT), fInitializedFields(0) { @@ -49,12 +49,12 @@ BTimeZone::BTimeZone(const char* zoneID, const BLanguage* language) BTimeZone::BTimeZone(const BTimeZone& other) : - fIcuTimeZone(other.fIcuTimeZone == NULL + fICUTimeZone(other.fICUTimeZone == NULL ? NULL - : other.fIcuTimeZone->clone()), - fIcuLocale(other.fIcuLocale == NULL + : other.fICUTimeZone->clone()), + fICULocale(other.fICULocale == NULL ? NULL - : other.fIcuLocale->clone()), + : other.fICULocale->clone()), fInitStatus(other.fInitStatus), fInitializedFields(other.fInitializedFields), fZoneID(other.fZoneID), @@ -70,20 +70,20 @@ BTimeZone::BTimeZone(const BTimeZone& other) BTimeZone::~BTimeZone() { - delete fIcuLocale; - delete fIcuTimeZone; + delete fICULocale; + delete fICUTimeZone; } BTimeZone& BTimeZone::operator=(const BTimeZone& source) { - delete fIcuTimeZone; - fIcuTimeZone = source.fIcuTimeZone == NULL + delete fICUTimeZone; + fICUTimeZone = source.fICUTimeZone == NULL ? NULL - : source.fIcuTimeZone->clone(); - fIcuLocale = source.fIcuLocale == NULL + : source.fICUTimeZone->clone(); + fICULocale = source.fICULocale == NULL ? NULL - : source.fIcuLocale->clone(); + : source.fICULocale->clone(); fInitStatus = source.fInitStatus; fInitializedFields = source.fInitializedFields; fZoneID = source.fZoneID; @@ -110,11 +110,11 @@ BTimeZone::Name() const { if ((fInitializedFields & skNameField) == 0) { UnicodeString unicodeString; - if (fIcuLocale != NULL) { - fIcuTimeZone->getDisplayName(false, TimeZone::GENERIC_LOCATION, - *fIcuLocale, unicodeString); + if (fICULocale != NULL) { + fICUTimeZone->getDisplayName(false, TimeZone::GENERIC_LOCATION, + *fICULocale, unicodeString); } else { - fIcuTimeZone->getDisplayName(false, TimeZone::GENERIC_LOCATION, + fICUTimeZone->getDisplayName(false, TimeZone::GENERIC_LOCATION, unicodeString); } BStringByteSink sink(&fName); @@ -131,11 +131,11 @@ BTimeZone::DaylightSavingName() const { if ((fInitializedFields & skDaylightSavingNameField) == 0) { UnicodeString unicodeString; - if (fIcuLocale != NULL) { - fIcuTimeZone->getDisplayName(true, TimeZone::GENERIC_LOCATION, - *fIcuLocale, unicodeString); + if (fICULocale != NULL) { + fICUTimeZone->getDisplayName(true, TimeZone::GENERIC_LOCATION, + *fICULocale, unicodeString); } else { - fIcuTimeZone->getDisplayName(true, TimeZone::GENERIC_LOCATION, + fICUTimeZone->getDisplayName(true, TimeZone::GENERIC_LOCATION, unicodeString); } BStringByteSink sink(&fDaylightSavingName); @@ -152,11 +152,11 @@ BTimeZone::ShortName() const { if ((fInitializedFields & skShortNameField) == 0) { UnicodeString unicodeString; - if (fIcuLocale != NULL) { - fIcuTimeZone->getDisplayName(false, TimeZone::SHORT_COMMONLY_USED, - *fIcuLocale, unicodeString); + if (fICULocale != NULL) { + fICUTimeZone->getDisplayName(false, TimeZone::SHORT_COMMONLY_USED, + *fICULocale, unicodeString); } else { - fIcuTimeZone->getDisplayName(false, TimeZone::SHORT_COMMONLY_USED, + fICUTimeZone->getDisplayName(false, TimeZone::SHORT_COMMONLY_USED, unicodeString); } BStringByteSink sink(&fShortName); @@ -173,11 +173,11 @@ BTimeZone::ShortDaylightSavingName() const { if ((fInitializedFields & skShortDaylightSavingNameField) == 0) { UnicodeString unicodeString; - if (fIcuLocale != NULL) { - fIcuTimeZone->getDisplayName(true, TimeZone::SHORT_COMMONLY_USED, - *fIcuLocale, unicodeString); + if (fICULocale != NULL) { + fICUTimeZone->getDisplayName(true, TimeZone::SHORT_COMMONLY_USED, + *fICULocale, unicodeString); } else { - fIcuTimeZone->getDisplayName(true, TimeZone::SHORT_COMMONLY_USED, + fICUTimeZone->getDisplayName(true, TimeZone::SHORT_COMMONLY_USED, unicodeString); } BStringByteSink sink(&fShortDaylightSavingName); @@ -198,7 +198,7 @@ BTimeZone::OffsetFromGMT() const UDate nowMillis = 1000 * (double)time(NULL); UErrorCode error = U_ZERO_ERROR; - fIcuTimeZone->getOffset(nowMillis, FALSE, rawOffset, dstOffset, error); + fICUTimeZone->getOffset(nowMillis, FALSE, rawOffset, dstOffset, error); if (!U_SUCCESS(error)) fOffsetFromGMT = 0; else { @@ -216,7 +216,7 @@ bool BTimeZone::SupportsDaylightSaving() const { if ((fInitializedFields & skSupportsDaylightSavingField) == 0) { - fSupportsDaylightSaving = fIcuTimeZone->useDaylightTime(); + fSupportsDaylightSaving = fICUTimeZone->useDaylightTime(); fInitializedFields |= skSupportsDaylightSavingField; } @@ -241,31 +241,31 @@ BTimeZone::SetLanguage(const BLanguage* language) status_t BTimeZone::SetTo(const char* zoneID, const BLanguage* language) { - delete fIcuLocale; - fIcuLocale = NULL; - delete fIcuTimeZone; + delete fICULocale; + fICULocale = NULL; + delete fICUTimeZone; fInitializedFields = 0; if (zoneID == NULL || zoneID[0] == '\0') - fIcuTimeZone = TimeZone::createDefault(); + fICUTimeZone = TimeZone::createDefault(); else - fIcuTimeZone = TimeZone::createTimeZone(zoneID); + fICUTimeZone = TimeZone::createTimeZone(zoneID); - if (fIcuTimeZone == NULL) { + if (fICUTimeZone == NULL) { fInitStatus = B_NAME_NOT_FOUND; return fInitStatus; } if (language != NULL) { - fIcuLocale = new Locale(language->Code()); - if (fIcuLocale == NULL) { + fICULocale = new Locale(language->Code()); + if (fICULocale == NULL) { fInitStatus = B_NO_MEMORY; return fInitStatus; } } UnicodeString unicodeString; - fIcuTimeZone->getID(unicodeString); + fICUTimeZone->getID(unicodeString); BStringByteSink sink(&fZoneID); unicodeString.toUTF8(sink); diff --git a/src/preferences/locale/FormatSettingsView.cpp b/src/preferences/locale/FormatSettingsView.cpp index 0baa3ce30f..586c469c2c 100644 --- a/src/preferences/locale/FormatSettingsView.cpp +++ b/src/preferences/locale/FormatSettingsView.cpp @@ -50,12 +50,12 @@ public: : BMenuItem(label, _MenuMessage(code, field)) { - fIcuCode = code; + fICUCode = code; } const BString& ICUCode() const { - return fIcuCode; + return fICUCode; } private: @@ -69,7 +69,7 @@ private: } private: - BString fIcuCode; + BString fICUCode; }; @@ -414,32 +414,33 @@ FormatView::MessageReceived(BMessage* message) menuField->MenuItem()->SetLabel(menuItem->Label()); _UpdateLongDateFormatString(); + // fall through } - // pass trough + case kSettingsContentsModified: - { - int32 separator = 0; - BMenuItem* item = fSeparatorMenuField->Menu()->FindMarked(); - if (item) { - separator = fSeparatorMenuField->Menu()->IndexOf(item); - if (separator >= 0) - // settings.SetTimeFormatSeparator( - // (FormatSeparator)separator); - ; - } - - // Make the notification message and send it to the tracker: - BMessage notificationMessage; - notificationMessage.AddInt32("TimeFormatSeparator", separator); - notificationMessage.AddBool("24HrClock", - f24HrRadioButton->Value() == 1); - - _UpdateExamples(); - - Window()->PostMessage(kSettingsContentsModified); - break; + { + int32 separator = 0; + BMenuItem* item = fSeparatorMenuField->Menu()->FindMarked(); + if (item) { + separator = fSeparatorMenuField->Menu()->IndexOf(item); + if (separator >= 0) + // settings.SetTimeFormatSeparator( + // (FormatSeparator)separator); + ; } + // Make the notification message and send it to the tracker: + BMessage notificationMessage; + notificationMessage.AddInt32("TimeFormatSeparator", separator); + notificationMessage.AddBool("24HrClock", + f24HrRadioButton->Value() == 1); + + _UpdateExamples(); + + Window()->PostMessage(kSettingsContentsModified); + break; + } + case kClockFormatChange: { BMessage newMessage(kMsgSettingsChanged); @@ -492,39 +493,6 @@ FormatView::MessageReceived(BMessage* message) } -void -FormatView::SetDefaults() -{ - /* - TrackerSettings settings; - - settings.SetTimeFormatSeparator(kSlashSeparator); - settings.SetDateOrderFormat(kMDYFormat); - settings.SetClockTo24Hr(false); - */ - - fLocale = *be_locale; - // We work on a copy of the default country and set the changes when - // closing the preflet - _UpdateExamples(); - _SendNotices(); -} - - -bool -FormatView::IsDefaultable() const -{ - /* - TrackerSettings settings; - - return settings.TimeFormatSeparator() != kSlashSeparator - || settings.DateOrderFormat() != kMDYFormat - || settings.ClockIs24Hr() != false; - */ - return true; -} - - void FormatView::Revert() { @@ -692,7 +660,6 @@ FormatView::_ParseCurrencyFormat() void FormatView::_ParseDateFormat() { - // TODO parse the short date too BString dateFormatString; fLocale.GetDateFormat(dateFormatString, true); const char* dateFormat = dateFormatString.String(); @@ -704,7 +671,8 @@ FormatView::_ParseDateFormat() for (int i = 0; i < 4; i++) { fieldBegin = parsePointer; - while (*parsePointer == *(parsePointer + 1)) parsePointer++ ; + while (*parsePointer == *(parsePointer + 1)) + parsePointer++; parsePointer++; BString str; str.Append(fieldBegin, parsePointer - fieldBegin); @@ -731,11 +699,13 @@ FormatView::_ParseDateFormat() fLongDateMenu[i]->MenuItem()->SetLabel(str.Append("*")); fieldBegin = parsePointer; - while ((!IsSpecialDateChar(*parsePointer)) && *parsePointer != '\0' - && *(parsePointer - 1) >= 0) { + while ((!IsSpecialDateChar(*parsePointer)) && *parsePointer != '\0') { if (*parsePointer == '\'') { parsePointer++; - while (*parsePointer != '\'') parsePointer++; + while (*parsePointer != '\0' && *parsePointer != '\'') + parsePointer++; + if (*parsePointer == '\0') + break; } parsePointer++; } @@ -754,7 +724,8 @@ FormatView::_ParseDateFormat() for (int i = 0; i < 3; i++) { fieldBegin = parsePointer; - while (*parsePointer == *(parsePointer + 1)) parsePointer++ ; + while (*parsePointer == *(parsePointer + 1)) + parsePointer++; parsePointer++; BString str; str.Append(fieldBegin, parsePointer - fieldBegin); @@ -783,11 +754,13 @@ FormatView::_ParseDateFormat() } fieldBegin = parsePointer; - while ((!IsSpecialDateChar(*parsePointer)) && *parsePointer != '\0' - && *(parsePointer - 1) >= 0) { + while ((!IsSpecialDateChar(*parsePointer)) && *parsePointer != '\0') { if (*parsePointer == '\'') { parsePointer++; - while (*parsePointer != '\'') parsePointer++; + while (*parsePointer != '\0' && *parsePointer != '\'') + parsePointer++; + if (*parsePointer == '\0') + break; } parsePointer++; } diff --git a/src/preferences/locale/FormatSettingsView.h b/src/preferences/locale/FormatSettingsView.h index 79c827638c..c0acb6b50b 100644 --- a/src/preferences/locale/FormatSettingsView.h +++ b/src/preferences/locale/FormatSettingsView.h @@ -43,8 +43,6 @@ public: virtual void MessageReceived(BMessage* message); virtual void AttachedToWindow(); - virtual void SetDefaults(); - virtual bool IsDefaultable() const; virtual void Revert(); virtual void SetLocale(const BLocale& locale); virtual void RecordRevertSettings(); diff --git a/src/preferences/locale/LanguageListView.cpp b/src/preferences/locale/LanguageListView.cpp index 6ec32484ea..5eb13b641e 100644 --- a/src/preferences/locale/LanguageListView.cpp +++ b/src/preferences/locale/LanguageListView.cpp @@ -89,9 +89,9 @@ LanguageListItem::DrawItem(BView* owner, BRect frame, bool complete) owner->SetHighColor(kBlack); else { owner->SetHighColor(tint_color(owner->LowColor(), B_DARKEN_3_TINT)); - text += " ("; + text += " ["; text += B_TRANSLATE("already chosen"); - text += ")"; + text += "]"; } BFont font = be_plain_font; diff --git a/src/preferences/locale/LocaleSettings.cpp b/src/preferences/locale/LocaleSettings.cpp index 04e6a13a31..376619e9eb 100644 --- a/src/preferences/locale/LocaleSettings.cpp +++ b/src/preferences/locale/LocaleSettings.cpp @@ -67,6 +67,8 @@ LocaleSettings::UpdateFrom(BMessage* message) { BString messageContent; + BLocale locale(*be_locale); + if (message->FindString("language", &messageContent) == B_OK) { fMessage.RemoveName("language"); @@ -78,30 +80,29 @@ LocaleSettings::UpdateFrom(BMessage* message) gMutableLocaleRoster->SetPreferredLanguages(message); } - BLocale locale(*be_locale); - bool countryChanged = false; + bool localeChanged = false; if (message->FindString("country", &messageContent) == B_OK) { fMessage.ReplaceString("country", messageContent); fMessage.RemoveName("shortTimeFormat"); fMessage.RemoveName("longTimeFormat"); - locale = BLocale(messageContent.String()); - countryChanged = true; + locale.SetCountry(messageContent.String()); + localeChanged = true; } if (message->FindString("shortTimeFormat", &messageContent) == B_OK) { fMessage.RemoveName("shortTimeFormat"); fMessage.AddString("shortTimeFormat", messageContent); locale.SetTimeFormat(messageContent, false); - countryChanged = true; + localeChanged = true; } if (message->FindString("longTimeFormat", &messageContent) == B_OK) { fMessage.RemoveName("longTimeFormat"); fMessage.AddString("longTimeFormat", messageContent); locale.SetTimeFormat(messageContent, true); - countryChanged = true; + localeChanged = true; } - if (countryChanged) + if (localeChanged) gMutableLocaleRoster->SetDefaultLocale(locale); } diff --git a/src/preferences/locale/LocaleWindow.cpp b/src/preferences/locale/LocaleWindow.cpp index 3df3e05df1..5f59a30095 100644 --- a/src/preferences/locale/LocaleWindow.cpp +++ b/src/preferences/locale/LocaleWindow.cpp @@ -29,6 +29,9 @@ #include "LanguageListView.h" +#include + + #undef B_TRANSLATE_CONTEXT #define B_TRANSLATE_CONTEXT "Locale Preflet Window" @@ -94,6 +97,9 @@ LocaleWindow::LocaleWindow() fLanguageListView->SetInvocationMessage(new BMessage(kMsgLanguageInvoked)); fLanguageListView->SetDragMessage(new BMessage(kMsgLanguageDragged)); + BFont font; + fLanguageListView->GetFont(&font); + // Fill the language list from the LocaleRoster data BMessage installedLanguages; if (be_locale_roster->GetInstalledLanguages(&installedLanguages) == B_OK) { @@ -102,40 +108,37 @@ LocaleWindow::LocaleWindow() for (int i = 0; installedLanguages.FindString("langs", i, ¤tID) == B_OK; i++) { - // Now get an human-readable, localized name for each language - BLanguage* currentLanguage; - be_locale_roster->GetLanguage(currentID.String(), - ¤tLanguage); - + // Now get the human-readable, native name for each language BString name; - currentLanguage->GetName(name); + BLanguage currentLanguage(currentID.String()); + currentLanguage.GetNativeName(name); - // TODO: as long as the app_server doesn't support font overlays, - // use the translated name if problematic characters are used... - const char* string = name.String(); - while (uint32 code = BUnicodeChar::FromUTF8(&string)) { - if (code > 1424) { - currentLanguage->GetTranslatedName(name); + // TODO: the following block fails to detect a couple of language + // names as containing glyphs we can't render. Why's that? + bool hasGlyphs[name.CountChars()]; + font.GetHasGlyphs(name.String(), name.CountChars(), hasGlyphs); + for (int32 i = 0; i < name.CountChars(); ++i) { + if (!hasGlyphs[i]) { + // replace by name translated to current language + currentLanguage.GetName(name); break; } } LanguageListItem* item = new LanguageListItem(name, - currentID.String(), currentLanguage->Code()); - if (currentLanguage->IsCountrySpecific() + currentID.String(), currentLanguage.Code()); + if (currentLanguage.IsCountrySpecific() && lastAddedCountryItem != NULL && lastAddedCountryItem->Code() == item->Code()) { fLanguageListView->AddUnder(item, lastAddedCountryItem); } else { // This is a language variant, add it at top-level fLanguageListView->AddItem(item); - if (!currentLanguage->IsCountrySpecific()) { + if (!currentLanguage.IsCountrySpecific()) { item->SetExpanded(false); lastAddedCountryItem = item; } } - - delete currentLanguage; } fLanguageListView->FullListSortItems(compare_typed_list_items); @@ -172,32 +175,31 @@ LocaleWindow::LocaleWindow() .End() .SetInsets(spacing, spacing, spacing, spacing); - BView* countryTab = new BView(B_TRANSLATE("Country"), B_WILL_DRAW); + BView* countryTab = new BView(B_TRANSLATE("Formatting"), B_WILL_DRAW); countryTab->SetLayout(new BGroupLayout(B_VERTICAL, 0)); - BListView* listView = new BListView("country", B_SINGLE_SELECTION_LIST); + BListView* listView = new BListView("formatting", B_SINGLE_SELECTION_LIST); scrollView = new BScrollView("scroller", listView, B_WILL_DRAW | B_FRAME_EVENTS, false, true); listView->SetSelectionMessage(new BMessage(kMsgCountrySelection)); - // get all available countries - BMessage countryList; - be_locale_roster->GetInstalledLanguages(&countryList); - BString countryCode; - + // get all available formatting conventions (by language) + BString formattingConventionCode; LanguageListItem* currentItem = NULL; - for (int i = 0; countryList.FindString("langs", i, &countryCode) == B_OK; - i++) { - BLocale locale(countryCode); - BString countryName; + BCountry defaultFormattingConvention; + be_locale->GetCountry(&defaultFormattingConvention); + for (int i = 0; + installedLanguages.FindString("langs", i, &formattingConventionCode) + == B_OK; i++) { + BCountry formattingConvention(formattingConventionCode); + BString formattingConventionName; + formattingConvention.GetName(formattingConventionName); - locale.GetName(countryName); - - LanguageListItem* item - = new LanguageListItem(countryName, countryCode, - NULL); + LanguageListItem* item = new LanguageListItem(formattingConventionName, + formattingConventionCode, NULL); listView->AddItem(item); - if (!strcmp(countryCode, be_locale->Code())) + if (!strcmp(formattingConventionCode, + defaultFormattingConvention.Code())) currentItem = item; } @@ -358,7 +360,8 @@ LocaleWindow::MessageReceived(BMessage* message) be_app_messenger.SendMessage(&newMessage); SettingsChanged(); - BLocale locale(item->ID()); + BCountry country(item->ID()); + BLocale locale(NULL, &country); fFormatView->SetLocale(locale); break; }