From 76a4353b79418ab1d9050821a5578bef0d40df0c Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Thu, 1 Jul 2010 11:54:09 +0000 Subject: [PATCH] Add a new way of using the locale kit with static accessors instead of global variables. This has the following consequences : * Applications don't have to declare BCatalog fCatalog themselves, it's now done automatically * Libs and add-ons can be localized just the same way (except static libraries) For now this new system is yet disabled as I'm looking for some peer review before going on. To enable it you have to define B_TRANSLATE_USE_NEW_MACROS in each file doing catalog access. This will not stay, I'll update the other apps to use it. The linking in jamfiles must be not only with liblocale.so, but also liblocalestub.a. Not sure how to handle this for user-side applications. Libraries are also required to provide a MIME signature to use any catalog. The locale preflet is updated to the new system (as a test). Othe rapps will follow if everyone is ok with this approach. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37323 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- build/jam/BuildSetup | 6 ++ headers/os/locale/Catalog.h | 34 +++++++++ headers/os/locale/LocaleRoster.h | 1 + src/kits/locale/Catalog.cpp | 24 +++++-- src/kits/locale/CatalogStub.cpp | 29 ++++++++ src/kits/locale/Jamfile | 4 ++ src/kits/locale/LocaleRoster.cpp | 69 ++++++++++++++++--- src/preferences/locale/Jamfile | 4 +- src/preferences/locale/LanguageListView.cpp | 1 + src/preferences/locale/Locale.cpp | 6 +- src/preferences/locale/LocaleWindow.cpp | 3 + .../locale/TimeFormatSettingsView.cpp | 3 + 12 files changed, 162 insertions(+), 22 deletions(-) create mode 100644 src/kits/locale/CatalogStub.cpp 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