b7f609650b
in BLocale (which is accessible via be_locale) * adjusted all users accordingly git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38459 a95241bf-73f2-0310-859d-f6bbb57e9c96
312 lines
6.8 KiB
C++
312 lines
6.8 KiB
C++
/*
|
|
* Copyright 2003-2010, Haiku. All rights reserved.
|
|
* Distributed under the terms of the MIT License.
|
|
*
|
|
* Authors:
|
|
* Axel Dörfler, axeld@pinc-software.de
|
|
* Oliver Tappe, zooey@hirschkaefer.de
|
|
*/
|
|
|
|
|
|
#include <LocaleRoster.h>
|
|
|
|
#include <set>
|
|
|
|
#include <assert.h>
|
|
#include <syslog.h>
|
|
|
|
#include <Autolock.h>
|
|
#include <AppFileInfo.h>
|
|
#include <Catalog.h>
|
|
#include <Collator.h>
|
|
#include <Country.h>
|
|
#include <DefaultCatalog.h>
|
|
#include <Directory.h>
|
|
#include <Entry.h>
|
|
#include <File.h>
|
|
#include <Language.h>
|
|
#include <Locale.h>
|
|
#include <MutableLocaleRoster.h>
|
|
#include <Node.h>
|
|
#include <Path.h>
|
|
#include <String.h>
|
|
#include <TimeZone.h>
|
|
|
|
#include <ICUWrapper.h>
|
|
|
|
// ICU includes
|
|
#include <unicode/locid.h>
|
|
#include <unicode/timezone.h>
|
|
|
|
|
|
using BPrivate::CatalogAddOnInfo;
|
|
|
|
|
|
/*
|
|
* several attributes/resource-IDs used within the Locale Kit:
|
|
*/
|
|
const char* BLocaleRoster::kCatLangAttr = "BEOS:LOCALE_LANGUAGE";
|
|
// name of catalog language, lives in every catalog file
|
|
const char* BLocaleRoster::kCatSigAttr = "BEOS:LOCALE_SIGNATURE";
|
|
// catalog signature, lives in every catalog file
|
|
const char* BLocaleRoster::kCatFingerprintAttr = "BEOS:LOCALE_FINGERPRINT";
|
|
// catalog fingerprint, may live in catalog file
|
|
|
|
const char* BLocaleRoster::kEmbeddedCatAttr = "BEOS:LOCALE_EMBEDDED_CATALOG";
|
|
// attribute which contains flattened data of embedded catalog
|
|
// this may live in an app- or add-on-file
|
|
int32 BLocaleRoster::kEmbeddedCatResId = 0xCADA;
|
|
// a unique value used to identify the resource (=> embedded CAtalog DAta)
|
|
// which contains flattened data of embedded catalog.
|
|
// this may live in an app- or add-on-file
|
|
|
|
|
|
BLocaleRoster::BLocaleRoster()
|
|
{
|
|
}
|
|
|
|
|
|
BLocaleRoster::~BLocaleRoster()
|
|
{
|
|
}
|
|
|
|
|
|
status_t
|
|
BLocaleRoster::Refresh()
|
|
{
|
|
return gRosterData.Refresh();
|
|
}
|
|
|
|
|
|
status_t
|
|
BLocaleRoster::GetDefaultTimeZone(BTimeZone* timezone) const
|
|
{
|
|
if (!timezone)
|
|
return B_BAD_VALUE;
|
|
|
|
BAutolock lock(gRosterData.fLock);
|
|
if (!lock.IsLocked())
|
|
return B_ERROR;
|
|
|
|
*timezone = gRosterData.fDefaultTimeZone;
|
|
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
status_t
|
|
BLocaleRoster::GetLanguage(const char* languageCode,
|
|
BLanguage** _language) const
|
|
{
|
|
if (_language == NULL || languageCode == NULL || languageCode[0] == '\0')
|
|
return B_BAD_VALUE;
|
|
|
|
BLanguage* language = new(std::nothrow) BLanguage(languageCode);
|
|
if (language == NULL)
|
|
return B_NO_MEMORY;
|
|
|
|
*_language = language;
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
status_t
|
|
BLocaleRoster::GetPreferredLanguages(BMessage* languages) const
|
|
{
|
|
if (!languages)
|
|
return B_BAD_VALUE;
|
|
|
|
BAutolock lock(gRosterData.fLock);
|
|
if (!lock.IsLocked())
|
|
return B_ERROR;
|
|
|
|
*languages = gRosterData.fPreferredLanguages;
|
|
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
status_t
|
|
BLocaleRoster::GetInstalledLanguages(BMessage* languages) const
|
|
{
|
|
if (!languages)
|
|
return B_BAD_VALUE;
|
|
|
|
int32 i;
|
|
UnicodeString icuLanguageName;
|
|
BString languageName;
|
|
|
|
int32_t localeCount;
|
|
const Locale* icuLocaleList
|
|
= Locale::getAvailableLocales(localeCount);
|
|
|
|
// TODO: Loop over the strings and add them to a std::set to remove
|
|
// duplicates?
|
|
for (i = 0; i < localeCount; i++)
|
|
languages->AddString("langs", icuLocaleList[i].getName());
|
|
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
status_t
|
|
BLocaleRoster::GetAvailableCountries(BMessage* countries) const
|
|
{
|
|
if (!countries)
|
|
return B_BAD_VALUE;
|
|
|
|
int32 i;
|
|
const char* const* countryList = uloc_getISOCountries();
|
|
|
|
for (i = 0; countryList[i] != NULL; i++)
|
|
countries->AddString("countries", countryList[i]);
|
|
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
status_t
|
|
BLocaleRoster::GetAvailableTimeZones(BMessage* timeZones) const
|
|
{
|
|
if (!timeZones)
|
|
return B_BAD_VALUE;
|
|
|
|
status_t status = B_OK;
|
|
|
|
StringEnumeration* zoneList = TimeZone::createEnumeration();
|
|
|
|
UErrorCode icuStatus = U_ZERO_ERROR;
|
|
int32 count = zoneList->count(icuStatus);
|
|
if (U_SUCCESS(icuStatus)) {
|
|
for (int i = 0; i < count; ++i) {
|
|
const char* zoneID = zoneList->next(NULL, icuStatus);
|
|
if (zoneID == NULL || !U_SUCCESS(icuStatus)) {
|
|
status = B_ERROR;
|
|
break;
|
|
}
|
|
timeZones->AddString("timeZone", zoneID);
|
|
}
|
|
} else
|
|
status = B_ERROR;
|
|
|
|
delete zoneList;
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
status_t
|
|
BLocaleRoster::GetAvailableTimeZonesForCountry(BMessage* timeZones,
|
|
const char* countryCode) const
|
|
{
|
|
if (!timeZones)
|
|
return B_BAD_VALUE;
|
|
|
|
status_t status = B_OK;
|
|
|
|
StringEnumeration* zoneList = TimeZone::createEnumeration(countryCode);
|
|
// countryCode == NULL will yield all timezones not bound to a country
|
|
|
|
UErrorCode icuStatus = U_ZERO_ERROR;
|
|
int32 count = zoneList->count(icuStatus);
|
|
if (U_SUCCESS(icuStatus)) {
|
|
for (int i = 0; i < count; ++i) {
|
|
const char* zoneID = zoneList->next(NULL, icuStatus);
|
|
if (zoneID == NULL || !U_SUCCESS(icuStatus)) {
|
|
status = B_ERROR;
|
|
break;
|
|
}
|
|
timeZones->AddString("timeZone", zoneID);
|
|
}
|
|
} else
|
|
status = B_ERROR;
|
|
|
|
delete zoneList;
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
status_t
|
|
BLocaleRoster::GetInstalledCatalogs(BMessage* languageList,
|
|
const char* sigPattern, const char* langPattern, int32 fingerprint) const
|
|
{
|
|
if (languageList == NULL)
|
|
return B_BAD_VALUE;
|
|
|
|
BAutolock lock(gRosterData.fLock);
|
|
if (!lock.IsLocked())
|
|
return B_ERROR;
|
|
|
|
int32 count = gRosterData.fCatalogAddOnInfos.CountItems();
|
|
for (int32 i = 0; i < count; ++i) {
|
|
CatalogAddOnInfo* info
|
|
= (CatalogAddOnInfo*)gRosterData.fCatalogAddOnInfos.ItemAt(i);
|
|
|
|
if (!info->MakeSureItsLoaded() || !info->fLanguagesFunc)
|
|
continue;
|
|
|
|
info->fLanguagesFunc(languageList, sigPattern, langPattern,
|
|
fingerprint);
|
|
}
|
|
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
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 (*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];
|
|
if (objectInfo.GetSignature(objectSignature) != B_OK) {
|
|
log_team(LOG_ERR, "File %s has no mimesignature, so it can't use"
|
|
"localization.", info.name);
|
|
return catalog;
|
|
}
|
|
|
|
// drop supertype from mimetype (should be "application/"):
|
|
char* stripSignature = objectSignature;
|
|
while (*stripSignature != '/')
|
|
stripSignature ++;
|
|
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;
|
|
}
|