Largish cleanup sweep concerning the Locale Kit (sorry it got so big):
* refactored private/mutable stuff out of LocaleRoster into MutableLocaleRoster * moved management of Locale/Time settings file and broadcasting of any changes out of preflets and into MutableLocaleRoster * added proper sorting to the listviews of the Locale preflet * the Time preflet no longer overlaps long timezone names into the actual time * several fixes with respect to leaking ICU objects, esp. in BCountry * the locale roster no longer passes out references to its own BCountry object, but uses copies, instead - this makes locking superfluous, as the clients' BCountry objects can no longer be changed by the setting a new default country in the locale roster * removed pretty useless POSIX-style symbol fetching from BCountry - if we need that at all, it should live in the dedicated formatter classes * adjusted readonlybootprompt, dstcheck and Deskbar to the changed Locale API * refactored existing Time-formatter into TimeUnitFormat and DurationFormat (the latter of which is now used by AboutSystem) * added stubs for Date, DateTime and Time formatters * lots of coding style fixes throughout the Locale Kit and the Locale and Time preflets This will probably break most external apps making use of the Locale Kit - it does break WebPositive. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37831 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -220,7 +220,6 @@ class BCatalog {
|
|||||||
// For BCatalog add-on implementations:
|
// For BCatalog add-on implementations:
|
||||||
|
|
||||||
class BCatalogAddOn {
|
class BCatalogAddOn {
|
||||||
friend class BLocaleRoster;
|
|
||||||
public:
|
public:
|
||||||
BCatalogAddOn(const char *signature, const char *language,
|
BCatalogAddOn(const char *signature, const char *language,
|
||||||
uint32 fingerprint);
|
uint32 fingerprint);
|
||||||
@@ -269,6 +268,8 @@ class BCatalogAddOn {
|
|||||||
const char *cmt);
|
const char *cmt);
|
||||||
static int32 MarkForTranslation(int32 id);
|
static int32 MarkForTranslation(int32 id);
|
||||||
|
|
||||||
|
void SetNext(BCatalogAddOn *next);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void UpdateFingerprint();
|
virtual void UpdateFingerprint();
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2010, Haiku, Inc.
|
* Copyright 2003-2010, Haiku, Inc.
|
||||||
* Distributed under the terms of the MIT Licence.
|
* Distributed under the terms of the MIT Licence.
|
||||||
*/
|
*/
|
||||||
#ifndef _COLLATOR_H_
|
#ifndef _COLLATOR_H_
|
||||||
#define _COLLATOR_H_
|
#define _COLLATOR_H_
|
||||||
|
|
||||||
|
|
||||||
#include <SupportDefs.h>
|
|
||||||
#include <Archivable.h>
|
#include <Archivable.h>
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
namespace icu_44 {
|
namespace icu_44 {
|
||||||
@@ -33,62 +33,72 @@ enum collator_strengths {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// N.B.: This class is not multithread-safe, as Compare() and GetKey() change
|
||||||
|
// the ICUCollator (the strength). So if you want to use a BCollator from
|
||||||
|
// more than one thread, you need to protect it with a lock
|
||||||
class BCollator : public BArchivable {
|
class BCollator : public BArchivable {
|
||||||
public:
|
public:
|
||||||
BCollator();
|
BCollator();
|
||||||
BCollator(const char *locale, int8 strength, bool ignorePunctuation);
|
BCollator(const char* locale,
|
||||||
BCollator(BMessage *archive);
|
int8 strength = B_COLLATE_PRIMARY,
|
||||||
~BCollator();
|
bool ignorePunctuation = false);
|
||||||
|
BCollator(BMessage* archive);
|
||||||
|
|
||||||
void SetDefaultStrength(int8 strength);
|
BCollator(const BCollator& other);
|
||||||
int8 DefaultStrength() const;
|
|
||||||
|
|
||||||
void SetIgnorePunctuation(bool ignore);
|
~BCollator();
|
||||||
bool IgnorePunctuation() const;
|
|
||||||
|
|
||||||
status_t GetSortKey(const char *string, BString *key,
|
BCollator& operator=(const BCollator& source);
|
||||||
int8 strength = B_COLLATE_DEFAULT);
|
|
||||||
|
|
||||||
int Compare(const char *, const char *, int32 len = -1,
|
void SetDefaultStrength(int8 strength);
|
||||||
int8 strength = B_COLLATE_DEFAULT);
|
int8 DefaultStrength() const;
|
||||||
bool Equal(const char *, const char *, int32 len = -1,
|
|
||||||
int8 strength = B_COLLATE_DEFAULT);
|
|
||||||
bool Greater(const char *, const char *, int32 len = -1,
|
|
||||||
int8 strength = B_COLLATE_DEFAULT);
|
|
||||||
bool GreaterOrEqual(const char *, const char *, int32 len = -1,
|
|
||||||
int8 strength = B_COLLATE_DEFAULT);
|
|
||||||
|
|
||||||
// (un-)archiving API
|
void SetIgnorePunctuation(bool ignore);
|
||||||
status_t Archive(BMessage *archive, bool deep) const;
|
bool IgnorePunctuation() const;
|
||||||
static BArchivable *Instantiate(BMessage *archive);
|
|
||||||
|
|
||||||
private:
|
status_t GetSortKey(const char* string, BString* key,
|
||||||
icu_44::Collator* fICUCollator;
|
int8 strength = B_COLLATE_DEFAULT) const;
|
||||||
icu_44::RuleBasedCollator* fFallbackICUCollator;
|
|
||||||
int8 fStrength;
|
int Compare(const char* s1, const char* s2,
|
||||||
bool fIgnorePunctuation;
|
int8 strength = B_COLLATE_DEFAULT) const;
|
||||||
|
bool Equal(const char* s1, const char* s2,
|
||||||
|
int8 strength = B_COLLATE_DEFAULT) const;
|
||||||
|
bool Greater(const char* s1, const char* s2,
|
||||||
|
int8 strength = B_COLLATE_DEFAULT) const;
|
||||||
|
bool GreaterOrEqual(const char* s1, const char* s2,
|
||||||
|
int8 strength = B_COLLATE_DEFAULT) const;
|
||||||
|
|
||||||
|
// (un-)archiving API
|
||||||
|
status_t Archive(BMessage* archive, bool deep) const;
|
||||||
|
static BArchivable* Instantiate(BMessage* archive);
|
||||||
|
|
||||||
|
private:
|
||||||
|
status_t _SetStrength(int8 strength) const;
|
||||||
|
|
||||||
|
mutable icu_44::Collator* fICUCollator;
|
||||||
|
int8 fDefaultStrength;
|
||||||
|
bool fIgnorePunctuation;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
BCollator::Equal(const char *s1, const char *s2, int32 len, int8 strength)
|
BCollator::Equal(const char *s1, const char *s2, int8 strength) const
|
||||||
{
|
{
|
||||||
return Compare(s1, s2, len, strength) == 0;
|
return Compare(s1, s2, strength) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
BCollator::Greater(const char *s1, const char *s2, int32 len, int8 strength)
|
BCollator::Greater(const char *s1, const char *s2, int8 strength) const
|
||||||
{
|
{
|
||||||
return Compare(s1, s2, len, strength) > 0;
|
return Compare(s1, s2, strength) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
BCollator::GreaterOrEqual(const char *s1, const char *s2, int32 len,
|
BCollator::GreaterOrEqual(const char *s1, const char *s2, int8 strength) const
|
||||||
int8 strength)
|
|
||||||
{
|
{
|
||||||
return Compare(s1, s2, len, strength) >= 0;
|
return Compare(s1, s2, strength) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+67
-79
@@ -1,10 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2003-2010, Haiku, Inc.
|
||||||
|
* Distributed under the terms of the MIT Licence.
|
||||||
|
*/
|
||||||
#ifndef _COUNTRY_H_
|
#ifndef _COUNTRY_H_
|
||||||
#define _COUNTRY_H_
|
#define _COUNTRY_H_
|
||||||
|
|
||||||
|
|
||||||
#include <List.h>
|
#include <List.h>
|
||||||
#include <LocaleStrings.h>
|
#include <LocaleStrings.h>
|
||||||
#include <Locker.h>
|
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
@@ -36,101 +39,86 @@ typedef enum {
|
|||||||
|
|
||||||
|
|
||||||
class BCountry {
|
class BCountry {
|
||||||
public:
|
public:
|
||||||
BCountry(const char* languageCode, const char* countryCode);
|
BCountry(const char* languageCode,
|
||||||
BCountry(const char* languageAndCountryCode = "en_US");
|
const char* countryCode);
|
||||||
BCountry(const BCountry& other);
|
BCountry(const char* languageAndCountryCode
|
||||||
BCountry& operator=(const BCountry& other);
|
= "en_US");
|
||||||
virtual ~BCountry();
|
BCountry(const BCountry& other);
|
||||||
|
BCountry& operator=(const BCountry& other);
|
||||||
|
~BCountry();
|
||||||
|
|
||||||
bool Name(BString& name) const;
|
bool GetName(BString& name) const;
|
||||||
bool LocaleName(BString& name) const;
|
bool GetLocaleName(BString& name) const;
|
||||||
const char* Code() const;
|
const char* Code() const;
|
||||||
status_t GetIcon(BBitmap* result);
|
status_t GetIcon(BBitmap* result) const;
|
||||||
|
|
||||||
const char* GetString(uint32 id) const;
|
const char* GetLocalizedString(uint32 id) const;
|
||||||
|
|
||||||
// Date
|
// Date
|
||||||
|
|
||||||
status_t FormatDate(char* string, size_t maxSize, time_t time,
|
status_t FormatDate(char* string, size_t maxSize,
|
||||||
bool longFormat);
|
time_t time, bool longFormat);
|
||||||
status_t FormatDate(BString* string, time_t time,
|
status_t FormatDate(BString* string, time_t time,
|
||||||
bool longFormat);
|
bool longFormat);
|
||||||
status_t FormatDate(BString* string, int*& fieldPositions,
|
status_t FormatDate(BString* string,
|
||||||
int& fieldCount, time_t time, bool longFormat);
|
int*& fieldPositions, int& fieldCount,
|
||||||
status_t DateFields(BDateElement*& fields, int& fieldCount,
|
time_t time, bool longFormat);
|
||||||
bool longFormat);
|
status_t GetDateFields(BDateElement*& fields,
|
||||||
status_t DateFormat(BString&, bool longFormat);
|
int& fieldCount, bool longFormat) const;
|
||||||
status_t SetDateFormat(const char* formatString,
|
status_t GetDateFormat(BString&, bool longFormat) const;
|
||||||
bool longFormat = true);
|
status_t SetDateFormat(const char* formatString,
|
||||||
|
bool longFormat = true);
|
||||||
|
|
||||||
int StartOfWeek();
|
int StartOfWeek() const;
|
||||||
|
|
||||||
// Time
|
// Time
|
||||||
|
|
||||||
status_t FormatTime(char* string, size_t maxSize, time_t time,
|
status_t FormatTime(char* string, size_t maxSize,
|
||||||
bool longFormat);
|
time_t time, bool longFormat);
|
||||||
status_t FormatTime(BString* string, time_t time,
|
status_t FormatTime(BString* string, time_t time,
|
||||||
bool longFormat);
|
bool longFormat);
|
||||||
status_t FormatTime(BString* string, int*& fieldPositions,
|
status_t FormatTime(BString* string,
|
||||||
int& fieldCount, time_t time, bool longFormat);
|
int*& fieldPositions, int& fieldCount,
|
||||||
status_t TimeFields(BDateElement*& fields, int& fieldCount,
|
time_t time, bool longFormat);
|
||||||
bool longFormat);
|
status_t GetTimeFields(BDateElement*& fields,
|
||||||
|
int& fieldCount, bool longFormat) const;
|
||||||
|
|
||||||
status_t SetTimeFormat(const char* formatString,
|
status_t SetTimeFormat(const char* formatString,
|
||||||
bool longFormat = true);
|
bool longFormat = true);
|
||||||
status_t TimeFormat(BString&, bool longFormat);
|
status_t GetTimeFormat(BString& out,
|
||||||
|
bool longFormat) const;
|
||||||
|
|
||||||
// numbers
|
// numbers
|
||||||
|
|
||||||
virtual void FormatNumber(char* string, size_t maxSize, double value);
|
status_t FormatNumber(char* string, size_t maxSize,
|
||||||
virtual status_t FormatNumber(BString* string, double value);
|
double value);
|
||||||
virtual void FormatNumber(char* string, size_t maxSize, int32 value);
|
status_t FormatNumber(BString* string, double value);
|
||||||
virtual void FormatNumber(BString* string, int32 value);
|
status_t FormatNumber(char* string, size_t maxSize,
|
||||||
|
int32 value);
|
||||||
|
status_t FormatNumber(BString* string, int32 value);
|
||||||
|
|
||||||
bool DecimalPoint(BString&) const;
|
// measurements
|
||||||
bool ThousandsSeparator(BString&) const;
|
|
||||||
bool Grouping(BString&) const;
|
|
||||||
|
|
||||||
bool PositiveSign(BString&) const;
|
int8 Measurement() const;
|
||||||
bool NegativeSign(BString&) const;
|
|
||||||
|
|
||||||
// measurements
|
// monetary
|
||||||
|
|
||||||
virtual int8 Measurement() const;
|
ssize_t FormatMonetary(char* string, size_t maxSize,
|
||||||
|
double value);
|
||||||
|
ssize_t FormatMonetary(BString* string, double value);
|
||||||
|
|
||||||
// monetary
|
// timezones
|
||||||
|
|
||||||
virtual ssize_t FormatMonetary(char* string, size_t maxSize,
|
int GetTimeZones(BList& timezones) const;
|
||||||
double value);
|
|
||||||
virtual ssize_t FormatMonetary(BString* string, double value);
|
|
||||||
|
|
||||||
bool CurrencySymbol(BString&) const;
|
private:
|
||||||
bool InternationalCurrencySymbol(BString&) const;
|
icu_44::Locale* fICULocale;
|
||||||
bool MonDecimalPoint(BString&) const;
|
BString fLongDateFormat;
|
||||||
bool MonThousandsSeparator(BString&) const;
|
BString fShortDateFormat;
|
||||||
bool MonGrouping(BString&) const;
|
BString fLongTimeFormat;
|
||||||
virtual int32 MonFracDigits() const;
|
BString fShortTimeFormat;
|
||||||
|
|
||||||
// timezones
|
|
||||||
int GetTimeZones(BList& timezones);
|
|
||||||
|
|
||||||
private:
|
|
||||||
icu_44::DateFormat* _LockDateFormatter(bool longFormat);
|
|
||||||
icu_44::DateFormat* _LockTimeFormatter(bool longFormat);
|
|
||||||
void _UnlockDateFormatter(bool longFormat);
|
|
||||||
void _UnlockTimeFormatter(bool longFormat);
|
|
||||||
|
|
||||||
icu_44::DateFormat* fICULongDateFormatter;
|
|
||||||
icu_44::DateFormat* fICUShortDateFormatter;
|
|
||||||
icu_44::DateFormat* fICULongTimeFormatter;
|
|
||||||
icu_44::DateFormat* fICUShortTimeFormatter;
|
|
||||||
icu_44::Locale* fICULocale;
|
|
||||||
|
|
||||||
BLocker fLongDateLock;
|
|
||||||
BLocker fShortDateLock;
|
|
||||||
BLocker fLongTimeLock;
|
|
||||||
BLocker fShortTimeLock;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* _COUNTRY_H_ */
|
#endif /* _COUNTRY_H_ */
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010, Haiku, Inc.
|
||||||
|
* Distributed under the terms of the MIT Licence.
|
||||||
|
*/
|
||||||
|
#ifndef _B_DATE_FORMAT_H_
|
||||||
|
#define _B_DATE_FORMAT_H_
|
||||||
|
|
||||||
|
#include <DateTimeFormat.h>
|
||||||
|
|
||||||
|
|
||||||
|
class BString;
|
||||||
|
|
||||||
|
class BDateFormat : public BDateTimeFormat {
|
||||||
|
public:
|
||||||
|
BDateFormat();
|
||||||
|
BDateFormat(const BDateFormat &other);
|
||||||
|
virtual ~BDateFormat();
|
||||||
|
|
||||||
|
// formatting
|
||||||
|
|
||||||
|
// no-frills version: Simply appends the
|
||||||
|
// formatted date to the string buffer.
|
||||||
|
// Can fail only with B_NO_MEMORY or B_BAD_VALUE.
|
||||||
|
virtual status_t Format(bigtime_t value, BString* buffer) const;
|
||||||
|
|
||||||
|
// TODO: ... all, basically!
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _B_DATE_FORMAT_H_
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010, Haiku, Inc.
|
||||||
|
* Distributed under the terms of the MIT Licence.
|
||||||
|
*/
|
||||||
|
#ifndef _B_DATE_TIME_FORMAT_H_
|
||||||
|
#define _B_DATE_TIME_FORMAT_H_
|
||||||
|
|
||||||
|
#include <Format.h>
|
||||||
|
#include <FormatParameters.h>
|
||||||
|
|
||||||
|
|
||||||
|
class BString;
|
||||||
|
|
||||||
|
class BDateTimeFormat : public BFormat {
|
||||||
|
public:
|
||||||
|
BDateTimeFormat();
|
||||||
|
BDateTimeFormat(const BDateTimeFormat &other);
|
||||||
|
virtual ~BDateTimeFormat();
|
||||||
|
|
||||||
|
// formatting
|
||||||
|
|
||||||
|
// no-frills version: Simply appends the
|
||||||
|
// formatted date to the string buffer.
|
||||||
|
// Can fail only with B_NO_MEMORY or B_BAD_VALUE.
|
||||||
|
virtual status_t Format(bigtime_t value, BString* buffer) const;
|
||||||
|
|
||||||
|
// TODO: ... basically, all of it!
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _B_DATE_TIME_FORMAT_H_
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010, Haiku, Inc.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _B_DURATION_FORMAT_H_
|
||||||
|
#define _B_DURATION_FORMAT_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include <DateTimeFormat.h>
|
||||||
|
#include <String.h>
|
||||||
|
#include <TimeUnitFormat.h>
|
||||||
|
|
||||||
|
|
||||||
|
class BDurationFormat : public BFormat {
|
||||||
|
public:
|
||||||
|
status_t Format(bigtime_t startValue,
|
||||||
|
bigtime_t stopValue, BString* buffer,
|
||||||
|
time_unit_style style = B_TIME_UNIT_FULL,
|
||||||
|
const BString& separator = ", "
|
||||||
|
) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,9 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2003-2010, Haiku, Inc.
|
||||||
|
* Distributed under the terms of the MIT Licence.
|
||||||
|
*/
|
||||||
#ifndef _B_FORMAT_H_
|
#ifndef _B_FORMAT_H_
|
||||||
#define _B_FORMAT_H_
|
#define _B_FORMAT_H_
|
||||||
|
|
||||||
#include <FormatParameters.h>
|
#include <FormatParameters.h>
|
||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
// types of fields contained in formatted strings
|
// types of fields contained in formatted strings
|
||||||
enum {
|
enum {
|
||||||
// number format fields
|
// number format fields
|
||||||
@@ -30,16 +35,18 @@ struct format_field_position {
|
|||||||
int32 length;
|
int32 length;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class BFormatImpl;
|
class BFormatImpl;
|
||||||
|
|
||||||
class BFormat {
|
class BFormat {
|
||||||
protected:
|
protected:
|
||||||
BFormat(const BFormat &other);
|
BFormat(const BFormat& other);
|
||||||
~BFormat();
|
virtual ~BFormat();
|
||||||
|
|
||||||
BFormat &operator=(const BFormat &other);
|
BFormat& operator=(const BFormat& other);
|
||||||
|
|
||||||
BFormat();
|
BFormat();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // _B_FORMAT_H_
|
#endif // _B_FORMAT_H_
|
||||||
|
|||||||
@@ -27,8 +27,13 @@ enum script_direction {
|
|||||||
|
|
||||||
class BLanguage {
|
class BLanguage {
|
||||||
public:
|
public:
|
||||||
|
BLanguage();
|
||||||
|
BLanguage(const char* language);
|
||||||
|
BLanguage(const BLanguage& other);
|
||||||
~BLanguage();
|
~BLanguage();
|
||||||
|
|
||||||
|
BLanguage& operator=(const BLanguage& source);
|
||||||
|
|
||||||
status_t GetName(BString& name) const;
|
status_t GetName(BString& name) const;
|
||||||
status_t GetTranslatedName(BString& name) const;
|
status_t GetTranslatedName(BString& name) const;
|
||||||
|
|
||||||
@@ -43,19 +48,15 @@ public:
|
|||||||
|
|
||||||
uint8 Direction() const;
|
uint8 Direction() const;
|
||||||
|
|
||||||
|
status_t SetTo(const char* language);
|
||||||
|
|
||||||
// see definitions below
|
// see definitions below
|
||||||
const char* GetString(uint32 id) const;
|
const char* GetString(uint32 id) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class BLocaleRoster;
|
// BString fStrings[B_NUM_LANGUAGE_STRINGS];
|
||||||
|
|
||||||
BLanguage(const char *language);
|
|
||||||
void Default();
|
|
||||||
|
|
||||||
private:
|
|
||||||
char* fStrings[B_NUM_LANGUAGE_STRINGS];
|
|
||||||
uint8 fDirection;
|
uint8 fDirection;
|
||||||
icu_44::Locale* fICULocale;
|
icu_44::Locale* fICULocale;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+56
-49
@@ -7,86 +7,92 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <Collator.h>
|
#include <Collator.h>
|
||||||
#include <Language.h>
|
|
||||||
#include <Country.h>
|
#include <Country.h>
|
||||||
|
#include <Language.h>
|
||||||
|
|
||||||
|
|
||||||
class BCatalog;
|
class BCatalog;
|
||||||
class BLocaleRoster;
|
|
||||||
class BString;
|
class BString;
|
||||||
|
|
||||||
|
|
||||||
class BLocale {
|
class BLocale {
|
||||||
public:
|
public:
|
||||||
BLocale();
|
BLocale();
|
||||||
~BLocale();
|
~BLocale();
|
||||||
|
|
||||||
BCollator *Collator() const { return fCollator; }
|
const BCollator* Collator() const { return &fCollator; }
|
||||||
BCountry *Country() const { return fCountry; }
|
const BCountry* Country() const { return &fCountry; }
|
||||||
BLanguage *Language() const { return fLanguage; }
|
const BLanguage* Language() const { return &fLanguage; }
|
||||||
|
|
||||||
// see definitions in LocaleStrings.h
|
// see definitions in LocaleStrings.h
|
||||||
const char *GetString(uint32 id);
|
const char* GetString(uint32 id);
|
||||||
|
|
||||||
void FormatString(char *target, size_t maxSize, char *fmt, ...);
|
void FormatString(char* target, size_t maxSize,
|
||||||
void FormatString(BString *, char *fmt, ...);
|
char* fmt, ...);
|
||||||
void FormatDateTime(char *target, size_t maxSize, const char *fmt,
|
void FormatString(BString* buffer, char* fmt, ...);
|
||||||
time_t);
|
void FormatDateTime(char* target, size_t maxSize,
|
||||||
void FormatDateTime(BString *, const char *fmt, time_t);
|
const char* fmt, time_t value);
|
||||||
|
void FormatDateTime(BString* buffer, const char* fmt,
|
||||||
|
time_t value);
|
||||||
|
|
||||||
// Country short-hands
|
// Country short-hands, TODO: all these should go, once the
|
||||||
|
// Date...Format classes are done
|
||||||
|
void FormatDate(char* target, size_t maxSize,
|
||||||
|
time_t value, bool longFormat);
|
||||||
|
void FormatDate(BString* target, time_t value,
|
||||||
|
bool longFormat);
|
||||||
|
void FormatTime(char* target, size_t maxSize,
|
||||||
|
time_t value, bool longFormat);
|
||||||
|
void FormatTime(BString* target, time_t value,
|
||||||
|
bool longFormat);
|
||||||
|
|
||||||
void FormatDate(char *target, size_t maxSize, time_t, bool longFormat);
|
// Collator short-hands
|
||||||
void FormatDate(BString *target, time_t, bool longFormat);
|
int StringCompare(const char* s1,
|
||||||
void FormatTime(char *target, size_t maxSize, time_t, bool longFormat);
|
const char* s2) const;
|
||||||
void FormatTime(BString *target, time_t, bool longFormat);
|
int StringCompare(const BString* s1,
|
||||||
|
const BString* s2) const;
|
||||||
|
|
||||||
// Collator short-hands
|
void GetSortKey(const char* string,
|
||||||
|
BString* key) const;
|
||||||
|
|
||||||
int StringCompare(const char *, const char *, int32 len = -1,
|
protected:
|
||||||
int8 strength = B_COLLATE_DEFAULT) const;
|
BCollator fCollator;
|
||||||
int StringCompare(const BString *, const BString *,
|
BCountry fCountry;
|
||||||
int32 len = -1, int8 strength = B_COLLATE_DEFAULT) const;
|
BLanguage fLanguage;
|
||||||
|
|
||||||
void GetSortKey(const char *string, BString *key);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
BCollator *fCollator;
|
|
||||||
BLanguage *fLanguage;
|
|
||||||
BCountry *fCountry;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// global objects
|
// global objects
|
||||||
extern BLocale *be_locale;
|
extern BLocale* be_locale;
|
||||||
extern BLocaleRoster *be_locale_roster;
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
//--- country short-hands inlines ---
|
//--- country short-hands inlines ---
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
BLocale::FormatDate(char *target, size_t maxSize, time_t timer, bool longFormat)
|
BLocale::FormatDate(char* target, size_t maxSize, time_t timer, bool longFormat)
|
||||||
{
|
{
|
||||||
fCountry->FormatDate(target, maxSize, timer, longFormat);
|
fCountry.FormatDate(target, maxSize, timer, longFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
BLocale::FormatDate(BString *target, time_t timer, bool longFormat)
|
BLocale::FormatDate(BString* target, time_t timer, bool longFormat)
|
||||||
{
|
{
|
||||||
fCountry->FormatDate(target, timer, longFormat);
|
fCountry.FormatDate(target, timer, longFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
BLocale::FormatTime(char *target, size_t maxSize, time_t timer, bool longFormat)
|
BLocale::FormatTime(char* target, size_t maxSize, time_t timer, bool longFormat)
|
||||||
{
|
{
|
||||||
fCountry->FormatTime(target, maxSize, timer, longFormat);
|
fCountry.FormatTime(target, maxSize, timer, longFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
BLocale::FormatTime(BString *target, time_t timer, bool longFormat)
|
BLocale::FormatTime(BString* target, time_t timer, bool longFormat)
|
||||||
{
|
{
|
||||||
fCountry->FormatTime(target, timer, longFormat);
|
fCountry.FormatTime(target, timer, longFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -94,23 +100,24 @@ BLocale::FormatTime(BString *target, time_t timer, bool longFormat)
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
inline int
|
inline int
|
||||||
BLocale::StringCompare(const char *string1, const char *string2, int32 length, int8 strength) const
|
BLocale::StringCompare(const char* s1, const char* s2) const
|
||||||
{
|
{
|
||||||
return fCollator->Compare(string1, string2, length, strength);
|
return fCollator.Compare(s1, s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline int
|
inline int
|
||||||
BLocale::StringCompare(const BString *string1, const BString *string2, int32 length, int8 strength) const
|
BLocale::StringCompare(const BString* s1, const BString* s2) const
|
||||||
{
|
{
|
||||||
return fCollator->Compare(string1->String(), string2->String(), length, strength);
|
return fCollator.Compare(s1->String(), s2->String());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
BLocale::GetSortKey(const char *string, BString *key)
|
BLocale::GetSortKey(const char* string, BString* key) const
|
||||||
{
|
{
|
||||||
fCollator->GetSortKey(string, key);
|
fCollator.GetSortKey(string, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* _B_LOCALE_H_ */
|
#endif /* _B_LOCALE_H_ */
|
||||||
|
|||||||
@@ -9,89 +9,70 @@
|
|||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
|
|
||||||
class BLanguage;
|
class BCatalog;
|
||||||
class BLocale;
|
|
||||||
class BCollator;
|
class BCollator;
|
||||||
class BCountry;
|
class BCountry;
|
||||||
class BCatalog;
|
class BLanguage;
|
||||||
class BCatalogAddOn;
|
class BLocale;
|
||||||
class BMessage;
|
class BMessage;
|
||||||
class BTimeZone;
|
class BTimeZone;
|
||||||
|
|
||||||
struct entry_ref;
|
|
||||||
|
|
||||||
namespace BPrivate {
|
|
||||||
class EditableCatalog;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
B_LOCALE_CHANGED = '_LCC',
|
B_LOCALE_CHANGED = '_LCC',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class BLocaleRoster {
|
class BLocaleRoster {
|
||||||
public:
|
public:
|
||||||
BLocaleRoster();
|
BLocaleRoster();
|
||||||
~BLocaleRoster();
|
~BLocaleRoster();
|
||||||
|
|
||||||
status_t GetSystemCatalog(BCatalogAddOn **catalog) const;
|
status_t GetDefaultCollator(BCollator* collator) const;
|
||||||
status_t GetDefaultCollator(BCollator **collator) const;
|
status_t GetDefaultLanguage(BLanguage* language) const;
|
||||||
status_t GetDefaultLanguage(BLanguage **language) const;
|
status_t GetDefaultCountry(BCountry* country) const;
|
||||||
status_t GetDefaultCountry(BCountry **contry) const;
|
status_t GetDefaultTimeZone(BTimeZone* timezone) const;
|
||||||
status_t GetDefaultTimeZone(BTimeZone**timezone) const;
|
|
||||||
|
|
||||||
void SetDefaultCountry(BCountry *) const;
|
status_t GetLanguage(const char* languageCode,
|
||||||
void SetDefaultTimeZone(const char* zone) const;
|
BLanguage** _language) const;
|
||||||
void UpdateSettings(BMessage* newSettings);
|
|
||||||
|
|
||||||
status_t GetLanguage(const char* languageCode, BLanguage** _language)
|
status_t GetPreferredLanguages(BMessage* message) const;
|
||||||
const;
|
|
||||||
|
|
||||||
status_t GetPreferredLanguages(BMessage *) const;
|
status_t GetInstalledLanguages(BMessage* message) const;
|
||||||
status_t SetPreferredLanguages(BMessage *);
|
// the message contains one or more
|
||||||
// the message contains one or more 'language'-string-fields
|
// 'language'-string-fields which
|
||||||
// which contain the language-name(s)
|
// contain the language-name(s)
|
||||||
|
|
||||||
status_t GetInstalledLanguages(BMessage *) const;
|
status_t GetAvailableCountries(BMessage* message) const;
|
||||||
// the message contains one or more 'language'-string-fields
|
|
||||||
// which contain the language-name(s)
|
|
||||||
|
|
||||||
status_t GetAvailableCountries(BMessage *) const;
|
status_t GetInstalledCatalogs(BMessage* message,
|
||||||
|
const char* sigPattern = NULL,
|
||||||
|
const char* langPattern = NULL,
|
||||||
|
int32 fingerprint = 0) const;
|
||||||
|
// the message contains...
|
||||||
|
|
||||||
status_t GetInstalledCatalogs(BMessage *, const char* sigPattern = NULL,
|
status_t Refresh();
|
||||||
const char* langPattern = NULL, int32 fingerprint = 0) const;
|
// Refresh the internal data from the
|
||||||
// the message contains...
|
// settings file(s)
|
||||||
|
|
||||||
BCatalog* GetCatalog();
|
BCatalog* GetCatalog();
|
||||||
// Get the catalog for the calling image (that needs to link with
|
// Get the catalog for the calling image
|
||||||
// liblocalestub.a)
|
// (that needs to link with liblocalestub.a)
|
||||||
|
|
||||||
static const char *kCatLangAttr;
|
static const char* kCatLangAttr;
|
||||||
static const char *kCatSigAttr;
|
static const char* kCatSigAttr;
|
||||||
static const char *kCatFingerprintAttr;
|
static const char* kCatFingerprintAttr;
|
||||||
|
|
||||||
static const char *kCatManagerMimeType;
|
static const char* kEmbeddedCatAttr;
|
||||||
static const char *kCatEditorMimeType;
|
static int32 kEmbeddedCatResId;
|
||||||
|
|
||||||
static const char *kEmbeddedCatAttr;
|
private:
|
||||||
static int32 kEmbeddedCatResId;
|
static BCatalog* _GetCatalog(BCatalog* catalog,
|
||||||
|
vint32* catalogInitStatus);
|
||||||
private:
|
|
||||||
BCatalog* GetCatalog(BCatalog* catalog, vint32* catalogInitStatus);
|
|
||||||
|
|
||||||
BCatalogAddOn* LoadCatalog(const char *signature,
|
|
||||||
const char *language = NULL, int32 fingerprint = 0);
|
|
||||||
BCatalogAddOn* LoadEmbeddedCatalog(entry_ref *appOrAddOnRef);
|
|
||||||
status_t UnloadCatalog(BCatalogAddOn *addOn);
|
|
||||||
|
|
||||||
BCatalogAddOn* CreateCatalog(const char *type,
|
|
||||||
const char *signature, const char *language);
|
|
||||||
|
|
||||||
friend class BCatalog;
|
|
||||||
friend class BCatalogStub;
|
|
||||||
friend class BPrivate::EditableCatalog;
|
|
||||||
friend status_t get_add_on_catalog(BCatalog*, const char *);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _LOCALE_ROSTER_H_ */
|
|
||||||
|
extern BLocaleRoster* be_locale_roster;
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _LOCALE_ROSTER_H_
|
||||||
|
|||||||
@@ -1,25 +1,29 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010, Haiku, Inc.
|
* Copyright 2010, Haiku, Inc.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT Licence.
|
||||||
*/
|
*/
|
||||||
#ifndef _B_TIME_FORMAT_H_
|
#ifndef _B_TIME_FORMAT_H_
|
||||||
#define _B_TIME_FORMAT_H_
|
#define _B_TIME_FORMAT_H_
|
||||||
|
|
||||||
|
#include <DateTimeFormat.h>
|
||||||
#include <NumberFormat.h>
|
|
||||||
#include <SupportDefs.h>
|
|
||||||
|
|
||||||
|
|
||||||
class BString;
|
class BString;
|
||||||
|
|
||||||
|
class BTimeFormat : public BDateTimeFormat {
|
||||||
|
public:
|
||||||
|
BTimeFormat(const BTimeFormat &other);
|
||||||
|
virtual ~BTimeFormat();
|
||||||
|
|
||||||
class BTimeFormat : public BNumberFormat {
|
// formatting
|
||||||
public:
|
|
||||||
status_t Format(int64 number, BString *buffer) const;
|
|
||||||
|
|
||||||
// TODO : version for char* buffer, size_t bufferSize
|
// no-frills version: Simply appends the
|
||||||
// TODO : parsing ?
|
// formatted date to the string buffer.
|
||||||
|
// Can fail only with B_NO_MEMORY or B_BAD_VALUE.
|
||||||
|
virtual status_t Format(bigtime_t value, BString* buffer) const;
|
||||||
|
|
||||||
|
// TODO: ... basically, all of it!
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif // _B_TIME_FORMAT_H_
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010, Haiku, Inc.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _B_TIME_UNIT_FORMAT_H_
|
||||||
|
#define _B_TIME_UNIT_FORMAT_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include <DateTimeFormat.h>
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
class BString;
|
||||||
|
|
||||||
|
|
||||||
|
enum time_unit_style {
|
||||||
|
B_TIME_UNIT_ABBREVIATED, // e.g. '5 hrs.'
|
||||||
|
B_TIME_UNIT_FULL, // e.g. '5 hours'
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum time_unit_element {
|
||||||
|
B_TIME_UNIT_YEAR,
|
||||||
|
B_TIME_UNIT_MONTH,
|
||||||
|
B_TIME_UNIT_WEEK,
|
||||||
|
B_TIME_UNIT_DAY,
|
||||||
|
B_TIME_UNIT_HOUR,
|
||||||
|
B_TIME_UNIT_MINUTE,
|
||||||
|
B_TIME_UNIT_SECOND,
|
||||||
|
|
||||||
|
B_TIME_UNIT_LAST = B_TIME_UNIT_SECOND
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class BTimeUnitFormat : public BFormat {
|
||||||
|
public:
|
||||||
|
status_t Format(int32 value, time_unit_element unit,
|
||||||
|
BString* buffer,
|
||||||
|
time_unit_style style = B_TIME_UNIT_FULL
|
||||||
|
) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -20,9 +20,11 @@ public:
|
|||||||
|
|
||||||
status_t InitCheck() const;
|
status_t InitCheck() const;
|
||||||
|
|
||||||
private:
|
status_t SetTo(const char* zoneCode);
|
||||||
void _Init(const char* zoneCode);
|
|
||||||
|
|
||||||
|
static const char* kNameOfGmtZone;
|
||||||
|
|
||||||
|
private:
|
||||||
BString fCode;
|
BString fCode;
|
||||||
BString fName;
|
BString fName;
|
||||||
int fOffsetFromGMT;
|
int fOffsetFromGMT;
|
||||||
|
|||||||
@@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010, Haiku. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT license.
|
||||||
|
*/
|
||||||
|
#ifndef _MUTABLE_LOCALE_ROSTER_H_
|
||||||
|
#define _MUTABLE_LOCALE_ROSTER_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include <Collator.h>
|
||||||
|
#include <Country.h>
|
||||||
|
#include <image.h>
|
||||||
|
#include <Language.h>
|
||||||
|
#include <List.h>
|
||||||
|
#include <Locker.h>
|
||||||
|
#include <LocaleRoster.h>
|
||||||
|
#include <Message.h>
|
||||||
|
#include <TimeZone.h>
|
||||||
|
|
||||||
|
|
||||||
|
class BLocale;
|
||||||
|
class BCatalog;
|
||||||
|
class BCatalogAddOn;
|
||||||
|
|
||||||
|
struct entry_ref;
|
||||||
|
|
||||||
|
|
||||||
|
namespace BPrivate {
|
||||||
|
|
||||||
|
|
||||||
|
class MutableLocaleRoster : public BLocaleRoster {
|
||||||
|
public:
|
||||||
|
MutableLocaleRoster();
|
||||||
|
~MutableLocaleRoster();
|
||||||
|
|
||||||
|
status_t SetDefaultCountry(const BCountry& country);
|
||||||
|
status_t SetDefaultTimeZone(const BTimeZone& zone);
|
||||||
|
|
||||||
|
status_t SetPreferredLanguages(const BMessage* message);
|
||||||
|
// the message contains one or more
|
||||||
|
// 'language'-string-fields which
|
||||||
|
// contain the language-name(s)
|
||||||
|
|
||||||
|
status_t GetSystemCatalog(BCatalogAddOn** catalog) const;
|
||||||
|
|
||||||
|
BCatalogAddOn* LoadCatalog(const char* signature,
|
||||||
|
const char* language = NULL,
|
||||||
|
int32 fingerprint = 0) const;
|
||||||
|
BCatalogAddOn* LoadEmbeddedCatalog(entry_ref* appOrAddOnRef);
|
||||||
|
status_t UnloadCatalog(BCatalogAddOn* addOn);
|
||||||
|
|
||||||
|
BCatalogAddOn* CreateCatalog(const char* type,
|
||||||
|
const char* signature,
|
||||||
|
const char* language);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern MutableLocaleRoster* mutable_locale_roster;
|
||||||
|
|
||||||
|
|
||||||
|
typedef BCatalogAddOn* (*InstantiateCatalogFunc)(const char* name,
|
||||||
|
const char* language, uint32 fingerprint);
|
||||||
|
|
||||||
|
typedef BCatalogAddOn* (*CreateCatalogFunc)(const char* name,
|
||||||
|
const char* language);
|
||||||
|
|
||||||
|
typedef BCatalogAddOn* (*InstantiateEmbeddedCatalogFunc)(
|
||||||
|
entry_ref* appOrAddOnRef);
|
||||||
|
|
||||||
|
typedef status_t (*GetAvailableLanguagesFunc)(BMessage*, const char*,
|
||||||
|
const char*, int32);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* info about a single catalog-add-on (representing a catalog type):
|
||||||
|
*/
|
||||||
|
struct CatalogAddOnInfo {
|
||||||
|
InstantiateCatalogFunc fInstantiateFunc;
|
||||||
|
InstantiateEmbeddedCatalogFunc fInstantiateEmbeddedFunc;
|
||||||
|
CreateCatalogFunc fCreateFunc;
|
||||||
|
GetAvailableLanguagesFunc fLanguagesFunc;
|
||||||
|
|
||||||
|
BString fName;
|
||||||
|
BString fPath;
|
||||||
|
image_id fAddOnImage;
|
||||||
|
uint8 fPriority;
|
||||||
|
BList fLoadedCatalogs;
|
||||||
|
bool fIsEmbedded;
|
||||||
|
// an embedded add-on actually isn't an
|
||||||
|
// add-on, it is included as part of the
|
||||||
|
// library.
|
||||||
|
// The DefaultCatalog is such a beast!
|
||||||
|
|
||||||
|
CatalogAddOnInfo(const BString& name,
|
||||||
|
const BString& path, uint8 priority);
|
||||||
|
~CatalogAddOnInfo();
|
||||||
|
|
||||||
|
bool MakeSureItsLoaded();
|
||||||
|
void UnloadIfPossible();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The global data that is shared between all roster-objects of a process.
|
||||||
|
*/
|
||||||
|
struct RosterData {
|
||||||
|
BLocker fLock;
|
||||||
|
BList fCatalogAddOnInfos;
|
||||||
|
BMessage fPreferredLanguages;
|
||||||
|
|
||||||
|
BCollator fDefaultCollator;
|
||||||
|
BCountry fDefaultCountry;
|
||||||
|
BLanguage fDefaultLanguage;
|
||||||
|
BTimeZone fDefaultTimeZone;
|
||||||
|
|
||||||
|
RosterData();
|
||||||
|
~RosterData();
|
||||||
|
|
||||||
|
void InitializeCatalogAddOns();
|
||||||
|
void CleanupCatalogAddOns();
|
||||||
|
status_t Refresh();
|
||||||
|
|
||||||
|
static int CompareInfos(const void* left,
|
||||||
|
const void* right);
|
||||||
|
|
||||||
|
status_t SetDefaultCountry(const BCountry& country);
|
||||||
|
status_t SetDefaultTimeZone(const BTimeZone& zone);
|
||||||
|
status_t SetPreferredLanguages(const BMessage* msg);
|
||||||
|
private:
|
||||||
|
status_t _LoadLocaleSettings();
|
||||||
|
status_t _SaveLocaleSettings();
|
||||||
|
|
||||||
|
status_t _LoadTimeSettings();
|
||||||
|
status_t _SaveTimeSettings();
|
||||||
|
|
||||||
|
status_t _SetDefaultCountry(const BCountry& country);
|
||||||
|
status_t _SetDefaultTimeZone(const BTimeZone& zone);
|
||||||
|
status_t _SetPreferredLanguages(const BMessage* msg);
|
||||||
|
|
||||||
|
status_t _AddDefaultCountryToMessage(
|
||||||
|
BMessage* message) const;
|
||||||
|
status_t _AddDefaultTimeZoneToMessage(
|
||||||
|
BMessage* message) const;
|
||||||
|
status_t _AddPreferredLanguagesToMessage(
|
||||||
|
BMessage* message) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern RosterData gRosterData;
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace BPrivate
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _MUTABLE_LOCALE_ROSTER_H_
|
||||||
@@ -22,6 +22,7 @@
|
|||||||
#include <AppFileInfo.h>
|
#include <AppFileInfo.h>
|
||||||
#include <Application.h>
|
#include <Application.h>
|
||||||
#include <Bitmap.h>
|
#include <Bitmap.h>
|
||||||
|
#include <DurationFormat.h>
|
||||||
#include <File.h>
|
#include <File.h>
|
||||||
#include <FindDirectory.h>
|
#include <FindDirectory.h>
|
||||||
#include <Font.h>
|
#include <Font.h>
|
||||||
@@ -36,7 +37,6 @@
|
|||||||
#include <ScrollView.h>
|
#include <ScrollView.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
#include <StringView.h>
|
#include <StringView.h>
|
||||||
#include <TimeFormat.h>
|
|
||||||
#include <TranslationUtils.h>
|
#include <TranslationUtils.h>
|
||||||
#include <TranslatorFormats.h>
|
#include <TranslatorFormats.h>
|
||||||
#include <View.h>
|
#include <View.h>
|
||||||
@@ -1724,12 +1724,14 @@ MemUsageToString(char string[], size_t size, system_info* info)
|
|||||||
static const char*
|
static const char*
|
||||||
UptimeToString(char string[], size_t size)
|
UptimeToString(char string[], size_t size)
|
||||||
{
|
{
|
||||||
BTimeFormat formatter;
|
BDurationFormat formatter;
|
||||||
BString str;
|
BString str;
|
||||||
|
|
||||||
formatter.Format(system_time() / 1000000, &str);
|
bigtime_t uptime = system_time();
|
||||||
|
bigtime_t now = (bigtime_t)time(NULL) * 1000000;
|
||||||
|
formatter.Format(now - uptime, now, &str);
|
||||||
str.CopyInto(string, 0, size);
|
str.CopyInto(string, 0, size);
|
||||||
string[str.Length()] = '\0';
|
string[std::min((size_t)str.Length(), size)] = '\0';
|
||||||
|
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -515,7 +515,7 @@ TBarApp::MessageReceived(BMessage* message)
|
|||||||
|
|
||||||
case B_LOCALE_CHANGED:
|
case B_LOCALE_CHANGED:
|
||||||
{
|
{
|
||||||
be_locale_roster->UpdateSettings(message);
|
be_locale_roster->Refresh();
|
||||||
|
|
||||||
BMessenger(fBarWindow->FindView("_deskbar_tv_")).SendMessage(
|
BMessenger(fBarWindow->FindView("_deskbar_tv_")).SendMessage(
|
||||||
message);
|
message);
|
||||||
|
|||||||
@@ -89,10 +89,10 @@ CalendarMenuWindow::CalendarMenuWindow(BPoint where)
|
|||||||
fCalendarView(NULL),
|
fCalendarView(NULL),
|
||||||
fSuppressFirstClose(true)
|
fSuppressFirstClose(true)
|
||||||
{
|
{
|
||||||
BCountry* here;
|
BCountry country;
|
||||||
be_locale_roster->GetDefaultCountry(&here);
|
be_locale_roster->GetDefaultCountry(&country);
|
||||||
BPrivate::week_start startOfWeek
|
BPrivate::week_start startOfWeek
|
||||||
= (BPrivate::week_start)here->StartOfWeek();
|
= (BPrivate::week_start)country.StartOfWeek();
|
||||||
|
|
||||||
RemoveShortcut('H', B_COMMAND_KEY | B_CONTROL_KEY);
|
RemoveShortcut('H', B_COMMAND_KEY | B_CONTROL_KEY);
|
||||||
AddShortcut('W', B_COMMAND_KEY, new BMessage(B_QUIT_REQUESTED));
|
AddShortcut('W', B_COMMAND_KEY, new BMessage(B_QUIT_REQUESTED));
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ TTimeView::TTimeView(float maxWidth, float height, bool showSeconds,
|
|||||||
fLastDateStr[0] = 0;
|
fLastDateStr[0] = 0;
|
||||||
fNeedToUpdate = true;
|
fNeedToUpdate = true;
|
||||||
|
|
||||||
be_locale_roster->GetDefaultCountry(&fHere);
|
be_locale_roster->GetDefaultCountry(&fCountry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@ TTimeView::TTimeView(BMessage* data)
|
|||||||
data->FindBool("interval", &fInterval);
|
data->FindBool("interval", &fInterval);
|
||||||
fShowingDate = false;
|
fShowingDate = false;
|
||||||
|
|
||||||
be_locale_roster->GetDefaultCountry(&fHere);
|
be_locale_roster->GetDefaultCountry(&fCountry);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -313,7 +313,7 @@ TTimeView::GetCurrentTime()
|
|||||||
fMinute = time.tm_min;
|
fMinute = time.tm_min;
|
||||||
fHour = time.tm_hour;
|
fHour = time.tm_hour;
|
||||||
|
|
||||||
fHere->FormatTime(fTimeStr, 64, fTime, fShowSeconds);
|
fCountry.FormatTime(fTimeStr, 64, fTime, fShowSeconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -322,7 +322,7 @@ TTimeView::GetCurrentDate()
|
|||||||
{
|
{
|
||||||
char tmp[64];
|
char tmp[64];
|
||||||
|
|
||||||
fHere->FormatDate(tmp, 64, fTime, fFullDate && CanShowFullDate());
|
fCountry.FormatDate(tmp, 64, fTime, fFullDate && CanShowFullDate());
|
||||||
|
|
||||||
// remove leading 0 from date when month is less than 10 (MM/DD/YY)
|
// remove leading 0 from date when month is less than 10 (MM/DD/YY)
|
||||||
// or remove leading 0 from date when day is less than 10 (DD/MM/YY)
|
// or remove leading 0 from date when day is less than 10 (DD/MM/YY)
|
||||||
@@ -465,6 +465,7 @@ TTimeView::AllowFullDate(bool allow)
|
|||||||
void
|
void
|
||||||
TTimeView::Update()
|
TTimeView::Update()
|
||||||
{
|
{
|
||||||
|
be_locale_roster->GetDefaultCountry(&fCountry);
|
||||||
GetCurrentTime();
|
GetCurrentTime();
|
||||||
GetCurrentDate();
|
GetCurrentDate();
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ All rights reserved.
|
|||||||
|
|
||||||
|
|
||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
|
#include <Country.h>
|
||||||
#include <Messenger.h>
|
#include <Messenger.h>
|
||||||
#include <View.h>
|
#include <View.h>
|
||||||
|
|
||||||
@@ -128,7 +129,7 @@ class TTimeView : public BView {
|
|||||||
BMessenger fCalendarWindow;
|
BMessenger fCalendarWindow;
|
||||||
BMessageRunner* fLongClickMessageRunner;
|
BMessageRunner* fLongClickMessageRunner;
|
||||||
|
|
||||||
BCountry* fHere; // For date and time localizing purposes
|
BCountry fCountry; // For date and time localizing purposes
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
#include <GroupLayoutBuilder.h>
|
#include <GroupLayoutBuilder.h>
|
||||||
#include <ListView.h>
|
#include <ListView.h>
|
||||||
#include <Locale.h>
|
#include <Locale.h>
|
||||||
#include <LocaleRoster.h>
|
#include <MutableLocaleRoster.h>
|
||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
#include <ScrollView.h>
|
#include <ScrollView.h>
|
||||||
#include <SeparatorView.h>
|
#include <SeparatorView.h>
|
||||||
@@ -32,6 +32,9 @@
|
|||||||
#include "KeymapListItem.h"
|
#include "KeymapListItem.h"
|
||||||
|
|
||||||
|
|
||||||
|
using BPrivate::mutable_locale_roster;
|
||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
MSG_LANGUAGE_SELECTED = 'lngs',
|
MSG_LANGUAGE_SELECTED = 'lngs',
|
||||||
MSG_KEYMAP_SELECTED = 'kmps'
|
MSG_KEYMAP_SELECTED = 'kmps'
|
||||||
@@ -156,7 +159,8 @@ BootPromptWindow::MessageReceived(BMessage* message)
|
|||||||
BMessage preferredLanguages;
|
BMessage preferredLanguages;
|
||||||
preferredLanguages.AddString("language",
|
preferredLanguages.AddString("language",
|
||||||
languageItem->Language());
|
languageItem->Language());
|
||||||
be_locale_roster->SetPreferredLanguages(&preferredLanguages);
|
mutable_locale_roster->SetPreferredLanguages(
|
||||||
|
&preferredLanguages);
|
||||||
_InitCatalog(true);
|
_InitCatalog(true);
|
||||||
}
|
}
|
||||||
// Calling it here is a cheap way of preventing the user to have
|
// Calling it here is a cheap way of preventing the user to have
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
SubDir HAIKU_TOP src apps readonlybootprompt ;
|
SubDir HAIKU_TOP src apps readonlybootprompt ;
|
||||||
|
|
||||||
UsePrivateHeaders interface shared ;
|
UsePrivateHeaders interface locale shared ;
|
||||||
|
|
||||||
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src preferences keymap ] ;
|
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src preferences keymap ] ;
|
||||||
|
|
||||||
|
|||||||
@@ -84,10 +84,10 @@ TimedAlert::GetLabel(BString &string)
|
|||||||
time(&t);
|
time(&t);
|
||||||
localtime_r(&t, &tm);
|
localtime_r(&t, &tm);
|
||||||
|
|
||||||
BCountry* here;
|
BCountry here;
|
||||||
be_locale_roster->GetDefaultCountry(&here);
|
be_locale_roster->GetDefaultCountry(&here);
|
||||||
|
|
||||||
here->FormatTime(timestring, 15, t, false);
|
here.FormatTime(timestring, 15, t, false);
|
||||||
|
|
||||||
string += " ";
|
string += " ";
|
||||||
string += timestring;
|
string += timestring;
|
||||||
|
|||||||
@@ -10,11 +10,14 @@
|
|||||||
|
|
||||||
#include <Application.h>
|
#include <Application.h>
|
||||||
#include <Locale.h>
|
#include <Locale.h>
|
||||||
#include <LocaleRoster.h>
|
#include <MutableLocaleRoster.h>
|
||||||
#include <Node.h>
|
#include <Node.h>
|
||||||
#include <Roster.h>
|
#include <Roster.h>
|
||||||
|
|
||||||
|
|
||||||
|
using BPrivate::mutable_locale_roster;
|
||||||
|
|
||||||
|
|
||||||
//#pragma mark - BCatalog
|
//#pragma mark - BCatalog
|
||||||
BCatalog::BCatalog()
|
BCatalog::BCatalog()
|
||||||
:
|
:
|
||||||
@@ -26,13 +29,14 @@ BCatalog::BCatalog()
|
|||||||
BCatalog::BCatalog(const char *signature, const char *language,
|
BCatalog::BCatalog(const char *signature, const char *language,
|
||||||
uint32 fingerprint)
|
uint32 fingerprint)
|
||||||
{
|
{
|
||||||
fCatalog = be_locale_roster->LoadCatalog(signature, language, fingerprint);
|
fCatalog
|
||||||
|
= mutable_locale_roster->LoadCatalog(signature, language, fingerprint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BCatalog::~BCatalog()
|
BCatalog::~BCatalog()
|
||||||
{
|
{
|
||||||
be_locale_roster->UnloadCatalog(fCatalog);
|
mutable_locale_roster->UnloadCatalog(fCatalog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -101,8 +105,7 @@ BCatalog::SetCatalog(const char* signature, uint32 fingerprint)
|
|||||||
// properly maintained.
|
// properly maintained.
|
||||||
// No other method should touch fCatalog directly, either (constructor for
|
// No other method should touch fCatalog directly, either (constructor for
|
||||||
// example)
|
// example)
|
||||||
fCatalog
|
fCatalog = mutable_locale_roster->LoadCatalog(signature, NULL, fingerprint);
|
||||||
= be_locale_roster->LoadCatalog(signature, NULL, fingerprint);
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -255,12 +258,19 @@ BCatalogAddOn::CountItems() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BCatalogAddOn::SetNext(BCatalogAddOn *next)
|
||||||
|
{
|
||||||
|
fNext = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//#pragma mark - EditableCatalog
|
//#pragma mark - EditableCatalog
|
||||||
namespace BPrivate {
|
namespace BPrivate {
|
||||||
EditableCatalog::EditableCatalog(const char *type, const char *signature,
|
EditableCatalog::EditableCatalog(const char *type, const char *signature,
|
||||||
const char *language)
|
const char *language)
|
||||||
{
|
{
|
||||||
fCatalog = be_locale_roster->CreateCatalog(type, signature, language);
|
fCatalog = mutable_locale_roster->CreateCatalog(type, signature, language);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,6 @@ BLocaleRoster::GetCatalog()
|
|||||||
asm volatile(".hidden _ZN13BLocaleRoster10GetCatalogEv");
|
asm volatile(".hidden _ZN13BLocaleRoster10GetCatalogEv");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return GetCatalog(&sCatalog, &sCatalogInitOnce);
|
return _GetCatalog(&sCatalog, &sCatalogInitOnce);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,23 +5,24 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <typeinfo>
|
||||||
|
|
||||||
#include <Collator.h>
|
#include <Collator.h>
|
||||||
#include <UnicodeChar.h>
|
#include <UnicodeChar.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
#include <Message.h>
|
#include <Message.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <typeinfo>
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#include <unicode/coll.h>
|
#include <unicode/coll.h>
|
||||||
#include <unicode/tblcoll.h>
|
#include <unicode/tblcoll.h>
|
||||||
|
|
||||||
|
|
||||||
BCollator::BCollator()
|
BCollator::BCollator()
|
||||||
:
|
:
|
||||||
fFallbackICUCollator(NULL),
|
fDefaultStrength(B_COLLATE_PRIMARY),
|
||||||
fStrength(B_COLLATE_PRIMARY),
|
|
||||||
fIgnorePunctuation(true)
|
fIgnorePunctuation(true)
|
||||||
{
|
{
|
||||||
// TODO: the collator construction will have to change; the default
|
// TODO: the collator construction will have to change; the default
|
||||||
@@ -33,11 +34,9 @@ BCollator::BCollator()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BCollator::BCollator(const char *locale, int8 strength,
|
BCollator::BCollator(const char* locale, int8 strength, bool ignorePunctuation)
|
||||||
bool ignorePunctuation)
|
|
||||||
:
|
:
|
||||||
fFallbackICUCollator(NULL),
|
fDefaultStrength(strength),
|
||||||
fStrength(strength),
|
|
||||||
fIgnorePunctuation(ignorePunctuation)
|
fIgnorePunctuation(ignorePunctuation)
|
||||||
{
|
{
|
||||||
UErrorCode error = U_ZERO_ERROR;
|
UErrorCode error = U_ZERO_ERROR;
|
||||||
@@ -45,57 +44,80 @@ BCollator::BCollator(const char *locale, int8 strength,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BCollator::BCollator(BMessage *archive)
|
BCollator::BCollator(BMessage* archive)
|
||||||
: BArchivable(archive),
|
:
|
||||||
|
BArchivable(archive),
|
||||||
fICUCollator(NULL),
|
fICUCollator(NULL),
|
||||||
fFallbackICUCollator(NULL),
|
fDefaultStrength(B_COLLATE_PRIMARY),
|
||||||
fIgnorePunctuation(true)
|
fIgnorePunctuation(true)
|
||||||
{
|
{
|
||||||
int32 data;
|
int32 data;
|
||||||
if (archive->FindInt32("loc:strength", &data) == B_OK)
|
if (archive->FindInt32("loc:strength", &data) == B_OK)
|
||||||
fStrength = (uint8)data;
|
fDefaultStrength = (uint8)data;
|
||||||
else
|
else
|
||||||
fStrength = B_COLLATE_PRIMARY;
|
fDefaultStrength = B_COLLATE_PRIMARY;
|
||||||
|
|
||||||
if (archive->FindBool("loc:punctuation", &fIgnorePunctuation) != B_OK)
|
archive->FindBool("loc:punctuation", &fIgnorePunctuation);
|
||||||
fIgnorePunctuation = true;
|
|
||||||
|
|
||||||
UErrorCode error = U_ZERO_ERROR;
|
UErrorCode error = U_ZERO_ERROR;
|
||||||
fFallbackICUCollator = static_cast<RuleBasedCollator*>
|
RuleBasedCollator* fallbackICUCollator
|
||||||
(Collator::createInstance(error));
|
= static_cast<RuleBasedCollator*>(Collator::createInstance(error));
|
||||||
|
|
||||||
ssize_t size;
|
ssize_t size;
|
||||||
const void* buffer = NULL;
|
const void* buffer = NULL;
|
||||||
if (archive->FindData("loc:collator", B_RAW_TYPE, &buffer, &size) == B_OK) {
|
if (archive->FindData("loc:collator", B_RAW_TYPE, &buffer, &size) == B_OK) {
|
||||||
fICUCollator = new RuleBasedCollator((const uint8_t*)buffer, (int)size,
|
fICUCollator = new RuleBasedCollator((const uint8_t*)buffer, (int)size,
|
||||||
fFallbackICUCollator, error);
|
fallbackICUCollator, error);
|
||||||
if (fICUCollator == NULL) {
|
if (fICUCollator == NULL) {
|
||||||
fICUCollator = fFallbackICUCollator;
|
fICUCollator = fallbackICUCollator;
|
||||||
// Unarchiving failed, so we revert to the fallback collator
|
// Unarchiving failed, so we revert to the fallback collator
|
||||||
|
// TODO: when can this happen, can it be avoided?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BCollator::BCollator(const BCollator& other)
|
||||||
|
:
|
||||||
|
fICUCollator(NULL)
|
||||||
|
{
|
||||||
|
*this = other;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BCollator::~BCollator()
|
BCollator::~BCollator()
|
||||||
{
|
{
|
||||||
delete fICUCollator;
|
delete fICUCollator;
|
||||||
fICUCollator = NULL;
|
}
|
||||||
delete fFallbackICUCollator;
|
|
||||||
|
|
||||||
|
BCollator& BCollator::operator=(const BCollator& source)
|
||||||
|
{
|
||||||
|
if (&source != this) {
|
||||||
|
delete fICUCollator;
|
||||||
|
|
||||||
|
fICUCollator = source.fICUCollator != NULL
|
||||||
|
? source.fICUCollator->clone()
|
||||||
|
: NULL;
|
||||||
|
fDefaultStrength = source.fDefaultStrength;
|
||||||
|
fIgnorePunctuation = source.fIgnorePunctuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BCollator::SetDefaultStrength(int8 strength)
|
BCollator::SetDefaultStrength(int8 strength)
|
||||||
{
|
{
|
||||||
fStrength = strength;
|
fDefaultStrength = strength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int8
|
int8
|
||||||
BCollator::DefaultStrength() const
|
BCollator::DefaultStrength() const
|
||||||
{
|
{
|
||||||
return fStrength;
|
return fDefaultStrength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -114,31 +136,11 @@ BCollator::IgnorePunctuation() const
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BCollator::GetSortKey(const char *string, BString *key, int8 strength)
|
BCollator::GetSortKey(const char* string, BString* key, int8 strength) const
|
||||||
{
|
{
|
||||||
|
_SetStrength(strength);
|
||||||
|
|
||||||
// TODO : handle fIgnorePunctuation
|
// TODO : handle fIgnorePunctuation
|
||||||
if (strength == B_COLLATE_DEFAULT)
|
|
||||||
strength = fStrength;
|
|
||||||
Collator::ECollationStrength icuStrength;
|
|
||||||
switch (strength) {
|
|
||||||
case B_COLLATE_PRIMARY:
|
|
||||||
icuStrength = Collator::PRIMARY;
|
|
||||||
break;
|
|
||||||
case B_COLLATE_SECONDARY:
|
|
||||||
icuStrength = Collator::SECONDARY;
|
|
||||||
break;
|
|
||||||
case B_COLLATE_TERTIARY:
|
|
||||||
default:
|
|
||||||
icuStrength = Collator::TERTIARY;
|
|
||||||
break;
|
|
||||||
case B_COLLATE_QUATERNARY:
|
|
||||||
icuStrength = Collator::QUATERNARY;
|
|
||||||
break;
|
|
||||||
case B_COLLATE_IDENTICAL:
|
|
||||||
icuStrength = Collator::IDENTICAL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
fICUCollator->setStrength(icuStrength);
|
|
||||||
|
|
||||||
int length = strlen(string);
|
int length = strlen(string);
|
||||||
|
|
||||||
@@ -154,6 +156,7 @@ BCollator::GetSortKey(const char *string, BString *key, int8 strength)
|
|||||||
buffer = (uint8_t*)realloc(buffer, requiredSize);
|
buffer = (uint8_t*)realloc(buffer, requiredSize);
|
||||||
if (buffer == NULL)
|
if (buffer == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
error = U_ZERO_ERROR;
|
error = U_ZERO_ERROR;
|
||||||
fICUCollator->getSortKey(UnicodeString(string, length, NULL, error),
|
fICUCollator->getSortKey(UnicodeString(string, length, NULL, error),
|
||||||
buffer, requiredSize);
|
buffer, requiredSize);
|
||||||
@@ -164,50 +167,32 @@ BCollator::GetSortKey(const char *string, BString *key, int8 strength)
|
|||||||
|
|
||||||
if (error == U_ZERO_ERROR)
|
if (error == U_ZERO_ERROR)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
BCollator::Compare(const char *a, const char *b, int32 length, int8 strength)
|
BCollator::Compare(const char* s1, const char* s2, int8 strength) const
|
||||||
{
|
{
|
||||||
|
_SetStrength(strength);
|
||||||
|
|
||||||
// TODO : handle fIgnorePunctuation
|
// TODO : handle fIgnorePunctuation
|
||||||
if (strength == B_COLLATE_DEFAULT)
|
|
||||||
strength = fStrength;
|
|
||||||
Collator::ECollationStrength icuStrength;
|
|
||||||
switch (strength) {
|
|
||||||
case B_COLLATE_PRIMARY:
|
|
||||||
icuStrength = Collator::PRIMARY;
|
|
||||||
break;
|
|
||||||
case B_COLLATE_SECONDARY:
|
|
||||||
icuStrength = Collator::SECONDARY;
|
|
||||||
break;
|
|
||||||
case B_COLLATE_TERTIARY:
|
|
||||||
default:
|
|
||||||
icuStrength = Collator::TERTIARY;
|
|
||||||
break;
|
|
||||||
case B_COLLATE_QUATERNARY:
|
|
||||||
icuStrength = Collator::QUATERNARY;
|
|
||||||
break;
|
|
||||||
case B_COLLATE_IDENTICAL:
|
|
||||||
icuStrength = Collator::IDENTICAL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
fICUCollator->setStrength(icuStrength);
|
|
||||||
UErrorCode error = U_ZERO_ERROR;
|
UErrorCode error = U_ZERO_ERROR;
|
||||||
return fICUCollator->compare(a, b, error);
|
return fICUCollator->compare(s1, s2, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BCollator::Archive(BMessage *archive, bool deep) const
|
BCollator::Archive(BMessage* archive, bool deep) const
|
||||||
{
|
{
|
||||||
status_t status = BArchivable::Archive(archive, deep);
|
status_t status = BArchivable::Archive(archive, deep);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
if (status == B_OK)
|
if (status == B_OK)
|
||||||
status = archive->AddInt32("loc:strength", fStrength);
|
status = archive->AddInt32("loc:strength", fDefaultStrength);
|
||||||
if (status == B_OK)
|
if (status == B_OK)
|
||||||
status = archive->AddBool("loc:punctuation", fIgnorePunctuation);
|
status = archive->AddBool("loc:punctuation", fIgnorePunctuation);
|
||||||
|
|
||||||
@@ -231,13 +216,42 @@ BCollator::Archive(BMessage *archive, bool deep) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BArchivable *
|
BArchivable*
|
||||||
BCollator::Instantiate(BMessage *archive)
|
BCollator::Instantiate(BMessage* archive)
|
||||||
{
|
{
|
||||||
if (validate_instantiation(archive, "BCollator"))
|
if (validate_instantiation(archive, "BCollator"))
|
||||||
return new BCollator(archive);
|
return new(std::nothrow) BCollator(archive);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BCollator::_SetStrength(int8 strength) const
|
||||||
|
{
|
||||||
|
if (strength == B_COLLATE_DEFAULT)
|
||||||
|
strength = fDefaultStrength;
|
||||||
|
|
||||||
|
Collator::ECollationStrength icuStrength;
|
||||||
|
switch (strength) {
|
||||||
|
case B_COLLATE_PRIMARY:
|
||||||
|
icuStrength = Collator::PRIMARY;
|
||||||
|
break;
|
||||||
|
case B_COLLATE_SECONDARY:
|
||||||
|
icuStrength = Collator::SECONDARY;
|
||||||
|
break;
|
||||||
|
case B_COLLATE_TERTIARY:
|
||||||
|
default:
|
||||||
|
icuStrength = Collator::TERTIARY;
|
||||||
|
break;
|
||||||
|
case B_COLLATE_QUATERNARY:
|
||||||
|
icuStrength = Collator::QUATERNARY;
|
||||||
|
break;
|
||||||
|
case B_COLLATE_IDENTICAL:
|
||||||
|
icuStrength = Collator::IDENTICAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fICUCollator->setStrength(icuStrength);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|||||||
+193
-549
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Oliver Tappe <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <DateFormat.h>
|
||||||
|
|
||||||
|
|
||||||
|
// default constructor
|
||||||
|
BDateFormat::BDateFormat()
|
||||||
|
: BDateTimeFormat()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy constructor
|
||||||
|
BDateFormat::BDateFormat(const BDateFormat &other)
|
||||||
|
: BDateTimeFormat(other)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
BDateFormat::~BDateFormat()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format
|
||||||
|
status_t
|
||||||
|
BDateFormat::Format(bigtime_t value, BString* buffer) const
|
||||||
|
{
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Oliver Tappe <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <DateTimeFormat.h>
|
||||||
|
|
||||||
|
|
||||||
|
// default constructor
|
||||||
|
BDateTimeFormat::BDateTimeFormat()
|
||||||
|
: BFormat()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy constructor
|
||||||
|
BDateTimeFormat::BDateTimeFormat(const BDateTimeFormat &other)
|
||||||
|
: BFormat(other)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
BDateTimeFormat::~BDateTimeFormat()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format
|
||||||
|
status_t
|
||||||
|
BDateTimeFormat::Format(bigtime_t value, BString* buffer) const
|
||||||
|
{
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
#include <Roster.h>
|
#include <Roster.h>
|
||||||
|
|
||||||
#include <DefaultCatalog.h>
|
#include <DefaultCatalog.h>
|
||||||
#include <LocaleRoster.h>
|
#include <MutableLocaleRoster.h>
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Oliver Tappe <[email protected]>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <DurationFormat.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include <unicode/calendar.h>
|
||||||
|
#include <unicode/tmunit.h>
|
||||||
|
#include <unicode/utypes.h>
|
||||||
|
|
||||||
|
#include <AutoDeleter.h>
|
||||||
|
#include <TimeUnitFormat.h>
|
||||||
|
|
||||||
|
|
||||||
|
using BPrivate::ObjectDeleter;
|
||||||
|
|
||||||
|
|
||||||
|
// maps our unit element to the corresponding ICU unit
|
||||||
|
static const UCalendarDateFields skUnitMap[] = {
|
||||||
|
UCAL_YEAR,
|
||||||
|
UCAL_MONTH,
|
||||||
|
UCAL_WEEK_OF_MONTH,
|
||||||
|
UCAL_DAY_OF_WEEK,
|
||||||
|
UCAL_HOUR_OF_DAY,
|
||||||
|
UCAL_MINUTE,
|
||||||
|
UCAL_SECOND,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
status_t BDurationFormat::Format(bigtime_t startValue, bigtime_t stopValue,
|
||||||
|
BString* buffer, time_unit_style style, const BString& separator) const
|
||||||
|
{
|
||||||
|
if (buffer == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
UErrorCode icuStatus = U_ZERO_ERROR;
|
||||||
|
ObjectDeleter<Calendar> calendar = Calendar::createInstance(icuStatus);
|
||||||
|
if (calendar.Get() == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
if (!U_SUCCESS(icuStatus))
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
calendar->setTime((UDate)startValue / 1000, icuStatus);
|
||||||
|
if (!U_SUCCESS(icuStatus))
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
BTimeUnitFormat timeUnitFormat;
|
||||||
|
UDate stop = (UDate)stopValue / 1000;
|
||||||
|
bool needSeparator = false;
|
||||||
|
for (int unit = 0; unit <= B_TIME_UNIT_LAST; ++unit) {
|
||||||
|
int delta = calendar->fieldDifference(stop, skUnitMap[unit], icuStatus);
|
||||||
|
if (!U_SUCCESS(icuStatus))
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
if (delta != 0) {
|
||||||
|
if (needSeparator)
|
||||||
|
buffer->Append(separator);
|
||||||
|
else
|
||||||
|
needSeparator = true;
|
||||||
|
status_t status = timeUnitFormat.Format(delta,
|
||||||
|
(time_unit_element)unit, buffer, style);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
@@ -18,8 +18,17 @@ local sources =
|
|||||||
LibraryInit.cpp
|
LibraryInit.cpp
|
||||||
Locale.cpp
|
Locale.cpp
|
||||||
LocaleRoster.cpp
|
LocaleRoster.cpp
|
||||||
|
MutableLocaleRoster.cpp
|
||||||
TimeZone.cpp
|
TimeZone.cpp
|
||||||
|
|
||||||
|
# in progress
|
||||||
|
DateFormat.cpp
|
||||||
|
DateTimeFormat.cpp
|
||||||
|
DurationFormat.cpp
|
||||||
|
TimeFormat.cpp
|
||||||
|
TimeUnitFormat.cpp
|
||||||
|
|
||||||
|
# old, needs investigation
|
||||||
Currency.cpp
|
Currency.cpp
|
||||||
FloatFormat.cpp
|
FloatFormat.cpp
|
||||||
FloatFormatImpl.cpp
|
FloatFormatImpl.cpp
|
||||||
@@ -36,7 +45,6 @@ local sources =
|
|||||||
NumberFormatImpl.cpp
|
NumberFormatImpl.cpp
|
||||||
NumberFormatParameters.cpp
|
NumberFormatParameters.cpp
|
||||||
PropertyFile.cpp
|
PropertyFile.cpp
|
||||||
TimeFormat.cpp
|
|
||||||
UnicodeChar.cpp
|
UnicodeChar.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,11 @@
|
|||||||
|
|
||||||
#include <Language.h>
|
#include <Language.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <Catalog.h>
|
#include <Catalog.h>
|
||||||
@@ -15,11 +20,6 @@
|
|||||||
#include <String.h>
|
#include <String.h>
|
||||||
#include <FindDirectory.h>
|
#include <FindDirectory.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#include <ICUWrapper.h>
|
#include <ICUWrapper.h>
|
||||||
|
|
||||||
#include <unicode/locid.h>
|
#include <unicode/locid.h>
|
||||||
@@ -28,91 +28,62 @@
|
|||||||
#define ICU_VERSION icu_44
|
#define ICU_VERSION icu_44
|
||||||
|
|
||||||
|
|
||||||
static const char *gBuiltInStrings[] = {
|
BLanguage::BLanguage()
|
||||||
"Yesterday",
|
:
|
||||||
"Today",
|
fDirection(B_LEFT_TO_RIGHT),
|
||||||
"Tomorrow",
|
fICULocale(NULL)
|
||||||
"Future",
|
{
|
||||||
|
SetTo(NULL);
|
||||||
"Sunday",
|
}
|
||||||
"Monday",
|
|
||||||
"Tuesday",
|
|
||||||
"Wednesday",
|
|
||||||
"Thursday",
|
|
||||||
"Friday",
|
|
||||||
"Saturday",
|
|
||||||
|
|
||||||
"Sun",
|
|
||||||
"Mon",
|
|
||||||
"Tue",
|
|
||||||
"Wed",
|
|
||||||
"Thu",
|
|
||||||
"Fri",
|
|
||||||
"Sat",
|
|
||||||
|
|
||||||
"January",
|
|
||||||
"February",
|
|
||||||
"March",
|
|
||||||
"April",
|
|
||||||
"May",
|
|
||||||
"June",
|
|
||||||
"July",
|
|
||||||
"August",
|
|
||||||
"September",
|
|
||||||
"October",
|
|
||||||
"November",
|
|
||||||
"December",
|
|
||||||
|
|
||||||
"Jan",
|
|
||||||
"Feb",
|
|
||||||
"Mar",
|
|
||||||
"Apr",
|
|
||||||
"May",
|
|
||||||
"Jun",
|
|
||||||
"Jul",
|
|
||||||
"Aug",
|
|
||||||
"Sep",
|
|
||||||
"Oct",
|
|
||||||
"Nov",
|
|
||||||
"Dec",
|
|
||||||
|
|
||||||
"^[yY]",
|
|
||||||
"^[nN]",
|
|
||||||
"yes",
|
|
||||||
"no"
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
BLanguage::BLanguage(const char* language)
|
BLanguage::BLanguage(const char* language)
|
||||||
:
|
:
|
||||||
fDirection(B_LEFT_TO_RIGHT)
|
fDirection(B_LEFT_TO_RIGHT),
|
||||||
|
fICULocale(NULL)
|
||||||
{
|
{
|
||||||
fICULocale = new ICU_VERSION::Locale(language);
|
SetTo(language);
|
||||||
|
}
|
||||||
|
|
||||||
for (int32 i = B_NUM_LANGUAGE_STRINGS;i-- > 0;)
|
|
||||||
fStrings[i] = NULL;
|
BLanguage::BLanguage(const BLanguage& other)
|
||||||
|
:
|
||||||
|
fICULocale(NULL)
|
||||||
|
{
|
||||||
|
*this = other;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BLanguage::~BLanguage()
|
BLanguage::~BLanguage()
|
||||||
{
|
{
|
||||||
delete fICULocale;
|
delete fICULocale;
|
||||||
|
|
||||||
for (int32 i = B_NUM_LANGUAGE_STRINGS;i-- > 0;)
|
|
||||||
free(fStrings[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
status_t
|
||||||
BLanguage::Default()
|
BLanguage::SetTo(const char* language)
|
||||||
{
|
{
|
||||||
fICULocale = new ICU_VERSION::Locale("en");
|
delete fICULocale;
|
||||||
fDirection = B_LEFT_TO_RIGHT;
|
fICULocale = new ICU_VERSION::Locale(language);
|
||||||
|
if (fICULocale == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
for (int32 i = B_NUM_LANGUAGE_STRINGS;i-- > 0;) {
|
return B_OK;
|
||||||
free(fStrings[i]);
|
}
|
||||||
fStrings[i] = strdup(gBuiltInStrings[i]);
|
|
||||||
|
|
||||||
|
BLanguage& BLanguage::operator=(const BLanguage& source)
|
||||||
|
{
|
||||||
|
if (&source != this) {
|
||||||
|
delete fICULocale;
|
||||||
|
|
||||||
|
fICULocale = source.fICULocale != NULL
|
||||||
|
? source.fICULocale->clone()
|
||||||
|
: NULL;
|
||||||
|
fDirection = source.fDirection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -130,7 +101,11 @@ BLanguage::GetString(uint32 id) const
|
|||||||
|| id > B_LANGUAGE_STRINGS_BASE + B_NUM_LANGUAGE_STRINGS)
|
|| id > B_LANGUAGE_STRINGS_BASE + B_NUM_LANGUAGE_STRINGS)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return fStrings[id - B_LANGUAGE_STRINGS_BASE];
|
return NULL;
|
||||||
|
|
||||||
|
// TODO: fetch string from ICU
|
||||||
|
|
||||||
|
// return fStrings[id - B_LANGUAGE_STRINGS_BASE];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include "Catalog.h"
|
#include "Catalog.h"
|
||||||
#include "Locale.h"
|
#include "Locale.h"
|
||||||
#include "LocaleRoster.h"
|
#include "MutableLocaleRoster.h"
|
||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ CreateLocaleBackendInstance()
|
|||||||
|
|
||||||
LibbeLocaleBackend::LibbeLocaleBackend()
|
LibbeLocaleBackend::LibbeLocaleBackend()
|
||||||
{
|
{
|
||||||
be_locale_roster->GetSystemCatalog(&systemCatalog);
|
mutable_locale_roster->GetSystemCatalog(&systemCatalog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -38,5 +38,5 @@ BLocale::GetString(uint32 id)
|
|||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
return fLanguage->GetString(id);
|
return fLanguage.GetString(id);
|
||||||
}
|
}
|
||||||
|
|||||||
+179
-769
@@ -13,11 +13,10 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h> // for debug only
|
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
|
||||||
#include <AppFileInfo.h>
|
|
||||||
#include <Autolock.h>
|
#include <Autolock.h>
|
||||||
|
#include <AppFileInfo.h>
|
||||||
#include <Catalog.h>
|
#include <Catalog.h>
|
||||||
#include <Collator.h>
|
#include <Collator.h>
|
||||||
#include <Country.h>
|
#include <Country.h>
|
||||||
@@ -25,9 +24,9 @@
|
|||||||
#include <Directory.h>
|
#include <Directory.h>
|
||||||
#include <Entry.h>
|
#include <Entry.h>
|
||||||
#include <File.h>
|
#include <File.h>
|
||||||
#include <FindDirectory.h>
|
|
||||||
#include <Language.h>
|
#include <Language.h>
|
||||||
#include <Locale.h>
|
#include <Locale.h>
|
||||||
|
#include <MutableLocaleRoster.h>
|
||||||
#include <Node.h>
|
#include <Node.h>
|
||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
@@ -40,19 +39,20 @@
|
|||||||
#include <unicode/timezone.h>
|
#include <unicode/timezone.h>
|
||||||
|
|
||||||
|
|
||||||
|
using BPrivate::CatalogAddOnInfo;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* several attributes/resource-IDs used within the Locale Kit:
|
* several attributes/resource-IDs used within the Locale Kit:
|
||||||
*/
|
*/
|
||||||
static const char *kPriorityAttr = "ADDON:priority";
|
const char* BLocaleRoster::kCatLangAttr = "BEOS:LOCALE_LANGUAGE";
|
||||||
|
|
||||||
const char *BLocaleRoster::kCatLangAttr = "BEOS:LOCALE_LANGUAGE";
|
|
||||||
// name of catalog language, lives in every catalog file
|
// name of catalog language, lives in every catalog file
|
||||||
const char *BLocaleRoster::kCatSigAttr = "BEOS:LOCALE_SIGNATURE";
|
const char* BLocaleRoster::kCatSigAttr = "BEOS:LOCALE_SIGNATURE";
|
||||||
// catalog signature, lives in every catalog file
|
// catalog signature, lives in every catalog file
|
||||||
const char *BLocaleRoster::kCatFingerprintAttr = "BEOS:LOCALE_FINGERPRINT";
|
const char* BLocaleRoster::kCatFingerprintAttr = "BEOS:LOCALE_FINGERPRINT";
|
||||||
// catalog fingerprint, may live in catalog file
|
// catalog fingerprint, may live in catalog file
|
||||||
|
|
||||||
const char *BLocaleRoster::kEmbeddedCatAttr = "BEOS:LOCALE_EMBEDDED_CATALOG";
|
const char* BLocaleRoster::kEmbeddedCatAttr = "BEOS:LOCALE_EMBEDDED_CATALOG";
|
||||||
// attribute which contains flattened data of embedded catalog
|
// attribute which contains flattened data of embedded catalog
|
||||||
// this may live in an app- or add-on-file
|
// this may live in an app- or add-on-file
|
||||||
int32 BLocaleRoster::kEmbeddedCatResId = 0xCADA;
|
int32 BLocaleRoster::kEmbeddedCatResId = 0xCADA;
|
||||||
@@ -61,340 +61,6 @@ int32 BLocaleRoster::kEmbeddedCatResId = 0xCADA;
|
|||||||
// this may live in an app- or add-on-file
|
// this may live in an app- or add-on-file
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef BCatalogAddOn *(*InstantiateCatalogFunc)(const char *name,
|
|
||||||
const char *language, uint32 fingerprint);
|
|
||||||
|
|
||||||
typedef BCatalogAddOn *(*CreateCatalogFunc)(const char *name,
|
|
||||||
const char *language);
|
|
||||||
|
|
||||||
typedef BCatalogAddOn *(*InstantiateEmbeddedCatalogFunc)(
|
|
||||||
entry_ref *appOrAddOnRef);
|
|
||||||
|
|
||||||
typedef status_t (*GetAvailableLanguagesFunc)(BMessage*, const char*,
|
|
||||||
const char*, int32);
|
|
||||||
|
|
||||||
static BLocaleRoster gLocaleRoster;
|
|
||||||
BLocaleRoster *be_locale_roster = &gLocaleRoster;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* info about a single catalog-add-on (representing a catalog type):
|
|
||||||
*/
|
|
||||||
struct BCatalogAddOnInfo {
|
|
||||||
BString fName;
|
|
||||||
BString fPath;
|
|
||||||
image_id fAddOnImage;
|
|
||||||
InstantiateCatalogFunc fInstantiateFunc;
|
|
||||||
InstantiateEmbeddedCatalogFunc fInstantiateEmbeddedFunc;
|
|
||||||
CreateCatalogFunc fCreateFunc;
|
|
||||||
GetAvailableLanguagesFunc fLanguagesFunc;
|
|
||||||
uint8 fPriority;
|
|
||||||
BList fLoadedCatalogs;
|
|
||||||
bool fIsEmbedded;
|
|
||||||
// an embedded add-on actually isn't an add-on, it is included
|
|
||||||
// as part of the library. The DefaultCatalog is such a beast!
|
|
||||||
|
|
||||||
BCatalogAddOnInfo(const BString& name, const BString& path, uint8 priority);
|
|
||||||
~BCatalogAddOnInfo();
|
|
||||||
bool MakeSureItsLoaded();
|
|
||||||
void UnloadIfPossible();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
BCatalogAddOnInfo::BCatalogAddOnInfo(const BString& name, const BString& path,
|
|
||||||
uint8 priority)
|
|
||||||
:
|
|
||||||
fName(name),
|
|
||||||
fPath(path),
|
|
||||||
fAddOnImage(B_NO_INIT),
|
|
||||||
fInstantiateFunc(NULL),
|
|
||||||
fInstantiateEmbeddedFunc(NULL),
|
|
||||||
fCreateFunc(NULL),
|
|
||||||
fLanguagesFunc(NULL),
|
|
||||||
fPriority(priority),
|
|
||||||
fIsEmbedded(path.Length()==0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BCatalogAddOnInfo::~BCatalogAddOnInfo()
|
|
||||||
{
|
|
||||||
int32 count = fLoadedCatalogs.CountItems();
|
|
||||||
for (int32 i = 0; i < count; ++i) {
|
|
||||||
BCatalogAddOn* cat
|
|
||||||
= static_cast<BCatalogAddOn*>(fLoadedCatalogs.ItemAt(i));
|
|
||||||
delete cat;
|
|
||||||
}
|
|
||||||
fLoadedCatalogs.MakeEmpty();
|
|
||||||
UnloadIfPossible();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
BCatalogAddOnInfo::MakeSureItsLoaded()
|
|
||||||
{
|
|
||||||
if (!fIsEmbedded && fAddOnImage < B_OK) {
|
|
||||||
// add-on has not been loaded yet, so we try to load it:
|
|
||||||
BString fullAddOnPath(fPath);
|
|
||||||
fullAddOnPath << "/" << fName;
|
|
||||||
fAddOnImage = load_add_on(fullAddOnPath.String());
|
|
||||||
if (fAddOnImage >= B_OK) {
|
|
||||||
get_image_symbol(fAddOnImage, "instantiate_catalog",
|
|
||||||
B_SYMBOL_TYPE_TEXT, (void **)&fInstantiateFunc);
|
|
||||||
get_image_symbol(fAddOnImage, "instantiate_embedded_catalog",
|
|
||||||
B_SYMBOL_TYPE_TEXT, (void **)&fInstantiateEmbeddedFunc);
|
|
||||||
get_image_symbol(fAddOnImage, "create_catalog",
|
|
||||||
B_SYMBOL_TYPE_TEXT, (void **)&fCreateFunc);
|
|
||||||
get_image_symbol(fAddOnImage, "get_available_languages",
|
|
||||||
B_SYMBOL_TYPE_TEXT, (void **)&fLanguagesFunc);
|
|
||||||
log_team(LOG_DEBUG, "catalog-add-on %s has been loaded",
|
|
||||||
fName.String());
|
|
||||||
} else {
|
|
||||||
log_team(LOG_DEBUG, "could not load catalog-add-on %s (%s)",
|
|
||||||
fName.String(), strerror(fAddOnImage));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else if (fIsEmbedded) {
|
|
||||||
// The built-in catalog still has to provide this function
|
|
||||||
fLanguagesFunc = default_catalog_get_available_languages;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BCatalogAddOnInfo::UnloadIfPossible()
|
|
||||||
{
|
|
||||||
if (!fIsEmbedded && fLoadedCatalogs.IsEmpty()) {
|
|
||||||
unload_add_on(fAddOnImage);
|
|
||||||
fAddOnImage = B_NO_INIT;
|
|
||||||
fInstantiateFunc = NULL;
|
|
||||||
fInstantiateEmbeddedFunc = NULL;
|
|
||||||
fCreateFunc = NULL;
|
|
||||||
fLanguagesFunc = NULL;
|
|
||||||
// log_team(LOG_DEBUG, "catalog-add-on %s has been unloaded",
|
|
||||||
// fName.String());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* the global data that is shared between all roster-objects:
|
|
||||||
*/
|
|
||||||
struct RosterData {
|
|
||||||
BLocker fLock;
|
|
||||||
BList fCatalogAddOnInfos;
|
|
||||||
BMessage fPreferredLanguages;
|
|
||||||
// BString fCountryCodeName;
|
|
||||||
// BString fCountryDateFormat;
|
|
||||||
BCountry fDefaultCountry;
|
|
||||||
|
|
||||||
RosterData();
|
|
||||||
~RosterData();
|
|
||||||
void InitializeCatalogAddOns();
|
|
||||||
void CleanupCatalogAddOns();
|
|
||||||
static int CompareInfos(const void *left, const void *right);
|
|
||||||
void UpdateSettings(BMessage* newSettings);
|
|
||||||
};
|
|
||||||
static RosterData gRosterData;
|
|
||||||
|
|
||||||
|
|
||||||
RosterData::RosterData()
|
|
||||||
:
|
|
||||||
fLock("LocaleRosterData")
|
|
||||||
{
|
|
||||||
|
|
||||||
openlog_team("liblocale.so", LOG_PID, LOG_USER);
|
|
||||||
#ifndef DEBUG
|
|
||||||
setlogmask_team(LOG_UPTO(LOG_WARNING));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
InitializeCatalogAddOns();
|
|
||||||
|
|
||||||
// Load preferences to get the preferred languages
|
|
||||||
BPath path;
|
|
||||||
BFile file;
|
|
||||||
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) {
|
|
||||||
path.Append("Locale settings");
|
|
||||||
BMessage settingsMessage;
|
|
||||||
if (file.SetTo(path.Path(), B_READ_ONLY) == B_OK
|
|
||||||
&& settingsMessage.Unflatten(&file) == B_OK) {
|
|
||||||
UpdateSettings(&settingsMessage);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Something went wrong (no settings file or invalid BMessage
|
|
||||||
// set everything to default values
|
|
||||||
fPreferredLanguages.AddString("language", "en");
|
|
||||||
fDefaultCountry = BCountry("en_US");
|
|
||||||
log_team(LOG_ERR, "*** No language preference found!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RosterData::~RosterData()
|
|
||||||
{
|
|
||||||
BAutolock lock(fLock);
|
|
||||||
assert(lock.IsLocked());
|
|
||||||
CleanupCatalogAddOns();
|
|
||||||
closelog();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
RosterData::CompareInfos(const void *left, const void *right)
|
|
||||||
{
|
|
||||||
return ((BCatalogAddOnInfo*)right)->fPriority
|
|
||||||
- ((BCatalogAddOnInfo*)left)->fPriority;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
iterate over add-on-folders and collect information about each
|
|
||||||
catalog-add-ons (types of catalogs) into fCatalogAddOnInfos.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
RosterData::InitializeCatalogAddOns()
|
|
||||||
{
|
|
||||||
BAutolock lock(fLock);
|
|
||||||
assert(lock.IsLocked());
|
|
||||||
|
|
||||||
// add info about embedded default catalog:
|
|
||||||
BCatalogAddOnInfo *defaultCatalogAddOnInfo
|
|
||||||
= new(std::nothrow) BCatalogAddOnInfo("Default", "",
|
|
||||||
DefaultCatalog::kDefaultCatalogAddOnPriority);
|
|
||||||
if (!defaultCatalogAddOnInfo)
|
|
||||||
return;
|
|
||||||
|
|
||||||
defaultCatalogAddOnInfo->fInstantiateFunc = DefaultCatalog::Instantiate;
|
|
||||||
defaultCatalogAddOnInfo->fInstantiateEmbeddedFunc
|
|
||||||
= DefaultCatalog::InstantiateEmbedded;
|
|
||||||
defaultCatalogAddOnInfo->fCreateFunc = DefaultCatalog::Create;
|
|
||||||
fCatalogAddOnInfos.AddItem((void*)defaultCatalogAddOnInfo);
|
|
||||||
|
|
||||||
directory_which folders[] = {
|
|
||||||
B_COMMON_ADDONS_DIRECTORY,
|
|
||||||
B_SYSTEM_ADDONS_DIRECTORY,
|
|
||||||
static_cast<directory_which>(-1)
|
|
||||||
};
|
|
||||||
BPath addOnPath;
|
|
||||||
BDirectory addOnFolder;
|
|
||||||
char buf[4096];
|
|
||||||
status_t err;
|
|
||||||
for (int f = 0; folders[f]>=0; ++f) {
|
|
||||||
find_directory(folders[f], &addOnPath);
|
|
||||||
BString addOnFolderName(addOnPath.Path());
|
|
||||||
addOnFolderName << "/locale/catalogs";
|
|
||||||
|
|
||||||
system_info info;
|
|
||||||
if (get_system_info(&info) == B_OK
|
|
||||||
&& (info.abi & B_HAIKU_ABI_MAJOR)
|
|
||||||
!= (B_HAIKU_ABI & B_HAIKU_ABI_MAJOR)) {
|
|
||||||
switch (B_HAIKU_ABI & B_HAIKU_ABI_MAJOR) {
|
|
||||||
case B_HAIKU_ABI_GCC_2:
|
|
||||||
addOnFolderName << "/gcc2";
|
|
||||||
break;
|
|
||||||
case B_HAIKU_ABI_GCC_4:
|
|
||||||
addOnFolderName << "/gcc4";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
err = addOnFolder.SetTo(addOnFolderName.String());
|
|
||||||
if (err != B_OK)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// scan through all the folder's entries for catalog add-ons:
|
|
||||||
int32 count;
|
|
||||||
int8 priority;
|
|
||||||
entry_ref eref;
|
|
||||||
BNode node;
|
|
||||||
BEntry entry;
|
|
||||||
dirent *dent;
|
|
||||||
while ((count = addOnFolder.GetNextDirents((dirent *)buf, 4096)) > 0) {
|
|
||||||
dent = (dirent *)buf;
|
|
||||||
while (count-- > 0) {
|
|
||||||
if (strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")
|
|
||||||
&& strcmp(dent->d_name, "gcc2")
|
|
||||||
&& strcmp(dent->d_name, "gcc4")) {
|
|
||||||
// we have found (what should be) a catalog-add-on:
|
|
||||||
eref.device = dent->d_pdev;
|
|
||||||
eref.directory = dent->d_pino;
|
|
||||||
eref.set_name(dent->d_name);
|
|
||||||
entry.SetTo(&eref, true);
|
|
||||||
// traverse through any links to get to the real thang!
|
|
||||||
node.SetTo(&entry);
|
|
||||||
priority = -1;
|
|
||||||
if (node.ReadAttr(kPriorityAttr, B_INT8_TYPE, 0,
|
|
||||||
&priority, sizeof(int8)) <= 0) {
|
|
||||||
// add-on has no priority-attribute yet, so we load it
|
|
||||||
// to fetch the priority from the corresponding
|
|
||||||
// symbol...
|
|
||||||
BString fullAddOnPath(addOnFolderName);
|
|
||||||
fullAddOnPath << "/" << dent->d_name;
|
|
||||||
image_id image = load_add_on(fullAddOnPath.String());
|
|
||||||
if (image >= B_OK) {
|
|
||||||
uint8 *prioPtr;
|
|
||||||
if (get_image_symbol(image, "gCatalogAddOnPriority",
|
|
||||||
B_SYMBOL_TYPE_DATA,
|
|
||||||
(void **)&prioPtr) == B_OK) {
|
|
||||||
priority = *prioPtr;
|
|
||||||
node.WriteAttr(kPriorityAttr, B_INT8_TYPE, 0,
|
|
||||||
&priority, sizeof(int8));
|
|
||||||
} else {
|
|
||||||
log_team(LOG_ERR,
|
|
||||||
"couldn't get priority for add-on %s\n",
|
|
||||||
fullAddOnPath.String());
|
|
||||||
}
|
|
||||||
unload_add_on(image);
|
|
||||||
} else {
|
|
||||||
log_team(LOG_ERR,
|
|
||||||
"couldn't load add-on %s, error: %s\n",
|
|
||||||
fullAddOnPath.String(), strerror(image));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priority >= 0) {
|
|
||||||
// add-ons with priority < 0 will be ignored
|
|
||||||
BCatalogAddOnInfo* addOnInfo
|
|
||||||
= new(std::nothrow) BCatalogAddOnInfo(dent->d_name,
|
|
||||||
addOnFolderName, priority);
|
|
||||||
if (addOnInfo)
|
|
||||||
fCatalogAddOnInfos.AddItem((void*)addOnInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Bump the dirent-pointer by length of the dirent just handled:
|
|
||||||
dent = (dirent *)((char *)dent + dent->d_reclen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fCatalogAddOnInfos.SortItems(CompareInfos);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* unloads all catalog-add-ons (which will throw away all loaded catalogs, too)
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
RosterData::CleanupCatalogAddOns()
|
|
||||||
{
|
|
||||||
BAutolock lock(fLock);
|
|
||||||
assert(lock.IsLocked());
|
|
||||||
int32 count = fCatalogAddOnInfos.CountItems();
|
|
||||||
for (int32 i = 0; i<count; ++i) {
|
|
||||||
BCatalogAddOnInfo *info
|
|
||||||
= static_cast<BCatalogAddOnInfo*>(fCatalogAddOnInfos.ItemAt(i));
|
|
||||||
delete info;
|
|
||||||
}
|
|
||||||
fCatalogAddOnInfos.MakeEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - BLocaleRoster
|
|
||||||
|
|
||||||
|
|
||||||
BLocaleRoster::BLocaleRoster()
|
BLocaleRoster::BLocaleRoster()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -405,8 +71,177 @@ BLocaleRoster::~BLocaleRoster()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BLocaleRoster::Refresh()
|
||||||
|
{
|
||||||
|
return gRosterData.Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BLocaleRoster::GetDefaultCollator(BCollator* collator) const
|
||||||
|
{
|
||||||
|
if (!collator)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
BAutolock lock(gRosterData.fLock);
|
||||||
|
if (!lock.IsLocked())
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
*collator = gRosterData.fDefaultCollator;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BLocaleRoster::GetDefaultLanguage(BLanguage* language) const
|
||||||
|
{
|
||||||
|
if (!language)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
BAutolock lock(gRosterData.fLock);
|
||||||
|
if (!lock.IsLocked())
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
*language = gRosterData.fDefaultLanguage;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BLocaleRoster::GetDefaultCountry(BCountry* country) const
|
||||||
|
{
|
||||||
|
if (!country)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
BAutolock lock(gRosterData.fLock);
|
||||||
|
if (!lock.IsLocked())
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
*country = gRosterData.fDefaultCountry;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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::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*
|
BCatalog*
|
||||||
BLocaleRoster::GetCatalog(BCatalog* catalog, vint32* catalogInitStatus)
|
BLocaleRoster::_GetCatalog(BCatalog* catalog, vint32* catalogInitStatus)
|
||||||
{
|
{
|
||||||
// This function is used in the translation macros, so it can't return a
|
// This function is used in the translation macros, so it can't return a
|
||||||
// status_t. Maybe it could throw exceptions ?
|
// status_t. Maybe it could throw exceptions ?
|
||||||
@@ -460,428 +295,3 @@ BLocaleRoster::GetCatalog(BCatalog* catalog, vint32* catalogInitStatus)
|
|||||||
|
|
||||||
return catalog;
|
return catalog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BLocaleRoster::GetSystemCatalog(BCatalogAddOn **catalog) const
|
|
||||||
{
|
|
||||||
if (!catalog)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
*catalog = be_locale_roster->LoadCatalog("system");
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BLocaleRoster::GetDefaultCollator(BCollator **collator) const
|
|
||||||
{
|
|
||||||
// It should just use the archived collator from the locale settings;
|
|
||||||
// if that is not available, just return the standard collator
|
|
||||||
if (!collator)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
*collator = new(std::nothrow) BCollator();
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BLocaleRoster::GetDefaultLanguage(BLanguage **language) const
|
|
||||||
{
|
|
||||||
if (!language)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
*language = new(std::nothrow) BLanguage(NULL);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BLocaleRoster::GetDefaultCountry(BCountry **country) const
|
|
||||||
{
|
|
||||||
if (!country)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
*country = &gRosterData.fDefaultCountry;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BLocaleRoster::GetDefaultTimeZone(BTimeZone **timezone) const
|
|
||||||
{
|
|
||||||
if (!timezone)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
*timezone = new(std::nothrow) BTimeZone();
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BLocaleRoster::SetDefaultCountry(BCountry* newDefault) const
|
|
||||||
{
|
|
||||||
if (newDefault == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
BAutolock lock(gRosterData.fLock);
|
|
||||||
assert(lock.IsLocked());
|
|
||||||
|
|
||||||
gRosterData.fDefaultCountry = *newDefault;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BLocaleRoster::SetDefaultTimeZone(const char* zone) const
|
|
||||||
{
|
|
||||||
TimeZone::adoptDefault(TimeZone::createTimeZone(zone));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BLocaleRoster::UpdateSettings(BMessage* newSettings)
|
|
||||||
{
|
|
||||||
gRosterData.UpdateSettings(newSettings);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
RosterData::UpdateSettings(BMessage* newSettings)
|
|
||||||
{
|
|
||||||
BAutolock lock(fLock);
|
|
||||||
assert(lock.IsLocked());
|
|
||||||
|
|
||||||
BString langName;
|
|
||||||
if (newSettings->FindString("language", &langName) == B_OK) {
|
|
||||||
UErrorCode icuError = U_ZERO_ERROR;
|
|
||||||
Locale icuLocale = Locale::createCanonical(langName.String());
|
|
||||||
assert(!icuLocale.isBogus());
|
|
||||||
UnicodeString ustr;
|
|
||||||
BString bstr;
|
|
||||||
BStringByteSink bbs(&bstr);
|
|
||||||
icuLocale.getDisplayName(ustr);
|
|
||||||
ustr.toUTF8(bbs);
|
|
||||||
|
|
||||||
Locale::setDefault(icuLocale, icuError);
|
|
||||||
assert(icuError == U_ZERO_ERROR);
|
|
||||||
fPreferredLanguages.RemoveName("language");
|
|
||||||
for (int i = 0; newSettings->FindString("language", i,
|
|
||||||
&langName) == B_OK; i++) {
|
|
||||||
fPreferredLanguages.AddString("language", langName);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
fPreferredLanguages.AddString("language", "en");
|
|
||||||
|
|
||||||
BString codeName;
|
|
||||||
|
|
||||||
if (newSettings->FindString("country", &codeName)
|
|
||||||
== B_OK)
|
|
||||||
fDefaultCountry = BCountry(codeName);
|
|
||||||
else
|
|
||||||
fDefaultCountry = BCountry("en_US");
|
|
||||||
|
|
||||||
BString timeFormat;
|
|
||||||
if (newSettings->FindString("shortTimeFormat", &timeFormat)
|
|
||||||
== B_OK)
|
|
||||||
fDefaultCountry.SetTimeFormat(timeFormat, false);
|
|
||||||
if (newSettings->FindString("longTimeFormat", &timeFormat)
|
|
||||||
== B_OK)
|
|
||||||
fDefaultCountry.SetTimeFormat(timeFormat, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BLocaleRoster::GetPreferredLanguages(BMessage* languages) const
|
|
||||||
{
|
|
||||||
if (!languages)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
BAutolock lock(gRosterData.fLock);
|
|
||||||
assert(lock.IsLocked());
|
|
||||||
|
|
||||||
*languages = gRosterData.fPreferredLanguages;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BLocaleRoster::SetPreferredLanguages(BMessage *languages)
|
|
||||||
{
|
|
||||||
BAutolock lock(gRosterData.fLock);
|
|
||||||
assert(lock.IsLocked());
|
|
||||||
|
|
||||||
if (languages)
|
|
||||||
gRosterData.fPreferredLanguages = *languages;
|
|
||||||
else
|
|
||||||
gRosterData.fPreferredLanguages.MakeEmpty();
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Get all the available languages from ICU
|
|
||||||
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);
|
|
||||||
|
|
||||||
// Loop over the strings and add them to an std::set to remove duplicates
|
|
||||||
for (i = 0; i < localeCount; i++) {
|
|
||||||
languages->AddString("langs", icuLocaleList[i].getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Get all the available countries from ICU
|
|
||||||
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::GetInstalledCatalogs(BMessage * languageList,
|
|
||||||
const char* sigPattern, const char* langPattern, int32 fingerprint) const
|
|
||||||
{
|
|
||||||
if (languageList == NULL)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
int32 count = gRosterData.fCatalogAddOnInfos.CountItems();
|
|
||||||
for (int32 i = 0; i < count; ++i) {
|
|
||||||
BCatalogAddOnInfo *info
|
|
||||||
= (BCatalogAddOnInfo*)gRosterData.fCatalogAddOnInfos.ItemAt(i);
|
|
||||||
|
|
||||||
if (!info->MakeSureItsLoaded() || !info->fLanguagesFunc)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
info->fLanguagesFunc(languageList, sigPattern, langPattern,
|
|
||||||
fingerprint);
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* creates a new (empty) catalog of the given type (the request is dispatched
|
|
||||||
* to the appropriate add-on).
|
|
||||||
* If the add-on doesn't support catalog-creation or if the creation fails,
|
|
||||||
* NULL is returned, otherwise a pointer to the freshly created catalog.
|
|
||||||
* Any created catalog will be initialized with the given signature and
|
|
||||||
* language-name.
|
|
||||||
*/
|
|
||||||
BCatalogAddOn*
|
|
||||||
BLocaleRoster::CreateCatalog(const char *type, const char *signature,
|
|
||||||
const char *language)
|
|
||||||
{
|
|
||||||
if (!type || !signature || !language)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
BAutolock lock(gRosterData.fLock);
|
|
||||||
assert(lock.IsLocked());
|
|
||||||
|
|
||||||
int32 count = gRosterData.fCatalogAddOnInfos.CountItems();
|
|
||||||
for (int32 i = 0; i < count; ++i) {
|
|
||||||
BCatalogAddOnInfo *info
|
|
||||||
= (BCatalogAddOnInfo*)gRosterData.fCatalogAddOnInfos.ItemAt(i);
|
|
||||||
if (info->fName.ICompare(type)!=0 || !info->MakeSureItsLoaded()
|
|
||||||
|| !info->fCreateFunc)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
BCatalogAddOn *catalog = info->fCreateFunc(signature, language);
|
|
||||||
if (catalog) {
|
|
||||||
info->fLoadedCatalogs.AddItem(catalog);
|
|
||||||
info->UnloadIfPossible();
|
|
||||||
return catalog;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Loads a catalog for the given signature, language and fingerprint.
|
|
||||||
* The request to load this catalog is dispatched to all add-ons in turn,
|
|
||||||
* until an add-on reports success.
|
|
||||||
* If a catalog depends on another language (as 'english-british' depends
|
|
||||||
* on 'english') the dependant catalogs are automatically loaded, too.
|
|
||||||
* So it is perfectly possible that this method returns a catalog-chain
|
|
||||||
* instead of a single catalog.
|
|
||||||
* NULL is returned if no matching catalog could be found.
|
|
||||||
*/
|
|
||||||
BCatalogAddOn*
|
|
||||||
BLocaleRoster::LoadCatalog(const char *signature, const char *language,
|
|
||||||
int32 fingerprint)
|
|
||||||
{
|
|
||||||
if (!signature)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
BAutolock lock(gRosterData.fLock);
|
|
||||||
assert(lock.IsLocked());
|
|
||||||
|
|
||||||
int32 count = gRosterData.fCatalogAddOnInfos.CountItems();
|
|
||||||
for (int32 i = 0; i < count; ++i) {
|
|
||||||
BCatalogAddOnInfo *info
|
|
||||||
= (BCatalogAddOnInfo*)gRosterData.fCatalogAddOnInfos.ItemAt(i);
|
|
||||||
|
|
||||||
if (!info->MakeSureItsLoaded() || !info->fInstantiateFunc)
|
|
||||||
continue;
|
|
||||||
BMessage languages;
|
|
||||||
if (language)
|
|
||||||
// try to load catalogs for the given language:
|
|
||||||
languages.AddString("language", language);
|
|
||||||
else
|
|
||||||
// try to load catalogs for one of the preferred languages:
|
|
||||||
GetPreferredLanguages(&languages);
|
|
||||||
|
|
||||||
BCatalogAddOn *catalog = NULL;
|
|
||||||
const char *lang;
|
|
||||||
for (int32 l=0; languages.FindString("language", l, &lang)==B_OK; ++l) {
|
|
||||||
catalog = info->fInstantiateFunc(signature, lang, fingerprint);
|
|
||||||
if (catalog)
|
|
||||||
info->fLoadedCatalogs.AddItem(catalog);
|
|
||||||
// Chain-load catalogs for languages that depend on
|
|
||||||
// other languages.
|
|
||||||
// The current implementation uses the filename in order to
|
|
||||||
// detect dependencies (parenthood) between languages (it
|
|
||||||
// traverses from "english_british_oxford" to "english_british"
|
|
||||||
// to "english"):
|
|
||||||
// TODO: use ICU facilities instead, so we can handle more
|
|
||||||
// complex things such as fr_FR@euro, or whatever, encodings
|
|
||||||
// and so on.
|
|
||||||
int32 pos;
|
|
||||||
BString langName(lang);
|
|
||||||
BCatalogAddOn *currCatalog=catalog, *nextCatalog;
|
|
||||||
while ((pos = langName.FindLast('_')) >= 0) {
|
|
||||||
// language is based on parent, so we load that, too:
|
|
||||||
// (even if the parent catalog was not found)
|
|
||||||
langName.Truncate(pos);
|
|
||||||
nextCatalog = info->fInstantiateFunc(signature,
|
|
||||||
langName.String(), fingerprint);
|
|
||||||
if (nextCatalog) {
|
|
||||||
info->fLoadedCatalogs.AddItem(nextCatalog);
|
|
||||||
if(currCatalog)
|
|
||||||
currCatalog->fNext = nextCatalog;
|
|
||||||
else
|
|
||||||
catalog = nextCatalog;
|
|
||||||
currCatalog = nextCatalog;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return catalog;
|
|
||||||
}
|
|
||||||
info->UnloadIfPossible();
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Loads an embedded catalog from the given entry-ref (which is usually an
|
|
||||||
* app- or add-on-file. The request to load the catalog is dispatched to all
|
|
||||||
* add-ons in turn, until an add-on reports success.
|
|
||||||
* NULL is returned if no embedded catalog could be found.
|
|
||||||
*/
|
|
||||||
BCatalogAddOn*
|
|
||||||
BLocaleRoster::LoadEmbeddedCatalog(entry_ref *appOrAddOnRef)
|
|
||||||
{
|
|
||||||
if (!appOrAddOnRef)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
BAutolock lock(gRosterData.fLock);
|
|
||||||
assert(lock.IsLocked());
|
|
||||||
|
|
||||||
int32 count = gRosterData.fCatalogAddOnInfos.CountItems();
|
|
||||||
for (int32 i = 0; i < count; ++i) {
|
|
||||||
BCatalogAddOnInfo *info
|
|
||||||
= (BCatalogAddOnInfo*)gRosterData.fCatalogAddOnInfos.ItemAt(i);
|
|
||||||
|
|
||||||
if (!info->MakeSureItsLoaded() || !info->fInstantiateEmbeddedFunc)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
BCatalogAddOn *catalog = NULL;
|
|
||||||
catalog = info->fInstantiateEmbeddedFunc(appOrAddOnRef);
|
|
||||||
if (catalog) {
|
|
||||||
info->fLoadedCatalogs.AddItem(catalog);
|
|
||||||
return catalog;
|
|
||||||
}
|
|
||||||
info->UnloadIfPossible();
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* unloads the given catalog (or rather: catalog-chain).
|
|
||||||
* Every single catalog of the chain will be deleted automatically.
|
|
||||||
* Add-ons that have no more current catalogs are unloaded, too.
|
|
||||||
*/
|
|
||||||
status_t
|
|
||||||
BLocaleRoster::UnloadCatalog(BCatalogAddOn *catalog)
|
|
||||||
{
|
|
||||||
if (!catalog)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
BAutolock lock(gRosterData.fLock);
|
|
||||||
assert(lock.IsLocked());
|
|
||||||
|
|
||||||
status_t res = B_ERROR;
|
|
||||||
BCatalogAddOn *nextCatalog;
|
|
||||||
// note: as we currently aren't chainloading catalogs, there is only
|
|
||||||
// one catalog to unload...
|
|
||||||
while (catalog) {
|
|
||||||
nextCatalog = catalog->fNext;
|
|
||||||
int32 count = gRosterData.fCatalogAddOnInfos.CountItems();
|
|
||||||
for (int32 i = 0; i < count; ++i) {
|
|
||||||
BCatalogAddOnInfo *info
|
|
||||||
= static_cast<BCatalogAddOnInfo*>(
|
|
||||||
gRosterData.fCatalogAddOnInfos.ItemAt(i)
|
|
||||||
);
|
|
||||||
if (info->fLoadedCatalogs.HasItem(catalog)) {
|
|
||||||
info->fLoadedCatalogs.RemoveItem(catalog);
|
|
||||||
delete catalog;
|
|
||||||
info->UnloadIfPossible();
|
|
||||||
res = B_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catalog = nextCatalog;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,861 @@
|
|||||||
|
/*
|
||||||
|
* 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 <MutableLocaleRoster.h>
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include <syslog.h>
|
||||||
|
|
||||||
|
#include <AppFileInfo.h>
|
||||||
|
#include <Autolock.h>
|
||||||
|
#include <Catalog.h>
|
||||||
|
#include <Collator.h>
|
||||||
|
#include <Country.h>
|
||||||
|
#include <DefaultCatalog.h>
|
||||||
|
#include <Directory.h>
|
||||||
|
#include <Entry.h>
|
||||||
|
#include <File.h>
|
||||||
|
#include <FindDirectory.h>
|
||||||
|
#include <Language.h>
|
||||||
|
#include <Locale.h>
|
||||||
|
#include <Node.h>
|
||||||
|
#include <Path.h>
|
||||||
|
#include <Roster.h>
|
||||||
|
#include <String.h>
|
||||||
|
#include <TimeZone.h>
|
||||||
|
|
||||||
|
#include <ICUWrapper.h>
|
||||||
|
|
||||||
|
// ICU includes
|
||||||
|
#include <unicode/locid.h>
|
||||||
|
#include <unicode/timezone.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace BPrivate {
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - CatalogAddOnInfo
|
||||||
|
|
||||||
|
|
||||||
|
CatalogAddOnInfo::CatalogAddOnInfo(const BString& name, const BString& path,
|
||||||
|
uint8 priority)
|
||||||
|
:
|
||||||
|
fInstantiateFunc(NULL),
|
||||||
|
fInstantiateEmbeddedFunc(NULL),
|
||||||
|
fCreateFunc(NULL),
|
||||||
|
fLanguagesFunc(NULL),
|
||||||
|
fName(name),
|
||||||
|
fPath(path),
|
||||||
|
fAddOnImage(B_NO_INIT),
|
||||||
|
fPriority(priority),
|
||||||
|
fIsEmbedded(path.Length()==0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CatalogAddOnInfo::~CatalogAddOnInfo()
|
||||||
|
{
|
||||||
|
int32 count = fLoadedCatalogs.CountItems();
|
||||||
|
for (int32 i = 0; i < count; ++i) {
|
||||||
|
BCatalogAddOn* cat
|
||||||
|
= static_cast<BCatalogAddOn*>(fLoadedCatalogs.ItemAt(i));
|
||||||
|
delete cat;
|
||||||
|
}
|
||||||
|
fLoadedCatalogs.MakeEmpty();
|
||||||
|
UnloadIfPossible();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
CatalogAddOnInfo::MakeSureItsLoaded()
|
||||||
|
{
|
||||||
|
if (!fIsEmbedded && fAddOnImage < B_OK) {
|
||||||
|
// add-on has not been loaded yet, so we try to load it:
|
||||||
|
BString fullAddOnPath(fPath);
|
||||||
|
fullAddOnPath << "/" << fName;
|
||||||
|
fAddOnImage = load_add_on(fullAddOnPath.String());
|
||||||
|
if (fAddOnImage >= B_OK) {
|
||||||
|
get_image_symbol(fAddOnImage, "instantiate_catalog",
|
||||||
|
B_SYMBOL_TYPE_TEXT, (void**)&fInstantiateFunc);
|
||||||
|
get_image_symbol(fAddOnImage, "instantiate_embedded_catalog",
|
||||||
|
B_SYMBOL_TYPE_TEXT, (void**)&fInstantiateEmbeddedFunc);
|
||||||
|
get_image_symbol(fAddOnImage, "create_catalog",
|
||||||
|
B_SYMBOL_TYPE_TEXT, (void**)&fCreateFunc);
|
||||||
|
get_image_symbol(fAddOnImage, "get_available_languages",
|
||||||
|
B_SYMBOL_TYPE_TEXT, (void**)&fLanguagesFunc);
|
||||||
|
log_team(LOG_DEBUG, "catalog-add-on %s has been loaded",
|
||||||
|
fName.String());
|
||||||
|
} else {
|
||||||
|
log_team(LOG_DEBUG, "could not load catalog-add-on %s (%s)",
|
||||||
|
fName.String(), strerror(fAddOnImage));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (fIsEmbedded) {
|
||||||
|
// The built-in catalog still has to provide this function
|
||||||
|
fLanguagesFunc = default_catalog_get_available_languages;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CatalogAddOnInfo::UnloadIfPossible()
|
||||||
|
{
|
||||||
|
if (!fIsEmbedded && fLoadedCatalogs.IsEmpty()) {
|
||||||
|
unload_add_on(fAddOnImage);
|
||||||
|
fAddOnImage = B_NO_INIT;
|
||||||
|
fInstantiateFunc = NULL;
|
||||||
|
fInstantiateEmbeddedFunc = NULL;
|
||||||
|
fCreateFunc = NULL;
|
||||||
|
fLanguagesFunc = NULL;
|
||||||
|
// log_team(LOG_DEBUG, "catalog-add-on %s has been unloaded",
|
||||||
|
// fName.String());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - MutableLocaleRoster
|
||||||
|
|
||||||
|
|
||||||
|
RosterData gRosterData;
|
||||||
|
|
||||||
|
static const char* kPriorityAttr = "ADDON:priority";
|
||||||
|
|
||||||
|
|
||||||
|
RosterData::RosterData()
|
||||||
|
:
|
||||||
|
fLock("LocaleRosterData")
|
||||||
|
{
|
||||||
|
openlog_team("liblocale.so", LOG_PID, LOG_USER);
|
||||||
|
#ifndef DEBUG
|
||||||
|
setlogmask_team(LOG_UPTO(LOG_WARNING));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
InitializeCatalogAddOns();
|
||||||
|
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RosterData::~RosterData()
|
||||||
|
{
|
||||||
|
BAutolock lock(fLock);
|
||||||
|
|
||||||
|
CleanupCatalogAddOns();
|
||||||
|
closelog();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
RosterData::CompareInfos(const void* left, const void* right)
|
||||||
|
{
|
||||||
|
return ((CatalogAddOnInfo*)right)->fPriority
|
||||||
|
- ((CatalogAddOnInfo*)left)->fPriority;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
RosterData::Refresh()
|
||||||
|
{
|
||||||
|
BAutolock lock(fLock);
|
||||||
|
if (!lock.IsLocked())
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
status_t status = _LoadLocaleSettings();
|
||||||
|
if (status == B_OK)
|
||||||
|
status = _LoadTimeSettings();
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
iterate over add-on-folders and collect information about each
|
||||||
|
catalog-add-ons (types of catalogs) into fCatalogAddOnInfos.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
RosterData::InitializeCatalogAddOns()
|
||||||
|
{
|
||||||
|
BAutolock lock(fLock);
|
||||||
|
if (!lock.IsLocked())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// add info about embedded default catalog:
|
||||||
|
CatalogAddOnInfo* defaultCatalogAddOnInfo
|
||||||
|
= new(std::nothrow) CatalogAddOnInfo("Default", "",
|
||||||
|
DefaultCatalog::kDefaultCatalogAddOnPriority);
|
||||||
|
if (!defaultCatalogAddOnInfo)
|
||||||
|
return;
|
||||||
|
|
||||||
|
defaultCatalogAddOnInfo->fInstantiateFunc = DefaultCatalog::Instantiate;
|
||||||
|
defaultCatalogAddOnInfo->fInstantiateEmbeddedFunc
|
||||||
|
= DefaultCatalog::InstantiateEmbedded;
|
||||||
|
defaultCatalogAddOnInfo->fCreateFunc = DefaultCatalog::Create;
|
||||||
|
fCatalogAddOnInfos.AddItem((void*)defaultCatalogAddOnInfo);
|
||||||
|
|
||||||
|
directory_which folders[] = {
|
||||||
|
B_COMMON_ADDONS_DIRECTORY,
|
||||||
|
B_SYSTEM_ADDONS_DIRECTORY,
|
||||||
|
static_cast<directory_which>(-1)
|
||||||
|
};
|
||||||
|
BPath addOnPath;
|
||||||
|
BDirectory addOnFolder;
|
||||||
|
char buf[4096];
|
||||||
|
status_t err;
|
||||||
|
for (int f = 0; folders[f]>=0; ++f) {
|
||||||
|
find_directory(folders[f], &addOnPath);
|
||||||
|
BString addOnFolderName(addOnPath.Path());
|
||||||
|
addOnFolderName << "/locale/catalogs";
|
||||||
|
|
||||||
|
system_info info;
|
||||||
|
if (get_system_info(&info) == B_OK
|
||||||
|
&& (info.abi & B_HAIKU_ABI_MAJOR)
|
||||||
|
!= (B_HAIKU_ABI & B_HAIKU_ABI_MAJOR)) {
|
||||||
|
switch (B_HAIKU_ABI & B_HAIKU_ABI_MAJOR) {
|
||||||
|
case B_HAIKU_ABI_GCC_2:
|
||||||
|
addOnFolderName << "/gcc2";
|
||||||
|
break;
|
||||||
|
case B_HAIKU_ABI_GCC_4:
|
||||||
|
addOnFolderName << "/gcc4";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
err = addOnFolder.SetTo(addOnFolderName.String());
|
||||||
|
if (err != B_OK)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// scan through all the folder's entries for catalog add-ons:
|
||||||
|
int32 count;
|
||||||
|
int8 priority;
|
||||||
|
entry_ref eref;
|
||||||
|
BNode node;
|
||||||
|
BEntry entry;
|
||||||
|
dirent* dent;
|
||||||
|
while ((count = addOnFolder.GetNextDirents((dirent*)buf, 4096)) > 0) {
|
||||||
|
dent = (dirent*)buf;
|
||||||
|
while (count-- > 0) {
|
||||||
|
if (strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")
|
||||||
|
&& strcmp(dent->d_name, "gcc2")
|
||||||
|
&& strcmp(dent->d_name, "gcc4")) {
|
||||||
|
// we have found (what should be) a catalog-add-on:
|
||||||
|
eref.device = dent->d_pdev;
|
||||||
|
eref.directory = dent->d_pino;
|
||||||
|
eref.set_name(dent->d_name);
|
||||||
|
entry.SetTo(&eref, true);
|
||||||
|
// traverse through any links to get to the real thang!
|
||||||
|
node.SetTo(&entry);
|
||||||
|
priority = -1;
|
||||||
|
if (node.ReadAttr(kPriorityAttr, B_INT8_TYPE, 0,
|
||||||
|
&priority, sizeof(int8)) <= 0) {
|
||||||
|
// add-on has no priority-attribute yet, so we load it
|
||||||
|
// to fetch the priority from the corresponding
|
||||||
|
// symbol...
|
||||||
|
BString fullAddOnPath(addOnFolderName);
|
||||||
|
fullAddOnPath << "/" << dent->d_name;
|
||||||
|
image_id image = load_add_on(fullAddOnPath.String());
|
||||||
|
if (image >= B_OK) {
|
||||||
|
uint8* prioPtr;
|
||||||
|
if (get_image_symbol(image, "gCatalogAddOnPriority",
|
||||||
|
B_SYMBOL_TYPE_DATA,
|
||||||
|
(void**)&prioPtr) == B_OK) {
|
||||||
|
priority = *prioPtr;
|
||||||
|
node.WriteAttr(kPriorityAttr, B_INT8_TYPE, 0,
|
||||||
|
&priority, sizeof(int8));
|
||||||
|
} else {
|
||||||
|
log_team(LOG_ERR,
|
||||||
|
"couldn't get priority for add-on %s\n",
|
||||||
|
fullAddOnPath.String());
|
||||||
|
}
|
||||||
|
unload_add_on(image);
|
||||||
|
} else {
|
||||||
|
log_team(LOG_ERR,
|
||||||
|
"couldn't load add-on %s, error: %s\n",
|
||||||
|
fullAddOnPath.String(), strerror(image));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priority >= 0) {
|
||||||
|
// add-ons with priority < 0 will be ignored
|
||||||
|
CatalogAddOnInfo* addOnInfo
|
||||||
|
= new(std::nothrow) CatalogAddOnInfo(dent->d_name,
|
||||||
|
addOnFolderName, priority);
|
||||||
|
if (addOnInfo)
|
||||||
|
fCatalogAddOnInfos.AddItem((void*)addOnInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Bump the dirent-pointer by length of the dirent just handled:
|
||||||
|
dent = (dirent*)((char*)dent + dent->d_reclen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fCatalogAddOnInfos.SortItems(CompareInfos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* unloads all catalog-add-ons (which will throw away all loaded catalogs, too)
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
RosterData::CleanupCatalogAddOns()
|
||||||
|
{
|
||||||
|
BAutolock lock(fLock);
|
||||||
|
if (!lock.IsLocked())
|
||||||
|
return;
|
||||||
|
|
||||||
|
int32 count = fCatalogAddOnInfos.CountItems();
|
||||||
|
for (int32 i = 0; i<count; ++i) {
|
||||||
|
CatalogAddOnInfo* info
|
||||||
|
= static_cast<CatalogAddOnInfo*>(fCatalogAddOnInfos.ItemAt(i));
|
||||||
|
delete info;
|
||||||
|
}
|
||||||
|
fCatalogAddOnInfos.MakeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
RosterData::SetDefaultCountry(const BCountry& newCountry)
|
||||||
|
{
|
||||||
|
status_t status = B_OK;
|
||||||
|
|
||||||
|
BAutolock lock(fLock);
|
||||||
|
if (!lock.IsLocked())
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
status = _SetDefaultCountry(newCountry);
|
||||||
|
|
||||||
|
if (status == B_OK)
|
||||||
|
status = _SaveLocaleSettings();
|
||||||
|
|
||||||
|
if (status == B_OK) {
|
||||||
|
BMessage updateMessage(B_LOCALE_CHANGED);
|
||||||
|
status = _AddDefaultCountryToMessage(&updateMessage);
|
||||||
|
if (status == B_OK)
|
||||||
|
status = be_roster->Broadcast(&updateMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
RosterData::SetDefaultTimeZone(const BTimeZone& newZone)
|
||||||
|
{
|
||||||
|
status_t status = B_OK;
|
||||||
|
|
||||||
|
BAutolock lock(fLock);
|
||||||
|
if (!lock.IsLocked())
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
status = _SetDefaultTimeZone(newZone);
|
||||||
|
|
||||||
|
if (status == B_OK)
|
||||||
|
status = _SaveTimeSettings();
|
||||||
|
|
||||||
|
if (status == B_OK) {
|
||||||
|
BMessage updateMessage(B_LOCALE_CHANGED);
|
||||||
|
status = _AddDefaultTimeZoneToMessage(&updateMessage);
|
||||||
|
if (status == B_OK)
|
||||||
|
status = be_roster->Broadcast(&updateMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
RosterData::SetPreferredLanguages(const BMessage* languages)
|
||||||
|
{
|
||||||
|
status_t status = B_OK;
|
||||||
|
|
||||||
|
BAutolock lock(fLock);
|
||||||
|
if (!lock.IsLocked())
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
status = _SetPreferredLanguages(languages);
|
||||||
|
|
||||||
|
if (status == B_OK)
|
||||||
|
status = _SaveLocaleSettings();
|
||||||
|
|
||||||
|
if (status == B_OK) {
|
||||||
|
BMessage updateMessage(B_LOCALE_CHANGED);
|
||||||
|
status = _AddPreferredLanguagesToMessage(&updateMessage);
|
||||||
|
if (status == B_OK)
|
||||||
|
status = be_roster->Broadcast(&updateMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
RosterData::_LoadLocaleSettings()
|
||||||
|
{
|
||||||
|
BPath path;
|
||||||
|
BFile file;
|
||||||
|
status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
|
||||||
|
if (status == B_OK) {
|
||||||
|
path.Append("Locale settings");
|
||||||
|
status = file.SetTo(path.Path(), B_READ_ONLY);
|
||||||
|
}
|
||||||
|
BMessage settings;
|
||||||
|
if (status == B_OK)
|
||||||
|
status = settings.Unflatten(&file);
|
||||||
|
if (status == B_OK)
|
||||||
|
status = _SetPreferredLanguages(&settings);
|
||||||
|
|
||||||
|
if (status == B_OK) {
|
||||||
|
BString codeName;
|
||||||
|
BCountry newDefaultCountry;
|
||||||
|
|
||||||
|
if (settings.FindString("country", &codeName) == B_OK)
|
||||||
|
newDefaultCountry = BCountry(codeName);
|
||||||
|
|
||||||
|
BString timeFormat;
|
||||||
|
if (settings.FindString("shortTimeFormat", &timeFormat) == B_OK)
|
||||||
|
newDefaultCountry.SetTimeFormat(timeFormat, false);
|
||||||
|
if (settings.FindString("longTimeFormat", &timeFormat) == B_OK)
|
||||||
|
newDefaultCountry.SetTimeFormat(timeFormat, true);
|
||||||
|
|
||||||
|
_SetDefaultCountry(newDefaultCountry);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Something went wrong (no settings file or invalid BMessage), so we
|
||||||
|
// set everything to default values
|
||||||
|
fPreferredLanguages.AddString("language", "en");
|
||||||
|
log_team(LOG_ERR, "*** No locale settings found!\n");
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
RosterData::_LoadTimeSettings()
|
||||||
|
{
|
||||||
|
BPath path;
|
||||||
|
BFile file;
|
||||||
|
status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
|
||||||
|
if (status == B_OK) {
|
||||||
|
path.Append("Time settings");
|
||||||
|
status = file.SetTo(path.Path(), B_READ_ONLY);
|
||||||
|
}
|
||||||
|
BMessage settings;
|
||||||
|
if (status == B_OK)
|
||||||
|
status = settings.Unflatten(&file);
|
||||||
|
if (status == B_OK) {
|
||||||
|
BString timeZoneCode;
|
||||||
|
if (settings.FindString("timezone", &timeZoneCode) == B_OK)
|
||||||
|
_SetDefaultTimeZone(BTimeZone(timeZoneCode.String()));
|
||||||
|
else
|
||||||
|
_SetDefaultTimeZone(BTimeZone(BTimeZone::kNameOfGmtZone));
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Something went wrong (no settings file or invalid BMessage), so we
|
||||||
|
// set everything to default values
|
||||||
|
_SetDefaultTimeZone(BTimeZone(BTimeZone::kNameOfGmtZone));
|
||||||
|
log_team(LOG_ERR, "*** No time settings found!\n");
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
RosterData::_SaveLocaleSettings()
|
||||||
|
{
|
||||||
|
BMessage settings;
|
||||||
|
status_t status = _AddDefaultCountryToMessage(&settings);
|
||||||
|
if (status == B_OK)
|
||||||
|
_AddPreferredLanguagesToMessage(&settings);
|
||||||
|
|
||||||
|
BPath path;
|
||||||
|
if (status == B_OK)
|
||||||
|
status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
|
||||||
|
|
||||||
|
BFile file;
|
||||||
|
if (status == B_OK) {
|
||||||
|
path.Append("Locale settings");
|
||||||
|
status = file.SetTo(path.Path(),
|
||||||
|
B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY);
|
||||||
|
}
|
||||||
|
if (status == B_OK)
|
||||||
|
status = settings.Flatten(&file);
|
||||||
|
if (status == B_OK)
|
||||||
|
status = file.Sync();
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
RosterData::_SaveTimeSettings()
|
||||||
|
{
|
||||||
|
BMessage settings;
|
||||||
|
status_t status = _AddDefaultTimeZoneToMessage(&settings);
|
||||||
|
|
||||||
|
BPath path;
|
||||||
|
if (status == B_OK)
|
||||||
|
status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
|
||||||
|
|
||||||
|
BFile file;
|
||||||
|
if (status == B_OK) {
|
||||||
|
path.Append("Time settings");
|
||||||
|
status = file.SetTo(path.Path(),
|
||||||
|
B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY);
|
||||||
|
}
|
||||||
|
if (status == B_OK)
|
||||||
|
status = settings.Flatten(&file);
|
||||||
|
if (status == B_OK)
|
||||||
|
status = file.Sync();
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
RosterData::_SetDefaultCountry(const BCountry& newCountry)
|
||||||
|
{
|
||||||
|
fDefaultCountry = newCountry;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
RosterData::_SetDefaultTimeZone(const BTimeZone& newZone)
|
||||||
|
{
|
||||||
|
fDefaultTimeZone = newZone;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
RosterData::_SetPreferredLanguages(const BMessage* languages)
|
||||||
|
{
|
||||||
|
BString langName;
|
||||||
|
if (languages != NULL
|
||||||
|
&& languages->FindString("language", &langName) == B_OK) {
|
||||||
|
UErrorCode icuError = U_ZERO_ERROR;
|
||||||
|
Locale icuLocale = Locale::createCanonical(langName.String());
|
||||||
|
if (icuLocale.isBogus())
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
Locale::setDefault(icuLocale, icuError);
|
||||||
|
if (!U_SUCCESS(icuError))
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
fDefaultCollator = BCollator(langName.String());
|
||||||
|
fDefaultLanguage.SetTo(langName.String());
|
||||||
|
|
||||||
|
fPreferredLanguages.RemoveName("language");
|
||||||
|
for (int i = 0; languages->FindString("language", i, &langName) == B_OK;
|
||||||
|
i++) {
|
||||||
|
fPreferredLanguages.AddString("language", langName);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fPreferredLanguages.MakeEmpty();
|
||||||
|
fPreferredLanguages.AddString("language", "en");
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
RosterData::_AddDefaultCountryToMessage(BMessage* message) const
|
||||||
|
{
|
||||||
|
status_t status = message->AddString("country", fDefaultCountry.Code());
|
||||||
|
BString timeFormat;
|
||||||
|
if (status == B_OK)
|
||||||
|
status = fDefaultCountry.GetTimeFormat(timeFormat, false);
|
||||||
|
if (status == B_OK)
|
||||||
|
status = message->AddString("shortTimeFormat", timeFormat.String());
|
||||||
|
if (status == B_OK)
|
||||||
|
status = fDefaultCountry.GetTimeFormat(timeFormat, true);
|
||||||
|
if (status == B_OK)
|
||||||
|
status = message->AddString("longTimeFormat", timeFormat.String());
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
RosterData::_AddDefaultTimeZoneToMessage(BMessage* message) const
|
||||||
|
{
|
||||||
|
return message->AddString("timezone", fDefaultTimeZone.Code());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
RosterData::_AddPreferredLanguagesToMessage(BMessage* message) const
|
||||||
|
{
|
||||||
|
status_t status = B_OK;
|
||||||
|
|
||||||
|
BString langName;
|
||||||
|
for (int i = 0; fPreferredLanguages.FindString("language", i,
|
||||||
|
&langName) == B_OK; i++) {
|
||||||
|
status = message->AddString("language", langName);
|
||||||
|
if (status != B_OK)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - MutableLocaleRoster
|
||||||
|
|
||||||
|
|
||||||
|
static MutableLocaleRoster gLocaleRoster;
|
||||||
|
MutableLocaleRoster* mutable_locale_roster = &gLocaleRoster;
|
||||||
|
|
||||||
|
|
||||||
|
MutableLocaleRoster::MutableLocaleRoster()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MutableLocaleRoster::~MutableLocaleRoster()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
MutableLocaleRoster::SetDefaultCountry(const BCountry& newCountry)
|
||||||
|
{
|
||||||
|
return gRosterData.SetDefaultCountry(newCountry);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
MutableLocaleRoster::SetDefaultTimeZone(const BTimeZone& newZone)
|
||||||
|
{
|
||||||
|
return gRosterData.SetDefaultTimeZone(newZone);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
MutableLocaleRoster::SetPreferredLanguages(const BMessage* languages)
|
||||||
|
{
|
||||||
|
return gRosterData.SetPreferredLanguages(languages);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
MutableLocaleRoster::GetSystemCatalog(BCatalogAddOn** catalog) const
|
||||||
|
{
|
||||||
|
if (!catalog)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
*catalog = LoadCatalog("system");
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* creates a new (empty) catalog of the given type (the request is dispatched
|
||||||
|
* to the appropriate add-on).
|
||||||
|
* If the add-on doesn't support catalog-creation or if the creation fails,
|
||||||
|
* NULL is returned, otherwise a pointer to the freshly created catalog.
|
||||||
|
* Any created catalog will be initialized with the given signature and
|
||||||
|
* language-name.
|
||||||
|
*/
|
||||||
|
BCatalogAddOn*
|
||||||
|
MutableLocaleRoster::CreateCatalog(const char* type, const char* signature,
|
||||||
|
const char* language)
|
||||||
|
{
|
||||||
|
if (!type || !signature || !language)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
BAutolock lock(gRosterData.fLock);
|
||||||
|
if (!lock.IsLocked())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
int32 count = gRosterData.fCatalogAddOnInfos.CountItems();
|
||||||
|
for (int32 i = 0; i < count; ++i) {
|
||||||
|
CatalogAddOnInfo* info
|
||||||
|
= (CatalogAddOnInfo*)gRosterData.fCatalogAddOnInfos.ItemAt(i);
|
||||||
|
if (info->fName.ICompare(type)!=0 || !info->MakeSureItsLoaded()
|
||||||
|
|| !info->fCreateFunc)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BCatalogAddOn* catalog = info->fCreateFunc(signature, language);
|
||||||
|
if (catalog) {
|
||||||
|
info->fLoadedCatalogs.AddItem(catalog);
|
||||||
|
info->UnloadIfPossible();
|
||||||
|
return catalog;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Loads a catalog for the given signature, language and fingerprint.
|
||||||
|
* The request to load this catalog is dispatched to all add-ons in turn,
|
||||||
|
* until an add-on reports success.
|
||||||
|
* If a catalog depends on another language (as 'english-british' depends
|
||||||
|
* on 'english') the dependant catalogs are automatically loaded, too.
|
||||||
|
* So it is perfectly possible that this method returns a catalog-chain
|
||||||
|
* instead of a single catalog.
|
||||||
|
* NULL is returned if no matching catalog could be found.
|
||||||
|
*/
|
||||||
|
BCatalogAddOn*
|
||||||
|
MutableLocaleRoster::LoadCatalog(const char* signature, const char* language,
|
||||||
|
int32 fingerprint) const
|
||||||
|
{
|
||||||
|
if (!signature)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
BAutolock lock(gRosterData.fLock);
|
||||||
|
if (!lock.IsLocked())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
int32 count = gRosterData.fCatalogAddOnInfos.CountItems();
|
||||||
|
for (int32 i = 0; i < count; ++i) {
|
||||||
|
CatalogAddOnInfo* info
|
||||||
|
= (CatalogAddOnInfo*)gRosterData.fCatalogAddOnInfos.ItemAt(i);
|
||||||
|
|
||||||
|
if (!info->MakeSureItsLoaded() || !info->fInstantiateFunc)
|
||||||
|
continue;
|
||||||
|
BMessage languages;
|
||||||
|
if (language)
|
||||||
|
// try to load catalogs for the given language:
|
||||||
|
languages.AddString("language", language);
|
||||||
|
else
|
||||||
|
// try to load catalogs for one of the preferred languages:
|
||||||
|
GetPreferredLanguages(&languages);
|
||||||
|
|
||||||
|
BCatalogAddOn* catalog = NULL;
|
||||||
|
const char* lang;
|
||||||
|
for (int32 l=0; languages.FindString("language", l, &lang)==B_OK; ++l) {
|
||||||
|
catalog = info->fInstantiateFunc(signature, lang, fingerprint);
|
||||||
|
if (catalog)
|
||||||
|
info->fLoadedCatalogs.AddItem(catalog);
|
||||||
|
// Chain-load catalogs for languages that depend on
|
||||||
|
// other languages.
|
||||||
|
// The current implementation uses the filename in order to
|
||||||
|
// detect dependencies (parenthood) between languages (it
|
||||||
|
// traverses from "english_british_oxford" to "english_british"
|
||||||
|
// to "english"):
|
||||||
|
// TODO: use ICU facilities instead, so we can handle more
|
||||||
|
// complex things such as fr_FR@euro, or whatever, encodings
|
||||||
|
// and so on.
|
||||||
|
int32 pos;
|
||||||
|
BString langName(lang);
|
||||||
|
BCatalogAddOn* currCatalog = catalog;
|
||||||
|
BCatalogAddOn* nextCatalog;
|
||||||
|
while ((pos = langName.FindLast('_')) >= 0) {
|
||||||
|
// language is based on parent, so we load that, too:
|
||||||
|
// (even if the parent catalog was not found)
|
||||||
|
langName.Truncate(pos);
|
||||||
|
nextCatalog = info->fInstantiateFunc(signature,
|
||||||
|
langName.String(), fingerprint);
|
||||||
|
if (nextCatalog) {
|
||||||
|
info->fLoadedCatalogs.AddItem(nextCatalog);
|
||||||
|
if(currCatalog)
|
||||||
|
currCatalog->SetNext(nextCatalog);
|
||||||
|
else
|
||||||
|
catalog = nextCatalog;
|
||||||
|
currCatalog = nextCatalog;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return catalog;
|
||||||
|
}
|
||||||
|
info->UnloadIfPossible();
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Loads an embedded catalog from the given entry-ref (which is usually an
|
||||||
|
* app- or add-on-file. The request to load the catalog is dispatched to all
|
||||||
|
* add-ons in turn, until an add-on reports success.
|
||||||
|
* NULL is returned if no embedded catalog could be found.
|
||||||
|
*/
|
||||||
|
BCatalogAddOn*
|
||||||
|
MutableLocaleRoster::LoadEmbeddedCatalog(entry_ref* appOrAddOnRef)
|
||||||
|
{
|
||||||
|
if (!appOrAddOnRef)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
BAutolock lock(gRosterData.fLock);
|
||||||
|
if (!lock.IsLocked())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
int32 count = gRosterData.fCatalogAddOnInfos.CountItems();
|
||||||
|
for (int32 i = 0; i < count; ++i) {
|
||||||
|
CatalogAddOnInfo* info
|
||||||
|
= (CatalogAddOnInfo*)gRosterData.fCatalogAddOnInfos.ItemAt(i);
|
||||||
|
|
||||||
|
if (!info->MakeSureItsLoaded() || !info->fInstantiateEmbeddedFunc)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BCatalogAddOn* catalog = NULL;
|
||||||
|
catalog = info->fInstantiateEmbeddedFunc(appOrAddOnRef);
|
||||||
|
if (catalog) {
|
||||||
|
info->fLoadedCatalogs.AddItem(catalog);
|
||||||
|
return catalog;
|
||||||
|
}
|
||||||
|
info->UnloadIfPossible();
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* unloads the given catalog (or rather: catalog-chain).
|
||||||
|
* Every single catalog of the chain will be deleted automatically.
|
||||||
|
* Add-ons that have no more current catalogs are unloaded, too.
|
||||||
|
*/
|
||||||
|
status_t
|
||||||
|
MutableLocaleRoster::UnloadCatalog(BCatalogAddOn* catalog)
|
||||||
|
{
|
||||||
|
if (!catalog)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
BAutolock lock(gRosterData.fLock);
|
||||||
|
if (!lock.IsLocked())
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
status_t res = B_ERROR;
|
||||||
|
BCatalogAddOn* nextCatalog;
|
||||||
|
|
||||||
|
while (catalog) {
|
||||||
|
nextCatalog = catalog->Next();
|
||||||
|
int32 count = gRosterData.fCatalogAddOnInfos.CountItems();
|
||||||
|
for (int32 i = 0; i < count; ++i) {
|
||||||
|
CatalogAddOnInfo* info = static_cast<CatalogAddOnInfo*>(
|
||||||
|
gRosterData.fCatalogAddOnInfos.ItemAt(i));
|
||||||
|
if (info->fLoadedCatalogs.HasItem(catalog)) {
|
||||||
|
info->fLoadedCatalogs.RemoveItem(catalog);
|
||||||
|
delete catalog;
|
||||||
|
info->UnloadIfPossible();
|
||||||
|
res = B_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catalog = nextCatalog;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace BPrivate
|
||||||
|
|
||||||
|
|
||||||
|
BLocaleRoster* be_locale_roster = &BPrivate::gLocaleRoster;
|
||||||
@@ -1,90 +1,28 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010, Adrien Destugues, pulkomandy@gmail.com
|
* Copyright 2010, Haiku, Inc. All Rights Reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Oliver Tappe <zooey@hirschkaefer.de>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <TimeFormat.h>
|
#include <TimeFormat.h>
|
||||||
|
|
||||||
#include <unicode/format.h>
|
|
||||||
#include <unicode/tmutfmt.h>
|
|
||||||
#include <unicode/utypes.h>
|
|
||||||
#include <ICUWrapper.h>
|
|
||||||
|
|
||||||
#define ICU_VERSION icu_44
|
// copy constructor
|
||||||
|
BTimeFormat::BTimeFormat(const BTimeFormat &other)
|
||||||
status_t BTimeFormat::Format(int64 number, BString* buffer) const
|
: BDateTimeFormat(other)
|
||||||
{
|
{
|
||||||
// create time unit amount instance - a combination of Number and time unit
|
}
|
||||||
UErrorCode status = U_ZERO_ERROR;
|
|
||||||
|
// destructor
|
||||||
int64 days, hours, minutes, seconds, remainder;
|
BTimeFormat::~BTimeFormat()
|
||||||
|
{
|
||||||
days = number / (24 * 3600);
|
}
|
||||||
remainder = number % (24 * 3600);
|
|
||||||
|
// Format
|
||||||
hours = remainder / 3600;
|
status_t
|
||||||
remainder %= 3600;
|
BTimeFormat::Format(bigtime_t value, BString* buffer) const
|
||||||
|
{
|
||||||
minutes = remainder / 60;
|
return B_ERROR;
|
||||||
remainder %= 60;
|
|
||||||
|
|
||||||
seconds = remainder;
|
|
||||||
|
|
||||||
TimeUnitFormat* format = new TimeUnitFormat(status);
|
|
||||||
UnicodeString formatted;
|
|
||||||
Formattable formattable;
|
|
||||||
BStringByteSink bbs(buffer);
|
|
||||||
|
|
||||||
if (!U_SUCCESS(status)) {
|
|
||||||
delete format;
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (days) {
|
|
||||||
TimeUnitAmount* daysAmount = new TimeUnitAmount(days,
|
|
||||||
TimeUnit::UTIMEUNIT_DAY, status);
|
|
||||||
|
|
||||||
formattable.adoptObject(daysAmount);
|
|
||||||
formatted = ((ICU_VERSION::Format*)format)->format(formattable, formatted,
|
|
||||||
status);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hours) {
|
|
||||||
TimeUnitAmount* hoursAmount = new TimeUnitAmount(hours,
|
|
||||||
TimeUnit::UTIMEUNIT_HOUR, status);
|
|
||||||
|
|
||||||
formattable.adoptObject(hoursAmount);
|
|
||||||
if (days)
|
|
||||||
formatted.append(", ");
|
|
||||||
formatted = ((ICU_VERSION::Format*)format)->format(formattable, formatted,
|
|
||||||
status);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (minutes) {
|
|
||||||
TimeUnitAmount* minutesAmount = new TimeUnitAmount(minutes,
|
|
||||||
TimeUnit::UTIMEUNIT_MINUTE, status);
|
|
||||||
|
|
||||||
formattable.adoptObject(minutesAmount);
|
|
||||||
if (days || hours)
|
|
||||||
formatted.append(", ");
|
|
||||||
formatted = ((ICU_VERSION::Format*)format)->format(formattable, formatted,
|
|
||||||
status);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (seconds || (minutes == 0 && hours == 0 && days == 0)) {
|
|
||||||
TimeUnitAmount* secondsAmount = new TimeUnitAmount(seconds,
|
|
||||||
TimeUnit::UTIMEUNIT_SECOND, status);
|
|
||||||
|
|
||||||
formattable.adoptObject(secondsAmount);
|
|
||||||
if (days || hours || minutes)
|
|
||||||
formatted.append(", ");
|
|
||||||
formatted = ((ICU_VERSION::Format*)format)->format(formattable, formatted,
|
|
||||||
status);
|
|
||||||
}
|
|
||||||
formatted.toUTF8(bbs);
|
|
||||||
|
|
||||||
|
|
||||||
delete format;
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Adrien Destugues <pulkomandy@gmail.com>
|
||||||
|
* Oliver Tappe <zooey@hirschkaefer.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <TimeUnitFormat.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include <unicode/format.h>
|
||||||
|
#include <unicode/tmutfmt.h>
|
||||||
|
#include <unicode/utypes.h>
|
||||||
|
#include <ICUWrapper.h>
|
||||||
|
|
||||||
|
|
||||||
|
// maps our unit element to the corresponding ICU unit
|
||||||
|
static const TimeUnit::UTimeUnitFields skUnitMap[] = {
|
||||||
|
TimeUnit::UTIMEUNIT_YEAR,
|
||||||
|
TimeUnit::UTIMEUNIT_MONTH,
|
||||||
|
TimeUnit::UTIMEUNIT_WEEK,
|
||||||
|
TimeUnit::UTIMEUNIT_DAY,
|
||||||
|
TimeUnit::UTIMEUNIT_HOUR,
|
||||||
|
TimeUnit::UTIMEUNIT_MINUTE,
|
||||||
|
TimeUnit::UTIMEUNIT_SECOND,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
status_t BTimeUnitFormat::Format(int32 value, time_unit_element unit,
|
||||||
|
BString* buffer, time_unit_style style) const
|
||||||
|
{
|
||||||
|
if (buffer == NULL || unit < 0 || unit > B_TIME_UNIT_LAST
|
||||||
|
|| (style != B_TIME_UNIT_ABBREVIATED && style != B_TIME_UNIT_FULL))
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
UErrorCode icuStatus = U_ZERO_ERROR;
|
||||||
|
TimeUnitFormat timeUnitFormatter(icuStatus);
|
||||||
|
|
||||||
|
if (!U_SUCCESS(icuStatus))
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
TimeUnitAmount* timeUnitAmount
|
||||||
|
= new TimeUnitAmount((double)value, skUnitMap[unit], icuStatus);
|
||||||
|
if (timeUnitAmount == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
if (!U_SUCCESS(icuStatus))
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
Formattable formattable;
|
||||||
|
formattable.adoptObject(timeUnitAmount);
|
||||||
|
FieldPosition pos(FieldPosition::DONT_CARE);
|
||||||
|
UnicodeString unicodeResult;
|
||||||
|
timeUnitFormatter.format(formattable, unicodeResult, pos, icuStatus);
|
||||||
|
if (!U_SUCCESS(icuStatus))
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
BStringByteSink byteSink(buffer);
|
||||||
|
unicodeResult.toUTF8(byteSink);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
@@ -14,9 +14,12 @@
|
|||||||
#include <ICUWrapper.h>
|
#include <ICUWrapper.h>
|
||||||
|
|
||||||
|
|
||||||
|
const char* BTimeZone::kNameOfGmtZone = "GMT";
|
||||||
|
|
||||||
|
|
||||||
BTimeZone::BTimeZone(const char* zoneCode)
|
BTimeZone::BTimeZone(const char* zoneCode)
|
||||||
{
|
{
|
||||||
_Init(zoneCode);
|
SetTo(zoneCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -53,8 +56,8 @@ BTimeZone::InitCheck() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
status_t
|
||||||
BTimeZone::_Init(const char* zoneCode)
|
BTimeZone::SetTo(const char* zoneCode)
|
||||||
{
|
{
|
||||||
TimeZone* icuTimeZone;
|
TimeZone* icuTimeZone;
|
||||||
if (zoneCode == NULL || zoneCode[0] == '\0')
|
if (zoneCode == NULL || zoneCode[0] == '\0')
|
||||||
@@ -86,4 +89,6 @@ BTimeZone::_Init(const char* zoneCode)
|
|||||||
// we want seconds, not ms (which ICU gives us)
|
// we want seconds, not ms (which ICU gives us)
|
||||||
fInitStatus = B_OK;
|
fInitStatus = B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return fInitStatus;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,20 +7,21 @@
|
|||||||
#include "LocaleSettings.h"
|
#include "LocaleSettings.h"
|
||||||
|
|
||||||
#include <FindDirectory.h>
|
#include <FindDirectory.h>
|
||||||
#include <LocaleRoster.h>
|
#include <MutableLocaleRoster.h>
|
||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
#include <Roster.h>
|
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
using BPrivate::mutable_locale_roster;
|
||||||
|
|
||||||
|
|
||||||
static const uint32 kMsgLocaleSettings = 'LCst';
|
static const uint32 kMsgLocaleSettings = 'LCst';
|
||||||
|
|
||||||
|
|
||||||
LocaleSettings::LocaleSettings()
|
LocaleSettings::LocaleSettings()
|
||||||
:
|
:
|
||||||
fMessage(kMsgLocaleSettings),
|
fMessage(kMsgLocaleSettings)
|
||||||
fSaved(false)
|
|
||||||
{
|
{
|
||||||
// Set default preferences
|
// Set default preferences
|
||||||
fMessage.AddString("language", "en");
|
fMessage.AddString("language", "en");
|
||||||
@@ -36,27 +37,14 @@ LocaleSettings::Load()
|
|||||||
err = _Open(&file, B_READ_ONLY);
|
err = _Open(&file, B_READ_ONLY);
|
||||||
if (err != B_OK)
|
if (err != B_OK)
|
||||||
return err;
|
return err;
|
||||||
err = fMessage.Unflatten(&file);
|
return fMessage.Unflatten(&file);
|
||||||
if (err == B_OK)
|
|
||||||
fSaved = true;
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
LocaleSettings::Save()
|
LocaleSettings::Save()
|
||||||
{
|
{
|
||||||
// Save on disk for next time we reboot
|
return B_OK;
|
||||||
BFile file;
|
|
||||||
status_t err;
|
|
||||||
err = _Open(&file, B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY);
|
|
||||||
if (err != B_OK)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
err = fMessage.Flatten(&file);
|
|
||||||
if (err == B_OK)
|
|
||||||
fSaved = true;
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -86,33 +74,35 @@ LocaleSettings::UpdateFrom(BMessage* message)
|
|||||||
break;
|
break;
|
||||||
fMessage.AddString("language", messageContent);
|
fMessage.AddString("language", messageContent);
|
||||||
}
|
}
|
||||||
fSaved = false;
|
mutable_locale_roster->SetPreferredLanguages(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BCountry defaultCountry;
|
||||||
|
mutable_locale_roster->GetDefaultCountry(&defaultCountry);
|
||||||
|
|
||||||
|
bool countryChanged = false;
|
||||||
if (message->FindString("country", &messageContent) == B_OK) {
|
if (message->FindString("country", &messageContent) == B_OK) {
|
||||||
fMessage.ReplaceString("country", messageContent);
|
fMessage.ReplaceString("country", messageContent);
|
||||||
fMessage.RemoveName("shortTimeFormat");
|
fMessage.RemoveName("shortTimeFormat");
|
||||||
fMessage.RemoveName("longTimeFormat");
|
fMessage.RemoveName("longTimeFormat");
|
||||||
fSaved = false;
|
defaultCountry = BCountry(messageContent.String());
|
||||||
|
countryChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message->FindString("shortTimeFormat", &messageContent) == B_OK) {
|
if (message->FindString("shortTimeFormat", &messageContent) == B_OK) {
|
||||||
fMessage.RemoveName("shortTimeFormat");
|
fMessage.RemoveName("shortTimeFormat");
|
||||||
fMessage.AddString("shortTimeFormat", messageContent);
|
fMessage.AddString("shortTimeFormat", messageContent);
|
||||||
fSaved = false;
|
defaultCountry.SetTimeFormat(messageContent, false);
|
||||||
|
countryChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message->FindString("longTimeFormat", &messageContent) == B_OK) {
|
if (message->FindString("longTimeFormat", &messageContent) == B_OK) {
|
||||||
fMessage.RemoveName("longTimeFormat");
|
fMessage.RemoveName("longTimeFormat");
|
||||||
fMessage.AddString("longTimeFormat", messageContent);
|
fMessage.AddString("longTimeFormat", messageContent);
|
||||||
fSaved = false;
|
defaultCountry.SetTimeFormat(messageContent, true);
|
||||||
|
countryChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fSaved == false) {
|
if (countryChanged)
|
||||||
// Send to all running apps to notify them they should update their
|
mutable_locale_roster->SetDefaultCountry(defaultCountry);
|
||||||
// settings
|
|
||||||
fMessage.what = B_LOCALE_CHANGED;
|
|
||||||
be_roster->Broadcast(&fMessage);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ class LocaleSettings {
|
|||||||
status_t Load();
|
status_t Load();
|
||||||
status_t Save();
|
status_t Save();
|
||||||
|
|
||||||
bool Saved();
|
|
||||||
bool operator==(const LocaleSettings& other);
|
bool operator==(const LocaleSettings& other);
|
||||||
|
|
||||||
void UpdateFrom(BMessage* message);
|
void UpdateFrom(BMessage* message);
|
||||||
@@ -44,7 +43,6 @@ class LocaleSettings {
|
|||||||
status_t _Open(BFile* file, int32 mode);
|
status_t _Open(BFile* file, int32 mode);
|
||||||
|
|
||||||
BMessage fMessage;
|
BMessage fMessage;
|
||||||
bool fSaved;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -47,10 +47,24 @@ static const uint32 kMsgPreferredLanguagesChanged = 'lang';
|
|||||||
static int
|
static int
|
||||||
compare_typed_list_items(const BListItem* _a, const BListItem* _b)
|
compare_typed_list_items(const BListItem* _a, const BListItem* _b)
|
||||||
{
|
{
|
||||||
// TODO: sort them using collators.
|
static BCollator collator;
|
||||||
|
|
||||||
LanguageListItem* a = (LanguageListItem*)_a;
|
LanguageListItem* a = (LanguageListItem*)_a;
|
||||||
LanguageListItem* b = (LanguageListItem*)_b;
|
LanguageListItem* b = (LanguageListItem*)_b;
|
||||||
return strcasecmp(a->Text(), b->Text());
|
|
||||||
|
return collator.Compare(a->Text(), b->Text());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
compare_void_list_items(const void* _a, const void* _b)
|
||||||
|
{
|
||||||
|
static BCollator collator;
|
||||||
|
|
||||||
|
LanguageListItem* a = *(LanguageListItem**)_a;
|
||||||
|
LanguageListItem* b = *(LanguageListItem**)_b;
|
||||||
|
|
||||||
|
return collator.Compare(a->Text(), b->Text());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -62,7 +76,7 @@ LocaleWindow::LocaleWindow()
|
|||||||
BWindow(BRect(0, 0, 0, 0), "Locale", B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE
|
BWindow(BRect(0, 0, 0, 0), "Locale", B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE
|
||||||
| B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS)
|
| B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS)
|
||||||
{
|
{
|
||||||
BCountry* defaultCountry;
|
BCountry defaultCountry;
|
||||||
be_locale_roster->GetDefaultCountry(&defaultCountry);
|
be_locale_roster->GetDefaultCountry(&defaultCountry);
|
||||||
|
|
||||||
SetLayout(new BGroupLayout(B_HORIZONTAL));
|
SetLayout(new BGroupLayout(B_HORIZONTAL));
|
||||||
@@ -173,21 +187,26 @@ LocaleWindow::LocaleWindow()
|
|||||||
be_locale_roster->GetInstalledLanguages(&countryList);
|
be_locale_roster->GetInstalledLanguages(&countryList);
|
||||||
BString countryCode;
|
BString countryCode;
|
||||||
|
|
||||||
|
LanguageListItem* currentItem = NULL;
|
||||||
for (int i = 0; countryList.FindString("langs", i, &countryCode) == B_OK;
|
for (int i = 0; countryList.FindString("langs", i, &countryCode) == B_OK;
|
||||||
i++) {
|
i++) {
|
||||||
BCountry country(countryCode);
|
BCountry country(countryCode);
|
||||||
BString countryName;
|
BString countryName;
|
||||||
|
|
||||||
country.LocaleName(countryName);
|
country.GetLocaleName(countryName);
|
||||||
|
|
||||||
LanguageListItem* item
|
LanguageListItem* item
|
||||||
= new LanguageListItem(countryName, countryCode,
|
= new LanguageListItem(countryName, countryCode,
|
||||||
NULL);
|
NULL);
|
||||||
listView->AddItem(item);
|
listView->AddItem(item);
|
||||||
if (!strcmp(countryCode, defaultCountry->Code()))
|
if (!strcmp(countryCode, defaultCountry.Code()))
|
||||||
listView->Select(listView->CountItems() - 1);
|
currentItem = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
listView->SortItems(compare_void_list_items);
|
||||||
|
if (currentItem != NULL)
|
||||||
|
listView->Select(listView->IndexOf(currentItem));
|
||||||
|
|
||||||
// TODO: find a real solution intead of this hack
|
// TODO: find a real solution intead of this hack
|
||||||
listView->SetExplicitMinSize(
|
listView->SetExplicitMinSize(
|
||||||
BSize(25 * be_plain_font->Size(), B_SIZE_UNSET));
|
BSize(25 * be_plain_font->Size(), B_SIZE_UNSET));
|
||||||
@@ -341,7 +360,7 @@ LocaleWindow::MessageReceived(BMessage* message)
|
|||||||
be_app_messenger.SendMessage(&newMessage);
|
be_app_messenger.SendMessage(&newMessage);
|
||||||
SettingsChanged();
|
SettingsChanged();
|
||||||
|
|
||||||
BCountry* country = new BCountry(item->ID());
|
BCountry country(item->ID());
|
||||||
fFormatView->SetCountry(country);
|
fFormatView->SetCountry(country);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
#include <GroupLayoutBuilder.h>
|
#include <GroupLayoutBuilder.h>
|
||||||
#include <LayoutBuilder.h>
|
#include <LayoutBuilder.h>
|
||||||
#include <Locale.h>
|
#include <Locale.h>
|
||||||
#include <LocaleRoster.h>
|
#include <MutableLocaleRoster.h>
|
||||||
#include <Message.h>
|
#include <Message.h>
|
||||||
#include <Menu.h>
|
#include <Menu.h>
|
||||||
#include <MenuField.h>
|
#include <MenuField.h>
|
||||||
@@ -34,6 +34,10 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
using BPrivate::mutable_locale_roster;
|
||||||
|
|
||||||
|
|
||||||
#undef B_TRANSLATE_CONTEXT
|
#undef B_TRANSLATE_CONTEXT
|
||||||
#define B_TRANSLATE_CONTEXT "TimeFormatSettings"
|
#define B_TRANSLATE_CONTEXT "TimeFormatSettings"
|
||||||
@@ -144,10 +148,10 @@ IsSpecialDateChar(char charToTest)
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
FormatView::FormatView(BCountry* country)
|
FormatView::FormatView(const BCountry& country)
|
||||||
:
|
:
|
||||||
BView("WindowsSettingsView", B_FRAME_EVENTS),
|
BView("WindowsSettingsView", B_FRAME_EVENTS),
|
||||||
fCountry(*country)
|
fCountry(country)
|
||||||
{
|
{
|
||||||
SetLayout(new BGroupLayout(B_HORIZONTAL));
|
SetLayout(new BGroupLayout(B_HORIZONTAL));
|
||||||
|
|
||||||
@@ -185,8 +189,8 @@ FormatView::FormatView(BCountry* country)
|
|||||||
f12HrRadioButton = new BRadioButton("", B_TRANSLATE("12 hour"),
|
f12HrRadioButton = new BRadioButton("", B_TRANSLATE("12 hour"),
|
||||||
new BMessage(kClockFormatChange));
|
new BMessage(kClockFormatChange));
|
||||||
|
|
||||||
fCountry.TimeFormat(fOriginalTimeFormat, false);
|
fCountry.GetTimeFormat(fOriginalTimeFormat, false);
|
||||||
fCountry.TimeFormat(fOriginalLongTimeFormat, true);
|
fCountry.GetTimeFormat(fOriginalLongTimeFormat, true);
|
||||||
if (fOriginalTimeFormat.FindFirst("a") != B_ERROR) {
|
if (fOriginalTimeFormat.FindFirst("a") != B_ERROR) {
|
||||||
f12HrRadioButton->SetValue(B_CONTROL_ON);
|
f12HrRadioButton->SetValue(B_CONTROL_ON);
|
||||||
fCountryIs24Hr = false;
|
fCountryIs24Hr = false;
|
||||||
@@ -356,7 +360,7 @@ FormatView::FormatView(BCountry* country)
|
|||||||
|
|
||||||
FormatView::~FormatView()
|
FormatView::~FormatView()
|
||||||
{
|
{
|
||||||
be_locale_roster->SetDefaultCountry(&fCountry);
|
mutable_locale_roster->SetDefaultCountry(fCountry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -510,9 +514,9 @@ FormatView::SetDefaults()
|
|||||||
settings.SetClockTo24Hr(false);
|
settings.SetClockTo24Hr(false);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BCountry* defaultCountry;
|
BCountry defaultCountry;
|
||||||
be_locale_roster->GetDefaultCountry(&defaultCountry);
|
be_locale_roster->GetDefaultCountry(&defaultCountry);
|
||||||
fCountry = *defaultCountry;
|
fCountry = defaultCountry;
|
||||||
// We work on a copy of the default country and set the changes when
|
// We work on a copy of the default country and set the changes when
|
||||||
// closing the preflet
|
// closing the preflet
|
||||||
_UpdateExamples();
|
_UpdateExamples();
|
||||||
@@ -551,14 +555,12 @@ FormatView::Revert()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FormatView::SetCountry(BCountry* country)
|
FormatView::SetCountry(const BCountry& country)
|
||||||
{
|
{
|
||||||
fCountry = *country;
|
fCountry = country;
|
||||||
|
|
||||||
fOriginalTimeFormat.Truncate(0);
|
fCountry.GetTimeFormat(fOriginalTimeFormat, false);
|
||||||
fCountry.TimeFormat(fOriginalTimeFormat, false);
|
fCountry.GetTimeFormat(fOriginalLongTimeFormat, true);
|
||||||
fOriginalLongTimeFormat.Truncate(0);
|
|
||||||
fCountry.TimeFormat(fOriginalLongTimeFormat, true);
|
|
||||||
|
|
||||||
if (fOriginalTimeFormat.FindFirst("a") != B_ERROR) {
|
if (fOriginalTimeFormat.FindFirst("a") != B_ERROR) {
|
||||||
f12HrRadioButton->SetValue(B_CONTROL_ON);
|
f12HrRadioButton->SetValue(B_CONTROL_ON);
|
||||||
@@ -666,10 +668,12 @@ FormatView::_ParseDateFormat()
|
|||||||
{
|
{
|
||||||
// TODO parse the short date too
|
// TODO parse the short date too
|
||||||
BString dateFormatString;
|
BString dateFormatString;
|
||||||
fCountry.DateFormat(dateFormatString, true);
|
fCountry.GetDateFormat(dateFormatString, true);
|
||||||
const char* dateFormat = dateFormatString.String();
|
const char* dateFormat = dateFormatString.String();
|
||||||
|
|
||||||
// Travel trough the string and parse it
|
printf("FV::_ParseDateFormat: df='%s'\n", dateFormat);
|
||||||
|
|
||||||
|
// Travel through the string and parse it
|
||||||
const char* parsePointer = dateFormat;
|
const char* parsePointer = dateFormat;
|
||||||
const char* fieldBegin = dateFormat;
|
const char* fieldBegin = dateFormat;
|
||||||
|
|
||||||
@@ -717,8 +721,7 @@ FormatView::_ParseDateFormat()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Short date is a bit more tricky, we want to extract the separator
|
// Short date is a bit more tricky, we want to extract the separator
|
||||||
dateFormatString.Truncate(0);
|
fCountry.GetDateFormat(dateFormatString, false);
|
||||||
fCountry.DateFormat(dateFormatString, false);
|
|
||||||
dateFormat = dateFormatString.String();
|
dateFormat = dateFormatString.String();
|
||||||
|
|
||||||
// Travel trough the string and parse it
|
// Travel trough the string and parse it
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ const uint32 kMenuMessage = 'FRMT';
|
|||||||
|
|
||||||
class FormatView : public BView {
|
class FormatView : public BView {
|
||||||
public:
|
public:
|
||||||
FormatView(BCountry* country);
|
FormatView(const BCountry& country);
|
||||||
~FormatView();
|
~FormatView();
|
||||||
|
|
||||||
virtual void MessageReceived(BMessage* message);
|
virtual void MessageReceived(BMessage* message);
|
||||||
@@ -46,7 +46,7 @@ public:
|
|||||||
virtual void SetDefaults();
|
virtual void SetDefaults();
|
||||||
virtual bool IsDefaultable() const;
|
virtual bool IsDefaultable() const;
|
||||||
virtual void Revert();
|
virtual void Revert();
|
||||||
virtual void SetCountry(BCountry* country);
|
virtual void SetCountry(const BCountry& country);
|
||||||
virtual void RecordRevertSettings();
|
virtual void RecordRevertSettings();
|
||||||
virtual bool IsRevertable() const;
|
virtual bool IsRevertable() const;
|
||||||
|
|
||||||
|
|||||||
@@ -105,9 +105,9 @@ TTimeEdit::DrawSection(uint32 index, bool hasFocus)
|
|||||||
int* fieldPositions;
|
int* fieldPositions;
|
||||||
int fieldCount;
|
int fieldCount;
|
||||||
|
|
||||||
BCountry* country;
|
BCountry country;
|
||||||
be_locale_roster->GetDefaultCountry(&country);
|
be_locale_roster->GetDefaultCountry(&country);
|
||||||
country->FormatTime(&text, fieldPositions, fieldCount, time, true);
|
country.FormatTime(&text, fieldPositions, fieldCount, time, true);
|
||||||
// TODO : this should be cached somehow to not redo it for each field
|
// TODO : this should be cached somehow to not redo it for each field
|
||||||
|
|
||||||
if (index * 2 + 1 > (uint32)fieldCount) {
|
if (index * 2 + 1 > (uint32)fieldCount) {
|
||||||
@@ -148,10 +148,10 @@ TTimeEdit::DrawSeparator(uint32 index)
|
|||||||
int* fieldPositions;
|
int* fieldPositions;
|
||||||
int fieldCount;
|
int fieldCount;
|
||||||
|
|
||||||
BCountry* country;
|
BCountry country;
|
||||||
be_locale_roster->GetDefaultCountry(&country);
|
be_locale_roster->GetDefaultCountry(&country);
|
||||||
time_t time = fTime.Time_t();
|
time_t time = fTime.Time_t();
|
||||||
country->FormatTime(&text, fieldPositions, fieldCount, time, true);
|
country.FormatTime(&text, fieldPositions, fieldCount, time, true);
|
||||||
// TODO : this should be cached somehow to not redo it for each field
|
// TODO : this should be cached somehow to not redo it for each field
|
||||||
|
|
||||||
if (index * 2 + 2 > (uint32)fieldCount) {
|
if (index * 2 + 2 > (uint32)fieldCount) {
|
||||||
@@ -265,9 +265,9 @@ TTimeEdit::BuildDispatch(BMessage* message)
|
|||||||
|
|
||||||
BDateElement* dateFormat;
|
BDateElement* dateFormat;
|
||||||
int fieldCount;
|
int fieldCount;
|
||||||
BCountry* here;
|
BCountry here;
|
||||||
be_locale_roster->GetDefaultCountry(&here);
|
be_locale_roster->GetDefaultCountry(&here);
|
||||||
here->TimeFields(dateFormat, fieldCount, true);
|
here.GetTimeFields(dateFormat, fieldCount, true);
|
||||||
if (fFocus > fieldCount) {
|
if (fFocus > fieldCount) {
|
||||||
free(dateFormat);
|
free(dateFormat);
|
||||||
return;
|
return;
|
||||||
@@ -303,9 +303,9 @@ TTimeEdit::_CheckRange()
|
|||||||
int32 value = fHoldValue;
|
int32 value = fHoldValue;
|
||||||
BDateElement* fields;
|
BDateElement* fields;
|
||||||
int fieldCount;
|
int fieldCount;
|
||||||
BCountry* here;
|
BCountry here;
|
||||||
be_locale_roster->GetDefaultCountry(&here);
|
be_locale_roster->GetDefaultCountry(&here);
|
||||||
here->TimeFields(fields, fieldCount, true);
|
here.GetTimeFields(fields, fieldCount, true);
|
||||||
if (fFocus > fieldCount) {
|
if (fFocus > fieldCount) {
|
||||||
free(fields);
|
free(fields);
|
||||||
return;
|
return;
|
||||||
@@ -373,9 +373,9 @@ TTimeEdit::_IsValidDoubleDigi(int32 value)
|
|||||||
bool isInRange = false;
|
bool isInRange = false;
|
||||||
BDateElement* fields;
|
BDateElement* fields;
|
||||||
int fieldCount;
|
int fieldCount;
|
||||||
BCountry* here;
|
BCountry here;
|
||||||
be_locale_roster->GetDefaultCountry(&here);
|
be_locale_roster->GetDefaultCountry(&here);
|
||||||
here->TimeFields(fields, fieldCount, true);
|
here.GetTimeFields(fields, fieldCount, true);
|
||||||
if (fFocus > fieldCount) {
|
if (fFocus > fieldCount) {
|
||||||
free(fields);
|
free(fields);
|
||||||
return false;
|
return false;
|
||||||
@@ -412,9 +412,9 @@ TTimeEdit::_SectionValue(int32 index) const
|
|||||||
int32 value;
|
int32 value;
|
||||||
BDateElement* fields;
|
BDateElement* fields;
|
||||||
int fieldCount;
|
int fieldCount;
|
||||||
BCountry* here;
|
BCountry here;
|
||||||
be_locale_roster->GetDefaultCountry(&here);
|
be_locale_roster->GetDefaultCountry(&here);
|
||||||
here->TimeFields(fields, fieldCount, true);
|
here.GetTimeFields(fields, fieldCount, true);
|
||||||
if (index > fieldCount) {
|
if (index > fieldCount) {
|
||||||
free(fields);
|
free(fields);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -487,9 +487,9 @@ TDateEdit::KeyDown(const char* bytes, int32 numBytes)
|
|||||||
|
|
||||||
BDateElement* dateFormat;
|
BDateElement* dateFormat;
|
||||||
int fieldCount;
|
int fieldCount;
|
||||||
BCountry* here;
|
BCountry here;
|
||||||
be_locale_roster->GetDefaultCountry(&here);
|
be_locale_roster->GetDefaultCountry(&here);
|
||||||
here->DateFields(dateFormat, fieldCount, false);
|
here.GetDateFields(dateFormat, fieldCount, false);
|
||||||
|
|
||||||
if (dateFormat[section] == B_DATE_ELEMENT_YEAR) {
|
if (dateFormat[section] == B_DATE_ELEMENT_YEAR) {
|
||||||
int32 oldCentury = int32(fHoldValue / 100) * 100;
|
int32 oldCentury = int32(fHoldValue / 100) * 100;
|
||||||
@@ -541,9 +541,9 @@ TDateEdit::DrawSection(uint32 index, bool hasFocus)
|
|||||||
int* fieldPositions;
|
int* fieldPositions;
|
||||||
int fieldCount;
|
int fieldCount;
|
||||||
|
|
||||||
BCountry* country;
|
BCountry country;
|
||||||
be_locale_roster->GetDefaultCountry(&country);
|
be_locale_roster->GetDefaultCountry(&country);
|
||||||
country->FormatDate(&text, fieldPositions, fieldCount, dateTime.Time_t(),
|
country.FormatDate(&text, fieldPositions, fieldCount, dateTime.Time_t(),
|
||||||
false);
|
false);
|
||||||
// TODO : this should be cached somehow to not redo it for each field
|
// TODO : this should be cached somehow to not redo it for each field
|
||||||
|
|
||||||
@@ -587,10 +587,10 @@ TDateEdit::DrawSeparator(uint32 index)
|
|||||||
int* fieldPositions;
|
int* fieldPositions;
|
||||||
int fieldCount;
|
int fieldCount;
|
||||||
|
|
||||||
BCountry* country;
|
BCountry country;
|
||||||
be_locale_roster->GetDefaultCountry(&country);
|
be_locale_roster->GetDefaultCountry(&country);
|
||||||
BDateTime dateTime(fDate, BTime());
|
BDateTime dateTime(fDate, BTime());
|
||||||
country->FormatDate(&text, fieldPositions, fieldCount, dateTime.Time_t(),
|
country.FormatDate(&text, fieldPositions, fieldCount, dateTime.Time_t(),
|
||||||
false);
|
false);
|
||||||
// TODO : this should be cached somehow to not redo it for each field
|
// TODO : this should be cached somehow to not redo it for each field
|
||||||
|
|
||||||
@@ -716,9 +716,9 @@ TDateEdit::BuildDispatch(BMessage* message)
|
|||||||
|
|
||||||
BDateElement* dateFormat;
|
BDateElement* dateFormat;
|
||||||
int fieldCount;
|
int fieldCount;
|
||||||
BCountry* here;
|
BCountry here;
|
||||||
be_locale_roster->GetDefaultCountry(&here);
|
be_locale_roster->GetDefaultCountry(&here);
|
||||||
here->DateFields(dateFormat, fieldCount, false);
|
here.GetDateFields(dateFormat, fieldCount, false);
|
||||||
if (fFocus > fieldCount) {
|
if (fFocus > fieldCount) {
|
||||||
free(dateFormat);
|
free(dateFormat);
|
||||||
return;
|
return;
|
||||||
@@ -754,9 +754,9 @@ TDateEdit::_CheckRange()
|
|||||||
int32 value = fHoldValue;
|
int32 value = fHoldValue;
|
||||||
BDateElement* fields;
|
BDateElement* fields;
|
||||||
int fieldCount;
|
int fieldCount;
|
||||||
BCountry* here;
|
BCountry here;
|
||||||
be_locale_roster->GetDefaultCountry(&here);
|
be_locale_roster->GetDefaultCountry(&here);
|
||||||
here->DateFields(fields, fieldCount, false);
|
here.GetDateFields(fields, fieldCount, false);
|
||||||
if (fFocus > fieldCount) {
|
if (fFocus > fieldCount) {
|
||||||
free(fields);
|
free(fields);
|
||||||
return;
|
return;
|
||||||
@@ -811,9 +811,9 @@ TDateEdit::_IsValidDoubleDigi(int32 value)
|
|||||||
bool isInRange = false;
|
bool isInRange = false;
|
||||||
BDateElement* fields;
|
BDateElement* fields;
|
||||||
int fieldCount;
|
int fieldCount;
|
||||||
BCountry* here;
|
BCountry here;
|
||||||
be_locale_roster->GetDefaultCountry(&here);
|
be_locale_roster->GetDefaultCountry(&here);
|
||||||
here->DateFields(fields, fieldCount, false);
|
here.GetDateFields(fields, fieldCount, false);
|
||||||
if (fFocus > fieldCount) {
|
if (fFocus > fieldCount) {
|
||||||
free(fields);
|
free(fields);
|
||||||
return false;
|
return false;
|
||||||
@@ -852,9 +852,9 @@ TDateEdit::_SectionValue(int32 index) const
|
|||||||
int32 value = 0;
|
int32 value = 0;
|
||||||
BDateElement* fields;
|
BDateElement* fields;
|
||||||
int fieldCount;
|
int fieldCount;
|
||||||
BCountry* here;
|
BCountry here;
|
||||||
be_locale_roster->GetDefaultCountry(&here);
|
be_locale_roster->GetDefaultCountry(&here);
|
||||||
here->DateFields(fields, fieldCount, false);
|
here.GetDateFields(fields, fieldCount, false);
|
||||||
if (index > fieldCount) {
|
if (index > fieldCount) {
|
||||||
free(fields);
|
free(fields);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
#include "TimeMessages.h"
|
#include "TimeMessages.h"
|
||||||
#include "TimeWindow.h"
|
#include "TimeWindow.h"
|
||||||
|
|
||||||
|
|
||||||
#include <CalendarView.h>
|
#include <CalendarView.h>
|
||||||
#include <CheckBox.h>
|
#include <CheckBox.h>
|
||||||
#include <DateTime.h>
|
#include <DateTime.h>
|
||||||
@@ -28,22 +27,18 @@
|
|||||||
#include <String.h>
|
#include <String.h>
|
||||||
#include <StringView.h>
|
#include <StringView.h>
|
||||||
#include <Window.h>
|
#include <Window.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <syscalls.h>
|
||||||
|
|
||||||
|
|
||||||
using BPrivate::BCalendarView;
|
using BPrivate::BCalendarView;
|
||||||
using BPrivate::BDateTime;
|
using BPrivate::BDateTime;
|
||||||
using BPrivate::B_LOCAL_TIME;
|
using BPrivate::B_LOCAL_TIME;
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
|
|
||||||
# include <syscalls.h>
|
|
||||||
#else
|
|
||||||
extern "C" void _kset_tzfilename_(const char* name, size_t length, bool isGMT);
|
|
||||||
# define _kern_set_tzfilename _kset_tzfilename_
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
DateTimeView::DateTimeView(BRect frame)
|
DateTimeView::DateTimeView(BRect frame)
|
||||||
: BView(frame, "dateTimeView", B_FOLLOW_NONE, B_WILL_DRAW
|
: BView(frame, "dateTimeView", B_FOLLOW_NONE, B_WILL_DRAW
|
||||||
| B_NAVIGABLE_JUMP),
|
| B_NAVIGABLE_JUMP),
|
||||||
@@ -266,6 +261,7 @@ DateTimeView::_InitView()
|
|||||||
AddChild(fGmtTime);
|
AddChild(fGmtTime);
|
||||||
fGmtTime->ResizeToPreferred();
|
fGmtTime->ResizeToPreferred();
|
||||||
|
|
||||||
|
printf("fUseGmtTime=%d\n", fUseGmtTime);
|
||||||
if (fUseGmtTime)
|
if (fUseGmtTime)
|
||||||
fGmtTime->SetValue(B_CONTROL_ON);
|
fGmtTime->SetValue(B_CONTROL_ON);
|
||||||
else
|
else
|
||||||
@@ -323,20 +319,6 @@ DateTimeView::_UpdateGmtSettings()
|
|||||||
{
|
{
|
||||||
_WriteRTCSettings();
|
_WriteRTCSettings();
|
||||||
|
|
||||||
BPath path;
|
|
||||||
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) {
|
|
||||||
path.Append("timezone");
|
|
||||||
BEntry entry(path.Path(), true);
|
|
||||||
if (entry.Exists()) {
|
|
||||||
entry.GetPath(&path);
|
|
||||||
|
|
||||||
// take the existing timezone and set it's gmt use
|
|
||||||
_kern_set_tzfilename(path.Path(), B_PATH_NAME_LENGTH, fUseGmtTime);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only update GMT
|
|
||||||
_kern_set_tzfilename(NULL, 0, fUseGmtTime);
|
_kern_set_tzfilename(NULL, 0, fUseGmtTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ SubDir HAIKU_TOP src preferences time ;
|
|||||||
|
|
||||||
SetSubDirSupportedPlatformsBeOSCompatible ;
|
SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||||
|
|
||||||
UsePrivateHeaders shared ;
|
UsePrivateHeaders locale shared ;
|
||||||
UsePrivateSystemHeaders ;
|
UsePrivateSystemHeaders ;
|
||||||
|
|
||||||
Preference Time :
|
local sources =
|
||||||
AnalogClock.cpp
|
AnalogClock.cpp
|
||||||
BaseView.cpp
|
BaseView.cpp
|
||||||
Bitmaps.cpp
|
Bitmaps.cpp
|
||||||
@@ -18,6 +18,16 @@ Preference Time :
|
|||||||
TimeZoneListItem.cpp
|
TimeZoneListItem.cpp
|
||||||
TZDisplay.cpp
|
TZDisplay.cpp
|
||||||
ZoneView.cpp
|
ZoneView.cpp
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
SubDirSysHdrs $(HAIKU_ICU_HEADERS) ;
|
||||||
|
Includes [ FGristFiles $(sources) ] : $(HAIKU_ICU_HEADERS_DEPENDENCY) ;
|
||||||
|
# Dependency needed to trigger downloading/unzipping the package before
|
||||||
|
# compiling the files.
|
||||||
|
|
||||||
|
Preference Time
|
||||||
|
: $(sources)
|
||||||
: be libshared.a $(TARGET_LIBSUPC++) $(HAIKU_LOCALE_LIBS)
|
: be libshared.a $(TARGET_LIBSUPC++) $(HAIKU_LOCALE_LIBS)
|
||||||
: Time.rdef
|
: Time.rdef
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ void
|
|||||||
TTZDisplay::SetLabel(const char* label)
|
TTZDisplay::SetLabel(const char* label)
|
||||||
{
|
{
|
||||||
fLabel.SetTo(label);
|
fLabel.SetTo(label);
|
||||||
Draw(Bounds());
|
Invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ void
|
|||||||
TTZDisplay::SetText(const char* text)
|
TTZDisplay::SetText(const char* text)
|
||||||
{
|
{
|
||||||
fText.SetTo(text);
|
fText.SetTo(text);
|
||||||
Draw(Bounds());
|
Invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -115,24 +115,9 @@ TTZDisplay::Time() const
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TTZDisplay::SetTime(int32 hour, int32 minute)
|
TTZDisplay::SetTime(const char* time)
|
||||||
{
|
{
|
||||||
int32 ahour = hour;
|
fTime.SetTo(time);
|
||||||
if (hour > 12)
|
|
||||||
ahour = hour -12;
|
|
||||||
|
|
||||||
if (ahour == 0)
|
|
||||||
ahour = 12;
|
|
||||||
|
|
||||||
const char* ap = "AM";
|
|
||||||
if (hour > 11)
|
|
||||||
ap = "PM";
|
|
||||||
|
|
||||||
char buffer[32];
|
|
||||||
snprintf(buffer, sizeof(buffer), "%ld:%02ld %s", ahour, minute, ap);
|
|
||||||
|
|
||||||
fTime.SetTo(buffer);
|
|
||||||
|
|
||||||
Invalidate();
|
Invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,12 +33,12 @@ public:
|
|||||||
void SetText(const char* text);
|
void SetText(const char* text);
|
||||||
|
|
||||||
const char* Time() const;
|
const char* Time() const;
|
||||||
void SetTime(int32 hour, int32 minute);
|
void SetTime(const char* time);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BString fLabel;
|
BString fLabel;
|
||||||
BString fText;
|
BString fText;
|
||||||
BString fTime;
|
BString fTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,8 @@ TimeZoneListItem::TimeZoneListItem(const char* text, BCountry* country,
|
|||||||
BTimeZone* timeZone)
|
BTimeZone* timeZone)
|
||||||
:
|
:
|
||||||
BStringItem(text),
|
BStringItem(text),
|
||||||
fIcon(NULL)
|
fIcon(NULL),
|
||||||
|
fTimeZone(timeZone)
|
||||||
{
|
{
|
||||||
if (country != NULL) {
|
if (country != NULL) {
|
||||||
fIcon = new(std::nothrow) BBitmap(BRect(0, 0, 15, 15), B_RGBA32);
|
fIcon = new(std::nothrow) BBitmap(BRect(0, 0, 15, 15), B_RGBA32);
|
||||||
@@ -37,8 +38,6 @@ TimeZoneListItem::TimeZoneListItem(const char* text, BCountry* country,
|
|||||||
fIcon = NULL;
|
fIcon = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fTimeZone = timeZone;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -95,6 +94,20 @@ TimeZoneListItem::DrawItem(BView* owner, BRect frame, bool complete)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
TimeZoneListItem::HasTimeZone() const
|
||||||
|
{
|
||||||
|
return fTimeZone != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const BTimeZone&
|
||||||
|
TimeZoneListItem::TimeZone() const
|
||||||
|
{
|
||||||
|
return *fTimeZone;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const BString&
|
const BString&
|
||||||
TimeZoneListItem::Code() const
|
TimeZoneListItem::Code() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ public:
|
|||||||
void DrawItem(BView* owner, BRect frame,
|
void DrawItem(BView* owner, BRect frame,
|
||||||
bool complete = false);
|
bool complete = false);
|
||||||
|
|
||||||
|
bool HasTimeZone() const;
|
||||||
|
const BTimeZone& TimeZone() const;
|
||||||
const BString& Code() const;
|
const BString& Code() const;
|
||||||
const BString& Name() const;
|
const BString& Name() const;
|
||||||
int OffsetFromGMT() const;
|
int OffsetFromGMT() const;
|
||||||
|
|||||||
+116
-133
@@ -10,16 +10,14 @@
|
|||||||
* Oliver Tappe <zooey@hirschkaefer.de>
|
* Oliver Tappe <zooey@hirschkaefer.de>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
Exceptions:
|
|
||||||
doesn't calc "Time in" time.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ZoneView.h"
|
#include "ZoneView.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include <AutoDeleter.h>
|
||||||
#include <Button.h>
|
#include <Button.h>
|
||||||
#include <Collator.h>
|
#include <Collator.h>
|
||||||
#include <Directory.h>
|
#include <Directory.h>
|
||||||
@@ -27,7 +25,7 @@
|
|||||||
#include <FindDirectory.h>
|
#include <FindDirectory.h>
|
||||||
#include <ListItem.h>
|
#include <ListItem.h>
|
||||||
#include <Locale.h>
|
#include <Locale.h>
|
||||||
#include <LocaleRoster.h>
|
#include <MutableLocaleRoster.h>
|
||||||
#include <OutlineListView.h>
|
#include <OutlineListView.h>
|
||||||
#include <ScrollView.h>
|
#include <ScrollView.h>
|
||||||
#include <StorageDefs.h>
|
#include <StorageDefs.h>
|
||||||
@@ -38,21 +36,25 @@
|
|||||||
|
|
||||||
#include <syscalls.h>
|
#include <syscalls.h>
|
||||||
|
|
||||||
|
#include <unicode/datefmt.h>
|
||||||
|
#include <unicode/utmscale.h>
|
||||||
|
#include <ICUWrapper.h>
|
||||||
|
|
||||||
#include "TimeMessages.h"
|
#include "TimeMessages.h"
|
||||||
#include "TimeZoneListItem.h"
|
#include "TimeZoneListItem.h"
|
||||||
#include "TZDisplay.h"
|
#include "TZDisplay.h"
|
||||||
#include "TimeWindow.h"
|
#include "TimeWindow.h"
|
||||||
|
|
||||||
|
|
||||||
static BCollator sCollator;
|
using BPrivate::mutable_locale_roster;
|
||||||
// used to sort the timezone list
|
using BPrivate::ObjectDeleter;
|
||||||
|
|
||||||
|
|
||||||
TimeZoneView::TimeZoneView(BRect frame)
|
TimeZoneView::TimeZoneView(BRect frame)
|
||||||
:
|
:
|
||||||
BView(frame, "timeZoneView", B_FOLLOW_NONE, B_WILL_DRAW | B_NAVIGABLE_JUMP),
|
BView(frame, "timeZoneView", B_FOLLOW_NONE, B_WILL_DRAW | B_NAVIGABLE_JUMP),
|
||||||
fCurrentZone(NULL),
|
fCurrentZoneItem(NULL),
|
||||||
fOldZone(NULL),
|
fOldZoneItem(NULL),
|
||||||
fInitialized(false)
|
fInitialized(false)
|
||||||
{
|
{
|
||||||
_InitView();
|
_InitView();
|
||||||
@@ -62,33 +64,30 @@ TimeZoneView::TimeZoneView(BRect frame)
|
|||||||
bool
|
bool
|
||||||
TimeZoneView::CheckCanRevert()
|
TimeZoneView::CheckCanRevert()
|
||||||
{
|
{
|
||||||
return fCurrentZone != fOldZone;
|
return fCurrentZoneItem != fOldZoneItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TimeZoneView::_Revert()
|
TimeZoneView::_Revert()
|
||||||
{
|
{
|
||||||
fCurrentZone = fOldZone;
|
fCurrentZoneItem = fOldZoneItem;
|
||||||
int32 czone = 0;
|
|
||||||
|
|
||||||
if (fCurrentZone != NULL) {
|
if (fCurrentZoneItem != NULL) {
|
||||||
czone = fCityList->IndexOf(fCurrentZone);
|
int32 currentZoneIndex = fZoneList->IndexOf(fCurrentZoneItem);
|
||||||
fCityList->Select(czone);
|
fZoneList->Select(currentZoneIndex);
|
||||||
}
|
} else
|
||||||
// TODO : else, select ??!
|
fZoneList->DeselectAll();
|
||||||
|
fZoneList->ScrollToSelection();
|
||||||
|
|
||||||
fCityList->ScrollToSelection();
|
_SetSystemTimeZone();
|
||||||
fCurrent->SetText(((TimeZoneListItem*)fCityList->ItemAt(czone))->Text());
|
_UpdatePreview();
|
||||||
_SetPreview();
|
_UpdateCurrent();
|
||||||
_SetTimeZone();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TimeZoneView::~TimeZoneView()
|
TimeZoneView::~TimeZoneView()
|
||||||
{
|
{
|
||||||
delete fCurrentZone;
|
|
||||||
delete fOldZone;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -102,23 +101,23 @@ TimeZoneView::AttachedToWindow()
|
|||||||
fInitialized = true;
|
fInitialized = true;
|
||||||
|
|
||||||
fSetZone->SetTarget(this);
|
fSetZone->SetTarget(this);
|
||||||
fCityList->SetTarget(this);
|
fZoneList->SetTarget(this);
|
||||||
|
|
||||||
// update displays
|
// update displays
|
||||||
int32 czone = 0;
|
int32 czone = 0;
|
||||||
if (fCurrentZone != NULL) {
|
if (fCurrentZoneItem != NULL) {
|
||||||
czone = fCityList->IndexOf(fCurrentZone);
|
czone = fZoneList->IndexOf(fCurrentZoneItem);
|
||||||
} else {
|
} else {
|
||||||
// TODO : else, select ??!
|
// TODO : else, select ??!
|
||||||
fCurrentZone = (TimeZoneListItem*)fCityList->ItemAt(0);
|
fCurrentZoneItem = (TimeZoneListItem*)fZoneList->ItemAt(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fCityList->Select(czone);
|
fZoneList->Select(czone);
|
||||||
|
|
||||||
fCityList->ScrollToSelection();
|
fZoneList->ScrollToSelection();
|
||||||
fCurrent->SetText(fCurrentZone->Text());
|
fCurrent->SetText(fCurrentZoneItem->Text());
|
||||||
}
|
}
|
||||||
fCityList->ScrollToSelection();
|
fZoneList->ScrollToSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -144,7 +143,7 @@ TimeZoneView::MessageReceived(BMessage* message)
|
|||||||
|
|
||||||
case H_SET_TIME_ZONE:
|
case H_SET_TIME_ZONE:
|
||||||
{
|
{
|
||||||
_SetTimeZone();
|
_SetSystemTimeZone();
|
||||||
((TTimeWindow*)Window())->SetRevertStatus();
|
((TTimeWindow*)Window())->SetRevertStatus();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -154,7 +153,7 @@ TimeZoneView::MessageReceived(BMessage* message)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case H_CITY_CHANGED:
|
case H_CITY_CHANGED:
|
||||||
_SetPreview();
|
_UpdatePreview();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -167,20 +166,14 @@ TimeZoneView::MessageReceived(BMessage* message)
|
|||||||
void
|
void
|
||||||
TimeZoneView::_UpdateDateTime(BMessage* message)
|
TimeZoneView::_UpdateDateTime(BMessage* message)
|
||||||
{
|
{
|
||||||
int32 hour;
|
// only need to update once every minute
|
||||||
int32 minute;
|
int32 minute;
|
||||||
|
if (message->FindInt32("minute", &minute) == B_OK) {
|
||||||
|
if (fLastUpdateMinute != minute) {
|
||||||
|
_UpdateCurrent();
|
||||||
|
_UpdatePreview();
|
||||||
|
|
||||||
// only need hour and minute
|
fLastUpdateMinute = minute;
|
||||||
if (message->FindInt32("hour", &hour) == B_OK
|
|
||||||
&& message->FindInt32("minute", &minute) == B_OK) {
|
|
||||||
if (fHour != hour || fMinute != minute) {
|
|
||||||
fHour = hour;
|
|
||||||
fMinute = minute;
|
|
||||||
fCurrent->SetTime(hour, minute);
|
|
||||||
|
|
||||||
// do calc to get other zone time
|
|
||||||
if (fCityList->CurrentSelection() > -1)
|
|
||||||
_SetPreview();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -195,14 +188,14 @@ TimeZoneView::_InitView()
|
|||||||
frameLeft.InsetBy(10.0f, 10.0f);
|
frameLeft.InsetBy(10.0f, 10.0f);
|
||||||
|
|
||||||
// City Listing
|
// City Listing
|
||||||
fCityList = new BOutlineListView(frameLeft, "cityList",
|
fZoneList = new BOutlineListView(frameLeft, "cityList",
|
||||||
B_SINGLE_SELECTION_LIST);
|
B_SINGLE_SELECTION_LIST);
|
||||||
fCityList->SetSelectionMessage(new BMessage(H_CITY_CHANGED));
|
fZoneList->SetSelectionMessage(new BMessage(H_CITY_CHANGED));
|
||||||
fCityList->SetInvocationMessage(new BMessage(H_SET_TIME_ZONE));
|
fZoneList->SetInvocationMessage(new BMessage(H_SET_TIME_ZONE));
|
||||||
|
|
||||||
_BuildRegionMenu();
|
_BuildRegionMenu();
|
||||||
|
|
||||||
BScrollView* scrollList = new BScrollView("scrollList", fCityList,
|
BScrollView* scrollList = new BScrollView("scrollList", fZoneList,
|
||||||
B_FOLLOW_ALL, 0, false, true);
|
B_FOLLOW_ALL, 0, false, true);
|
||||||
AddChild(scrollList);
|
AddChild(scrollList);
|
||||||
|
|
||||||
@@ -237,7 +230,7 @@ TimeZoneView::_InitView()
|
|||||||
void
|
void
|
||||||
TimeZoneView::_BuildRegionMenu()
|
TimeZoneView::_BuildRegionMenu()
|
||||||
{
|
{
|
||||||
BTimeZone* defaultTimeZone = NULL;
|
BTimeZone defaultTimeZone = NULL;
|
||||||
be_locale_roster->GetDefaultTimeZone(&defaultTimeZone);
|
be_locale_roster->GetDefaultTimeZone(&defaultTimeZone);
|
||||||
|
|
||||||
// Get a list of countries and, for each country, get all the timezones and
|
// Get a list of countries and, for each country, get all the timezones and
|
||||||
@@ -252,7 +245,7 @@ TimeZoneView::_BuildRegionMenu()
|
|||||||
== B_OK; i++) {
|
== B_OK; i++) {
|
||||||
BCountry country("", countryCode);
|
BCountry country("", countryCode);
|
||||||
BString fullName;
|
BString fullName;
|
||||||
country.Name(fullName);
|
country.GetName(fullName);
|
||||||
|
|
||||||
// Now list the timezones for this country
|
// Now list the timezones for this country
|
||||||
BList tzList;
|
BList tzList;
|
||||||
@@ -269,24 +262,24 @@ TimeZoneView::_BuildRegionMenu()
|
|||||||
timeZone = (BTimeZone*)tzList.ItemAt(0);
|
timeZone = (BTimeZone*)tzList.ItemAt(0);
|
||||||
countryItem
|
countryItem
|
||||||
= new TimeZoneListItem(fullName, &country, timeZone);
|
= new TimeZoneListItem(fullName, &country, timeZone);
|
||||||
fCityList->AddItem(countryItem);
|
fZoneList->AddItem(countryItem);
|
||||||
if (timeZone->Code() == defaultTimeZone->Code())
|
if (timeZone->Code() == defaultTimeZone.Code())
|
||||||
fCurrentZone = countryItem;
|
fCurrentZoneItem = countryItem;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
countryItem = new TimeZoneListItem(fullName, &country, NULL);
|
countryItem = new TimeZoneListItem(fullName, &country, NULL);
|
||||||
countryItem->SetExpanded(false);
|
countryItem->SetExpanded(false);
|
||||||
fCityList->AddItem(countryItem);
|
fZoneList->AddItem(countryItem);
|
||||||
|
|
||||||
for (int j = 0;
|
for (int j = 0;
|
||||||
(timeZone = (BTimeZone*)tzList.ItemAt(j)) != NULL;
|
(timeZone = (BTimeZone*)tzList.ItemAt(j)) != NULL;
|
||||||
j++) {
|
j++) {
|
||||||
TimeZoneListItem* tzItem = new TimeZoneListItem(
|
TimeZoneListItem* tzItem = new TimeZoneListItem(
|
||||||
timeZone->Name(), NULL, timeZone);
|
timeZone->Name(), NULL, timeZone);
|
||||||
fCityList->AddUnder(tzItem, countryItem);
|
fZoneList->AddUnder(tzItem, countryItem);
|
||||||
if (timeZone->Code() == defaultTimeZone->Code())
|
if (timeZone->Code() == defaultTimeZone.Code())
|
||||||
{
|
{
|
||||||
fCurrentZone = tzItem;
|
fCurrentZoneItem = tzItem;
|
||||||
countryItem->SetExpanded(true);
|
countryItem->SetExpanded(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -294,103 +287,93 @@ TimeZoneView::_BuildRegionMenu()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fOldZone = fCurrentZone;
|
// add an artifical (i.e. belongs to no country) entry for GMT/UTC
|
||||||
|
BTimeZone* gmtZone = new(std::nothrow) BTimeZone(BTimeZone::kNameOfGmtZone);
|
||||||
|
TimeZoneListItem* gmtItem
|
||||||
|
= new TimeZoneListItem("- GMT/UTC (Universal Time) -", NULL, gmtZone);
|
||||||
|
fZoneList->AddItem(gmtItem);
|
||||||
|
if (gmtZone->Code() == defaultTimeZone.Code())
|
||||||
|
fCurrentZoneItem = gmtItem;
|
||||||
|
|
||||||
delete defaultTimeZone;
|
fOldZoneItem = fCurrentZoneItem;
|
||||||
|
|
||||||
struct ListSorter {
|
struct ListSorter {
|
||||||
static int compare(const BListItem* first, const BListItem* second)
|
static int compare(const BListItem* first, const BListItem* second)
|
||||||
{
|
{
|
||||||
return sCollator.Compare(((BStringItem*)first)->Text(),
|
static BCollator collator;
|
||||||
|
return collator.Compare(((BStringItem*)first)->Text(),
|
||||||
((BStringItem*)second)->Text());
|
((BStringItem*)second)->Text());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
fCityList->SortItemsUnder(NULL, false, ListSorter::compare);
|
fZoneList->SortItemsUnder(NULL, false, ListSorter::compare);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TimeZoneView::_SetPreview()
|
TimeZoneView::_UpdatePreview()
|
||||||
{
|
{
|
||||||
int32 selection = fCityList->CurrentSelection();
|
int32 selection = fZoneList->CurrentSelection();
|
||||||
if (selection >= 0) {
|
|
||||||
TimeZoneListItem* item
|
|
||||||
= (TimeZoneListItem*)fCityList->ItemAt(selection);
|
|
||||||
|
|
||||||
// calc preview time
|
|
||||||
time_t current = time(NULL) + item->OffsetFromGMT();
|
|
||||||
struct tm localTime;
|
|
||||||
gmtime_r(¤t, &localTime);
|
|
||||||
|
|
||||||
// update prview
|
|
||||||
fPreview->SetText(item->Text());
|
|
||||||
fPreview->SetTime(localTime.tm_hour, localTime.tm_min);
|
|
||||||
|
|
||||||
fSetZone->SetEnabled((strcmp(fCurrent->Text(), item->Text()) != 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
TimeZoneView::_SetCurrent(const char* text)
|
|
||||||
{
|
|
||||||
_SetTimeZone(fCurrentZone->Code().String());
|
|
||||||
|
|
||||||
time_t current = time(NULL);
|
|
||||||
struct tm localTime;
|
|
||||||
localtime_r(¤t, &localTime);
|
|
||||||
|
|
||||||
fCurrent->SetText(text);
|
|
||||||
fCurrent->SetTime(localTime.tm_hour, localTime.tm_min);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
TimeZoneView::_SetTimeZone()
|
|
||||||
{
|
|
||||||
/* set time based on supplied timezone. How to do this?
|
|
||||||
1) replace symlink "timezone" in B_USER_SETTINGS_DIR with a link to the
|
|
||||||
new timezone
|
|
||||||
2) set TZ environment var
|
|
||||||
3) call settz()
|
|
||||||
4) call set_timezone from OS.h passing path to timezone file
|
|
||||||
*/
|
|
||||||
|
|
||||||
int32 selection = fCityList->CurrentSelection();
|
|
||||||
if (selection < 0)
|
if (selection < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const BString& code
|
TimeZoneListItem* item = (TimeZoneListItem*)fZoneList->ItemAt(selection);
|
||||||
= ((TimeZoneListItem*)fCityList->ItemAt(selection))->Code();
|
if (!item->HasTimeZone())
|
||||||
_SetTimeZone(code.String());
|
return;
|
||||||
|
|
||||||
// update display
|
BString timeString = _FormatTime(item);
|
||||||
time_t current = time(NULL);
|
fPreview->SetText(item->Text());
|
||||||
struct tm localTime;
|
fPreview->SetTime(timeString.String());
|
||||||
localtime_r(¤t, &localTime);
|
|
||||||
|
|
||||||
set_timezone(code.String());
|
fSetZone->SetEnabled((strcmp(fCurrent->Text(), item->Text()) != 0));
|
||||||
// disable button
|
|
||||||
fSetZone->SetEnabled(false);
|
|
||||||
|
|
||||||
time_t newTime = mktime(&localTime);
|
|
||||||
localtime_r(&newTime, &localTime);
|
|
||||||
stime(&newTime);
|
|
||||||
|
|
||||||
fHour = localTime.tm_hour;
|
|
||||||
fMinute = localTime.tm_min;
|
|
||||||
fCurrentZone = (TimeZoneListItem*)(fCityList->ItemAt(selection));
|
|
||||||
_SetCurrent(((TimeZoneListItem*)fCityList->ItemAt(selection))->Text());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TimeZoneView::_SetTimeZone(const char* zone)
|
TimeZoneView::_UpdateCurrent()
|
||||||
{
|
{
|
||||||
putenv(BString("TZ=").Append(zone).String());
|
if (fCurrentZoneItem == NULL)
|
||||||
tzset();
|
return;
|
||||||
|
|
||||||
be_locale_roster->SetDefaultTimeZone(zone);
|
BString timeString = _FormatTime(fCurrentZoneItem);
|
||||||
|
fCurrent->SetText(fCurrentZoneItem->Text());
|
||||||
|
fCurrent->SetTime(timeString.String());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TimeZoneView::_SetSystemTimeZone()
|
||||||
|
{
|
||||||
|
/* Set sytem timezone for all different API levels. How to do this?
|
||||||
|
* 1) tell locale-roster about new default timezone
|
||||||
|
* 2) write new POSIX-timezone file
|
||||||
|
*/
|
||||||
|
|
||||||
|
int32 selection = fZoneList->CurrentSelection();
|
||||||
|
if (selection < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fCurrentZoneItem = (TimeZoneListItem*)(fZoneList->ItemAt(selection));
|
||||||
|
|
||||||
|
mutable_locale_roster->SetDefaultTimeZone(fCurrentZoneItem->TimeZone());
|
||||||
|
|
||||||
|
set_timezone(fCurrentZoneItem->Code());
|
||||||
|
|
||||||
|
fSetZone->SetEnabled(false);
|
||||||
|
fLastUpdateMinute = -1;
|
||||||
|
// just to trigger updating immediately
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BString
|
||||||
|
TimeZoneView::_FormatTime(TimeZoneListItem* zoneItem)
|
||||||
|
{
|
||||||
|
BString result;
|
||||||
|
|
||||||
|
if (zoneItem == NULL)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
time_t nowInTimeZone = time(NULL) + zoneItem->OffsetFromGMT();
|
||||||
|
be_locale->FormatTime(&result, nowInTimeZone, false);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
@@ -33,24 +33,28 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void _UpdateDateTime(BMessage* message);
|
void _UpdateDateTime(BMessage* message);
|
||||||
void _SetTimeZone();
|
|
||||||
void _SetTimeZone(const char* zone);
|
void _SetSystemTimeZone();
|
||||||
void _SetPreview();
|
|
||||||
void _SetCurrent(const char* text);
|
void _UpdatePreview();
|
||||||
|
void _UpdateCurrent();
|
||||||
|
BString _FormatTime(TimeZoneListItem* zoneItem);
|
||||||
|
|
||||||
void _InitView();
|
void _InitView();
|
||||||
void _BuildRegionMenu();
|
void _BuildRegionMenu();
|
||||||
|
|
||||||
void _Revert();
|
void _Revert();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BOutlineListView* fCityList;
|
BOutlineListView* fZoneList;
|
||||||
BButton* fSetZone;
|
BButton* fSetZone;
|
||||||
TTZDisplay* fCurrent;
|
TTZDisplay* fCurrent;
|
||||||
TTZDisplay* fPreview;
|
TTZDisplay* fPreview;
|
||||||
|
|
||||||
int32 fHour;
|
int32 fLastUpdateMinute;
|
||||||
int32 fMinute;
|
|
||||||
TimeZoneListItem* fCurrentZone;
|
TimeZoneListItem* fCurrentZoneItem;
|
||||||
TimeZoneListItem* fOldZone;
|
TimeZoneListItem* fOldZoneItem;
|
||||||
bool fInitialized;
|
bool fInitialized;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user