[haiku-commits] haiku: hrev44898 - src/kits/locale headers/private/locale

  • From: zooey@xxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Mon, 26 Nov 2012 01:20:13 +0100 (CET)

hrev44898 adds 2 changesets to branch 'master'
old head: 2510baa4685f8f570c607ceedfd73473d69342c4
new head: 52cdfde04b346aa33eaebd4063321b80683973aa
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=52cdfde+%5E2510baa

----------------------------------------------------------------------------

a22e8c6: Cleanup: respect 80 chars/line limit.

52cdfde: Fix relying on order of static object destruction in Locale Kit.
  
  * use only a single static object (MutableLocaleRoster) instead of
    two, which avoids any problems if the order of static object
    destruction would destroy RosterData before MutableLocaleRoster
  * rename BPrivate::RosterData to BPrivate::LocaleRosterData and move
    it into a header and implementation file of its own
  This should hopefully fix problems encountered with a clang-compiled
  Locale Kit.

                                    [ Oliver Tappe <zooey@xxxxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

8 files changed, 900 insertions(+), 846 deletions(-)
headers/os/locale/LocaleRoster.h             |  16 +-
headers/private/locale/LocaleRosterData.h    | 142 +++++
headers/private/locale/MutableLocaleRoster.h | 107 ----
src/kits/locale/Jamfile                      |   1 +
src/kits/locale/Locale.cpp                   |   3 +-
src/kits/locale/LocaleRoster.cpp             |  87 ++-
src/kits/locale/LocaleRosterData.cpp         | 682 ++++++++++++++++++++++
src/kits/locale/MutableLocaleRoster.cpp      | 708 +----------------------

############################################################################

Commit:      a22e8c6fe28437bc4b4036d1388282e1f5a756e4
URL:         http://cgit.haiku-os.org/haiku/commit/?id=a22e8c6
Author:      Oliver Tappe <zooey@xxxxxxxxxxxxxxx>
Date:        Sat Nov 24 14:03:01 2012 UTC

Cleanup: respect 80 chars/line limit.

----------------------------------------------------------------------------

diff --git a/src/kits/locale/MutableLocaleRoster.cpp 
b/src/kits/locale/MutableLocaleRoster.cpp
index 2b4d606..6689dd2 100644
--- a/src/kits/locale/MutableLocaleRoster.cpp
+++ b/src/kits/locale/MutableLocaleRoster.cpp
@@ -724,7 +724,8 @@ MutableLocaleRoster::Default()
 
 
 status_t
-MutableLocaleRoster::SetDefaultFormattingConventions(const 
BFormattingConventions& newFormattingConventions)
+MutableLocaleRoster::SetDefaultFormattingConventions(
+       const BFormattingConventions& newFormattingConventions)
 {
        return RosterData::Default()->SetDefaultFormattingConventions(
                newFormattingConventions);

############################################################################

Revision:    hrev44898
Commit:      52cdfde04b346aa33eaebd4063321b80683973aa
URL:         http://cgit.haiku-os.org/haiku/commit/?id=52cdfde
Author:      Oliver Tappe <zooey@xxxxxxxxxxxxxxx>
Date:        Mon Nov 26 00:18:57 2012 UTC

Fix relying on order of static object destruction in Locale Kit.

* use only a single static object (MutableLocaleRoster) instead of
  two, which avoids any problems if the order of static object
  destruction would destroy RosterData before MutableLocaleRoster
* rename BPrivate::RosterData to BPrivate::LocaleRosterData and move
  it into a header and implementation file of its own
This should hopefully fix problems encountered with a clang-compiled
Locale Kit.

----------------------------------------------------------------------------

diff --git a/headers/os/locale/LocaleRoster.h b/headers/os/locale/LocaleRoster.h
index 8e77e59..fab2469 100644
--- a/headers/os/locale/LocaleRoster.h
+++ b/headers/os/locale/LocaleRoster.h
@@ -21,14 +21,19 @@ class BMessage;
 class BTimeZone;
 
 
+namespace BPrivate {
+       class LocaleRosterData;
+}
+
+
 enum {
        B_LOCALE_CHANGED = '_LCC',
 };
 
 
 class BLocaleRoster {
+
 public:
-                                                               BLocaleRoster();
                                                                
~BLocaleRoster();
 
        static  BLocaleRoster*          Default();
@@ -70,6 +75,8 @@ public:
                                                                        // Get 
the catalog for the calling image
                                                                        // 
(that needs to link with liblocalestub.a)
 
+                       const BLocale*          GetDefaultLocale() const;
+
                        bool                            
IsFilesystemTranslationPreferred() const;
 
                        status_t                        
GetLocalizedFileName(BString& localizedFileName,
@@ -83,6 +90,12 @@ public:
        static  const char*                     kEmbeddedCatAttr;
        static  int32                           kEmbeddedCatResId;
 
+protected:
+                                                               BLocaleRoster();
+
+protected:
+                       BPrivate::LocaleRosterData*     fData;
+
 private:
        static  BCatalog*                       _GetCatalog(BCatalog* catalog,
                                                                        vint32* 
catalogInitStatus);
@@ -90,6 +103,7 @@ private:
                        status_t                        
_PrepareCatalogEntry(const entry_ref& ref,
                                                                        
BString& signature, BString& context,
                                                                        
BString& string, bool traverse);
+
 };
 
 
diff --git a/headers/private/locale/LocaleRosterData.h 
b/headers/private/locale/LocaleRosterData.h
new file mode 100644
index 0000000..6e84bde
--- /dev/null
+++ b/headers/private/locale/LocaleRosterData.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2010-2012, Haiku. All rights reserved.
+ * Distributed under the terms of the MIT license.
+ */
+#ifndef _LOCALE_ROSTER_DATA_H_
+#define _LOCALE_ROSTER_DATA_H_
+
+
+#include <Collator.h>
+#include <FormattingConventions.h>
+#include <image.h>
+#include <Language.h>
+#include <List.h>
+#include <Locale.h>
+#include <Locker.h>
+#include <Message.h>
+#include <Resources.h>
+#include <TimeZone.h>
+
+
+class BCatalogData;
+class BLocale;
+
+struct entry_ref;
+
+
+namespace BPrivate {
+
+
+/*
+ * Struct containing the actual locale data.
+ */
+struct LocaleRosterData {
+                       BLocker                         fLock;
+                       BList                           fCatalogAddOnInfos;
+                       BMessage                        fPreferredLanguages;
+
+                       BLocale                         fDefaultLocale;
+                       BTimeZone                       fDefaultTimeZone;
+
+                       bool                            
fIsFilesystemTranslationPreferred;
+
+                                                               
LocaleRosterData(const BLanguage& language,
+                                                                       const 
BFormattingConventions& conventions);
+                                                               
~LocaleRosterData();
+
+                       status_t                        InitCheck() const;
+
+                       status_t                        Refresh();
+
+       static  int                                     CompareInfos(const 
void* left,
+                                                                       const 
void* right);
+
+                       status_t                        
GetResources(BResources** resources);
+
+                       status_t                        
SetDefaultFormattingConventions(
+                                                                       const 
BFormattingConventions& convetions);
+                       status_t                        
SetDefaultTimeZone(const BTimeZone& zone);
+                       status_t                        
SetPreferredLanguages(const BMessage* msg);
+                       status_t                        
SetFilesystemTranslationPreferred(
+                                                                       bool 
preferred);
+private:
+                       status_t                        _Initialize();
+
+                       status_t                        
_InitializeCatalogAddOns();
+                       void                            _CleanupCatalogAddOns();
+
+                       status_t                        _LoadLocaleSettings();
+                       status_t                        _SaveLocaleSettings();
+
+                       status_t                        _LoadTimeSettings();
+                       status_t                        _SaveTimeSettings();
+
+                       status_t                        
_SetDefaultFormattingConventions(
+                                                                       const 
BFormattingConventions& conventions);
+                       status_t                        
_SetDefaultTimeZone(const BTimeZone& zone);
+                       status_t                        
_SetPreferredLanguages(const BMessage* msg);
+                       void                            
_SetFilesystemTranslationPreferred(
+                                                                       bool 
preferred);
+
+                       status_t                        
_AddDefaultFormattingConventionsToMessage(
+                                                                       
BMessage* message) const;
+                       status_t                        
_AddDefaultTimeZoneToMessage(
+                                                                       
BMessage* message) const;
+                       status_t                        
_AddPreferredLanguagesToMessage(
+                                                                       
BMessage* message) const;
+                       status_t                        
_AddFilesystemTranslationPreferenceToMessage(
+                                                                       
BMessage* message) const;
+
+private:
+                       status_t                        fInitStatus;
+
+                       bool                            fAreResourcesLoaded;
+                       BResources                      fResources;
+};
+
+
+typedef BCatalogData* (*InstantiateCatalogFunc)(const entry_ref& catalogOwner,
+       const char* language, uint32 fingerprint);
+
+typedef BCatalogData* (*CreateCatalogFunc)(const char* name,
+       const char* language);
+
+typedef BCatalogData* (*InstantiateEmbeddedCatalogFunc)(
+       entry_ref* appOrAddOnRef);
+
+typedef status_t (*GetAvailableLanguagesFunc)(BMessage*, const char*,
+       const char*, int32);
+
+
+/*
+ * info about a single catalog-add-on (representing a catalog type):
+ */
+struct CatalogAddOnInfo {
+                       InstantiateCatalogFunc          fInstantiateFunc;
+                       CreateCatalogFunc                       fCreateFunc;
+                       GetAvailableLanguagesFunc       fLanguagesFunc;
+
+                       BString                         fName;
+                       BString                         fPath;
+                       image_id                        fAddOnImage;
+                       uint8                           fPriority;
+                       BList                           fLoadedCatalogs;
+                       bool                            fIsEmbedded;
+                                                                       // an 
embedded add-on actually isn't an
+                                                                       // 
add-on, it is included as part of the
+                                                                       // 
library.
+                                                                       // The 
DefaultCatalog is such a beast!
+
+                                                               
CatalogAddOnInfo(const BString& name,
+                                                                       const 
BString& path, uint8 priority);
+                                                               
~CatalogAddOnInfo();
+
+                       bool                            MakeSureItsLoaded();
+                       void                            UnloadIfPossible();
+};
+
+
+}      // namespace BPrivate
+
+
+#endif // _LOCALE_ROSTER_DATA_H_
diff --git a/headers/private/locale/MutableLocaleRoster.h 
b/headers/private/locale/MutableLocaleRoster.h
index 4eb072b..c4cd209 100644
--- a/headers/private/locale/MutableLocaleRoster.h
+++ b/headers/private/locale/MutableLocaleRoster.h
@@ -60,113 +60,6 @@ public:
 };
 
 
-typedef BCatalogData* (*InstantiateCatalogFunc)(const entry_ref& catalogOwner,
-       const char* language, uint32 fingerprint);
-
-typedef BCatalogData* (*CreateCatalogFunc)(const char* name,
-       const char* language);
-
-typedef BCatalogData* (*InstantiateEmbeddedCatalogFunc)(
-       entry_ref* appOrAddOnRef);
-
-typedef status_t (*GetAvailableLanguagesFunc)(BMessage*, const char*,
-       const char*, int32);
-
-/*
- * info about a single catalog-add-on (representing a catalog type):
- */
-struct CatalogAddOnInfo {
-                       InstantiateCatalogFunc                  
fInstantiateFunc;
-                       CreateCatalogFunc                               
fCreateFunc;
-                       GetAvailableLanguagesFunc               fLanguagesFunc;
-
-                       BString                         fName;
-                       BString                         fPath;
-                       image_id                        fAddOnImage;
-                       uint8                           fPriority;
-                       BList                           fLoadedCatalogs;
-                       bool                            fIsEmbedded;
-                                                                       // an 
embedded add-on actually isn't an
-                                                                       // 
add-on, it is included as part of the
-                                                                       // 
library.
-                                                                       // The 
DefaultCatalog is such a beast!
-
-                                                               
CatalogAddOnInfo(const BString& name,
-                                                                       const 
BString& path, uint8 priority);
-                                                               
~CatalogAddOnInfo();
-
-                       bool                            MakeSureItsLoaded();
-                       void                            UnloadIfPossible();
-};
-
-
-/*
- * The global data that is shared between all roster-objects of a process.
- */
-struct RosterData {
-                       BLocker                         fLock;
-                       BList                           fCatalogAddOnInfos;
-                       BMessage                        fPreferredLanguages;
-
-                       BLocale                         fDefaultLocale;
-                       BTimeZone                       fDefaultTimeZone;
-
-                       bool                            
fIsFilesystemTranslationPreferred;
-
-                       bool                            fAreResourcesLoaded;
-                       BResources                      fResources;
-
-                       status_t                        fInitStatus;
-
-                                                               
RosterData(const BLanguage& language,
-                                                                       const 
BFormattingConventions& conventions);
-                                                               ~RosterData();
-
-       static  RosterData*                     Default();
-
-                       status_t                        InitCheck() const;
-
-                       status_t                        Refresh();
-
-       static  int                                     CompareInfos(const 
void* left,
-                                                                       const 
void* right);
-
-                       status_t                        
SetDefaultFormattingConventions(
-                                                                       const 
BFormattingConventions& convetions);
-                       status_t                        
SetDefaultTimeZone(const BTimeZone& zone);
-                       status_t                        
SetPreferredLanguages(const BMessage* msg);
-                       status_t                        
SetFilesystemTranslationPreferred(
-                                                                       bool 
preferred);
-private:
-                       status_t                        _Initialize();
-
-                       status_t                        
_InitializeCatalogAddOns();
-                       void                            _CleanupCatalogAddOns();
-
-                       status_t                        _LoadLocaleSettings();
-                       status_t                        _SaveLocaleSettings();
-
-                       status_t                        _LoadTimeSettings();
-                       status_t                        _SaveTimeSettings();
-
-                       status_t                        
_SetDefaultFormattingConventions(
-                                                                       const 
BFormattingConventions& conventions);
-                       status_t                        
_SetDefaultTimeZone(const BTimeZone& zone);
-                       status_t                        
_SetPreferredLanguages(const BMessage* msg);
-                       void                            
_SetFilesystemTranslationPreferred(
-                                                                       bool 
preferred);
-
-                       status_t                        
_AddDefaultFormattingConventionsToMessage(
-                                                                       
BMessage* message) const;
-                       status_t                        
_AddDefaultTimeZoneToMessage(
-                                                                       
BMessage* message) const;
-                       status_t                        
_AddPreferredLanguagesToMessage(
-                                                                       
BMessage* message) const;
-                       status_t                        
_AddFilesystemTranslationPreferenceToMessage(
-                                                                       
BMessage* message) const;
-};
-
-
 }      // namespace BPrivate
 
 
diff --git a/src/kits/locale/Jamfile b/src/kits/locale/Jamfile
index 007f6e9..61ad69f 100644
--- a/src/kits/locale/Jamfile
+++ b/src/kits/locale/Jamfile
@@ -19,6 +19,7 @@ local sources =
        Language.cpp
        Locale.cpp
        LocaleRoster.cpp
+       LocaleRosterData.cpp
        MutableLocaleRoster.cpp
        TimeZone.cpp
 
diff --git a/src/kits/locale/Locale.cpp b/src/kits/locale/Locale.cpp
index b25a416..ed2b95e 100644
--- a/src/kits/locale/Locale.cpp
+++ b/src/kits/locale/Locale.cpp
@@ -14,7 +14,6 @@
 #include <LanguagePrivate.h>
 #include <Locale.h>
 #include <LocaleRoster.h>
-#include <MutableLocaleRoster.h>
 #include <TimeZone.h>
 
 #include <ICUWrapper.h>
@@ -59,7 +58,7 @@ BLocale::BLocale(const BLocale& other)
 /*static*/ const BLocale*
 BLocale::Default()
 {
-       return &BPrivate::RosterData::Default()->fDefaultLocale;
+       return BLocaleRoster::Default()->GetDefaultLocale();
 }
 
 
diff --git a/src/kits/locale/LocaleRoster.cpp b/src/kits/locale/LocaleRoster.cpp
index c4238b9..22d2961 100644
--- a/src/kits/locale/LocaleRoster.cpp
+++ b/src/kits/locale/LocaleRoster.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2010, Haiku. All rights reserved.
+ * Copyright 2003-2012, Haiku. All rights reserved.
  * Distributed under the terms of the MIT License.
  *
  * Authors:
@@ -10,27 +10,23 @@
 
 #include <LocaleRoster.h>
 
+#include <assert.h>
 #include <ctype.h>
-#include <set>
 
-#include <assert.h>
+#include <new>
 
 #include <Autolock.h>
 #include <Bitmap.h>
 #include <Catalog.h>
-#include <Collator.h>
-#include <DefaultCatalog.h>
-#include <Directory.h>
 #include <Entry.h>
-#include <File.h>
 #include <FormattingConventions.h>
 #include <fs_attr.h>
 #include <IconUtils.h>
 #include <Language.h>
 #include <Locale.h>
+#include <LocaleRosterData.h>
 #include <MutableLocaleRoster.h>
 #include <Node.h>
-#include <Path.h>
 #include <Roster.h>
 #include <String.h>
 #include <TimeZone.h>
@@ -45,7 +41,6 @@
 
 using BPrivate::CatalogAddOnInfo;
 using BPrivate::MutableLocaleRoster;
-using BPrivate::RosterData;
 
 
 /*
@@ -67,26 +62,6 @@ int32 BLocaleRoster::kEmbeddedCatResId = 0xCADA;
        // this may live in an app- or add-on-file
 
 
-static status_t
-load_resources_if_needed(RosterData* rosterData)
-{
-       if (rosterData->fAreResourcesLoaded)
-               return B_OK;
-
-       status_t result = rosterData->fResources.SetToImage(
-               (const void*)&BLocaleRoster::Default);
-       if (result != B_OK)
-               return result;
-
-       result = rosterData->fResources.PreloadResourceType();
-       if (result != B_OK)
-               return result;
-
-       rosterData->fAreResourcesLoaded = true;
-       return B_OK;
-}
-
-
 static const char*
 country_code_for_language(const BLanguage& language)
 {
@@ -149,12 +124,16 @@ country_code_for_language(const BLanguage& language)
 
 
 BLocaleRoster::BLocaleRoster()
+       :
+       fData(new(std::nothrow) BPrivate::LocaleRosterData(BLanguage("en_US"),
+               BFormattingConventions("en_US")))
 {
 }
 
 
 BLocaleRoster::~BLocaleRoster()
 {
+       delete fData;
 }
 
 
@@ -168,7 +147,7 @@ BLocaleRoster::Default()
 status_t
 BLocaleRoster::Refresh()
 {
-       return RosterData::Default()->Refresh();
+       return fData->Refresh();
 }
 
 
@@ -178,17 +157,22 @@ BLocaleRoster::GetDefaultTimeZone(BTimeZone* timezone) 
const
        if (!timezone)
                return B_BAD_VALUE;
 
-       RosterData* rosterData = RosterData::Default();
-       BAutolock lock(rosterData->fLock);
+       BAutolock lock(fData->fLock);
        if (!lock.IsLocked())
                return B_ERROR;
 
-       *timezone = rosterData->fDefaultTimeZone;
+       *timezone = fData->fDefaultTimeZone;
 
        return B_OK;
 }
 
 
+const BLocale*
+BLocaleRoster::GetDefaultLocale() const
+{
+       return &fData->fDefaultLocale;
+}
+
 status_t
 BLocaleRoster::GetLanguage(const char* languageCode,
        BLanguage** _language) const
@@ -211,12 +195,11 @@ BLocaleRoster::GetPreferredLanguages(BMessage* languages) 
const
        if (!languages)
                return B_BAD_VALUE;
 
-       RosterData* rosterData = RosterData::Default();
-       BAutolock lock(rosterData->fLock);
+       BAutolock lock(fData->fLock);
        if (!lock.IsLocked())
                return B_ERROR;
 
-       *languages = rosterData->fPreferredLanguages;
+       *languages = fData->fPreferredLanguages;
 
        return B_OK;
 }
@@ -367,12 +350,12 @@ BLocaleRoster::GetFlagIconForCountry(BBitmap* flagIcon, 
const char* countryCode)
        if (countryCode == NULL)
                return B_BAD_VALUE;
 
-       RosterData* rosterData = RosterData::Default();
-       BAutolock lock(rosterData->fLock);
+       BAutolock lock(fData->fLock);
        if (!lock.IsLocked())
                return B_ERROR;
 
-       status_t status = load_resources_if_needed(rosterData);
+       BResources* resources;
+       status_t status = fData->GetResources(&resources);
        if (status != B_OK)
                return status;
 
@@ -389,8 +372,8 @@ BLocaleRoster::GetFlagIconForCountry(BBitmap* flagIcon, 
const char* countryCode)
        normalizedCode[2] = '\0';
 
        size_t size;
-       const void* buffer = rosterData->fResources.LoadResource(
-               B_VECTOR_ICON_TYPE, normalizedCode, &size);
+       const void* buffer = resources->LoadResource(B_VECTOR_ICON_TYPE,
+               normalizedCode, &size);
        if (buffer == NULL || size == 0)
                return B_NAME_NOT_FOUND;
 
@@ -407,12 +390,12 @@ BLocaleRoster::GetFlagIconForLanguage(BBitmap* flagIcon,
                || languageCode[1] == '\0')
                return B_BAD_VALUE;
 
-       RosterData* rosterData = RosterData::Default();
-       BAutolock lock(rosterData->fLock);
+       BAutolock lock(fData->fLock);
        if (!lock.IsLocked())
                return B_ERROR;
 
-       status_t status = load_resources_if_needed(rosterData);
+       BResources* resources;
+       status_t status = fData->GetResources(&resources);
        if (status != B_OK)
                return status;
 
@@ -424,8 +407,8 @@ BLocaleRoster::GetFlagIconForLanguage(BBitmap* flagIcon,
        normalizedCode[2] = '\0';
 
        size_t size;
-       const void* buffer = rosterData->fResources.LoadResource(
-               B_VECTOR_ICON_TYPE, normalizedCode, &size);
+       const void* buffer = resources->LoadResource(B_VECTOR_ICON_TYPE,
+               normalizedCode, &size);
        if (buffer != NULL && size != 0) {
                return BIconUtils::GetVectorIcon(static_cast<const 
uint8*>(buffer),
                        size, flagIcon);
@@ -450,15 +433,14 @@ BLocaleRoster::GetAvailableCatalogs(BMessage*  
languageList,
        if (languageList == NULL)
                return B_BAD_VALUE;
 
-       RosterData* rosterData = RosterData::Default();
-       BAutolock lock(rosterData->fLock);
+       BAutolock lock(fData->fLock);
        if (!lock.IsLocked())
                return B_ERROR;
 
-       int32 count = rosterData->fCatalogAddOnInfos.CountItems();
+       int32 count = fData->fCatalogAddOnInfos.CountItems();
        for (int32 i = 0; i < count; ++i) {
                CatalogAddOnInfo* info
-                       = 
(CatalogAddOnInfo*)rosterData->fCatalogAddOnInfos.ItemAt(i);
+                       = 
(CatalogAddOnInfo*)fData->fCatalogAddOnInfos.ItemAt(i);
 
                if (!info->MakeSureItsLoaded() || !info->fLanguagesFunc)
                        continue;
@@ -474,12 +456,11 @@ BLocaleRoster::GetAvailableCatalogs(BMessage*  
languageList,
 bool
 BLocaleRoster::IsFilesystemTranslationPreferred() const
 {
-       RosterData* rosterData = RosterData::Default();
-       BAutolock lock(rosterData->fLock);
+       BAutolock lock(fData->fLock);
        if (!lock.IsLocked())
                return B_ERROR;
 
-       return rosterData->fIsFilesystemTranslationPreferred;
+       return fData->fIsFilesystemTranslationPreferred;
 }
 
 
diff --git a/src/kits/locale/LocaleRosterData.cpp 
b/src/kits/locale/LocaleRosterData.cpp
new file mode 100644
index 0000000..d87b01b
--- /dev/null
+++ b/src/kits/locale/LocaleRosterData.cpp
@@ -0,0 +1,682 @@
+/*
+ * Copyright 2003-2012, Haiku. All rights reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Axel DÃrfler, axeld@xxxxxxxxxxxxxxxx
+ *             Oliver Tappe, zooey@xxxxxxxxxxxxxxx
+ */
+
+
+#include <LocaleRosterData.h>
+
+#include <Autolock.h>
+#include <Catalog.h>
+#include <Collator.h>
+#include <Debug.h>
+#include <DefaultCatalog.h>
+#include <Directory.h>
+#include <Entry.h>
+#include <File.h>
+#include <FindDirectory.h>
+#include <FormattingConventions.h>
+#include <Language.h>
+#include <Locale.h>
+#include <Node.h>
+#include <Path.h>
+#include <Roster.h>
+#include <String.h>
+#include <TimeZone.h>
+
+// ICU includes
+#include <unicode/locid.h>
+#include <unicode/timezone.h>
+
+
+namespace BPrivate {
+
+
+// #pragma mark - CatalogAddOnInfo
+
+
+CatalogAddOnInfo::CatalogAddOnInfo(const BString& name, const BString& path,
+       uint8 priority)
+       :
+       fInstantiateFunc(NULL),
+       fCreateFunc(NULL),
+       fLanguagesFunc(NULL),
+       fName(name),
+       fPath(path),
+       fAddOnImage(B_NO_INIT),
+       fPriority(priority),
+       fIsEmbedded(path.Length()==0)
+{
+}
+
+
+CatalogAddOnInfo::~CatalogAddOnInfo()
+{
+       int32 count = fLoadedCatalogs.CountItems();
+       for (int32 i = 0; i < count; ++i) {
+               BCatalogData* cat
+                       = static_cast<BCatalogData*>(fLoadedCatalogs.ItemAt(i));
+               delete cat;
+       }
+       fLoadedCatalogs.MakeEmpty();
+       UnloadIfPossible();
+}
+
+
+bool
+CatalogAddOnInfo::MakeSureItsLoaded()
+{
+       if (!fIsEmbedded && fAddOnImage < B_OK) {
+               // add-on has not been loaded yet, so we try to load it:
+               BString fullAddOnPath(fPath);
+               fullAddOnPath << "/" << fName;
+               fAddOnImage = load_add_on(fullAddOnPath.String());
+               if (fAddOnImage >= B_OK) {
+                       get_image_symbol(fAddOnImage, "instantiate_catalog",
+                               B_SYMBOL_TYPE_TEXT, (void**)&fInstantiateFunc);
+                       get_image_symbol(fAddOnImage, "create_catalog",
+                               B_SYMBOL_TYPE_TEXT, (void**)&fCreateFunc);
+                       get_image_symbol(fAddOnImage, "get_available_languages",
+                               B_SYMBOL_TYPE_TEXT, (void**)&fLanguagesFunc);
+               } else
+                       return false;
+       } else if (fIsEmbedded) {
+               // The built-in catalog still has to provide this function
+               fLanguagesFunc = default_catalog_get_available_languages;
+       }
+       return true;
+}
+
+
+void
+CatalogAddOnInfo::UnloadIfPossible()
+{
+       if (!fIsEmbedded && fLoadedCatalogs.IsEmpty()) {
+               unload_add_on(fAddOnImage);
+               fAddOnImage = B_NO_INIT;
+               fInstantiateFunc = NULL;
+               fCreateFunc = NULL;
+               fLanguagesFunc = NULL;
+       }
+}
+
+
+// #pragma mark - LocaleRosterData
+
+
+namespace {
+
+
+static const char* kPriorityAttr = "ADDON:priority";
+
+static const char* kLanguageField = "language";
+static const char* kTimezoneField = "timezone";
+static const char* kTranslateFilesystemField = "filesys";
+
+
+}      // anonymous namespace
+
+
+LocaleRosterData::LocaleRosterData(const BLanguage& language,
+       const BFormattingConventions& conventions)
+       :
+       fLock("LocaleRosterData"),
+       fDefaultLocale(&language, &conventions),
+       fIsFilesystemTranslationPreferred(false),
+       fAreResourcesLoaded(false)
+{
+       fInitStatus = _Initialize();
+}
+
+
+LocaleRosterData::~LocaleRosterData()
+{
+       BAutolock lock(fLock);
+
+       _CleanupCatalogAddOns();
+}
+
+
+status_t
+LocaleRosterData::InitCheck() const
+{
+       return fAreResourcesLoaded ? B_OK : B_NO_INIT;
+}
+
+
+status_t
+LocaleRosterData::Refresh()
+{
+       BAutolock lock(fLock);
+       if (!lock.IsLocked())
+               return B_ERROR;
+
+       _LoadLocaleSettings();
+       _LoadTimeSettings();
+
+       return B_OK;
+}
+
+
+int
+LocaleRosterData::CompareInfos(const void* left, const void* right)
+{
+       return ((CatalogAddOnInfo*)right)->fPriority
+               - ((CatalogAddOnInfo*)left)->fPriority;
+}
+
+
+status_t
+LocaleRosterData::SetDefaultFormattingConventions(
+       const BFormattingConventions& newFormattingConventions)
+{
+       status_t status = B_OK;
+
+       BAutolock lock(fLock);
+       if (!lock.IsLocked())
+               return B_ERROR;
+
+       status = _SetDefaultFormattingConventions(newFormattingConventions);
+
+       if (status == B_OK)
+               status = _SaveLocaleSettings();
+
+       if (status == B_OK) {
+               BMessage updateMessage(B_LOCALE_CHANGED);
+               status = 
_AddDefaultFormattingConventionsToMessage(&updateMessage);
+               if (status == B_OK)
+                       status = be_roster->Broadcast(&updateMessage);
+       }
+
+       return status;
+}
+
+
+status_t
+LocaleRosterData::SetDefaultTimeZone(const BTimeZone& newZone)
+{
+       status_t status = B_OK;
+
+       BAutolock lock(fLock);
+       if (!lock.IsLocked())
+               return B_ERROR;
+
+       status = _SetDefaultTimeZone(newZone);
+
+       if (status == B_OK)
+               status = _SaveTimeSettings();
+
+       if (status == B_OK) {
+               BMessage updateMessage(B_LOCALE_CHANGED);
+               status = _AddDefaultTimeZoneToMessage(&updateMessage);
+               if (status == B_OK)
+                       status = be_roster->Broadcast(&updateMessage);
+       }
+
+       return status;
+}
+
+
+status_t
+LocaleRosterData::SetPreferredLanguages(const BMessage* languages)
+{
+       status_t status = B_OK;
+
+       BAutolock lock(fLock);
+       if (!lock.IsLocked())
+               return B_ERROR;
+
+       status = _SetPreferredLanguages(languages);
+
+       if (status == B_OK)
+               status = _SaveLocaleSettings();
+
+       if (status == B_OK) {
+               BMessage updateMessage(B_LOCALE_CHANGED);
+               status = _AddPreferredLanguagesToMessage(&updateMessage);
+               if (status == B_OK)
+                       status = be_roster->Broadcast(&updateMessage);
+       }
+
+       return status;
+}
+
+
+status_t
+LocaleRosterData::SetFilesystemTranslationPreferred(bool preferred)
+{
+       BAutolock lock(fLock);
+       if (!lock.IsLocked())
+               return B_ERROR;
+
+       _SetFilesystemTranslationPreferred(preferred);
+
+       status_t status = _SaveLocaleSettings();
+
+       if (status == B_OK) {
+               BMessage updateMessage(B_LOCALE_CHANGED);
+               status = 
_AddFilesystemTranslationPreferenceToMessage(&updateMessage);
+               if (status == B_OK)
+                       status = be_roster->Broadcast(&updateMessage);
+       }
+
+       return status;
+}
+
+
+status_t
+LocaleRosterData::GetResources(BResources** resources)
+{
+       if (resources == NULL)
+               return B_BAD_VALUE;
+
+       if (!fAreResourcesLoaded) {
+               status_t result
+                       = fResources.SetToImage((const 
void*)&BLocaleRoster::Default);
+               if (result != B_OK)
+                       return result;
+
+               result = fResources.PreloadResourceType();
+               if (result != B_OK)
+                       return result;
+
+               fAreResourcesLoaded = true;
+       }
+
+       *resources = &fResources;
+       return B_OK;
+}
+
+
+status_t
+LocaleRosterData::_Initialize()
+{
+       status_t result = _InitializeCatalogAddOns();
+       if (result != B_OK)
+               return result;
+
+       if ((result = Refresh()) != B_OK)
+               return result;
+
+       fInitStatus = B_OK;
+       return B_OK;
+}
+
+
+/*
+iterate over add-on-folders and collect information about each
+catalog-add-ons (types of catalogs) into fCatalogAddOnInfos.
+*/
+status_t
+LocaleRosterData::_InitializeCatalogAddOns()
+{
+       BAutolock lock(fLock);
+       if (!lock.IsLocked())
+               return B_ERROR;
+
+       // add info about embedded default catalog:
+       CatalogAddOnInfo* defaultCatalogAddOnInfo
+               = new(std::nothrow) CatalogAddOnInfo("Default", "",
+                       DefaultCatalog::kDefaultCatalogAddOnPriority);
+       if (!defaultCatalogAddOnInfo)
+               return B_NO_MEMORY;
+
+       defaultCatalogAddOnInfo->fInstantiateFunc = DefaultCatalog::Instantiate;
+       defaultCatalogAddOnInfo->fCreateFunc = DefaultCatalog::Create;
+       fCatalogAddOnInfos.AddItem((void*)defaultCatalogAddOnInfo);
+
+       directory_which folders[] = {
+               B_USER_ADDONS_DIRECTORY,
+               B_COMMON_ADDONS_DIRECTORY,
+               B_SYSTEM_ADDONS_DIRECTORY,
+       };
+       BPath addOnPath;
+       BDirectory addOnFolder;
+       char buf[4096];
+       status_t err;
+       for (uint32 f = 0; f < sizeof(folders) / sizeof(directory_which); ++f) {
+               find_directory(folders[f], &addOnPath);
+               BString addOnFolderName(addOnPath.Path());
+               addOnFolderName << "/locale/catalogs";
+
+               system_info info;
+               if (get_system_info(&info) == B_OK
+                               && (info.abi & B_HAIKU_ABI_MAJOR)
+                               != (B_HAIKU_ABI & B_HAIKU_ABI_MAJOR)) {
+                       switch (B_HAIKU_ABI & B_HAIKU_ABI_MAJOR) {
+                               case B_HAIKU_ABI_GCC_2:
+                                       addOnFolderName << "/gcc2";
+                                       break;
+                               case B_HAIKU_ABI_GCC_4:
+                                       addOnFolderName << "/gcc4";
+                                       break;
+                       }
+               }
+
+
+               err = addOnFolder.SetTo(addOnFolderName.String());
+               if (err != B_OK)
+                       continue;
+
+               // scan through all the folder's entries for catalog add-ons:
+               int32 count;
+               int8 priority;
+               entry_ref eref;
+               BNode node;
+               BEntry entry;
+               dirent* dent;
+               while ((count = addOnFolder.GetNextDirents((dirent*)buf, 4096)) 
> 0) {
+                       dent = (dirent*)buf;
+                       while (count-- > 0) {
+                               if (strcmp(dent->d_name, ".") && 
strcmp(dent->d_name, "..")
+                                               && strcmp(dent->d_name, "gcc2")
+                                               && strcmp(dent->d_name, 
"gcc4")) {
+                                       // we have found (what should be) a 
catalog-add-on:
+                                       eref.device = dent->d_pdev;
+                                       eref.directory = dent->d_pino;
+                                       eref.set_name(dent->d_name);
+                                       entry.SetTo(&eref, true);
+                                               // traverse through any links 
to get to the real thang!
+                                       node.SetTo(&entry);
+                                       priority = -1;
+                                       if (node.ReadAttr(kPriorityAttr, 
B_INT8_TYPE, 0,
+                                               &priority, sizeof(int8)) <= 0) {
+                                               // add-on has no 
priority-attribute yet, so we load it
+                                               // to fetch the priority from 
the corresponding
+                                               // symbol...
+                                               BString 
fullAddOnPath(addOnFolderName);
+                                               fullAddOnPath << "/" << 
dent->d_name;
+                                               image_id image = 
load_add_on(fullAddOnPath.String());
+                                               if (image >= B_OK) {
+                                                       uint8* prioPtr;
+                                                       if 
(get_image_symbol(image, "gCatalogAddOnPriority",
+                                                               
B_SYMBOL_TYPE_DATA,
+                                                               
(void**)&prioPtr) == B_OK) {
+                                                               priority = 
*prioPtr;
+                                                               
node.WriteAttr(kPriorityAttr, B_INT8_TYPE, 0,
+                                                                       
&priority, sizeof(int8));
+                                                       }
+                                                       unload_add_on(image);
+                                               }
+                                       }
+
+                                       if (priority >= 0) {
+                                               // add-ons with priority < 0 
will be ignored
+                                               CatalogAddOnInfo* addOnInfo
+                                                       = new(std::nothrow) 
CatalogAddOnInfo(dent->d_name,
+                                                               
addOnFolderName, priority);
+                                               if (addOnInfo)
+                                                       
fCatalogAddOnInfos.AddItem((void*)addOnInfo);
+                                       }
+                               }
+                               // Bump the dirent-pointer by length of the 
dirent just handled:
+                               dent = (dirent*)((char*)dent + dent->d_reclen);
+                       }
+               }
+       }
+       fCatalogAddOnInfos.SortItems(CompareInfos);
+
+       return B_OK;
+}
+
+
+/*
+ * unloads all catalog-add-ons (which will throw away all loaded catalogs, too)
+ */
+void
+LocaleRosterData::_CleanupCatalogAddOns()
+{
+       BAutolock lock(fLock);
+       if (!lock.IsLocked())
+               return;
+
+       int32 count = fCatalogAddOnInfos.CountItems();
+       for (int32 i = 0; i<count; ++i) {
+               CatalogAddOnInfo* info
+                       = 
static_cast<CatalogAddOnInfo*>(fCatalogAddOnInfos.ItemAt(i));
+               delete info;
+       }
+       fCatalogAddOnInfos.MakeEmpty();
+}
+
+
+status_t
+LocaleRosterData::_LoadLocaleSettings()
+{
+       BPath path;
+       BFile file;
+       status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
+       if (status == B_OK) {
+               path.Append("Locale settings");
+               status = file.SetTo(path.Path(), B_READ_ONLY);
+       }
+       BMessage settings;
+       if (status == B_OK)
+               status = settings.Unflatten(&file);
+
+       if (status == B_OK) {
+               BFormattingConventions conventions(&settings);
+               fDefaultLocale.SetFormattingConventions(conventions);
+
+               _SetPreferredLanguages(&settings);
+
+               bool preferred;
+               if (settings.FindBool(kTranslateFilesystemField, &preferred) == 
B_OK)
+                       _SetFilesystemTranslationPreferred(preferred);
+
+               return B_OK;
+       }
+
+
+       // Something went wrong (no settings file or invalid BMessage), so we
+       // set everything to default values
+
+       fPreferredLanguages.MakeEmpty();
+       fPreferredLanguages.AddString(kLanguageField, "en");
+       BLanguage defaultLanguage("en_US");
+       fDefaultLocale.SetLanguage(defaultLanguage);
+       BFormattingConventions conventions("en_US");
+       fDefaultLocale.SetFormattingConventions(conventions);
+
+       return status;
+}
+
+
+status_t
+LocaleRosterData::_LoadTimeSettings()
+{
+       BPath path;
+       BFile file;
+       status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
+       if (status == B_OK) {
+               path.Append("Time settings");
+               status = file.SetTo(path.Path(), B_READ_ONLY);
+       }
+       BMessage settings;
+       if (status == B_OK)
+               status = settings.Unflatten(&file);
+       if (status == B_OK) {
+               BString timeZoneID;
+               if (settings.FindString(kTimezoneField, &timeZoneID) == B_OK)
+                       _SetDefaultTimeZone(BTimeZone(timeZoneID.String()));
+               else
+                       
_SetDefaultTimeZone(BTimeZone(BTimeZone::kNameOfGmtZone));
+
+               return B_OK;
+       }
+
+       // Something went wrong (no settings file or invalid BMessage), so we
+       // set everything to default values
+       _SetDefaultTimeZone(BTimeZone(BTimeZone::kNameOfGmtZone));
+
+       return status;
+}
+
+
+status_t
+LocaleRosterData::_SaveLocaleSettings()
+{
+       BMessage settings;
+       status_t status = _AddDefaultFormattingConventionsToMessage(&settings);
+       if (status == B_OK)
+               _AddPreferredLanguagesToMessage(&settings);
+       if (status == B_OK)
+               _AddFilesystemTranslationPreferenceToMessage(&settings);
+
+       BPath path;
+       if (status == B_OK)
+               status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
+
+       BFile file;
+       if (status == B_OK) {
+               path.Append("Locale settings");
+               status = file.SetTo(path.Path(),
+                       B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY);
+       }
+       if (status == B_OK)
+               status = settings.Flatten(&file);
+       if (status == B_OK)
+               status = file.Sync();
+
+       return status;
+}
+
+
+status_t
+LocaleRosterData::_SaveTimeSettings()
+{
+       BMessage settings;
+       status_t status = _AddDefaultTimeZoneToMessage(&settings);
+
+       BPath path;
+       if (status == B_OK)
+               status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
+
+       BFile file;
+       if (status == B_OK) {
+               path.Append("Time settings");
+               status = file.SetTo(path.Path(),
+                       B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY);
+       }
+       if (status == B_OK)
+               status = settings.Flatten(&file);
+       if (status == B_OK)
+               status = file.Sync();
+
+       return status;
+}
+
+
+status_t
+LocaleRosterData::_SetDefaultFormattingConventions(
+       const BFormattingConventions& newFormattingConventions)
+{
+       fDefaultLocale.SetFormattingConventions(newFormattingConventions);
+
+       UErrorCode icuError = U_ZERO_ERROR;
+       Locale icuLocale = 
Locale::createCanonical(newFormattingConventions.ID());
+       if (icuLocale.isBogus())
+               return B_ERROR;
+
+       Locale::setDefault(icuLocale, icuError);
+       if (!U_SUCCESS(icuError))
+               return B_ERROR;
+
+       return B_OK;
+}
+
+
+status_t
+LocaleRosterData::_SetDefaultTimeZone(const BTimeZone& newZone)
+{
+       fDefaultTimeZone = newZone;
+
+       TimeZone* timeZone = TimeZone::createTimeZone(newZone.ID().String());
+       if (timeZone == NULL)
+               return B_ERROR;
+       TimeZone::adoptDefault(timeZone);
+
+       return B_OK;
+}
+
+
+status_t
+LocaleRosterData::_SetPreferredLanguages(const BMessage* languages)
+{
+       BString langName;
+       if (languages != NULL
+               && languages->FindString(kLanguageField, &langName) == B_OK) {
+               fDefaultLocale.SetCollator(BCollator(langName.String()));
+               fDefaultLocale.SetLanguage(BLanguage(langName.String()));
+
+               fPreferredLanguages.RemoveName(kLanguageField);
+               for (int i = 0; languages->FindString(kLanguageField, i, 
&langName)
+                               == B_OK; i++) {
+                       fPreferredLanguages.AddString(kLanguageField, langName);
+               }
+       } else {
+               fPreferredLanguages.MakeEmpty();
+               fPreferredLanguages.AddString(kLanguageField, "en");
+               fDefaultLocale.SetCollator(BCollator("en"));
+       }
+
+       return B_OK;
+}
+
+
+void
+LocaleRosterData::_SetFilesystemTranslationPreferred(bool preferred)
+{
+       fIsFilesystemTranslationPreferred = preferred;
+}
+
+
+status_t
+LocaleRosterData::_AddDefaultFormattingConventionsToMessage(
+       BMessage* message) const
+{
+       BFormattingConventions conventions;
+       fDefaultLocale.GetFormattingConventions(&conventions);
+
+       return conventions.Archive(message);
+}
+
+
+status_t
+LocaleRosterData::_AddDefaultTimeZoneToMessage(BMessage* message) const
+{
+       return message->AddString(kTimezoneField, fDefaultTimeZone.ID());
+}
+
+
+status_t
+LocaleRosterData::_AddPreferredLanguagesToMessage(BMessage* message) const
+{
+       status_t status = B_OK;
+
+       BString langName;
+       for (int i = 0; fPreferredLanguages.FindString("language", i,
+                       &langName) == B_OK; i++) {
+               status = message->AddString(kLanguageField, langName);
+               if (status != B_OK)
+                       break;
+       }
+
+       return status;
+}
+
+
+status_t
+LocaleRosterData::_AddFilesystemTranslationPreferenceToMessage(
+       BMessage* message) const
+{
+       return message->AddBool(kTranslateFilesystemField,
+               fIsFilesystemTranslationPreferred);
+}
+
+
+}      // namespace BPrivate
diff --git a/src/kits/locale/MutableLocaleRoster.cpp 
b/src/kits/locale/MutableLocaleRoster.cpp
index 6689dd2..3ca25e3 100644
--- a/src/kits/locale/MutableLocaleRoster.cpp
+++ b/src/kits/locale/MutableLocaleRoster.cpp
@@ -10,702 +10,41 @@
 
 #include <MutableLocaleRoster.h>
 
-#include <set>
-
 #include <pthread.h>
 
-#include <AppFileInfo.h>
 #include <Application.h>
 #include <Autolock.h>
 #include <Catalog.h>
-#include <Collator.h>
+#include <CatalogData.h>
 #include <Debug.h>
-#include <DefaultCatalog.h>
-#include <Directory.h>
 #include <Entry.h>
-#include <File.h>
-#include <FindDirectory.h>
 #include <FormattingConventions.h>
 #include <Language.h>
-#include <Locale.h>
-#include <Node.h>
-#include <Path.h>
-#include <Roster.h>
+#include <LocaleRosterData.h>
 #include <String.h>
-#include <TimeZone.h>
-
-#include <ICUWrapper.h>
-
-// ICU includes
-#include <unicode/locid.h>
-#include <unicode/timezone.h>
 
 
 namespace BPrivate {
 
 
-// #pragma mark - CatalogAddOnInfo
-
-
-CatalogAddOnInfo::CatalogAddOnInfo(const BString& name, const BString& path,
-       uint8 priority)
-       :
-       fInstantiateFunc(NULL),
-       fCreateFunc(NULL),
-       fLanguagesFunc(NULL),
-       fName(name),
-       fPath(path),
-       fAddOnImage(B_NO_INIT),
-       fPriority(priority),
-       fIsEmbedded(path.Length()==0)
-{
-}
-
-
-CatalogAddOnInfo::~CatalogAddOnInfo()
-{
-       int32 count = fLoadedCatalogs.CountItems();
-       for (int32 i = 0; i < count; ++i) {
-               BCatalogData* cat
-                       = static_cast<BCatalogData*>(fLoadedCatalogs.ItemAt(i));
-               delete cat;
-       }
-       fLoadedCatalogs.MakeEmpty();
-       UnloadIfPossible();
-}
-
-
-bool
-CatalogAddOnInfo::MakeSureItsLoaded()
-{
-       if (!fIsEmbedded && fAddOnImage < B_OK) {
-               // add-on has not been loaded yet, so we try to load it:
-               BString fullAddOnPath(fPath);
-               fullAddOnPath << "/" << fName;
-               fAddOnImage = load_add_on(fullAddOnPath.String());
-               if (fAddOnImage >= B_OK) {
-                       get_image_symbol(fAddOnImage, "instantiate_catalog",
-                               B_SYMBOL_TYPE_TEXT, (void**)&fInstantiateFunc);
-                       get_image_symbol(fAddOnImage, "create_catalog",
-                               B_SYMBOL_TYPE_TEXT, (void**)&fCreateFunc);
-                       get_image_symbol(fAddOnImage, "get_available_languages",
-                               B_SYMBOL_TYPE_TEXT, (void**)&fLanguagesFunc);
-               } else
-                       return false;
-       } else if (fIsEmbedded) {
-               // The built-in catalog still has to provide this function
-               fLanguagesFunc = default_catalog_get_available_languages;
-       }
-       return true;
-}
-
-
-void
-CatalogAddOnInfo::UnloadIfPossible()
-{
-       if (!fIsEmbedded && fLoadedCatalogs.IsEmpty()) {
-               unload_add_on(fAddOnImage);
-               fAddOnImage = B_NO_INIT;
-               fInstantiateFunc = NULL;
-               fCreateFunc = NULL;
-               fLanguagesFunc = NULL;
-       }
-}
-
-
-// #pragma mark - RosterData
-
-
 namespace {
 
 
-static const char* kPriorityAttr = "ADDON:priority";
-
-static const char* kLanguageField = "language";
-static const char* kTimezoneField = "timezone";
-static const char* kTranslateFilesystemField = "filesys";
-
+static MutableLocaleRoster* sLocaleRoster;
 
-static RosterData* sRosterData = NULL;
-static pthread_once_t sRosterDataInitOnce = PTHREAD_ONCE_INIT;
-
-
-static struct RosterDataReaper {
-       ~RosterDataReaper()
-       {
-               delete sRosterData;
-               sRosterData = NULL;
-       }
-} sRosterDataReaper;
+static pthread_once_t sLocaleRosterInitOnce = PTHREAD_ONCE_INIT;
 
 
 }      // anonymous namespace
 
 
-
 static void
-InitializeRosterData()
-{
-       sRosterData = new (std::nothrow) RosterData(BLanguage("en_US"),
-               BFormattingConventions("en_US"));
-}
-
-
-RosterData::RosterData(const BLanguage& language,
-       const BFormattingConventions& conventions)
-       :
-       fLock("LocaleRosterData"),
-       fDefaultLocale(&language, &conventions),
-       fIsFilesystemTranslationPreferred(false),
-       fAreResourcesLoaded(false)
-{
-       fInitStatus = _Initialize();
-}
-
-
-RosterData::~RosterData()
-{
-       BAutolock lock(fLock);
-
-       _CleanupCatalogAddOns();
-}
-
-
-/*static*/ RosterData*
-RosterData::Default()
-{
-       if (sRosterData == NULL)
-               pthread_once(&sRosterDataInitOnce, 
&BPrivate::InitializeRosterData);
-
-       return sRosterData;
-}
-
-
-status_t
-RosterData::InitCheck() const
-{
-       return fAreResourcesLoaded ? B_OK : B_NO_INIT;
-}
-
-
-status_t
-RosterData::Refresh()
-{
-       BAutolock lock(fLock);
-       if (!lock.IsLocked())
-               return B_ERROR;
-
-       _LoadLocaleSettings();
-       _LoadTimeSettings();
-
-       return B_OK;
-}
-
-
-int
-RosterData::CompareInfos(const void* left, const void* right)
-{
-       return ((CatalogAddOnInfo*)right)->fPriority
-               - ((CatalogAddOnInfo*)left)->fPriority;
-}
-
-
-status_t
-RosterData::SetDefaultFormattingConventions(
-       const BFormattingConventions& newFormattingConventions)
-{
-       status_t status = B_OK;
-
-       BAutolock lock(fLock);
-       if (!lock.IsLocked())
-               return B_ERROR;
-
-       status = _SetDefaultFormattingConventions(newFormattingConventions);
-
-       if (status == B_OK)
-               status = _SaveLocaleSettings();
-
-       if (status == B_OK) {
-               BMessage updateMessage(B_LOCALE_CHANGED);
-               status = 
_AddDefaultFormattingConventionsToMessage(&updateMessage);
-               if (status == B_OK)
-                       status = be_roster->Broadcast(&updateMessage);
-       }
-
-       return status;
-}
-
-
-status_t
-RosterData::SetDefaultTimeZone(const BTimeZone& newZone)
-{
-       status_t status = B_OK;
-
-       BAutolock lock(fLock);
-       if (!lock.IsLocked())
-               return B_ERROR;
-
-       status = _SetDefaultTimeZone(newZone);
-
-       if (status == B_OK)
-               status = _SaveTimeSettings();
-
-       if (status == B_OK) {
-               BMessage updateMessage(B_LOCALE_CHANGED);
-               status = _AddDefaultTimeZoneToMessage(&updateMessage);
-               if (status == B_OK)
-                       status = be_roster->Broadcast(&updateMessage);
-       }
-
-       return status;
-}
-
-
-status_t
-RosterData::SetPreferredLanguages(const BMessage* languages)
-{
-       status_t status = B_OK;
-
-       BAutolock lock(fLock);
-       if (!lock.IsLocked())
-               return B_ERROR;
-
-       status = _SetPreferredLanguages(languages);
-
-       if (status == B_OK)
-               status = _SaveLocaleSettings();
-
-       if (status == B_OK) {
-               BMessage updateMessage(B_LOCALE_CHANGED);
-               status = _AddPreferredLanguagesToMessage(&updateMessage);
-               if (status == B_OK)
-                       status = be_roster->Broadcast(&updateMessage);
-       }
-
-       return status;
-}
-
-
-status_t
-RosterData::SetFilesystemTranslationPreferred(bool preferred)
-{
-       BAutolock lock(fLock);
-       if (!lock.IsLocked())
-               return B_ERROR;
-
-       _SetFilesystemTranslationPreferred(preferred);
-
-       status_t status = _SaveLocaleSettings();
-
-       if (status == B_OK) {
-               BMessage updateMessage(B_LOCALE_CHANGED);
-               status = 
_AddFilesystemTranslationPreferenceToMessage(&updateMessage);
-               if (status == B_OK)
-                       status = be_roster->Broadcast(&updateMessage);
-       }
-
-       return status;
-}
-
-
-status_t
-RosterData::_Initialize()
-{
-       status_t result = _InitializeCatalogAddOns();
-       if (result != B_OK)
-               return result;
-
-       if ((result = Refresh()) != B_OK)
-               return result;
-
-       fInitStatus = B_OK;
-       return B_OK;
-}
-
-
-/*
-iterate over add-on-folders and collect information about each
-catalog-add-ons (types of catalogs) into fCatalogAddOnInfos.
-*/
-status_t
-RosterData::_InitializeCatalogAddOns()
+InitializeLocaleRoster()
 {
-       BAutolock lock(fLock);
-       if (!lock.IsLocked())
-               return B_ERROR;
-
-       // add info about embedded default catalog:
-       CatalogAddOnInfo* defaultCatalogAddOnInfo
-               = new(std::nothrow) CatalogAddOnInfo("Default", "",
-                       DefaultCatalog::kDefaultCatalogAddOnPriority);
-       if (!defaultCatalogAddOnInfo)
-               return B_NO_MEMORY;
-
-       defaultCatalogAddOnInfo->fInstantiateFunc = DefaultCatalog::Instantiate;
-       defaultCatalogAddOnInfo->fCreateFunc = DefaultCatalog::Create;
-       fCatalogAddOnInfos.AddItem((void*)defaultCatalogAddOnInfo);
-
-       directory_which folders[] = {
-               B_USER_ADDONS_DIRECTORY,
-               B_COMMON_ADDONS_DIRECTORY,
-               B_SYSTEM_ADDONS_DIRECTORY,
-       };
-       BPath addOnPath;
-       BDirectory addOnFolder;
-       char buf[4096];
-       status_t err;
-       for (uint32 f = 0; f < sizeof(folders) / sizeof(directory_which); ++f) {
-               find_directory(folders[f], &addOnPath);
-               BString addOnFolderName(addOnPath.Path());
-               addOnFolderName << "/locale/catalogs";
-
-               system_info info;
-               if (get_system_info(&info) == B_OK
-                               && (info.abi & B_HAIKU_ABI_MAJOR)
-                               != (B_HAIKU_ABI & B_HAIKU_ABI_MAJOR)) {
-                       switch (B_HAIKU_ABI & B_HAIKU_ABI_MAJOR) {
-                               case B_HAIKU_ABI_GCC_2:
-                                       addOnFolderName << "/gcc2";
-                                       break;
-                               case B_HAIKU_ABI_GCC_4:
-                                       addOnFolderName << "/gcc4";
-                                       break;
-                       }
-               }
-
-
-               err = addOnFolder.SetTo(addOnFolderName.String());
-               if (err != B_OK)
-                       continue;
-
-               // scan through all the folder's entries for catalog add-ons:
-               int32 count;
-               int8 priority;
-               entry_ref eref;
-               BNode node;
-               BEntry entry;
-               dirent* dent;
-               while ((count = addOnFolder.GetNextDirents((dirent*)buf, 4096)) 
> 0) {
-                       dent = (dirent*)buf;
-                       while (count-- > 0) {
-                               if (strcmp(dent->d_name, ".") && 
strcmp(dent->d_name, "..")
-                                               && strcmp(dent->d_name, "gcc2")
-                                               && strcmp(dent->d_name, 
"gcc4")) {
-                                       // we have found (what should be) a 
catalog-add-on:
-                                       eref.device = dent->d_pdev;
-                                       eref.directory = dent->d_pino;
-                                       eref.set_name(dent->d_name);
-                                       entry.SetTo(&eref, true);
-                                               // traverse through any links 
to get to the real thang!
-                                       node.SetTo(&entry);
-                                       priority = -1;
-                                       if (node.ReadAttr(kPriorityAttr, 
B_INT8_TYPE, 0,
-                                               &priority, sizeof(int8)) <= 0) {
-                                               // add-on has no 
priority-attribute yet, so we load it
-                                               // to fetch the priority from 
the corresponding
-                                               // symbol...
-                                               BString 
fullAddOnPath(addOnFolderName);
-                                               fullAddOnPath << "/" << 
dent->d_name;
-                                               image_id image = 
load_add_on(fullAddOnPath.String());
-                                               if (image >= B_OK) {
-                                                       uint8* prioPtr;
-                                                       if 
(get_image_symbol(image, "gCatalogAddOnPriority",
-                                                               
B_SYMBOL_TYPE_DATA,
-                                                               
(void**)&prioPtr) == B_OK) {
-                                                               priority = 
*prioPtr;
-                                                               
node.WriteAttr(kPriorityAttr, B_INT8_TYPE, 0,
-                                                                       
&priority, sizeof(int8));
-                                                       }
-                                                       unload_add_on(image);
-                                               }
-                                       }
-
-                                       if (priority >= 0) {
-                                               // add-ons with priority < 0 
will be ignored
-                                               CatalogAddOnInfo* addOnInfo
-                                                       = new(std::nothrow) 
CatalogAddOnInfo(dent->d_name,
-                                                               
addOnFolderName, priority);
-                                               if (addOnInfo)
-                                                       
fCatalogAddOnInfos.AddItem((void*)addOnInfo);
-                                       }
-                               }
-                               // Bump the dirent-pointer by length of the 
dirent just handled:
-                               dent = (dirent*)((char*)dent + dent->d_reclen);
-                       }
-               }
-       }
-       fCatalogAddOnInfos.SortItems(CompareInfos);
-
-       return B_OK;
-}
-
-
-/*
- * unloads all catalog-add-ons (which will throw away all loaded catalogs, too)
- */
-void
-RosterData::_CleanupCatalogAddOns()
-{
-       BAutolock lock(fLock);
-       if (!lock.IsLocked())
-               return;
-
-       int32 count = fCatalogAddOnInfos.CountItems();
-       for (int32 i = 0; i<count; ++i) {
-               CatalogAddOnInfo* info
-                       = 
static_cast<CatalogAddOnInfo*>(fCatalogAddOnInfos.ItemAt(i));
-               delete info;
-       }
-       fCatalogAddOnInfos.MakeEmpty();
-}
-
-
-status_t
-RosterData::_LoadLocaleSettings()
-{
-       BPath path;
-       BFile file;
-       status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
-       if (status == B_OK) {
-               path.Append("Locale settings");
-               status = file.SetTo(path.Path(), B_READ_ONLY);
-       }
-       BMessage settings;
-       if (status == B_OK)
-               status = settings.Unflatten(&file);
-
-       if (status == B_OK) {
-               BFormattingConventions conventions(&settings);
-               fDefaultLocale.SetFormattingConventions(conventions);
-
-               _SetPreferredLanguages(&settings);
-
-               bool preferred;
-               if (settings.FindBool(kTranslateFilesystemField, &preferred) == 
B_OK)
-                       _SetFilesystemTranslationPreferred(preferred);
-
-               return B_OK;
-       }
-
-
-       // Something went wrong (no settings file or invalid BMessage), so we
-       // set everything to default values
-
-       fPreferredLanguages.MakeEmpty();
-       fPreferredLanguages.AddString(kLanguageField, "en");
-       BLanguage defaultLanguage("en_US");
-       fDefaultLocale.SetLanguage(defaultLanguage);
-       BFormattingConventions conventions("en_US");
-       fDefaultLocale.SetFormattingConventions(conventions);
-
-       return status;
-}
-
-
-status_t
-RosterData::_LoadTimeSettings()
-{
-       BPath path;
-       BFile file;
-       status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
-       if (status == B_OK) {
-               path.Append("Time settings");
-               status = file.SetTo(path.Path(), B_READ_ONLY);
-       }
-       BMessage settings;
-       if (status == B_OK)
-               status = settings.Unflatten(&file);
-       if (status == B_OK) {
-               BString timeZoneID;
-               if (settings.FindString(kTimezoneField, &timeZoneID) == B_OK)
-                       _SetDefaultTimeZone(BTimeZone(timeZoneID.String()));
-               else
-                       
_SetDefaultTimeZone(BTimeZone(BTimeZone::kNameOfGmtZone));
-
-               return B_OK;
-       }
-
-       // Something went wrong (no settings file or invalid BMessage), so we
-       // set everything to default values
-       _SetDefaultTimeZone(BTimeZone(BTimeZone::kNameOfGmtZone));
-
-       return status;
-}
-
-
-status_t
-RosterData::_SaveLocaleSettings()
-{
-       BMessage settings;
-       status_t status = _AddDefaultFormattingConventionsToMessage(&settings);
-       if (status == B_OK)
-               _AddPreferredLanguagesToMessage(&settings);
-       if (status == B_OK)
-               _AddFilesystemTranslationPreferenceToMessage(&settings);
-
-       BPath path;
-       if (status == B_OK)
-               status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
-
-       BFile file;
-       if (status == B_OK) {
-               path.Append("Locale settings");
-               status = file.SetTo(path.Path(),
-                       B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY);
-       }
-       if (status == B_OK)
-               status = settings.Flatten(&file);
-       if (status == B_OK)
-               status = file.Sync();
-
-       return status;
-}
-
-
-status_t
-RosterData::_SaveTimeSettings()
-{
-       BMessage settings;
-       status_t status = _AddDefaultTimeZoneToMessage(&settings);
-
-       BPath path;
-       if (status == B_OK)
-               status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
-
-       BFile file;
-       if (status == B_OK) {
-               path.Append("Time settings");
-               status = file.SetTo(path.Path(),
-                       B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY);
-       }
-       if (status == B_OK)
-               status = settings.Flatten(&file);
-       if (status == B_OK)
-               status = file.Sync();
-
-       return status;
-}
-
-
-status_t
-RosterData::_SetDefaultFormattingConventions(
-       const BFormattingConventions& newFormattingConventions)
-{
-       fDefaultLocale.SetFormattingConventions(newFormattingConventions);
-
-       UErrorCode icuError = U_ZERO_ERROR;
-       Locale icuLocale = 
Locale::createCanonical(newFormattingConventions.ID());
-       if (icuLocale.isBogus())
-               return B_ERROR;
-
-       Locale::setDefault(icuLocale, icuError);
-       if (!U_SUCCESS(icuError))
-               return B_ERROR;
-
-       return B_OK;
-}
-
-
-status_t
-RosterData::_SetDefaultTimeZone(const BTimeZone& newZone)
-{
-       fDefaultTimeZone = newZone;
-
-       TimeZone* timeZone = TimeZone::createTimeZone(newZone.ID().String());
-       if (timeZone == NULL)
-               return B_ERROR;
-       TimeZone::adoptDefault(timeZone);
-
-       return B_OK;
+       sLocaleRoster = new (std::nothrow) MutableLocaleRoster();
 }
 
 
-status_t
-RosterData::_SetPreferredLanguages(const BMessage* languages)
-{
-       BString langName;
-       if (languages != NULL
-               && languages->FindString(kLanguageField, &langName) == B_OK) {
-               fDefaultLocale.SetCollator(BCollator(langName.String()));
-               fDefaultLocale.SetLanguage(BLanguage(langName.String()));
-
-               fPreferredLanguages.RemoveName(kLanguageField);
-               for (int i = 0; languages->FindString(kLanguageField, i, 
&langName)
-                               == B_OK; i++) {
-                       fPreferredLanguages.AddString(kLanguageField, langName);
-               }
-       } else {
-               fPreferredLanguages.MakeEmpty();
-               fPreferredLanguages.AddString(kLanguageField, "en");
-               fDefaultLocale.SetCollator(BCollator("en"));
-       }
-
-       return B_OK;
-}
-
-
-void
-RosterData::_SetFilesystemTranslationPreferred(bool preferred)
-{
-       fIsFilesystemTranslationPreferred = preferred;
-}
-
-
-status_t
-RosterData::_AddDefaultFormattingConventionsToMessage(BMessage* message) const
-{
-       BFormattingConventions conventions;
-       fDefaultLocale.GetFormattingConventions(&conventions);
-
-       return conventions.Archive(message);
-}
-
-
-status_t
-RosterData::_AddDefaultTimeZoneToMessage(BMessage* message) const
-{
-       return message->AddString(kTimezoneField, fDefaultTimeZone.ID());
-}
-
-
-status_t
-RosterData::_AddPreferredLanguagesToMessage(BMessage* message) const
-{
-       status_t status = B_OK;
-
-       BString langName;
-       for (int i = 0; fPreferredLanguages.FindString("language", i,
-                       &langName) == B_OK; i++) {
-               status = message->AddString(kLanguageField, langName);
-               if (status != B_OK)
-                       break;
-       }
-
-       return status;
-}
-
-
-status_t
-RosterData::_AddFilesystemTranslationPreferenceToMessage(BMessage* message)
-       const
-{
-       return message->AddBool(kTranslateFilesystemField,
-               fIsFilesystemTranslationPreferred);
-}
-
-
-// #pragma mark - MutableLocaleRoster
-
-
-namespace {
-
-
-static MutableLocaleRoster sLocaleRoster;
-
-
-}      // anonymous namespace
-
-
 MutableLocaleRoster::MutableLocaleRoster()
 {
 }
@@ -719,7 +58,10 @@ MutableLocaleRoster::~MutableLocaleRoster()
 /*static*/ MutableLocaleRoster*
 MutableLocaleRoster::Default()
 {
-       return &sLocaleRoster;
+       if (sLocaleRoster == NULL)
+               pthread_once(&sLocaleRosterInitOnce, &InitializeLocaleRoster);
+
+       return sLocaleRoster;
 }
 
 
@@ -727,29 +69,28 @@ status_t
 MutableLocaleRoster::SetDefaultFormattingConventions(
        const BFormattingConventions& newFormattingConventions)
 {
-       return RosterData::Default()->SetDefaultFormattingConventions(
-               newFormattingConventions);
+       return fData->SetDefaultFormattingConventions(newFormattingConventions);
 }
 
 
 status_t
 MutableLocaleRoster::SetDefaultTimeZone(const BTimeZone& newZone)
 {
-       return RosterData::Default()->SetDefaultTimeZone(newZone);
+       return fData->SetDefaultTimeZone(newZone);
 }
 
 
 status_t
 MutableLocaleRoster::SetPreferredLanguages(const BMessage* languages)
 {
-       return RosterData::Default()->SetPreferredLanguages(languages);
+       return fData->SetPreferredLanguages(languages);
 }
 
 
 status_t
 MutableLocaleRoster::SetFilesystemTranslationPreferred(bool preferred)
 {
-       return 
RosterData::Default()->SetFilesystemTranslationPreferred(preferred);
+       return fData->SetFilesystemTranslationPreferred(preferred);
 }
 
 
@@ -800,14 +141,14 @@ MutableLocaleRoster::CreateCatalog(const char* type, 
const char* signature,
        if (!type || !signature || !language)
                return NULL;
 
-       BAutolock lock(RosterData::Default()->fLock);
+       BAutolock lock(fData->fLock);
        if (!lock.IsLocked())
                return NULL;
 
-       int32 count = RosterData::Default()->fCatalogAddOnInfos.CountItems();
+       int32 count = fData->fCatalogAddOnInfos.CountItems();
        for (int32 i = 0; i < count; ++i) {
                CatalogAddOnInfo* info = (CatalogAddOnInfo*)
-                       RosterData::Default()->fCatalogAddOnInfos.ItemAt(i);
+                       fData->fCatalogAddOnInfos.ItemAt(i);
                if (info->fName.ICompare(type)!=0 || !info->MakeSureItsLoaded()
                        || !info->fCreateFunc)
                        continue;
@@ -838,14 +179,14 @@ BCatalogData*
 MutableLocaleRoster::LoadCatalog(const entry_ref& catalogOwner,
        const char* language, int32 fingerprint) const
 {
-       BAutolock lock(RosterData::Default()->fLock);
+       BAutolock lock(fData->fLock);
        if (!lock.IsLocked())
                return NULL;
 
-       int32 count = RosterData::Default()->fCatalogAddOnInfos.CountItems();
+       int32 count = fData->fCatalogAddOnInfos.CountItems();
        for (int32 i = 0; i < count; ++i) {
                CatalogAddOnInfo* info = (CatalogAddOnInfo*)
-                       RosterData::Default()->fCatalogAddOnInfos.ItemAt(i);
+                       fData->fCatalogAddOnInfos.ItemAt(i);
 
                if (!info->MakeSureItsLoaded() || !info->fInstantiateFunc)
                        continue;
@@ -909,7 +250,7 @@ MutableLocaleRoster::UnloadCatalog(BCatalogData* catalog)
        if (!catalog)
                return B_BAD_VALUE;
 
-       BAutolock lock(RosterData::Default()->fLock);
+       BAutolock lock(fData->fLock);
        if (!lock.IsLocked())
                return B_ERROR;
 
@@ -918,10 +259,10 @@ MutableLocaleRoster::UnloadCatalog(BCatalogData* catalog)
 
        while (catalog != NULL) {
                nextCatalog = catalog->Next();
-               int32 count = 
RosterData::Default()->fCatalogAddOnInfos.CountItems();
+               int32 count = fData->fCatalogAddOnInfos.CountItems();
                for (int32 i = 0; i < count; ++i) {
                        CatalogAddOnInfo* info = static_cast<CatalogAddOnInfo*>(
-                               
RosterData::Default()->fCatalogAddOnInfos.ItemAt(i));
+                               fData->fCatalogAddOnInfos.ItemAt(i));
                        if (info->fLoadedCatalogs.HasItem(catalog)) {
                                info->fLoadedCatalogs.RemoveItem(catalog);
                                delete catalog;


Other related posts:

  • » [haiku-commits] haiku: hrev44898 - src/kits/locale headers/private/locale - zooey