BPicture: Fix archive constructor.
[haiku.git] / src / kits / locale / MutableLocaleRoster.cpp
blob3ca25e33ef00c1c1cd97b9a39b49d06a75528c70
1 /*
2 * Copyright 2003-2012, Haiku. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Axel Dörfler, axeld@pinc-software.de
7 * Oliver Tappe, zooey@hirschkaefer.de
8 */
11 #include <MutableLocaleRoster.h>
13 #include <pthread.h>
15 #include <Application.h>
16 #include <Autolock.h>
17 #include <Catalog.h>
18 #include <CatalogData.h>
19 #include <Debug.h>
20 #include <Entry.h>
21 #include <FormattingConventions.h>
22 #include <Language.h>
23 #include <LocaleRosterData.h>
24 #include <String.h>
27 namespace BPrivate {
30 namespace {
33 static MutableLocaleRoster* sLocaleRoster;
35 static pthread_once_t sLocaleRosterInitOnce = PTHREAD_ONCE_INIT;
38 } // anonymous namespace
41 static void
42 InitializeLocaleRoster()
44 sLocaleRoster = new (std::nothrow) MutableLocaleRoster();
48 MutableLocaleRoster::MutableLocaleRoster()
53 MutableLocaleRoster::~MutableLocaleRoster()
58 /*static*/ MutableLocaleRoster*
59 MutableLocaleRoster::Default()
61 if (sLocaleRoster == NULL)
62 pthread_once(&sLocaleRosterInitOnce, &InitializeLocaleRoster);
64 return sLocaleRoster;
68 status_t
69 MutableLocaleRoster::SetDefaultFormattingConventions(
70 const BFormattingConventions& newFormattingConventions)
72 return fData->SetDefaultFormattingConventions(newFormattingConventions);
76 status_t
77 MutableLocaleRoster::SetDefaultTimeZone(const BTimeZone& newZone)
79 return fData->SetDefaultTimeZone(newZone);
83 status_t
84 MutableLocaleRoster::SetPreferredLanguages(const BMessage* languages)
86 return fData->SetPreferredLanguages(languages);
90 status_t
91 MutableLocaleRoster::SetFilesystemTranslationPreferred(bool preferred)
93 return fData->SetFilesystemTranslationPreferred(preferred);
97 status_t
98 MutableLocaleRoster::LoadSystemCatalog(BCatalog* catalog) const
100 if (!catalog)
101 return B_BAD_VALUE;
103 // figure out libbe-image (shared object) by name
104 image_info info;
105 int32 cookie = 0;
106 bool found = false;
108 while (get_next_image_info(0, &cookie, &info) == B_OK) {
109 if (info.data < (void*)&be_app
110 && (char*)info.data + info.data_size > (void*)&be_app) {
111 found = true;
112 break;
116 if (!found)
117 return B_ERROR;
119 // load the catalog for libbe into the given catalog
120 entry_ref ref;
121 status_t status = BEntry(info.name).GetRef(&ref);
122 if (status != B_OK)
123 return status;
125 return catalog->SetTo(ref);
130 * creates a new (empty) catalog of the given type (the request is dispatched
131 * to the appropriate add-on).
132 * If the add-on doesn't support catalog-creation or if the creation fails,
133 * NULL is returned, otherwise a pointer to the freshly created catalog.
134 * Any created catalog will be initialized with the given signature and
135 * language-name.
137 BCatalogData*
138 MutableLocaleRoster::CreateCatalog(const char* type, const char* signature,
139 const char* language)
141 if (!type || !signature || !language)
142 return NULL;
144 BAutolock lock(fData->fLock);
145 if (!lock.IsLocked())
146 return NULL;
148 int32 count = fData->fCatalogAddOnInfos.CountItems();
149 for (int32 i = 0; i < count; ++i) {
150 CatalogAddOnInfo* info = (CatalogAddOnInfo*)
151 fData->fCatalogAddOnInfos.ItemAt(i);
152 if (info->fName.ICompare(type)!=0 || !info->MakeSureItsLoaded()
153 || !info->fCreateFunc)
154 continue;
156 BCatalogData* catalog = info->fCreateFunc(signature, language);
157 if (catalog) {
158 info->fLoadedCatalogs.AddItem(catalog);
159 info->UnloadIfPossible();
160 return catalog;
164 return NULL;
169 * Loads a catalog for the given signature, language and fingerprint.
170 * The request to load this catalog is dispatched to all add-ons in turn,
171 * until an add-on reports success.
172 * If a catalog depends on another language (as 'english-british' depends
173 * on 'english') the dependant catalogs are automatically loaded, too.
174 * So it is perfectly possible that this method returns a catalog-chain
175 * instead of a single catalog.
176 * NULL is returned if no matching catalog could be found.
178 BCatalogData*
179 MutableLocaleRoster::LoadCatalog(const entry_ref& catalogOwner,
180 const char* language, int32 fingerprint) const
182 BAutolock lock(fData->fLock);
183 if (!lock.IsLocked())
184 return NULL;
186 int32 count = fData->fCatalogAddOnInfos.CountItems();
187 for (int32 i = 0; i < count; ++i) {
188 CatalogAddOnInfo* info = (CatalogAddOnInfo*)
189 fData->fCatalogAddOnInfos.ItemAt(i);
191 if (!info->MakeSureItsLoaded() || !info->fInstantiateFunc)
192 continue;
193 BMessage languages;
194 if (language)
195 // try to load catalogs for the given language:
196 languages.AddString("language", language);
197 else
198 // try to load catalogs for one of the preferred languages:
199 GetPreferredLanguages(&languages);
201 BCatalogData* catalog = NULL;
202 const char* lang;
203 for (int32 l=0; languages.FindString("language", l, &lang)==B_OK; ++l) {
204 catalog = info->fInstantiateFunc(catalogOwner, lang, fingerprint);
205 if (catalog)
206 info->fLoadedCatalogs.AddItem(catalog);
207 // Chain-load catalogs for languages that depend on
208 // other languages.
209 // The current implementation uses the filename in order to
210 // detect dependencies (parenthood) between languages (it
211 // traverses from "english_british_oxford" to "english_british"
212 // to "english"):
213 int32 pos;
214 BString langName(lang);
215 BCatalogData* currCatalog = catalog;
216 BCatalogData* nextCatalog = NULL;
217 while ((pos = langName.FindLast('_')) >= 0) {
218 // language is based on parent, so we load that, too:
219 // (even if the parent catalog was not found)
220 langName.Truncate(pos);
221 nextCatalog = info->fInstantiateFunc(catalogOwner,
222 langName.String(), fingerprint);
223 if (nextCatalog) {
224 info->fLoadedCatalogs.AddItem(nextCatalog);
225 if(currCatalog)
226 currCatalog->SetNext(nextCatalog);
227 else
228 catalog = nextCatalog;
229 currCatalog = nextCatalog;
232 if (catalog != NULL)
233 return catalog;
235 info->UnloadIfPossible();
238 return NULL;
243 * unloads the given catalog (or rather: catalog-chain).
244 * Every single catalog of the chain will be deleted automatically.
245 * Add-ons that have no more current catalogs are unloaded, too.
247 status_t
248 MutableLocaleRoster::UnloadCatalog(BCatalogData* catalog)
250 if (!catalog)
251 return B_BAD_VALUE;
253 BAutolock lock(fData->fLock);
254 if (!lock.IsLocked())
255 return B_ERROR;
257 status_t res = B_ERROR;
258 BCatalogData* nextCatalog;
260 while (catalog != NULL) {
261 nextCatalog = catalog->Next();
262 int32 count = fData->fCatalogAddOnInfos.CountItems();
263 for (int32 i = 0; i < count; ++i) {
264 CatalogAddOnInfo* info = static_cast<CatalogAddOnInfo*>(
265 fData->fCatalogAddOnInfos.ItemAt(i));
266 if (info->fLoadedCatalogs.HasItem(catalog)) {
267 info->fLoadedCatalogs.RemoveItem(catalog);
268 delete catalog;
269 info->UnloadIfPossible();
270 res = B_OK;
271 break;
274 catalog = nextCatalog;
276 return res;
280 } // namespace BPrivate