diff --git a/build/jam/BuildSetup b/build/jam/BuildSetup index 0e4cfc5c77..1967531d5b 100644 --- a/build/jam/BuildSetup +++ b/build/jam/BuildSetup @@ -456,11 +456,17 @@ if $(HAIKU_SHARED_LIBSUPC++) { HAIKU_LIBSUPC++ = $(HAIKU_SHARED_LIBSUPC++) ; } + # network libraries HAIKU_NETWORK_LIBS = network ; HAIKU_NETAPI_LIB = bnetapi ; HAIKU_SELECT_UNAME_ETC_LIB = ; # libroot, against which we link anyway + +# locale libraries +HAIKU_LOCALE_LIBS = liblocale.so liblocalestub.a ; + + # library and executable glue code local commonGlueCode = init_term_dyn.o diff --git a/headers/os/locale/Catalog.h b/headers/os/locale/Catalog.h index d5c866c7c9..87dd55eb83 100644 --- a/headers/os/locale/Catalog.h +++ b/headers/os/locale/Catalog.h @@ -33,6 +33,8 @@ class BCatalog { status_t GetLanguage(BString *lang); status_t GetFingerprint(uint32 *fp); + status_t SetCatalog(const char* signature, uint32 fingerprint); + status_t InitCheck() const; int32 CountItems() const; @@ -56,6 +58,21 @@ class BCatalog { extern BCatalog* be_catalog; extern BCatalog* be_app_catalog; + +// Proxy class for handling a "shared object local" catalog. +// This must be included (statically linked) into each shared object needing +// a catalog on its own (application, add-on, library, ...). The shared object +// must also have a mimetype so that the catalog can be identified. +class BCatalogStub { + private: + static BCatalog sCatalog; + static vint32 sCatalogInitOnce; + + public: + static BCatalog* GetCatalog(); +}; + + #ifndef B_AVOID_TRANSLATION_MACROS // macros for easy catalog-access, define B_AVOID_TRANSLATION_MACROS if // you don't want these: @@ -79,8 +96,24 @@ extern BCatalog* be_app_catalog; // source-file. +#ifdef B_TRANSLATE_USE_NEW_MACROS // Translation macros which may be used to shorten translation requests: #undef B_TRANSLATE +#define B_TRANSLATE(str) \ + BCatalogStub::GetCatalog()->GetString((str), B_TRANSLATE_CONTEXT) + +#undef B_TRANSLATE_COMMENT +#define B_TRANSLATE_COMMENT(str, cmt) \ + BCatalogStub::GetCatalog()->GetString((str), B_TRANSLATE_CONTEXT, (cmt)) + +#undef B_TRANSLATE_ALL +#define B_TRANSLATE_ALL(str, ctx, cmt) \ + BCatalogStub::GetCatalog()->GetString((str), (ctx), (cmt)) + +#undef B_TRANSLATE_ID +#define B_TRANSLATE_ID(id) \ + BCatalogStub::GetCatalog()->GetString((id)) +#else #define B_TRANSLATE(str) \ be_catalog->GetString((str), B_TRANSLATE_CONTEXT) @@ -95,6 +128,7 @@ extern BCatalog* be_app_catalog; #undef B_TRANSLATE_ID #define B_TRANSLATE_ID(id) \ be_catalog->GetString((id)) +#endif // Translation markers which can be used to mark static strings/IDs which // are used as key for translation requests (at other places in the code): diff --git a/headers/os/locale/LocaleRoster.h b/headers/os/locale/LocaleRoster.h index 3e72f02042..001cc2b42e 100644 --- a/headers/os/locale/LocaleRoster.h +++ b/headers/os/locale/LocaleRoster.h @@ -36,6 +36,7 @@ class BLocaleRoster { // status_t GetCatalog(BLocale *,const char *mimeType, BCatalog *catalog); // status_t GetCatalog(const char *mimeType, BCatalog *catalog); // status_t SetCatalog(BLocale *,const char *mimeType, BCatalog *catalog); + BCatalog* GetCatalog(BCatalog* catalog, vint32* catalogInitStatus); // status_t GetLocaleFor(const char *langCode, const char *countryCode); diff --git a/src/kits/locale/Catalog.cpp b/src/kits/locale/Catalog.cpp index e93d59cf62..58bcad0053 100644 --- a/src/kits/locale/Catalog.cpp +++ b/src/kits/locale/Catalog.cpp @@ -102,6 +102,21 @@ BCatalog::GetData(uint32 id, BMessage *msg) } +status_t +BCatalog::SetCatalog(const char* signature, uint32 fingerprint) +{ + // TODO: The previous fCatalog is leaked here. (The whole chain, it + // looks like.) We should take care that internal members are always + // properly maintained. + // No other method should touch fCatalog directly, either (constructor for + // example) + fCatalog + = be_locale_roster->LoadCatalog(signature, NULL, fingerprint); + + return B_OK; +} + + status_t BCatalog::GetAppCatalog(BCatalog* catalog) { @@ -120,14 +135,9 @@ BCatalog::GetAppCatalog(BCatalog* catalog) BNode appNode(&appInfo.ref); appNode.ReadAttr(BLocaleRoster::kCatFingerprintAttr, B_UINT32_TYPE, 0, &fingerprint, sizeof(uint32)); + catalog->SetCatalog(sig.String(), fingerprint); // try to load catalog (with given fingerprint): - // TODO: Not so nice C++ design here, leading to such bugs: The previous - // fCatalog is leaked here. (The whole chain, it looks like.) There should - // be a SetCatalog() method (it can be private), and that should take care - // that internal members are always properly maintained. - catalog->fCatalog - = be_locale_roster->LoadCatalog(sig.String(), NULL, fingerprint); - + // load native embedded id-based catalog. If such a catalog exists, // we can fall back to native strings for id-based access, too. BCatalogAddOn *embeddedCatalog diff --git a/src/kits/locale/CatalogStub.cpp b/src/kits/locale/CatalogStub.cpp new file mode 100644 index 0000000000..501f55356a --- /dev/null +++ b/src/kits/locale/CatalogStub.cpp @@ -0,0 +1,29 @@ +/* + * Copyright 2010, Adrien Destugues . + * Distributed under the terms of the MIT License. + */ + + +#ifndef __CATALOG_STUB_H__ +#define __CATALOG_STUB_H__ + + +#define B_TRANSLATE_USE_NEW_MACROS + + +#include +#include +#include + +BCatalog BCatalogStub::sCatalog; +vint32 BCatalogStub::sCatalogInitOnce = false; + + +/* static */ BCatalog* +BCatalogStub::GetCatalog() +{ + return be_locale_roster->GetCatalog(&sCatalog, &sCatalogInitOnce); +} + + +#endif diff --git a/src/kits/locale/Jamfile b/src/kits/locale/Jamfile index f272b90292..448b9400de 100644 --- a/src/kits/locale/Jamfile +++ b/src/kits/locale/Jamfile @@ -41,6 +41,10 @@ SharedLibrary liblocale.so : be $(TARGET_LIBSTDC++) libicu-common.so libicu-i18n.so ; +StaticLibrary liblocalestub.a + : CatalogStub.cpp + ; + SEARCH on [ FGristFiles StringForSize.cpp ] += [ FDirName $(HAIKU_TOP) src kits shared ] ; SEARCH on [ FGristFiles ColorControl.cpp ] += [ FDirName $(HAIKU_TOP) src kits interface ] ; diff --git a/src/kits/locale/LocaleRoster.cpp b/src/kits/locale/LocaleRoster.cpp index 73eec7caba..cacc8674a4 100644 --- a/src/kits/locale/LocaleRoster.cpp +++ b/src/kits/locale/LocaleRoster.cpp @@ -16,6 +16,7 @@ #include // for debug only #include +#include #include #include #include @@ -177,8 +178,8 @@ BCatalogAddOnInfo::UnloadIfPossible() fInstantiateEmbeddedFunc = NULL; fCreateFunc = NULL; fLanguagesFunc = NULL; - log_team(LOG_DEBUG, "catalog-add-on %s has been unloaded", - fName.String()); +// log_team(LOG_DEBUG, "catalog-add-on %s has been unloaded", +// fName.String()); } } @@ -364,9 +365,6 @@ RosterData::InitializeCatalogAddOns() } } - log_team(LOG_ERR, "Found : %s priority: %d\n", - dent->d_name,priority); - if (priority >= 0) { // add-ons with priority < 0 will be ignored BCatalogAddOnInfo* addOnInfo @@ -386,10 +384,6 @@ RosterData::InitializeCatalogAddOns() for (int32 i=0; i(fCatalogAddOnInfos.ItemAt(i)); - log_team(LOG_INFO, - "roster uses catalog-add-on %s/%s with priority %d", - info->fIsEmbedded ? "(embedded)" : info->fPath.String(), - info->fName.String(), info->fPriority); } } @@ -425,10 +419,65 @@ BLocaleRoster::~BLocaleRoster() } +BCatalog* +BLocaleRoster::GetCatalog(BCatalog* catalog, vint32* catalogInitStatus) +{ + // This function is used in the translation macros, so it can't return a + // status_t. Maybe it could throw exceptions ? + + if (catalog == NULL) { + log_team(LOG_ERR, "GetCatalog called with a NULL catalog!"); + return catalog; + } + + if (*catalogInitStatus == true) { + // Catalog already loaded - nothing else to do + return catalog; + } + + // figure out image (shared object) from catalog address + image_info info; + int32 cookie = 0; + bool found = false; + + while (get_next_image_info(0, &cookie, &info) == B_OK) { + if ((char*)info.data < (char*)catalog && (char*)info.data+info.data_size + > (char*)catalog) { + found = true; + break; + } + } + + if (!found) { + log_team(LOG_DEBUG, "Catalog %x doesn't belong to any image !",catalog); + return catalog; + } + // figure out mimetype from image + BFile objectFile(info.name, B_READ_ONLY); + BAppFileInfo objectInfo(&objectFile); + char objectSignature[B_MIME_TYPE_LENGTH]; + objectInfo.GetSignature(objectSignature); + + // drop supertype from mimetype (should be "application/"): + char* stripSignature = objectSignature; + while(*(stripSignature++)!='/'); + + log_team(LOG_DEBUG, + "Image %s (address %x) requested catalog with mimetype %s", + info.name, catalog, stripSignature); + + // load the catalog for this mimetype and return it to the app + catalog->SetCatalog(stripSignature, 0); + *catalogInitStatus = true; + + return catalog; +} + + status_t BLocaleRoster::GetSystemCatalog(BCatalogAddOn **catalog) const { - if(!catalog) + if (!catalog) return B_BAD_VALUE; *catalog = be_locale_roster->LoadCatalog("system"); return B_OK; diff --git a/src/preferences/locale/Jamfile b/src/preferences/locale/Jamfile index 9f601fd6d4..6945205959 100644 --- a/src/preferences/locale/Jamfile +++ b/src/preferences/locale/Jamfile @@ -10,8 +10,8 @@ Preference Locale : LocaleWindow.cpp TimeFormatSettingsView.cpp - : be liblocale.so $(TARGET_LIBSTDC++) $(TARGET_LIBSUPC++) libicu-common.so - libicu-data.so libshared.a + : be $(TARGET_LIBSTDC++) $(TARGET_LIBSUPC++) libicu-common.so + libicu-data.so libshared.a $(HAIKU_LOCALE_LIBS) : Locale.rdef ; diff --git a/src/preferences/locale/LanguageListView.cpp b/src/preferences/locale/LanguageListView.cpp index 55db29f817..f8e41426ae 100644 --- a/src/preferences/locale/LanguageListView.cpp +++ b/src/preferences/locale/LanguageListView.cpp @@ -16,6 +16,7 @@ #include +#define B_TRANSLATE_USE_NEW_MACROS #include #include #include diff --git a/src/preferences/locale/Locale.cpp b/src/preferences/locale/Locale.cpp index 2586aa9d05..1068dbce5f 100644 --- a/src/preferences/locale/Locale.cpp +++ b/src/preferences/locale/Locale.cpp @@ -4,6 +4,9 @@ */ +#define B_TRANSLATE_USE_NEW_MACROS + + #include "Locale.h" #include "LocaleWindow.h" @@ -57,7 +60,6 @@ public: private: Settings fSettings; LocaleWindow* fLocaleWindow; - BCatalog fCatalog; }; @@ -140,8 +142,6 @@ LocalePreflet::LocalePreflet() : BApplication(kSignature) { - be_locale->GetAppCatalog(&fCatalog); - fLocaleWindow = new LocaleWindow(); if (fSettings.Message().HasPoint("window_location")) { diff --git a/src/preferences/locale/LocaleWindow.cpp b/src/preferences/locale/LocaleWindow.cpp index b375fde500..fd750c2969 100644 --- a/src/preferences/locale/LocaleWindow.cpp +++ b/src/preferences/locale/LocaleWindow.cpp @@ -5,6 +5,9 @@ */ +#define B_TRANSLATE_USE_NEW_MACROS + + #include "Locale.h" #include "LocaleWindow.h" #include "LanguageListView.h" diff --git a/src/preferences/locale/TimeFormatSettingsView.cpp b/src/preferences/locale/TimeFormatSettingsView.cpp index bff8580726..dcf586fe8d 100644 --- a/src/preferences/locale/TimeFormatSettingsView.cpp +++ b/src/preferences/locale/TimeFormatSettingsView.cpp @@ -4,6 +4,9 @@ */ +#define B_TRANSLATE_USE_NEW_MACROS + + #include "TimeFormatSettingsView.h" #include