2 * Copyright 2003-2012, Haiku. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Axel Dörfler, axeld@pinc-software.de
7 * Oliver Tappe, zooey@hirschkaefer.de
11 #include <MutableLocaleRoster.h>
15 #include <Application.h>
18 #include <CatalogData.h>
21 #include <FormattingConventions.h>
23 #include <LocaleRosterData.h>
33 static MutableLocaleRoster
* sLocaleRoster
;
35 static pthread_once_t sLocaleRosterInitOnce
= PTHREAD_ONCE_INIT
;
38 } // anonymous namespace
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
);
69 MutableLocaleRoster::SetDefaultFormattingConventions(
70 const BFormattingConventions
& newFormattingConventions
)
72 return fData
->SetDefaultFormattingConventions(newFormattingConventions
);
77 MutableLocaleRoster::SetDefaultTimeZone(const BTimeZone
& newZone
)
79 return fData
->SetDefaultTimeZone(newZone
);
84 MutableLocaleRoster::SetPreferredLanguages(const BMessage
* languages
)
86 return fData
->SetPreferredLanguages(languages
);
91 MutableLocaleRoster::SetFilesystemTranslationPreferred(bool preferred
)
93 return fData
->SetFilesystemTranslationPreferred(preferred
);
98 MutableLocaleRoster::LoadSystemCatalog(BCatalog
* catalog
) const
103 // figure out libbe-image (shared object) by name
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
) {
119 // load the catalog for libbe into the given catalog
121 status_t status
= BEntry(info
.name
).GetRef(&ref
);
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
138 MutableLocaleRoster::CreateCatalog(const char* type
, const char* signature
,
139 const char* language
)
141 if (!type
|| !signature
|| !language
)
144 BAutolock
lock(fData
->fLock
);
145 if (!lock
.IsLocked())
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
)
156 BCatalogData
* catalog
= info
->fCreateFunc(signature
, language
);
158 info
->fLoadedCatalogs
.AddItem(catalog
);
159 info
->UnloadIfPossible();
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.
179 MutableLocaleRoster::LoadCatalog(const entry_ref
& catalogOwner
,
180 const char* language
, int32 fingerprint
) const
182 BAutolock
lock(fData
->fLock
);
183 if (!lock
.IsLocked())
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
)
195 // try to load catalogs for the given language:
196 languages
.AddString("language", language
);
198 // try to load catalogs for one of the preferred languages:
199 GetPreferredLanguages(&languages
);
201 BCatalogData
* catalog
= NULL
;
203 for (int32 l
=0; languages
.FindString("language", l
, &lang
)==B_OK
; ++l
) {
204 catalog
= info
->fInstantiateFunc(catalogOwner
, lang
, fingerprint
);
206 info
->fLoadedCatalogs
.AddItem(catalog
);
207 // Chain-load catalogs for languages that depend on
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"
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
);
224 info
->fLoadedCatalogs
.AddItem(nextCatalog
);
226 currCatalog
->SetNext(nextCatalog
);
228 catalog
= nextCatalog
;
229 currCatalog
= nextCatalog
;
235 info
->UnloadIfPossible();
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.
248 MutableLocaleRoster::UnloadCatalog(BCatalogData
* catalog
)
253 BAutolock
lock(fData
->fLock
);
254 if (!lock
.IsLocked())
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
);
269 info
->UnloadIfPossible();
274 catalog
= nextCatalog
;
280 } // namespace BPrivate