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
This commit is contained in:
Oliver Tappe
2010-10-19 21:36:44 +00:00
parent 1959f8502b
commit d1d8fda637
24 changed files with 590 additions and 275 deletions
+9 -1
View File
@@ -13,6 +13,7 @@
class BBitmap; class BBitmap;
class BLanguage;
class BMessage; class BMessage;
namespace icu_44 { namespace icu_44 {
@@ -37,7 +38,11 @@ public:
BCountry& operator=(const BCountry& other); BCountry& operator=(const BCountry& other);
~BCountry(); ~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; const char* Code() const;
status_t GetIcon(BBitmap* result) const; status_t GetIcon(BBitmap* result) const;
@@ -48,7 +53,10 @@ public:
int8 Measurement() const; int8 Measurement() const;
class Private;
private: private:
friend class Private;
icu_44::Locale* fICULocale; icu_44::Locale* fICULocale;
}; };
+12 -5
View File
@@ -34,12 +34,17 @@ public:
BLanguage& operator=(const BLanguage& source); BLanguage& operator=(const BLanguage& source);
status_t GetName(BString& name) const; status_t GetNativeName(BString& name) const;
status_t GetTranslatedName(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* 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* Variant() const;
const char* ID() const; const char* ID() const;
@@ -50,10 +55,12 @@ public:
status_t SetTo(const char* language); status_t SetTo(const char* language);
// see definitions below
const char* GetString(uint32 id) const; const char* GetString(uint32 id) const;
class Private;
private: private:
friend class Private;
// BString fStrings[B_NUM_LANGUAGE_STRINGS]; // BString fStrings[B_NUM_LANGUAGE_STRINGS];
uint8 fDirection; uint8 fDirection;
icu_44::Locale* fICULocale; icu_44::Locale* fICULocale;
+9 -7
View File
@@ -38,8 +38,8 @@ typedef enum {
class BLocale { class BLocale {
public: public:
BLocale(const char* languageAndCountryCode BLocale(const BLanguage* language = NULL,
= "en_US"); const BCountry* country = NULL);
BLocale(const BLocale& other); BLocale(const BLocale& other);
~BLocale(); ~BLocale();
@@ -48,12 +48,12 @@ public:
status_t GetCollator(BCollator* collator) const; status_t GetCollator(BCollator* collator) const;
status_t GetLanguage(BLanguage* language) const; status_t GetLanguage(BLanguage* language) const;
status_t GetCountry(BCountry* country) const; status_t GetCountry(BCountry* country) const;
const char* Code() const;
bool GetName(BString& name) const;
void SetCountry(const BCountry& newCountry); void SetCountry(const BCountry& newCountry);
void SetCollator(const BCollator& newCollator); 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 // see definitions in LocaleStrings.h
const char* GetString(uint32 id) const; const char* GetString(uint32 id) const;
@@ -140,17 +140,19 @@ public:
void GetSortKey(const char* string, void GetSortKey(const char* string,
BString* key) const; BString* key) const;
protected: private:
void _UpdateFormats();
mutable BLocker fLock; mutable BLocker fLock;
BCollator fCollator; BCollator fCollator;
BCountry fCountry; BCountry fCountry;
BLanguage fLanguage; BLanguage fLanguage;
icu_44::Locale* fICULocale;
BString fLongDateFormat; BString fLongDateFormat;
BString fShortDateFormat; BString fShortDateFormat;
BString fLongTimeFormat; BString fLongTimeFormat;
BString fShortTimeFormat; BString fShortTimeFormat;
}; };
+4
View File
@@ -9,6 +9,7 @@
#include <String.h> #include <String.h>
class BBitmap;
class BCatalog; class BCatalog;
class BCollator; class BCollator;
class BCountry; class BCountry;
@@ -48,6 +49,9 @@ public:
BMessage* message, BMessage* message,
const char* countryCode) const; const char* countryCode) const;
status_t GetFlagIconForCountry(BBitmap* flagIcon,
const char* countryCode);
status_t GetInstalledCatalogs(BMessage* message, status_t GetInstalledCatalogs(BMessage* message,
const char* sigPattern = NULL, const char* sigPattern = NULL,
const char* langPattern = NULL, const char* langPattern = NULL,
+2 -2
View File
@@ -46,8 +46,8 @@ public:
private: private:
friend class Private; friend class Private;
icu_44::TimeZone* fIcuTimeZone; icu_44::TimeZone* fICUTimeZone;
icu_44::Locale* fIcuLocale; icu_44::Locale* fICULocale;
status_t fInitStatus; status_t fInitStatus;
mutable uint32 fInitializedFields; mutable uint32 fInitializedFields;
+37
View File
@@ -0,0 +1,37 @@
/*
* Copyright 2010, Oliver Tappe <[email protected]>
* Distributed under the terms of the MIT License.
*/
#ifndef _COUNTRY_PRIVATE_H
#define _COUNTRY_PRIVATE_H
#include <Country.h>
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
+37
View File
@@ -0,0 +1,37 @@
/*
* Copyright 2010, Oliver Tappe <[email protected]>
* Distributed under the terms of the MIT License.
*/
#ifndef _LANGUAGE_PRIVATE_H
#define _LANGUAGE_PRIVATE_H
#include <Language.h>
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
@@ -15,6 +15,7 @@
#include <Locker.h> #include <Locker.h>
#include <LocaleRoster.h> #include <LocaleRoster.h>
#include <Message.h> #include <Message.h>
#include <Resources.h>
#include <TimeZone.h> #include <TimeZone.h>
@@ -113,6 +114,9 @@ struct RosterData {
BLocale fDefaultLocale; BLocale fDefaultLocale;
BTimeZone fDefaultTimeZone; BTimeZone fDefaultTimeZone;
bool fAreResourcesLoaded;
BResources fResources;
RosterData(); RosterData();
~RosterData(); ~RosterData();
+2 -2
View File
@@ -24,9 +24,9 @@ public:
} }
icu_44::TimeZone* icu_44::TimeZone*
IcuTimeZone() ICUTimeZone()
{ {
return fTimeZone->fIcuTimeZone; return fTimeZone->fICUTimeZone;
} }
private: private:
+3 -3
View File
@@ -182,7 +182,7 @@ TranslationComparator(const void* left, const void* right)
BString leftName; BString leftName;
if (be_locale_roster->GetLanguage(leftTranslation->languageCode, &language) if (be_locale_roster->GetLanguage(leftTranslation->languageCode, &language)
== B_OK) { == B_OK) {
language->GetTranslatedName(leftName); language->GetName(leftName);
delete language; delete language;
} else } else
leftName = leftTranslation->languageCode; leftName = leftTranslation->languageCode;
@@ -190,7 +190,7 @@ TranslationComparator(const void* left, const void* right)
BString rightName; BString rightName;
if (be_locale_roster->GetLanguage(rightTranslation->languageCode, &language) if (be_locale_roster->GetLanguage(rightTranslation->languageCode, &language)
== B_OK) { == B_OK) {
language->GetTranslatedName(rightName); language->GetName(rightName);
delete language; delete language;
} else } else
rightName = rightTranslation->languageCode; rightName = rightTranslation->languageCode;
@@ -1101,7 +1101,7 @@ AboutView::_CreateCreditsView()
langName.Truncate(0); langName.Truncate(0);
if (be_locale_roster->GetLanguage(translation.languageCode, &lang) if (be_locale_roster->GetLanguage(translation.languageCode, &lang)
== B_OK) { == B_OK) {
lang->GetTranslatedName(langName); lang->GetName(langName);
delete lang; delete lang;
} else { } else {
// We failed to get the localized readable name, // We failed to get the localized readable name,
+1 -1
View File
@@ -1587,7 +1587,7 @@ MainWin::_SetupTrackMenus(BMenu* audioTrackMenu, BMenu* videoTrackMenu,
if (languageString != NULL) { if (languageString != NULL) {
BLanguage language(languageString); BLanguage language(languageString);
BString languageName; BString languageName;
if (language.GetTranslatedName(languageName) == B_OK) if (language.GetName(languageName) == B_OK)
languageString = languageName.String(); languageString = languageName.String();
snprintf(s, sizeof(s), "%s", languageString); snprintf(s, sizeof(s), "%s", languageString);
} else } else
@@ -260,6 +260,9 @@ BootPromptWindow::_PopulateLanguages()
be_locale_roster->GetInstalledCatalogs(&installedCatalogs, be_locale_roster->GetInstalledCatalogs(&installedCatalogs,
"x-vnd.Haiku-ReadOnlyBootPrompt"); "x-vnd.Haiku-ReadOnlyBootPrompt");
BFont font;
fLanguagesListView->GetFont(&font);
// Try to instantiate a BCatalog for each language, it will only work // Try to instantiate a BCatalog for each language, it will only work
// for translations of this application. So the list of languages will be // for translations of this application. So the list of languages will be
// limited to catalogs written for this application, which is on purpose! // limited to catalogs written for this application, which is on purpose!
@@ -270,14 +273,16 @@ BootPromptWindow::_PopulateLanguages()
BLanguage* language; BLanguage* language;
if (be_locale_roster->GetLanguage(languageString, &language) == B_OK) { if (be_locale_roster->GetLanguage(languageString, &language) == B_OK) {
BString name; BString name;
language->GetName(name); language->GetNativeName(name);
// TODO: as long as the app_server doesn't support font overlays, // TODO: the following block fails to detect a couple of language
// use the translated name if problematic characters are used... // names as containing glyphs we can't render. Why's that?
const char* string = name.String(); bool hasGlyphs[name.CountChars()];
while (uint32 code = BUnicodeChar::FromUTF8(&string)) { font.GetHasGlyphs(name.String(), name.CountChars(), hasGlyphs);
if (code > 1424) { for (int32 i = 0; i < name.CountChars(); ++i) {
language->GetTranslatedName(name); if (!hasGlyphs[i]) {
// replace by name translated to current language
language->GetName(name);
break; break;
} }
} }
+33 -20
View File
@@ -10,6 +10,7 @@
#include <AutoDeleter.h> #include <AutoDeleter.h>
#include <IconUtils.h> #include <IconUtils.h>
#include <List.h> #include <List.h>
#include <Language.h>
#include <LocaleRoster.h> #include <LocaleRoster.h>
#include <Resources.h> #include <Resources.h>
#include <String.h> #include <String.h>
@@ -68,14 +69,39 @@ BCountry::~BCountry()
} }
bool status_t
BCountry::GetName(BString& name) const 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; UnicodeString uString;
fICULocale->getDisplayCountry(uString); fICULocale->getDisplayName(Locale(appLanguage), uString);
BStringByteSink stringConverter(&name); BStringByteSink stringConverter(&name);
uString.toUTF8(stringConverter); uString.toUTF8(stringConverter);
return true;
return B_OK;
} }
@@ -89,23 +115,10 @@ BCountry::Code() const
status_t status_t
BCountry::GetIcon(BBitmap* result) const 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(); const char* code = fICULocale->getCountry();
if (code != NULL) { if (code == NULL)
const void* buffer = storage.LoadResource(B_VECTOR_ICON_TYPE, code, return B_ERROR;
&size); return be_locale_roster->GetFlagIconForCountry(result, code);
if (buffer != NULL && size != 0) {
return BIconUtils::GetVectorIcon(static_cast<const uint8*>(buffer),
size, result);
}
}
return B_BAD_DATA;
} }
+1 -1
View File
@@ -123,7 +123,7 @@ BDurationFormat::SetTimeZone(const BTimeZone* timeZone)
} else } else
zonePrivate.SetTo(timeZone); zonePrivate.SetTo(timeZone);
TimeZone* icuTimeZone = zonePrivate.IcuTimeZone(); TimeZone* icuTimeZone = zonePrivate.ICUTimeZone();
if (icuTimeZone != NULL) if (icuTimeZone != NULL)
fCalendar->setTimeZone(*icuTimeZone); fCalendar->setTimeZone(*icuTimeZone);
+23 -8
View File
@@ -110,10 +110,11 @@ BLanguage::GetString(uint32 id) const
status_t status_t
BLanguage::GetName(BString& name) const BLanguage::GetNativeName(BString& name) const
{ {
UnicodeString string; UnicodeString string;
fICULocale->getDisplayName(*fICULocale, string); fICULocale->getDisplayName(*fICULocale, string);
string.toTitle(NULL, *fICULocale);
name.Truncate(0); name.Truncate(0);
BStringByteSink converter(&name); BStringByteSink converter(&name);
@@ -124,13 +125,16 @@ BLanguage::GetName(BString& name) const
status_t status_t
BLanguage::GetTranslatedName(BString& name) const BLanguage::GetName(BString& name, const BLanguage* displayLanguage) const
{ {
BMessage preferredLanguage;
be_locale_roster->GetPreferredLanguages(&preferredLanguage);
BString appLanguage; 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; UnicodeString string;
fICULocale->getDisplayName(Locale(appLanguage), string); fICULocale->getDisplayName(Locale(appLanguage), string);
@@ -151,7 +155,7 @@ BLanguage::Code() const
const char* const char*
BLanguage::Country() const BLanguage::CountryCode() const
{ {
const char* country = fICULocale->getCountry(); const char* country = fICULocale->getCountry();
if (country == NULL || country[0] == '\0') 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* const char*
BLanguage::Variant() const BLanguage::Variant() const
{ {
@@ -182,7 +197,7 @@ BLanguage::ID() const
bool bool
BLanguage::IsCountrySpecific() const BLanguage::IsCountrySpecific() const
{ {
return Country() != NULL; return CountryCode() != NULL;
} }
+222 -57
View File
@@ -1,6 +1,7 @@
/* /*
** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. ** Copyright 2003, Axel Dörfler, axeld@pinc-software.de.
** Distributed under the terms of the OpenBeOS License. ** Copyright 2010, Oliver Tappe, zooey@hirschkaefer.de.
** All rights reserved. Distributed under the terms of the OpenBeOS License.
*/ */
@@ -8,6 +9,8 @@
#include <Autolock.h> #include <Autolock.h>
#include <CalendarView.h> #include <CalendarView.h>
#include <Catalog.h> #include <Catalog.h>
#include <CountryPrivate.h>
#include <LanguagePrivate.h>
#include <Locale.h> #include <Locale.h>
#include <LocaleRoster.h> #include <LocaleRoster.h>
#include <MutableLocaleRoster.h> #include <MutableLocaleRoster.h>
@@ -37,14 +40,25 @@ static DateFormat* CreateDateFormat(bool longFormat, const Locale& locale,
const BString& format); const BString& format);
static DateFormat* CreateTimeFormat(bool longFormat, const Locale& locale, static DateFormat* CreateTimeFormat(bool longFormat, const Locale& locale,
const BString& format); 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) BLocale::BLocale(const BLanguage* language, const BCountry* country)
:
fCountry(languageAndCountryCode),
fLanguage(languageAndCountryCode),
fICULocale(new ICU_VERSION::Locale(languageAndCountryCode))
{ {
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), fCountry(other.fCountry),
fLanguage(other.fLanguage), fLanguage(other.fLanguage),
fICULocale(new ICU_VERSION::Locale(*other.fICULocale)),
fLongDateFormat(other.fLongDateFormat), fLongDateFormat(other.fLongDateFormat),
fShortDateFormat(other.fShortDateFormat), fShortDateFormat(other.fShortDateFormat),
fLongTimeFormat(other.fLongTimeFormat), fLongTimeFormat(other.fLongTimeFormat),
@@ -67,8 +80,6 @@ BLocale::operator=(const BLocale& other)
if (this == &other) if (this == &other)
return *this; return *this;
*fICULocale = *other.fICULocale;
fLongDateFormat = other.fLongDateFormat; fLongDateFormat = other.fLongDateFormat;
fShortDateFormat = other.fShortDateFormat; fShortDateFormat = other.fShortDateFormat;
fLongTimeFormat = other.fLongTimeFormat; fLongTimeFormat = other.fLongTimeFormat;
@@ -83,7 +94,6 @@ BLocale::operator=(const BLocale& other)
BLocale::~BLocale() BLocale::~BLocale()
{ {
delete fICULocale;
} }
@@ -140,6 +150,10 @@ BLocale::GetString(uint32 id) const
{ {
// Note: this code assumes a certain order of the string bases // 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_OTHER_STRINGS_BASE) {
if (id == B_CODESET) if (id == B_CODESET)
return "UTF-8"; return "UTF-8";
@@ -153,41 +167,54 @@ BLocale::GetString(uint32 id) const
void void
BLocale::SetCountry(const BCountry& newCountry) BLocale::SetCountry(const BCountry& newCountry)
{ {
BAutolock lock(fLock);
if (!lock.IsLocked())
return;
fCountry = newCountry; fCountry = newCountry;
_UpdateFormats();
} }
void void
BLocale::SetCollator(const BCollator& newCollator) BLocale::SetCollator(const BCollator& newCollator)
{ {
BAutolock lock(fLock);
if (!lock.IsLocked())
return;
fCollator = newCollator; fCollator = newCollator;
} }
void void
BLocale::SetLanguage(const char* languageCode) BLocale::SetLanguage(const BLanguage& newLanguage)
{ {
fLanguage.SetTo(languageCode); BAutolock lock(fLock);
} if (!lock.IsLocked())
return;
fLanguage = newLanguage;
const char*
BLocale::Code() const
{
return fICULocale->getName();
} }
bool bool
BLocale::GetName(BString& name) const BLocale::GetName(BString& name) const
{ {
Locale icuLocale = Locale::createCanonical(fCountry.Code());
if (icuLocale.isBogus())
return false;
UnicodeString uString; UnicodeString uString;
fICULocale->getDisplayName(uString); const Locale* countryLocale = BCountry::Private(&fCountry).ICULocale();
countryLocale->getDisplayName(icuLocale, uString);
BStringByteSink stringConverter(&name); BStringByteSink stringConverter(&name);
uString.toUTF8(stringConverter); uString.toUTF8(stringConverter);
return true; return true;
} }
// #pragma mark - Date // #pragma mark - Date
@@ -195,8 +222,13 @@ status_t
BLocale::FormatDate(char* string, size_t maxSize, time_t time, BLocale::FormatDate(char* string, size_t maxSize, time_t time,
bool longFormat) const bool longFormat) const
{ {
BAutolock lock(fLock);
if (!lock.IsLocked())
return B_ERROR;
ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat, ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat,
*fICULocale, longFormat ? fLongDateFormat : fShortDateFormat); *BLanguage::Private(&fLanguage).ICULocale(),
longFormat ? fLongDateFormat : fShortDateFormat);
if (dateFormatter.Get() == NULL) if (dateFormatter.Get() == NULL)
return B_NO_MEMORY; 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); ICUString = dateFormatter->format((UDate)time * 1000, ICUString);
CheckedArrayByteSink stringConverter(string, maxSize); CheckedArrayByteSink stringConverter(string, maxSize);
ICUString.toUTF8(stringConverter); ICUString.toUTF8(stringConverter);
if (stringConverter.Overflowed()) if (stringConverter.Overflowed())
@@ -218,12 +249,13 @@ status_t
BLocale::FormatDate(BString *string, time_t time, bool longFormat, BLocale::FormatDate(BString *string, time_t time, bool longFormat,
const BTimeZone* timeZone) const const BTimeZone* timeZone) const
{ {
string->Truncate(0); BAutolock lock(fLock);
// We make the string empty, this way even in cases where ICU fail we at if (!lock.IsLocked())
// least return something sane return B_ERROR;
Locale locale(fLanguage.Code());
ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat, ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat,
locale, longFormat ? fLongDateFormat : fShortDateFormat); *BLanguage::Private(&fLanguage).ICULocale(),
longFormat ? fLongDateFormat : fShortDateFormat);
if (dateFormatter.Get() == NULL) if (dateFormatter.Get() == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -238,6 +270,7 @@ BLocale::FormatDate(BString *string, time_t time, bool longFormat,
UnicodeString ICUString; UnicodeString ICUString;
ICUString = dateFormatter->format((UDate)time * 1000, ICUString); ICUString = dateFormatter->format((UDate)time * 1000, ICUString);
string->Truncate(0);
BStringByteSink stringConverter(string); BStringByteSink stringConverter(string);
ICUString.toUTF8(stringConverter); ICUString.toUTF8(stringConverter);
@@ -249,10 +282,13 @@ status_t
BLocale::FormatDate(BString* string, int*& fieldPositions, int& fieldCount, BLocale::FormatDate(BString* string, int*& fieldPositions, int& fieldCount,
time_t time, bool longFormat) const time_t time, bool longFormat) const
{ {
string->Truncate(0); BAutolock lock(fLock);
if (!lock.IsLocked())
return B_ERROR;
ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat, ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat,
*fICULocale, longFormat ? fLongDateFormat : fShortDateFormat); *BLanguage::Private(&fLanguage).ICULocale(),
longFormat ? fLongDateFormat : fShortDateFormat);
if (dateFormatter.Get() == NULL) if (dateFormatter.Get() == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -280,6 +316,7 @@ BLocale::FormatDate(BString* string, int*& fieldPositions, int& fieldCount,
for (int i = 0 ; i < fieldCount ; i++ ) for (int i = 0 ; i < fieldCount ; i++ )
fieldPositions[i] = fieldPosStorage[i]; fieldPositions[i] = fieldPosStorage[i];
string->Truncate(0);
BStringByteSink stringConverter(string); BStringByteSink stringConverter(string);
ICUString.toUTF8(stringConverter); ICUString.toUTF8(stringConverter);
@@ -291,6 +328,10 @@ BLocale::FormatDate(BString* string, int*& fieldPositions, int& fieldCount,
status_t status_t
BLocale::GetDateFormat(BString& format, bool longFormat) const BLocale::GetDateFormat(BString& format, bool longFormat) const
{ {
BAutolock lock(fLock);
if (!lock.IsLocked())
return B_ERROR;
if (longFormat && fLongDateFormat.Length() > 0) if (longFormat && fLongDateFormat.Length() > 0)
format = fLongDateFormat; format = fLongDateFormat;
else if (!longFormat && fShortDateFormat.Length() > 0) else if (!longFormat && fShortDateFormat.Length() > 0)
@@ -299,7 +340,7 @@ BLocale::GetDateFormat(BString& format, bool longFormat) const
format.Truncate(0); format.Truncate(0);
ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat, ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat,
*fICULocale, longFormat ? fLongDateFormat : fShortDateFormat); *BCountry::Private(&fCountry).ICULocale(), format);
if (dateFormatter.Get() == NULL) if (dateFormatter.Get() == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -321,6 +362,10 @@ BLocale::GetDateFormat(BString& format, bool longFormat) const
status_t status_t
BLocale::SetDateFormat(const char* formatString, bool longFormat) BLocale::SetDateFormat(const char* formatString, bool longFormat)
{ {
BAutolock lock(fLock);
if (!lock.IsLocked())
return B_ERROR;
if (longFormat) if (longFormat)
fLongDateFormat = formatString; fLongDateFormat = formatString;
else else
@@ -334,8 +379,13 @@ status_t
BLocale::GetDateFields(BDateElement*& fields, int& fieldCount, BLocale::GetDateFields(BDateElement*& fields, int& fieldCount,
bool longFormat) const bool longFormat) const
{ {
BAutolock lock(fLock);
if (!lock.IsLocked())
return B_ERROR;
ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat, ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat,
*fICULocale, longFormat ? fLongDateFormat : fShortDateFormat); *BCountry::Private(&fCountry).ICULocale(),
longFormat ? fLongDateFormat : fShortDateFormat);
if (dateFormatter.Get() == NULL) if (dateFormatter.Get() == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -384,8 +434,14 @@ BLocale::GetDateFields(BDateElement*& fields, int& fieldCount,
int int
BLocale::StartOfWeek() const BLocale::StartOfWeek() const
{ {
BAutolock lock(fLock);
if (!lock.IsLocked())
return B_ERROR;
UErrorCode err = U_ZERO_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) { if (err == U_ZERO_ERROR && c->getFirstDayOfWeek(err) == UCAL_SUNDAY) {
delete c; delete c;
@@ -402,13 +458,19 @@ status_t
BLocale::FormatDateTime(char* target, size_t maxSize, time_t time, BLocale::FormatDateTime(char* target, size_t maxSize, time_t time,
bool longFormat) const bool longFormat) const
{ {
BAutolock lock(fLock);
if (!lock.IsLocked())
return B_ERROR;
ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat, ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat,
*fICULocale, longFormat ? fLongDateFormat : fShortDateFormat); *BLanguage::Private(&fLanguage).ICULocale(),
longFormat ? fLongDateFormat : fShortDateFormat);
if (dateFormatter.Get() == NULL) if (dateFormatter.Get() == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat, ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat,
*fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); *BLanguage::Private(&fLanguage).ICULocale(),
longFormat ? fLongTimeFormat : fShortTimeFormat);
if (timeFormatter.Get() == NULL) if (timeFormatter.Get() == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -433,13 +495,19 @@ status_t
BLocale::FormatDateTime(BString* target, time_t time, bool longFormat, BLocale::FormatDateTime(BString* target, time_t time, bool longFormat,
const BTimeZone* timeZone) const const BTimeZone* timeZone) const
{ {
BAutolock lock(fLock);
if (!lock.IsLocked())
return B_ERROR;
ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat, ObjectDeleter<DateFormat> dateFormatter = CreateDateFormat(longFormat,
*fICULocale, longFormat ? fLongDateFormat : fShortDateFormat); *BLanguage::Private(&fLanguage).ICULocale(),
longFormat ? fLongDateFormat : fShortDateFormat);
if (dateFormatter.Get() == NULL) if (dateFormatter.Get() == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat, ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat,
*fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); *BLanguage::Private(&fLanguage).ICULocale(),
longFormat ? fLongTimeFormat : fShortTimeFormat);
if (timeFormatter.Get() == NULL) if (timeFormatter.Get() == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -458,6 +526,7 @@ BLocale::FormatDateTime(BString* target, time_t time, bool longFormat,
ICUString = timeFormatter->format((UDate)time * 1000, ICUString); ICUString = timeFormatter->format((UDate)time * 1000, ICUString);
target->Truncate(0);
BStringByteSink stringConverter(target); BStringByteSink stringConverter(target);
ICUString.toUTF8(stringConverter); ICUString.toUTF8(stringConverter);
@@ -472,8 +541,13 @@ status_t
BLocale::FormatTime(char* string, size_t maxSize, time_t time, BLocale::FormatTime(char* string, size_t maxSize, time_t time,
bool longFormat) const bool longFormat) const
{ {
BAutolock lock(fLock);
if (!lock.IsLocked())
return B_ERROR;
ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat, ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat,
*fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); *BLanguage::Private(&fLanguage).ICULocale(),
longFormat ? fLongTimeFormat : fShortTimeFormat);
if (timeFormatter.Get() == NULL) if (timeFormatter.Get() == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -495,10 +569,13 @@ status_t
BLocale::FormatTime(BString* string, time_t time, bool longFormat, BLocale::FormatTime(BString* string, time_t time, bool longFormat,
const BTimeZone* timeZone) const const BTimeZone* timeZone) const
{ {
string->Truncate(0); BAutolock lock(fLock);
if (!lock.IsLocked())
return B_ERROR;
ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat, ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat,
*fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); *BLanguage::Private(&fLanguage).ICULocale(),
longFormat ? fLongTimeFormat : fShortTimeFormat);
if (timeFormatter.Get() == NULL) if (timeFormatter.Get() == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -513,6 +590,7 @@ BLocale::FormatTime(BString* string, time_t time, bool longFormat,
UnicodeString ICUString; UnicodeString ICUString;
ICUString = timeFormatter->format((UDate)time * 1000, ICUString); ICUString = timeFormatter->format((UDate)time * 1000, ICUString);
string->Truncate(0);
BStringByteSink stringConverter(string); BStringByteSink stringConverter(string);
ICUString.toUTF8(stringConverter); ICUString.toUTF8(stringConverter);
@@ -525,10 +603,13 @@ status_t
BLocale::FormatTime(BString* string, int*& fieldPositions, int& fieldCount, BLocale::FormatTime(BString* string, int*& fieldPositions, int& fieldCount,
time_t time, bool longFormat) const time_t time, bool longFormat) const
{ {
string->Truncate(0); BAutolock lock(fLock);
if (!lock.IsLocked())
return B_ERROR;
ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat, ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat,
*fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); *BLanguage::Private(&fLanguage).ICULocale(),
longFormat ? fLongTimeFormat : fShortTimeFormat);
if (timeFormatter.Get() == NULL) if (timeFormatter.Get() == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -556,6 +637,7 @@ BLocale::FormatTime(BString* string, int*& fieldPositions, int& fieldCount,
for (int i = 0 ; i < fieldCount ; i++ ) for (int i = 0 ; i < fieldCount ; i++ )
fieldPositions[i] = fieldPosStorage[i]; fieldPositions[i] = fieldPosStorage[i];
string->Truncate(0);
BStringByteSink stringConverter(string); BStringByteSink stringConverter(string);
ICUString.toUTF8(stringConverter); ICUString.toUTF8(stringConverter);
@@ -568,8 +650,13 @@ status_t
BLocale::GetTimeFields(BDateElement*& fields, int& fieldCount, BLocale::GetTimeFields(BDateElement*& fields, int& fieldCount,
bool longFormat) const bool longFormat) const
{ {
BAutolock lock(fLock);
if (!lock.IsLocked())
return B_ERROR;
ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat, ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat,
*fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); *BCountry::Private(&fCountry).ICULocale(),
longFormat ? fLongTimeFormat : fShortTimeFormat);
if (timeFormatter.Get() == NULL) if (timeFormatter.Get() == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -624,6 +711,10 @@ BLocale::GetTimeFields(BDateElement*& fields, int& fieldCount,
status_t status_t
BLocale::SetTimeFormat(const char* formatString, bool longFormat) BLocale::SetTimeFormat(const char* formatString, bool longFormat)
{ {
BAutolock lock(fLock);
if (!lock.IsLocked())
return B_ERROR;
if (longFormat) if (longFormat)
fLongTimeFormat = formatString; fLongTimeFormat = formatString;
else else
@@ -636,6 +727,10 @@ BLocale::SetTimeFormat(const char* formatString, bool longFormat)
status_t status_t
BLocale::GetTimeFormat(BString& format, bool longFormat) const BLocale::GetTimeFormat(BString& format, bool longFormat) const
{ {
BAutolock lock(fLock);
if (!lock.IsLocked())
return B_ERROR;
if (longFormat && fLongTimeFormat.Length() > 0) if (longFormat && fLongTimeFormat.Length() > 0)
format = fLongTimeFormat; format = fLongTimeFormat;
else if (!longFormat && fShortTimeFormat.Length() > 0) else if (!longFormat && fShortTimeFormat.Length() > 0)
@@ -644,7 +739,8 @@ BLocale::GetTimeFormat(BString& format, bool longFormat) const
format.Truncate(0); format.Truncate(0);
ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat, ObjectDeleter<DateFormat> timeFormatter = CreateTimeFormat(longFormat,
*fICULocale, longFormat ? fLongTimeFormat : fShortTimeFormat); *BCountry::Private(&fCountry).ICULocale(),
longFormat ? fLongTimeFormat : fShortTimeFormat);
if (timeFormatter.Get() == NULL) if (timeFormatter.Get() == NULL)
return B_NO_MEMORY; 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 // #pragma mark - Numbers
@@ -680,9 +790,14 @@ BLocale::FormatNumber(char* string, size_t maxSize, double value) const
status_t status_t
BLocale::FormatNumber(BString* string, double value) const BLocale::FormatNumber(BString* string, double value) const
{ {
BAutolock lock(fLock);
if (!lock.IsLocked())
return B_ERROR;
UErrorCode err = U_ZERO_ERROR; UErrorCode err = U_ZERO_ERROR;
ObjectDeleter<NumberFormat> numberFormatter = NumberFormat::createInstance( ObjectDeleter<NumberFormat> numberFormatter = NumberFormat::createInstance(
*fICULocale, NumberFormat::kNumberStyle, err); *BCountry::Private(&fCountry).ICULocale(), NumberFormat::kNumberStyle,
err);
if (numberFormatter.Get() == NULL) if (numberFormatter.Get() == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -715,9 +830,14 @@ BLocale::FormatNumber(char* string, size_t maxSize, int32 value) const
status_t status_t
BLocale::FormatNumber(BString* string, int32 value) const BLocale::FormatNumber(BString* string, int32 value) const
{ {
BAutolock lock(fLock);
if (!lock.IsLocked())
return B_ERROR;
UErrorCode err = U_ZERO_ERROR; UErrorCode err = U_ZERO_ERROR;
ObjectDeleter<NumberFormat> numberFormatter = NumberFormat::createInstance( ObjectDeleter<NumberFormat> numberFormatter = NumberFormat::createInstance(
*fICULocale, NumberFormat::kNumberStyle, err); *BCountry::Private(&fCountry).ICULocale(), NumberFormat::kNumberStyle,
err);
if (numberFormatter.Get() == NULL) if (numberFormatter.Get() == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -753,9 +873,14 @@ BLocale::FormatMonetary(BString* string, double value) const
if (string == NULL) if (string == NULL)
return B_BAD_VALUE; return B_BAD_VALUE;
BAutolock lock(fLock);
if (!lock.IsLocked())
return B_ERROR;
UErrorCode err; UErrorCode err;
ObjectDeleter<NumberFormat> numberFormatter ObjectDeleter<NumberFormat> numberFormatter
= NumberFormat::createCurrencyInstance(*fICULocale, err); = NumberFormat::createCurrencyInstance(
*BCountry::Private(&fCountry).ICULocale(), err);
if (numberFormatter.Get() == NULL) if (numberFormatter.Get() == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -777,14 +902,17 @@ status_t
BLocale::FormatMonetary(BString* string, int*& fieldPositions, BLocale::FormatMonetary(BString* string, int*& fieldPositions,
BNumberElement*& fieldTypes, int& fieldCount, double value) const BNumberElement*& fieldTypes, int& fieldCount, double value) const
{ {
BAutolock lock(fLock);
if (!lock.IsLocked())
return B_ERROR;
UErrorCode err = U_ZERO_ERROR; UErrorCode err = U_ZERO_ERROR;
ObjectDeleter<NumberFormat> numberFormatter ObjectDeleter<NumberFormat> numberFormatter
= NumberFormat::createCurrencyInstance(*fICULocale, err); = NumberFormat::createCurrencyInstance(
*BCountry::Private(&fCountry).ICULocale(), err);
if (U_FAILURE(err)) if (U_FAILURE(err))
return B_NO_MEMORY; return B_NO_MEMORY;
string->Truncate(0);
fieldPositions = NULL; fieldPositions = NULL;
fieldTypes = NULL; fieldTypes = NULL;
ICU_VERSION::FieldPositionIterator positionIterator; ICU_VERSION::FieldPositionIterator positionIterator;
@@ -827,6 +955,7 @@ BLocale::FormatMonetary(BString* string, int*& fieldPositions,
} }
} }
string->Truncate(0);
BStringByteSink stringConverter(string); BStringByteSink stringConverter(string);
ICUString.toUTF8(stringConverter); ICUString.toUTF8(stringConverter);
@@ -838,9 +967,13 @@ BLocale::FormatMonetary(BString* string, int*& fieldPositions,
status_t status_t
BLocale::GetCurrencySymbol(BString& result) const BLocale::GetCurrencySymbol(BString& result) const
{ {
BAutolock lock(fLock);
if (!lock.IsLocked())
return B_ERROR;
UErrorCode error = U_ZERO_ERROR; UErrorCode error = U_ZERO_ERROR;
NumberFormat* format = NumberFormat::createCurrencyInstance(*fICULocale, NumberFormat* format = NumberFormat::createCurrencyInstance(
error); *BCountry::Private(&fCountry).ICULocale(), error);
if (U_FAILURE(error)) if (U_FAILURE(error))
return B_ERROR; return B_ERROR;
@@ -860,11 +993,10 @@ BLocale::GetCurrencySymbol(BString& result) const
static DateFormat* static DateFormat*
CreateDateFormat(bool longFormat, const Locale& locale, CreateDateFormat(bool longFormat, const Locale& locale, const BString& format)
const BString& format)
{ {
DateFormat* dateFormatter = DateFormat::createDateInstance( DateFormat* dateFormatter = DateFormat::createDateInstance(
longFormat ? DateFormat::FULL : DateFormat::SHORT, locale); longFormat ? DateFormat::kFull : DateFormat::kShort, locale);
if (format.Length() > 0) { if (format.Length() > 0) {
SimpleDateFormat* dateFormatterImpl SimpleDateFormat* dateFormatterImpl
@@ -879,11 +1011,10 @@ CreateDateFormat(bool longFormat, const Locale& locale,
static DateFormat* static DateFormat*
CreateTimeFormat(bool longFormat, const Locale& locale, CreateTimeFormat(bool longFormat, const Locale& locale, const BString& format)
const BString& format)
{ {
DateFormat* timeFormatter = DateFormat::createTimeInstance( DateFormat* timeFormatter = DateFormat::createTimeInstance(
longFormat ? DateFormat::MEDIUM : DateFormat::SHORT, locale); longFormat ? DateFormat::kMedium: DateFormat::kShort, locale);
if (format.Length() > 0) { if (format.Length() > 0) {
SimpleDateFormat* timeFormatterImpl SimpleDateFormat* timeFormatterImpl
@@ -895,3 +1026,37 @@ CreateTimeFormat(bool longFormat, const Locale& locale,
return timeFormatter; 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<SimpleDateFormat*>(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<SimpleDateFormat*>(timeFormatter);
UnicodeString pattern;
timeFormatterImpl->toPattern(pattern);
format.Truncate(0);
BStringByteSink stringConverter(&format);
pattern.toUTF8(stringConverter);
}
+35
View File
@@ -17,6 +17,7 @@
#include <Autolock.h> #include <Autolock.h>
#include <AppFileInfo.h> #include <AppFileInfo.h>
#include <Bitmap.h>
#include <Catalog.h> #include <Catalog.h>
#include <Collator.h> #include <Collator.h>
#include <Country.h> #include <Country.h>
@@ -24,6 +25,7 @@
#include <Directory.h> #include <Directory.h>
#include <Entry.h> #include <Entry.h>
#include <File.h> #include <File.h>
#include <IconUtils.h>
#include <Language.h> #include <Language.h>
#include <Locale.h> #include <Locale.h>
#include <MutableLocaleRoster.h> #include <MutableLocaleRoster.h>
@@ -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<const uint8*>(buffer), size,
flagIcon);
}
status_t status_t
BLocaleRoster::GetInstalledCatalogs(BMessage* languageList, BLocaleRoster::GetInstalledCatalogs(BMessage* languageList,
const char* sigPattern, const char* langPattern, int32 fingerprint) const const char* sigPattern, const char* langPattern, int32 fingerprint) const
+16 -8
View File
@@ -122,7 +122,7 @@ CatalogAddOnInfo::UnloadIfPossible()
} }
// #pragma mark - MutableLocaleRoster // #pragma mark - RosterData
RosterData gRosterData; RosterData gRosterData;
@@ -132,7 +132,8 @@ static const char* kPriorityAttr = "ADDON:priority";
RosterData::RosterData() RosterData::RosterData()
: :
fLock("LocaleRosterData") fLock("LocaleRosterData"),
fAreResourcesLoaded(false)
{ {
openlog_team("liblocale.so", LOG_PID, LOG_USER); openlog_team("liblocale.so", LOG_PID, LOG_USER);
#ifndef DEBUG #ifndef DEBUG
@@ -439,8 +440,10 @@ RosterData::_LoadLocaleSettings()
BString codeName; BString codeName;
BLocale newDefaultLocale; BLocale newDefaultLocale;
if (settings.FindString("country", &codeName) == B_OK) if (settings.FindString("country", &codeName) == B_OK) {
newDefaultLocale = BLocale(codeName); BCountry country(codeName);
newDefaultLocale = BLocale(NULL, &country);
}
BString timeFormat; BString timeFormat;
if (settings.FindString("shortTimeFormat", &timeFormat) == B_OK) if (settings.FindString("shortTimeFormat", &timeFormat) == B_OK)
@@ -461,7 +464,8 @@ RosterData::_LoadLocaleSettings()
fPreferredLanguages.MakeEmpty(); fPreferredLanguages.MakeEmpty();
fPreferredLanguages.AddString("language", "en"); fPreferredLanguages.AddString("language", "en");
_SetDefaultLocale("en_US"); BLanguage defaultLanguage("en_US");
_SetDefaultLocale(BLocale(&defaultLanguage));
return status; return status;
} }
@@ -574,7 +578,9 @@ RosterData::_SetDefaultLocale(const BLocale& newLocale)
fDefaultLocale = newLocale; fDefaultLocale = newLocale;
UErrorCode icuError = U_ZERO_ERROR; 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()) if (icuLocale.isBogus())
return B_ERROR; return B_ERROR;
@@ -607,7 +613,7 @@ RosterData::_SetPreferredLanguages(const BMessage* languages)
if (languages != NULL if (languages != NULL
&& languages->FindString("language", &langName) == B_OK) { && languages->FindString("language", &langName) == B_OK) {
fDefaultLocale.SetCollator(BCollator(langName.String())); fDefaultLocale.SetCollator(BCollator(langName.String()));
fDefaultLocale.SetLanguage(langName.String()); fDefaultLocale.SetLanguage(BLanguage(langName.String()));
fPreferredLanguages.RemoveName("language"); fPreferredLanguages.RemoveName("language");
for (int i = 0; languages->FindString("language", i, &langName) == B_OK; for (int i = 0; languages->FindString("language", i, &langName) == B_OK;
@@ -627,7 +633,9 @@ RosterData::_SetPreferredLanguages(const BMessage* languages)
status_t status_t
RosterData::_AddDefaultCountryToMessage(BMessage* message) const 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; BString timeFormat;
if (status == B_OK) if (status == B_OK)
status = fDefaultLocale.GetTimeFormat(timeFormat, false); status = fDefaultLocale.GetTimeFormat(timeFormat, false);
+40 -40
View File
@@ -38,8 +38,8 @@ static const uint32 skOffsetFromGMTField = 1U << 8;
BTimeZone::BTimeZone(const char* zoneID, const BLanguage* language) BTimeZone::BTimeZone(const char* zoneID, const BLanguage* language)
: :
fIcuTimeZone(NULL), fICUTimeZone(NULL),
fIcuLocale(NULL), fICULocale(NULL),
fInitStatus(B_NO_INIT), fInitStatus(B_NO_INIT),
fInitializedFields(0) fInitializedFields(0)
{ {
@@ -49,12 +49,12 @@ BTimeZone::BTimeZone(const char* zoneID, const BLanguage* language)
BTimeZone::BTimeZone(const BTimeZone& other) BTimeZone::BTimeZone(const BTimeZone& other)
: :
fIcuTimeZone(other.fIcuTimeZone == NULL fICUTimeZone(other.fICUTimeZone == NULL
? NULL ? NULL
: other.fIcuTimeZone->clone()), : other.fICUTimeZone->clone()),
fIcuLocale(other.fIcuLocale == NULL fICULocale(other.fICULocale == NULL
? NULL ? NULL
: other.fIcuLocale->clone()), : other.fICULocale->clone()),
fInitStatus(other.fInitStatus), fInitStatus(other.fInitStatus),
fInitializedFields(other.fInitializedFields), fInitializedFields(other.fInitializedFields),
fZoneID(other.fZoneID), fZoneID(other.fZoneID),
@@ -70,20 +70,20 @@ BTimeZone::BTimeZone(const BTimeZone& other)
BTimeZone::~BTimeZone() BTimeZone::~BTimeZone()
{ {
delete fIcuLocale; delete fICULocale;
delete fIcuTimeZone; delete fICUTimeZone;
} }
BTimeZone& BTimeZone::operator=(const BTimeZone& source) BTimeZone& BTimeZone::operator=(const BTimeZone& source)
{ {
delete fIcuTimeZone; delete fICUTimeZone;
fIcuTimeZone = source.fIcuTimeZone == NULL fICUTimeZone = source.fICUTimeZone == NULL
? NULL ? NULL
: source.fIcuTimeZone->clone(); : source.fICUTimeZone->clone();
fIcuLocale = source.fIcuLocale == NULL fICULocale = source.fICULocale == NULL
? NULL ? NULL
: source.fIcuLocale->clone(); : source.fICULocale->clone();
fInitStatus = source.fInitStatus; fInitStatus = source.fInitStatus;
fInitializedFields = source.fInitializedFields; fInitializedFields = source.fInitializedFields;
fZoneID = source.fZoneID; fZoneID = source.fZoneID;
@@ -110,11 +110,11 @@ BTimeZone::Name() const
{ {
if ((fInitializedFields & skNameField) == 0) { if ((fInitializedFields & skNameField) == 0) {
UnicodeString unicodeString; UnicodeString unicodeString;
if (fIcuLocale != NULL) { if (fICULocale != NULL) {
fIcuTimeZone->getDisplayName(false, TimeZone::GENERIC_LOCATION, fICUTimeZone->getDisplayName(false, TimeZone::GENERIC_LOCATION,
*fIcuLocale, unicodeString); *fICULocale, unicodeString);
} else { } else {
fIcuTimeZone->getDisplayName(false, TimeZone::GENERIC_LOCATION, fICUTimeZone->getDisplayName(false, TimeZone::GENERIC_LOCATION,
unicodeString); unicodeString);
} }
BStringByteSink sink(&fName); BStringByteSink sink(&fName);
@@ -131,11 +131,11 @@ BTimeZone::DaylightSavingName() const
{ {
if ((fInitializedFields & skDaylightSavingNameField) == 0) { if ((fInitializedFields & skDaylightSavingNameField) == 0) {
UnicodeString unicodeString; UnicodeString unicodeString;
if (fIcuLocale != NULL) { if (fICULocale != NULL) {
fIcuTimeZone->getDisplayName(true, TimeZone::GENERIC_LOCATION, fICUTimeZone->getDisplayName(true, TimeZone::GENERIC_LOCATION,
*fIcuLocale, unicodeString); *fICULocale, unicodeString);
} else { } else {
fIcuTimeZone->getDisplayName(true, TimeZone::GENERIC_LOCATION, fICUTimeZone->getDisplayName(true, TimeZone::GENERIC_LOCATION,
unicodeString); unicodeString);
} }
BStringByteSink sink(&fDaylightSavingName); BStringByteSink sink(&fDaylightSavingName);
@@ -152,11 +152,11 @@ BTimeZone::ShortName() const
{ {
if ((fInitializedFields & skShortNameField) == 0) { if ((fInitializedFields & skShortNameField) == 0) {
UnicodeString unicodeString; UnicodeString unicodeString;
if (fIcuLocale != NULL) { if (fICULocale != NULL) {
fIcuTimeZone->getDisplayName(false, TimeZone::SHORT_COMMONLY_USED, fICUTimeZone->getDisplayName(false, TimeZone::SHORT_COMMONLY_USED,
*fIcuLocale, unicodeString); *fICULocale, unicodeString);
} else { } else {
fIcuTimeZone->getDisplayName(false, TimeZone::SHORT_COMMONLY_USED, fICUTimeZone->getDisplayName(false, TimeZone::SHORT_COMMONLY_USED,
unicodeString); unicodeString);
} }
BStringByteSink sink(&fShortName); BStringByteSink sink(&fShortName);
@@ -173,11 +173,11 @@ BTimeZone::ShortDaylightSavingName() const
{ {
if ((fInitializedFields & skShortDaylightSavingNameField) == 0) { if ((fInitializedFields & skShortDaylightSavingNameField) == 0) {
UnicodeString unicodeString; UnicodeString unicodeString;
if (fIcuLocale != NULL) { if (fICULocale != NULL) {
fIcuTimeZone->getDisplayName(true, TimeZone::SHORT_COMMONLY_USED, fICUTimeZone->getDisplayName(true, TimeZone::SHORT_COMMONLY_USED,
*fIcuLocale, unicodeString); *fICULocale, unicodeString);
} else { } else {
fIcuTimeZone->getDisplayName(true, TimeZone::SHORT_COMMONLY_USED, fICUTimeZone->getDisplayName(true, TimeZone::SHORT_COMMONLY_USED,
unicodeString); unicodeString);
} }
BStringByteSink sink(&fShortDaylightSavingName); BStringByteSink sink(&fShortDaylightSavingName);
@@ -198,7 +198,7 @@ BTimeZone::OffsetFromGMT() const
UDate nowMillis = 1000 * (double)time(NULL); UDate nowMillis = 1000 * (double)time(NULL);
UErrorCode error = U_ZERO_ERROR; UErrorCode error = U_ZERO_ERROR;
fIcuTimeZone->getOffset(nowMillis, FALSE, rawOffset, dstOffset, error); fICUTimeZone->getOffset(nowMillis, FALSE, rawOffset, dstOffset, error);
if (!U_SUCCESS(error)) if (!U_SUCCESS(error))
fOffsetFromGMT = 0; fOffsetFromGMT = 0;
else { else {
@@ -216,7 +216,7 @@ bool
BTimeZone::SupportsDaylightSaving() const BTimeZone::SupportsDaylightSaving() const
{ {
if ((fInitializedFields & skSupportsDaylightSavingField) == 0) { if ((fInitializedFields & skSupportsDaylightSavingField) == 0) {
fSupportsDaylightSaving = fIcuTimeZone->useDaylightTime(); fSupportsDaylightSaving = fICUTimeZone->useDaylightTime();
fInitializedFields |= skSupportsDaylightSavingField; fInitializedFields |= skSupportsDaylightSavingField;
} }
@@ -241,31 +241,31 @@ BTimeZone::SetLanguage(const BLanguage* language)
status_t status_t
BTimeZone::SetTo(const char* zoneID, const BLanguage* language) BTimeZone::SetTo(const char* zoneID, const BLanguage* language)
{ {
delete fIcuLocale; delete fICULocale;
fIcuLocale = NULL; fICULocale = NULL;
delete fIcuTimeZone; delete fICUTimeZone;
fInitializedFields = 0; fInitializedFields = 0;
if (zoneID == NULL || zoneID[0] == '\0') if (zoneID == NULL || zoneID[0] == '\0')
fIcuTimeZone = TimeZone::createDefault(); fICUTimeZone = TimeZone::createDefault();
else else
fIcuTimeZone = TimeZone::createTimeZone(zoneID); fICUTimeZone = TimeZone::createTimeZone(zoneID);
if (fIcuTimeZone == NULL) { if (fICUTimeZone == NULL) {
fInitStatus = B_NAME_NOT_FOUND; fInitStatus = B_NAME_NOT_FOUND;
return fInitStatus; return fInitStatus;
} }
if (language != NULL) { if (language != NULL) {
fIcuLocale = new Locale(language->Code()); fICULocale = new Locale(language->Code());
if (fIcuLocale == NULL) { if (fICULocale == NULL) {
fInitStatus = B_NO_MEMORY; fInitStatus = B_NO_MEMORY;
return fInitStatus; return fInitStatus;
} }
} }
UnicodeString unicodeString; UnicodeString unicodeString;
fIcuTimeZone->getID(unicodeString); fICUTimeZone->getID(unicodeString);
BStringByteSink sink(&fZoneID); BStringByteSink sink(&fZoneID);
unicodeString.toUTF8(sink); unicodeString.toUTF8(sink);
+40 -67
View File
@@ -50,12 +50,12 @@ public:
: :
BMenuItem(label, _MenuMessage(code, field)) BMenuItem(label, _MenuMessage(code, field))
{ {
fIcuCode = code; fICUCode = code;
} }
const BString& ICUCode() const const BString& ICUCode() const
{ {
return fIcuCode; return fICUCode;
} }
private: private:
@@ -69,7 +69,7 @@ private:
} }
private: private:
BString fIcuCode; BString fICUCode;
}; };
@@ -414,32 +414,33 @@ FormatView::MessageReceived(BMessage* message)
menuField->MenuItem()->SetLabel(menuItem->Label()); menuField->MenuItem()->SetLabel(menuItem->Label());
_UpdateLongDateFormatString(); _UpdateLongDateFormatString();
// fall through
} }
// pass trough
case kSettingsContentsModified: case kSettingsContentsModified:
{ {
int32 separator = 0; int32 separator = 0;
BMenuItem* item = fSeparatorMenuField->Menu()->FindMarked(); BMenuItem* item = fSeparatorMenuField->Menu()->FindMarked();
if (item) { if (item) {
separator = fSeparatorMenuField->Menu()->IndexOf(item); separator = fSeparatorMenuField->Menu()->IndexOf(item);
if (separator >= 0) if (separator >= 0)
// settings.SetTimeFormatSeparator( // settings.SetTimeFormatSeparator(
// (FormatSeparator)separator); // (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;
} }
// 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: case kClockFormatChange:
{ {
BMessage newMessage(kMsgSettingsChanged); 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 void
FormatView::Revert() FormatView::Revert()
{ {
@@ -692,7 +660,6 @@ FormatView::_ParseCurrencyFormat()
void void
FormatView::_ParseDateFormat() FormatView::_ParseDateFormat()
{ {
// TODO parse the short date too
BString dateFormatString; BString dateFormatString;
fLocale.GetDateFormat(dateFormatString, true); fLocale.GetDateFormat(dateFormatString, true);
const char* dateFormat = dateFormatString.String(); const char* dateFormat = dateFormatString.String();
@@ -704,7 +671,8 @@ FormatView::_ParseDateFormat()
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
fieldBegin = parsePointer; fieldBegin = parsePointer;
while (*parsePointer == *(parsePointer + 1)) parsePointer++ ; while (*parsePointer == *(parsePointer + 1))
parsePointer++;
parsePointer++; parsePointer++;
BString str; BString str;
str.Append(fieldBegin, parsePointer - fieldBegin); str.Append(fieldBegin, parsePointer - fieldBegin);
@@ -731,11 +699,13 @@ FormatView::_ParseDateFormat()
fLongDateMenu[i]->MenuItem()->SetLabel(str.Append("*")); fLongDateMenu[i]->MenuItem()->SetLabel(str.Append("*"));
fieldBegin = parsePointer; fieldBegin = parsePointer;
while ((!IsSpecialDateChar(*parsePointer)) && *parsePointer != '\0' while ((!IsSpecialDateChar(*parsePointer)) && *parsePointer != '\0') {
&& *(parsePointer - 1) >= 0) {
if (*parsePointer == '\'') { if (*parsePointer == '\'') {
parsePointer++; parsePointer++;
while (*parsePointer != '\'') parsePointer++; while (*parsePointer != '\0' && *parsePointer != '\'')
parsePointer++;
if (*parsePointer == '\0')
break;
} }
parsePointer++; parsePointer++;
} }
@@ -754,7 +724,8 @@ FormatView::_ParseDateFormat()
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
fieldBegin = parsePointer; fieldBegin = parsePointer;
while (*parsePointer == *(parsePointer + 1)) parsePointer++ ; while (*parsePointer == *(parsePointer + 1))
parsePointer++;
parsePointer++; parsePointer++;
BString str; BString str;
str.Append(fieldBegin, parsePointer - fieldBegin); str.Append(fieldBegin, parsePointer - fieldBegin);
@@ -783,11 +754,13 @@ FormatView::_ParseDateFormat()
} }
fieldBegin = parsePointer; fieldBegin = parsePointer;
while ((!IsSpecialDateChar(*parsePointer)) && *parsePointer != '\0' while ((!IsSpecialDateChar(*parsePointer)) && *parsePointer != '\0') {
&& *(parsePointer - 1) >= 0) {
if (*parsePointer == '\'') { if (*parsePointer == '\'') {
parsePointer++; parsePointer++;
while (*parsePointer != '\'') parsePointer++; while (*parsePointer != '\0' && *parsePointer != '\'')
parsePointer++;
if (*parsePointer == '\0')
break;
} }
parsePointer++; parsePointer++;
} }
@@ -43,8 +43,6 @@ public:
virtual void MessageReceived(BMessage* message); virtual void MessageReceived(BMessage* message);
virtual void AttachedToWindow(); virtual void AttachedToWindow();
virtual void SetDefaults();
virtual bool IsDefaultable() const;
virtual void Revert(); virtual void Revert();
virtual void SetLocale(const BLocale& locale); virtual void SetLocale(const BLocale& locale);
virtual void RecordRevertSettings(); virtual void RecordRevertSettings();
+2 -2
View File
@@ -89,9 +89,9 @@ LanguageListItem::DrawItem(BView* owner, BRect frame, bool complete)
owner->SetHighColor(kBlack); owner->SetHighColor(kBlack);
else { else {
owner->SetHighColor(tint_color(owner->LowColor(), B_DARKEN_3_TINT)); owner->SetHighColor(tint_color(owner->LowColor(), B_DARKEN_3_TINT));
text += " ("; text += " [";
text += B_TRANSLATE("already chosen"); text += B_TRANSLATE("already chosen");
text += ")"; text += "]";
} }
BFont font = be_plain_font; BFont font = be_plain_font;
+8 -7
View File
@@ -67,6 +67,8 @@ LocaleSettings::UpdateFrom(BMessage* message)
{ {
BString messageContent; BString messageContent;
BLocale locale(*be_locale);
if (message->FindString("language", &messageContent) == B_OK) { if (message->FindString("language", &messageContent) == B_OK) {
fMessage.RemoveName("language"); fMessage.RemoveName("language");
@@ -78,30 +80,29 @@ LocaleSettings::UpdateFrom(BMessage* message)
gMutableLocaleRoster->SetPreferredLanguages(message); gMutableLocaleRoster->SetPreferredLanguages(message);
} }
BLocale locale(*be_locale); bool localeChanged = false;
bool countryChanged = false;
if (message->FindString("country", &messageContent) == B_OK) { if (message->FindString("country", &messageContent) == B_OK) {
fMessage.ReplaceString("country", messageContent); fMessage.ReplaceString("country", messageContent);
fMessage.RemoveName("shortTimeFormat"); fMessage.RemoveName("shortTimeFormat");
fMessage.RemoveName("longTimeFormat"); fMessage.RemoveName("longTimeFormat");
locale = BLocale(messageContent.String()); locale.SetCountry(messageContent.String());
countryChanged = true; localeChanged = true;
} }
if (message->FindString("shortTimeFormat", &messageContent) == B_OK) { if (message->FindString("shortTimeFormat", &messageContent) == B_OK) {
fMessage.RemoveName("shortTimeFormat"); fMessage.RemoveName("shortTimeFormat");
fMessage.AddString("shortTimeFormat", messageContent); fMessage.AddString("shortTimeFormat", messageContent);
locale.SetTimeFormat(messageContent, false); locale.SetTimeFormat(messageContent, false);
countryChanged = true; localeChanged = true;
} }
if (message->FindString("longTimeFormat", &messageContent) == B_OK) { if (message->FindString("longTimeFormat", &messageContent) == B_OK) {
fMessage.RemoveName("longTimeFormat"); fMessage.RemoveName("longTimeFormat");
fMessage.AddString("longTimeFormat", messageContent); fMessage.AddString("longTimeFormat", messageContent);
locale.SetTimeFormat(messageContent, true); locale.SetTimeFormat(messageContent, true);
countryChanged = true; localeChanged = true;
} }
if (countryChanged) if (localeChanged)
gMutableLocaleRoster->SetDefaultLocale(locale); gMutableLocaleRoster->SetDefaultLocale(locale);
} }
+38 -35
View File
@@ -29,6 +29,9 @@
#include "LanguageListView.h" #include "LanguageListView.h"
#include <stdio.h>
#undef B_TRANSLATE_CONTEXT #undef B_TRANSLATE_CONTEXT
#define B_TRANSLATE_CONTEXT "Locale Preflet Window" #define B_TRANSLATE_CONTEXT "Locale Preflet Window"
@@ -94,6 +97,9 @@ LocaleWindow::LocaleWindow()
fLanguageListView->SetInvocationMessage(new BMessage(kMsgLanguageInvoked)); fLanguageListView->SetInvocationMessage(new BMessage(kMsgLanguageInvoked));
fLanguageListView->SetDragMessage(new BMessage(kMsgLanguageDragged)); fLanguageListView->SetDragMessage(new BMessage(kMsgLanguageDragged));
BFont font;
fLanguageListView->GetFont(&font);
// Fill the language list from the LocaleRoster data // Fill the language list from the LocaleRoster data
BMessage installedLanguages; BMessage installedLanguages;
if (be_locale_roster->GetInstalledLanguages(&installedLanguages) == B_OK) { if (be_locale_roster->GetInstalledLanguages(&installedLanguages) == B_OK) {
@@ -102,40 +108,37 @@ LocaleWindow::LocaleWindow()
for (int i = 0; installedLanguages.FindString("langs", i, &currentID) for (int i = 0; installedLanguages.FindString("langs", i, &currentID)
== B_OK; i++) { == B_OK; i++) {
// Now get an human-readable, localized name for each language // Now get the human-readable, native name for each language
BLanguage* currentLanguage;
be_locale_roster->GetLanguage(currentID.String(),
&currentLanguage);
BString name; BString name;
currentLanguage->GetName(name); BLanguage currentLanguage(currentID.String());
currentLanguage.GetNativeName(name);
// TODO: as long as the app_server doesn't support font overlays, // TODO: the following block fails to detect a couple of language
// use the translated name if problematic characters are used... // names as containing glyphs we can't render. Why's that?
const char* string = name.String(); bool hasGlyphs[name.CountChars()];
while (uint32 code = BUnicodeChar::FromUTF8(&string)) { font.GetHasGlyphs(name.String(), name.CountChars(), hasGlyphs);
if (code > 1424) { for (int32 i = 0; i < name.CountChars(); ++i) {
currentLanguage->GetTranslatedName(name); if (!hasGlyphs[i]) {
// replace by name translated to current language
currentLanguage.GetName(name);
break; break;
} }
} }
LanguageListItem* item = new LanguageListItem(name, LanguageListItem* item = new LanguageListItem(name,
currentID.String(), currentLanguage->Code()); currentID.String(), currentLanguage.Code());
if (currentLanguage->IsCountrySpecific() if (currentLanguage.IsCountrySpecific()
&& lastAddedCountryItem != NULL && lastAddedCountryItem != NULL
&& lastAddedCountryItem->Code() == item->Code()) { && lastAddedCountryItem->Code() == item->Code()) {
fLanguageListView->AddUnder(item, lastAddedCountryItem); fLanguageListView->AddUnder(item, lastAddedCountryItem);
} else { } else {
// This is a language variant, add it at top-level // This is a language variant, add it at top-level
fLanguageListView->AddItem(item); fLanguageListView->AddItem(item);
if (!currentLanguage->IsCountrySpecific()) { if (!currentLanguage.IsCountrySpecific()) {
item->SetExpanded(false); item->SetExpanded(false);
lastAddedCountryItem = item; lastAddedCountryItem = item;
} }
} }
delete currentLanguage;
} }
fLanguageListView->FullListSortItems(compare_typed_list_items); fLanguageListView->FullListSortItems(compare_typed_list_items);
@@ -172,32 +175,31 @@ LocaleWindow::LocaleWindow()
.End() .End()
.SetInsets(spacing, spacing, spacing, spacing); .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)); 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, scrollView = new BScrollView("scroller", listView,
B_WILL_DRAW | B_FRAME_EVENTS, false, true); B_WILL_DRAW | B_FRAME_EVENTS, false, true);
listView->SetSelectionMessage(new BMessage(kMsgCountrySelection)); listView->SetSelectionMessage(new BMessage(kMsgCountrySelection));
// get all available countries // get all available formatting conventions (by language)
BMessage countryList; BString formattingConventionCode;
be_locale_roster->GetInstalledLanguages(&countryList);
BString countryCode;
LanguageListItem* currentItem = NULL; LanguageListItem* currentItem = NULL;
for (int i = 0; countryList.FindString("langs", i, &countryCode) == B_OK; BCountry defaultFormattingConvention;
i++) { be_locale->GetCountry(&defaultFormattingConvention);
BLocale locale(countryCode); for (int i = 0;
BString countryName; installedLanguages.FindString("langs", i, &formattingConventionCode)
== B_OK; i++) {
BCountry formattingConvention(formattingConventionCode);
BString formattingConventionName;
formattingConvention.GetName(formattingConventionName);
locale.GetName(countryName); LanguageListItem* item = new LanguageListItem(formattingConventionName,
formattingConventionCode, NULL);
LanguageListItem* item
= new LanguageListItem(countryName, countryCode,
NULL);
listView->AddItem(item); listView->AddItem(item);
if (!strcmp(countryCode, be_locale->Code())) if (!strcmp(formattingConventionCode,
defaultFormattingConvention.Code()))
currentItem = item; currentItem = item;
} }
@@ -358,7 +360,8 @@ LocaleWindow::MessageReceived(BMessage* message)
be_app_messenger.SendMessage(&newMessage); be_app_messenger.SendMessage(&newMessage);
SettingsChanged(); SettingsChanged();
BLocale locale(item->ID()); BCountry country(item->ID());
BLocale locale(NULL, &country);
fFormatView->SetLocale(locale); fFormatView->SetLocale(locale);
break; break;
} }