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:
parent
98dc4f9c65
commit
38ac8def5a
@ -220,7 +220,6 @@ class BCatalog {
|
||||
// For BCatalog add-on implementations:
|
||||
|
||||
class BCatalogAddOn {
|
||||
friend class BLocaleRoster;
|
||||
public:
|
||||
BCatalogAddOn(const char *signature, const char *language,
|
||||
uint32 fingerprint);
|
||||
@ -269,6 +268,8 @@ class BCatalogAddOn {
|
||||
const char *cmt);
|
||||
static int32 MarkForTranslation(int32 id);
|
||||
|
||||
void SetNext(BCatalogAddOn *next);
|
||||
|
||||
protected:
|
||||
virtual void UpdateFingerprint();
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
/*
|
||||
* Copyright 2003-2010, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT Licence.
|
||||
*/
|
||||
*/
|
||||
#ifndef _COLLATOR_H_
|
||||
#define _COLLATOR_H_
|
||||
|
||||
|
||||
#include <SupportDefs.h>
|
||||
#include <Archivable.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
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 {
|
||||
public:
|
||||
BCollator();
|
||||
BCollator(const char *locale, int8 strength, bool ignorePunctuation);
|
||||
BCollator(BMessage *archive);
|
||||
~BCollator();
|
||||
public:
|
||||
BCollator();
|
||||
BCollator(const char* locale,
|
||||
int8 strength = B_COLLATE_PRIMARY,
|
||||
bool ignorePunctuation = false);
|
||||
BCollator(BMessage* archive);
|
||||
|
||||
void SetDefaultStrength(int8 strength);
|
||||
int8 DefaultStrength() const;
|
||||
BCollator(const BCollator& other);
|
||||
|
||||
void SetIgnorePunctuation(bool ignore);
|
||||
bool IgnorePunctuation() const;
|
||||
~BCollator();
|
||||
|
||||
status_t GetSortKey(const char *string, BString *key,
|
||||
int8 strength = B_COLLATE_DEFAULT);
|
||||
BCollator& operator=(const BCollator& source);
|
||||
|
||||
int Compare(const char *, const char *, int32 len = -1,
|
||||
int8 strength = B_COLLATE_DEFAULT);
|
||||
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);
|
||||
void SetDefaultStrength(int8 strength);
|
||||
int8 DefaultStrength() const;
|
||||
|
||||
// (un-)archiving API
|
||||
status_t Archive(BMessage *archive, bool deep) const;
|
||||
static BArchivable *Instantiate(BMessage *archive);
|
||||
void SetIgnorePunctuation(bool ignore);
|
||||
bool IgnorePunctuation() const;
|
||||
|
||||
private:
|
||||
icu_44::Collator* fICUCollator;
|
||||
icu_44::RuleBasedCollator* fFallbackICUCollator;
|
||||
int8 fStrength;
|
||||
bool fIgnorePunctuation;
|
||||
status_t GetSortKey(const char* string, BString* key,
|
||||
int8 strength = B_COLLATE_DEFAULT) const;
|
||||
|
||||
int Compare(const char* s1, const char* s2,
|
||||
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
|
||||
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
|
||||
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
|
||||
BCollator::GreaterOrEqual(const char *s1, const char *s2, int32 len,
|
||||
int8 strength)
|
||||
BCollator::GreaterOrEqual(const char *s1, const char *s2, int8 strength) const
|
||||
{
|
||||
return Compare(s1, s2, len, strength) >= 0;
|
||||
return Compare(s1, s2, strength) >= 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,10 +1,13 @@
|
||||
/*
|
||||
* Copyright 2003-2010, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT Licence.
|
||||
*/
|
||||
#ifndef _COUNTRY_H_
|
||||
#define _COUNTRY_H_
|
||||
|
||||
|
||||
#include <List.h>
|
||||
#include <LocaleStrings.h>
|
||||
#include <Locker.h>
|
||||
#include <String.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
@ -36,101 +39,86 @@ typedef enum {
|
||||
|
||||
|
||||
class BCountry {
|
||||
public:
|
||||
BCountry(const char* languageCode, const char* countryCode);
|
||||
BCountry(const char* languageAndCountryCode = "en_US");
|
||||
BCountry(const BCountry& other);
|
||||
BCountry& operator=(const BCountry& other);
|
||||
virtual ~BCountry();
|
||||
public:
|
||||
BCountry(const char* languageCode,
|
||||
const char* countryCode);
|
||||
BCountry(const char* languageAndCountryCode
|
||||
= "en_US");
|
||||
BCountry(const BCountry& other);
|
||||
BCountry& operator=(const BCountry& other);
|
||||
~BCountry();
|
||||
|
||||
bool Name(BString& name) const;
|
||||
bool LocaleName(BString& name) const;
|
||||
const char* Code() const;
|
||||
status_t GetIcon(BBitmap* result);
|
||||
bool GetName(BString& name) const;
|
||||
bool GetLocaleName(BString& name) const;
|
||||
const char* Code() const;
|
||||
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,
|
||||
bool longFormat);
|
||||
status_t FormatDate(BString* string, time_t time,
|
||||
bool longFormat);
|
||||
status_t FormatDate(BString* string, int*& fieldPositions,
|
||||
int& fieldCount, time_t time, bool longFormat);
|
||||
status_t DateFields(BDateElement*& fields, int& fieldCount,
|
||||
bool longFormat);
|
||||
status_t DateFormat(BString&, bool longFormat);
|
||||
status_t SetDateFormat(const char* formatString,
|
||||
bool longFormat = true);
|
||||
status_t FormatDate(char* string, size_t maxSize,
|
||||
time_t time, bool longFormat);
|
||||
status_t FormatDate(BString* string, time_t time,
|
||||
bool longFormat);
|
||||
status_t FormatDate(BString* string,
|
||||
int*& fieldPositions, int& fieldCount,
|
||||
time_t time, bool longFormat);
|
||||
status_t GetDateFields(BDateElement*& fields,
|
||||
int& fieldCount, bool longFormat) const;
|
||||
status_t GetDateFormat(BString&, bool longFormat) const;
|
||||
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,
|
||||
bool longFormat);
|
||||
status_t FormatTime(BString* string, time_t time,
|
||||
bool longFormat);
|
||||
status_t FormatTime(BString* string, int*& fieldPositions,
|
||||
int& fieldCount, time_t time, bool longFormat);
|
||||
status_t TimeFields(BDateElement*& fields, int& fieldCount,
|
||||
bool longFormat);
|
||||
status_t FormatTime(char* string, size_t maxSize,
|
||||
time_t time, bool longFormat);
|
||||
status_t FormatTime(BString* string, time_t time,
|
||||
bool longFormat);
|
||||
status_t FormatTime(BString* string,
|
||||
int*& fieldPositions, int& fieldCount,
|
||||
time_t time, bool longFormat);
|
||||
status_t GetTimeFields(BDateElement*& fields,
|
||||
int& fieldCount, bool longFormat) const;
|
||||
|
||||
status_t SetTimeFormat(const char* formatString,
|
||||
bool longFormat = true);
|
||||
status_t TimeFormat(BString&, bool longFormat);
|
||||
status_t SetTimeFormat(const char* formatString,
|
||||
bool longFormat = true);
|
||||
status_t GetTimeFormat(BString& out,
|
||||
bool longFormat) const;
|
||||
|
||||
// numbers
|
||||
// numbers
|
||||
|
||||
virtual void FormatNumber(char* string, size_t maxSize, double value);
|
||||
virtual status_t FormatNumber(BString* string, double value);
|
||||
virtual void FormatNumber(char* string, size_t maxSize, int32 value);
|
||||
virtual void FormatNumber(BString* string, int32 value);
|
||||
status_t FormatNumber(char* string, size_t maxSize,
|
||||
double value);
|
||||
status_t FormatNumber(BString* string, double value);
|
||||
status_t FormatNumber(char* string, size_t maxSize,
|
||||
int32 value);
|
||||
status_t FormatNumber(BString* string, int32 value);
|
||||
|
||||
bool DecimalPoint(BString&) const;
|
||||
bool ThousandsSeparator(BString&) const;
|
||||
bool Grouping(BString&) const;
|
||||
// measurements
|
||||
|
||||
bool PositiveSign(BString&) const;
|
||||
bool NegativeSign(BString&) const;
|
||||
int8 Measurement() 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,
|
||||
double value);
|
||||
virtual ssize_t FormatMonetary(BString* string, double value);
|
||||
int GetTimeZones(BList& timezones) const;
|
||||
|
||||
bool CurrencySymbol(BString&) const;
|
||||
bool InternationalCurrencySymbol(BString&) const;
|
||||
bool MonDecimalPoint(BString&) const;
|
||||
bool MonThousandsSeparator(BString&) const;
|
||||
bool MonGrouping(BString&) const;
|
||||
virtual int32 MonFracDigits() const;
|
||||
|
||||
// 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;
|
||||
private:
|
||||
icu_44::Locale* fICULocale;
|
||||
BString fLongDateFormat;
|
||||
BString fShortDateFormat;
|
||||
BString fLongTimeFormat;
|
||||
BString fShortTimeFormat;
|
||||
};
|
||||
|
||||
|
||||
#endif /* _COUNTRY_H_ */
|
||||
|
30
headers/os/locale/DateFormat.h
Normal file
30
headers/os/locale/DateFormat.h
Normal file
@ -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_
|
31
headers/os/locale/DateTimeFormat.h
Normal file
31
headers/os/locale/DateTimeFormat.h
Normal file
@ -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_
|
24
headers/os/locale/DurationFormat.h
Normal file
24
headers/os/locale/DurationFormat.h
Normal file
@ -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_
|
||||
#define _B_FORMAT_H_
|
||||
|
||||
#include <FormatParameters.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
// types of fields contained in formatted strings
|
||||
enum {
|
||||
// number format fields
|
||||
@ -30,16 +35,18 @@ struct format_field_position {
|
||||
int32 length;
|
||||
};
|
||||
|
||||
|
||||
class BFormatImpl;
|
||||
|
||||
class BFormat {
|
||||
protected:
|
||||
BFormat(const BFormat &other);
|
||||
~BFormat();
|
||||
protected:
|
||||
BFormat(const BFormat& other);
|
||||
virtual ~BFormat();
|
||||
|
||||
BFormat &operator=(const BFormat &other);
|
||||
BFormat& operator=(const BFormat& other);
|
||||
|
||||
BFormat();
|
||||
BFormat();
|
||||
};
|
||||
|
||||
|
||||
#endif // _B_FORMAT_H_
|
||||
|
@ -27,8 +27,13 @@ enum script_direction {
|
||||
|
||||
class BLanguage {
|
||||
public:
|
||||
BLanguage();
|
||||
BLanguage(const char* language);
|
||||
BLanguage(const BLanguage& other);
|
||||
~BLanguage();
|
||||
|
||||
BLanguage& operator=(const BLanguage& source);
|
||||
|
||||
status_t GetName(BString& name) const;
|
||||
status_t GetTranslatedName(BString& name) const;
|
||||
|
||||
@ -43,19 +48,15 @@ public:
|
||||
|
||||
uint8 Direction() const;
|
||||
|
||||
status_t SetTo(const char* language);
|
||||
|
||||
// see definitions below
|
||||
const char* GetString(uint32 id) const;
|
||||
|
||||
private:
|
||||
friend class BLocaleRoster;
|
||||
|
||||
BLanguage(const char *language);
|
||||
void Default();
|
||||
|
||||
private:
|
||||
char* fStrings[B_NUM_LANGUAGE_STRINGS];
|
||||
// BString fStrings[B_NUM_LANGUAGE_STRINGS];
|
||||
uint8 fDirection;
|
||||
icu_44::Locale* fICULocale;
|
||||
icu_44::Locale* fICULocale;
|
||||
};
|
||||
|
||||
|
||||
|
@ -7,86 +7,92 @@
|
||||
|
||||
|
||||
#include <Collator.h>
|
||||
#include <Language.h>
|
||||
#include <Country.h>
|
||||
#include <Language.h>
|
||||
|
||||
|
||||
class BCatalog;
|
||||
class BLocaleRoster;
|
||||
class BString;
|
||||
|
||||
|
||||
class BLocale {
|
||||
public:
|
||||
BLocale();
|
||||
~BLocale();
|
||||
public:
|
||||
BLocale();
|
||||
~BLocale();
|
||||
|
||||
BCollator *Collator() const { return fCollator; }
|
||||
BCountry *Country() const { return fCountry; }
|
||||
BLanguage *Language() const { return fLanguage; }
|
||||
const BCollator* Collator() const { return &fCollator; }
|
||||
const BCountry* Country() const { return &fCountry; }
|
||||
const BLanguage* Language() const { return &fLanguage; }
|
||||
|
||||
// see definitions in LocaleStrings.h
|
||||
const char *GetString(uint32 id);
|
||||
// see definitions in LocaleStrings.h
|
||||
const char* GetString(uint32 id);
|
||||
|
||||
void FormatString(char *target, size_t maxSize, char *fmt, ...);
|
||||
void FormatString(BString *, char *fmt, ...);
|
||||
void FormatDateTime(char *target, size_t maxSize, const char *fmt,
|
||||
time_t);
|
||||
void FormatDateTime(BString *, const char *fmt, time_t);
|
||||
void FormatString(char* target, size_t maxSize,
|
||||
char* fmt, ...);
|
||||
void FormatString(BString* buffer, char* fmt, ...);
|
||||
void FormatDateTime(char* target, size_t maxSize,
|
||||
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);
|
||||
void FormatDate(BString *target, time_t, bool longFormat);
|
||||
void FormatTime(char *target, size_t maxSize, time_t, bool longFormat);
|
||||
void FormatTime(BString *target, time_t, bool longFormat);
|
||||
// Collator short-hands
|
||||
int StringCompare(const char* s1,
|
||||
const char* s2) const;
|
||||
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,
|
||||
int8 strength = B_COLLATE_DEFAULT) const;
|
||||
int StringCompare(const BString *, const BString *,
|
||||
int32 len = -1, int8 strength = B_COLLATE_DEFAULT) const;
|
||||
|
||||
void GetSortKey(const char *string, BString *key);
|
||||
|
||||
protected:
|
||||
BCollator *fCollator;
|
||||
BLanguage *fLanguage;
|
||||
BCountry *fCountry;
|
||||
protected:
|
||||
BCollator fCollator;
|
||||
BCountry fCountry;
|
||||
BLanguage fLanguage;
|
||||
};
|
||||
|
||||
|
||||
// global objects
|
||||
extern BLocale *be_locale;
|
||||
extern BLocaleRoster *be_locale_roster;
|
||||
extern BLocale* be_locale;
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//--- country short-hands inlines ---
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
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 -
|
||||
|
||||
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
|
||||
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
|
||||
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_ */
|
||||
|
@ -9,89 +9,70 @@
|
||||
#include <String.h>
|
||||
|
||||
|
||||
class BLanguage;
|
||||
class BLocale;
|
||||
class BCatalog;
|
||||
class BCollator;
|
||||
class BCountry;
|
||||
class BCatalog;
|
||||
class BCatalogAddOn;
|
||||
class BLanguage;
|
||||
class BLocale;
|
||||
class BMessage;
|
||||
class BTimeZone;
|
||||
|
||||
struct entry_ref;
|
||||
|
||||
namespace BPrivate {
|
||||
class EditableCatalog;
|
||||
}
|
||||
|
||||
|
||||
enum {
|
||||
B_LOCALE_CHANGED = '_LCC',
|
||||
B_LOCALE_CHANGED = '_LCC',
|
||||
};
|
||||
|
||||
|
||||
class BLocaleRoster {
|
||||
public:
|
||||
BLocaleRoster();
|
||||
~BLocaleRoster();
|
||||
public:
|
||||
BLocaleRoster();
|
||||
~BLocaleRoster();
|
||||
|
||||
status_t GetSystemCatalog(BCatalogAddOn **catalog) const;
|
||||
status_t GetDefaultCollator(BCollator **collator) const;
|
||||
status_t GetDefaultLanguage(BLanguage **language) const;
|
||||
status_t GetDefaultCountry(BCountry **contry) const;
|
||||
status_t GetDefaultTimeZone(BTimeZone**timezone) const;
|
||||
status_t GetDefaultCollator(BCollator* collator) const;
|
||||
status_t GetDefaultLanguage(BLanguage* language) const;
|
||||
status_t GetDefaultCountry(BCountry* country) const;
|
||||
status_t GetDefaultTimeZone(BTimeZone* timezone) const;
|
||||
|
||||
void SetDefaultCountry(BCountry *) const;
|
||||
void SetDefaultTimeZone(const char* zone) const;
|
||||
void UpdateSettings(BMessage* newSettings);
|
||||
status_t GetLanguage(const char* languageCode,
|
||||
BLanguage** _language) const;
|
||||
|
||||
status_t GetLanguage(const char* languageCode, BLanguage** _language)
|
||||
const;
|
||||
status_t GetPreferredLanguages(BMessage* message) const;
|
||||
|
||||
status_t GetPreferredLanguages(BMessage *) const;
|
||||
status_t SetPreferredLanguages(BMessage *);
|
||||
// the message contains one or more 'language'-string-fields
|
||||
// which contain the language-name(s)
|
||||
status_t GetInstalledLanguages(BMessage* message) const;
|
||||
// the message contains one or more
|
||||
// 'language'-string-fields which
|
||||
// contain the language-name(s)
|
||||
|
||||
status_t GetInstalledLanguages(BMessage *) const;
|
||||
// the message contains one or more 'language'-string-fields
|
||||
// which contain the language-name(s)
|
||||
status_t GetAvailableCountries(BMessage* message) const;
|
||||
|
||||
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,
|
||||
const char* langPattern = NULL, int32 fingerprint = 0) const;
|
||||
// the message contains...
|
||||
status_t Refresh();
|
||||
// Refresh the internal data from the
|
||||
// settings file(s)
|
||||
|
||||
BCatalog* GetCatalog();
|
||||
// Get the catalog for the calling image (that needs to link with
|
||||
// liblocalestub.a)
|
||||
BCatalog* GetCatalog();
|
||||
// Get the catalog for the calling image
|
||||
// (that needs to link with liblocalestub.a)
|
||||
|
||||
static const char *kCatLangAttr;
|
||||
static const char *kCatSigAttr;
|
||||
static const char *kCatFingerprintAttr;
|
||||
static const char* kCatLangAttr;
|
||||
static const char* kCatSigAttr;
|
||||
static const char* kCatFingerprintAttr;
|
||||
|
||||
static const char *kCatManagerMimeType;
|
||||
static const char *kCatEditorMimeType;
|
||||
static const char* kEmbeddedCatAttr;
|
||||
static int32 kEmbeddedCatResId;
|
||||
|
||||
static const char *kEmbeddedCatAttr;
|
||||
static int32 kEmbeddedCatResId;
|
||||
|
||||
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 *);
|
||||
private:
|
||||
static BCatalog* _GetCatalog(BCatalog* catalog,
|
||||
vint32* catalogInitStatus);
|
||||
};
|
||||
|
||||
#endif /* _LOCALE_ROSTER_H_ */
|
||||
|
||||
extern BLocaleRoster* be_locale_roster;
|
||||
|
||||
|
||||
#endif // _LOCALE_ROSTER_H_
|
||||
|
@ -1,25 +1,29 @@
|
||||
/*
|
||||
/*
|
||||
* 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_
|
||||
#define _B_TIME_FORMAT_H_
|
||||
|
||||
|
||||
#include <NumberFormat.h>
|
||||
#include <SupportDefs.h>
|
||||
#include <DateTimeFormat.h>
|
||||
|
||||
|
||||
class BString;
|
||||
|
||||
class BTimeFormat : public BDateTimeFormat {
|
||||
public:
|
||||
BTimeFormat(const BTimeFormat &other);
|
||||
virtual ~BTimeFormat();
|
||||
|
||||
class BTimeFormat : public BNumberFormat {
|
||||
public:
|
||||
status_t Format(int64 number, BString *buffer) const;
|
||||
// formatting
|
||||
|
||||
// TODO : version for char* buffer, size_t bufferSize
|
||||
// TODO : parsing ?
|
||||
// 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
|
||||
#endif // _B_TIME_FORMAT_H_
|
||||
|
44
headers/os/locale/TimeUnitFormat.h
Normal file
44
headers/os/locale/TimeUnitFormat.h
Normal file
@ -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;
|
||||
|
||||
private:
|
||||
void _Init(const char* zoneCode);
|
||||
status_t SetTo(const char* zoneCode);
|
||||
|
||||
static const char* kNameOfGmtZone;
|
||||
|
||||
private:
|
||||
BString fCode;
|
||||
BString fName;
|
||||
int fOffsetFromGMT;
|
||||
|
153
headers/private/locale/MutableLocaleRoster.h
Normal file
153
headers/private/locale/MutableLocaleRoster.h
Normal file
@ -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 <Application.h>
|
||||
#include <Bitmap.h>
|
||||
#include <DurationFormat.h>
|
||||
#include <File.h>
|
||||
#include <FindDirectory.h>
|
||||
#include <Font.h>
|
||||
@ -36,7 +37,6 @@
|
||||
#include <ScrollView.h>
|
||||
#include <String.h>
|
||||
#include <StringView.h>
|
||||
#include <TimeFormat.h>
|
||||
#include <TranslationUtils.h>
|
||||
#include <TranslatorFormats.h>
|
||||
#include <View.h>
|
||||
@ -1724,12 +1724,14 @@ MemUsageToString(char string[], size_t size, system_info* info)
|
||||
static const char*
|
||||
UptimeToString(char string[], size_t size)
|
||||
{
|
||||
BTimeFormat formatter;
|
||||
BDurationFormat formatter;
|
||||
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);
|
||||
string[str.Length()] = '\0';
|
||||
string[std::min((size_t)str.Length(), size)] = '\0';
|
||||
|
||||
return string;
|
||||
}
|
||||
|
@ -515,7 +515,7 @@ TBarApp::MessageReceived(BMessage* message)
|
||||
|
||||
case B_LOCALE_CHANGED:
|
||||
{
|
||||
be_locale_roster->UpdateSettings(message);
|
||||
be_locale_roster->Refresh();
|
||||
|
||||
BMessenger(fBarWindow->FindView("_deskbar_tv_")).SendMessage(
|
||||
message);
|
||||
|
@ -89,10 +89,10 @@ CalendarMenuWindow::CalendarMenuWindow(BPoint where)
|
||||
fCalendarView(NULL),
|
||||
fSuppressFirstClose(true)
|
||||
{
|
||||
BCountry* here;
|
||||
be_locale_roster->GetDefaultCountry(&here);
|
||||
BPrivate::week_start startOfWeek
|
||||
= (BPrivate::week_start)here->StartOfWeek();
|
||||
BCountry country;
|
||||
be_locale_roster->GetDefaultCountry(&country);
|
||||
BPrivate::week_start startOfWeek
|
||||
= (BPrivate::week_start)country.StartOfWeek();
|
||||
|
||||
RemoveShortcut('H', B_COMMAND_KEY | B_CONTROL_KEY);
|
||||
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;
|
||||
fNeedToUpdate = true;
|
||||
|
||||
be_locale_roster->GetDefaultCountry(&fHere);
|
||||
be_locale_roster->GetDefaultCountry(&fCountry);
|
||||
}
|
||||
|
||||
|
||||
@ -105,7 +105,7 @@ TTimeView::TTimeView(BMessage* data)
|
||||
data->FindBool("interval", &fInterval);
|
||||
fShowingDate = false;
|
||||
|
||||
be_locale_roster->GetDefaultCountry(&fHere);
|
||||
be_locale_roster->GetDefaultCountry(&fCountry);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -313,7 +313,7 @@ TTimeView::GetCurrentTime()
|
||||
fMinute = time.tm_min;
|
||||
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];
|
||||
|
||||
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)
|
||||
// or remove leading 0 from date when day is less than 10 (DD/MM/YY)
|
||||
@ -465,6 +465,7 @@ TTimeView::AllowFullDate(bool allow)
|
||||
void
|
||||
TTimeView::Update()
|
||||
{
|
||||
be_locale_roster->GetDefaultCountry(&fCountry);
|
||||
GetCurrentTime();
|
||||
GetCurrentDate();
|
||||
|
||||
|
@ -36,6 +36,7 @@ All rights reserved.
|
||||
|
||||
|
||||
#include <OS.h>
|
||||
#include <Country.h>
|
||||
#include <Messenger.h>
|
||||
#include <View.h>
|
||||
|
||||
@ -127,8 +128,8 @@ class TTimeView : public BView {
|
||||
|
||||
BMessenger fCalendarWindow;
|
||||
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 <ListView.h>
|
||||
#include <Locale.h>
|
||||
#include <LocaleRoster.h>
|
||||
#include <MutableLocaleRoster.h>
|
||||
#include <Path.h>
|
||||
#include <ScrollView.h>
|
||||
#include <SeparatorView.h>
|
||||
@ -32,6 +32,9 @@
|
||||
#include "KeymapListItem.h"
|
||||
|
||||
|
||||
using BPrivate::mutable_locale_roster;
|
||||
|
||||
|
||||
enum {
|
||||
MSG_LANGUAGE_SELECTED = 'lngs',
|
||||
MSG_KEYMAP_SELECTED = 'kmps'
|
||||
@ -156,7 +159,8 @@ BootPromptWindow::MessageReceived(BMessage* message)
|
||||
BMessage preferredLanguages;
|
||||
preferredLanguages.AddString("language",
|
||||
languageItem->Language());
|
||||
be_locale_roster->SetPreferredLanguages(&preferredLanguages);
|
||||
mutable_locale_roster->SetPreferredLanguages(
|
||||
&preferredLanguages);
|
||||
_InitCatalog(true);
|
||||
}
|
||||
// Calling it here is a cheap way of preventing the user to have
|
||||
|
@ -1,6 +1,6 @@
|
||||
SubDir HAIKU_TOP src apps readonlybootprompt ;
|
||||
|
||||
UsePrivateHeaders interface shared ;
|
||||
UsePrivateHeaders interface locale shared ;
|
||||
|
||||
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src preferences keymap ] ;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright 2004, Jérôme Duval, jerome.duval@free.fr.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
@ -29,7 +29,7 @@ const uint32 TIMEDALERT_UPDATE = 'taup';
|
||||
class TimedAlert : public BAlert {
|
||||
public:
|
||||
TimedAlert(const char *title, const char *text, const char *button1,
|
||||
const char *button2 = NULL, const char *button3 = NULL,
|
||||
const char *button2 = NULL, const char *button3 = NULL,
|
||||
button_width width = B_WIDTH_AS_USUAL, alert_type type = B_INFO_ALERT);
|
||||
void MessageReceived(BMessage *);
|
||||
void Show();
|
||||
@ -59,12 +59,12 @@ TimedAlert::Show()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
void
|
||||
TimedAlert::MessageReceived(BMessage *msg)
|
||||
{
|
||||
if (msg->what == TIMEDALERT_UPDATE) {
|
||||
BString string;
|
||||
GetLabel(string);
|
||||
GetLabel(string);
|
||||
TextView()->SetText(string.String());
|
||||
} else
|
||||
BAlert::MessageReceived(msg);
|
||||
@ -83,12 +83,12 @@ TimedAlert::GetLabel(BString &string)
|
||||
char timestring[15];
|
||||
time(&t);
|
||||
localtime_r(&t, &tm);
|
||||
|
||||
BCountry* here;
|
||||
|
||||
BCountry here;
|
||||
be_locale_roster->GetDefaultCountry(&here);
|
||||
|
||||
here->FormatTime(timestring, 15, t, false);
|
||||
|
||||
|
||||
here.FormatTime(timestring, 15, t, false);
|
||||
|
||||
string += " ";
|
||||
string += timestring;
|
||||
|
||||
@ -106,9 +106,9 @@ main(int argc, char **argv)
|
||||
struct tm tm;
|
||||
tzset();
|
||||
time(&t);
|
||||
localtime_r(&t, &tm);
|
||||
localtime_r(&t, &tm);
|
||||
|
||||
char path[B_PATH_NAME_LENGTH];
|
||||
char path[B_PATH_NAME_LENGTH];
|
||||
if (find_directory(B_USER_SETTINGS_DIRECTORY, -1, true, path, B_PATH_NAME_LENGTH) != B_OK) {
|
||||
fprintf(stderr, "%s: can't find settings directory\n", argv[0]);
|
||||
exit(1);
|
||||
@ -148,7 +148,7 @@ main(int argc, char **argv)
|
||||
|
||||
if (index == 2) {
|
||||
index = (new BAlert("dstcheck",
|
||||
B_TRANSLATE("Would you like to set the clock?"),
|
||||
B_TRANSLATE("Would you like to set the clock?"),
|
||||
B_TRANSLATE("No"), B_TRANSLATE("Yes")))->Go();
|
||||
|
||||
if (index == 1)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright 2003-2004, Axel Dörfler, axeld@pinc-software.de
|
||||
* Copyright 2003-2004, Oliver Tappe, zooey@hirschkaefer.de
|
||||
* Distributed under the terms of the MIT License.
|
||||
@ -10,11 +10,14 @@
|
||||
|
||||
#include <Application.h>
|
||||
#include <Locale.h>
|
||||
#include <LocaleRoster.h>
|
||||
#include <MutableLocaleRoster.h>
|
||||
#include <Node.h>
|
||||
#include <Roster.h>
|
||||
|
||||
|
||||
using BPrivate::mutable_locale_roster;
|
||||
|
||||
|
||||
//#pragma mark - BCatalog
|
||||
BCatalog::BCatalog()
|
||||
:
|
||||
@ -26,13 +29,14 @@ BCatalog::BCatalog()
|
||||
BCatalog::BCatalog(const char *signature, const char *language,
|
||||
uint32 fingerprint)
|
||||
{
|
||||
fCatalog = be_locale_roster->LoadCatalog(signature, language, fingerprint);
|
||||
fCatalog
|
||||
= mutable_locale_roster->LoadCatalog(signature, language, fingerprint);
|
||||
}
|
||||
|
||||
|
||||
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.
|
||||
// No other method should touch fCatalog directly, either (constructor for
|
||||
// example)
|
||||
fCatalog
|
||||
= be_locale_roster->LoadCatalog(signature, NULL, fingerprint);
|
||||
fCatalog = mutable_locale_roster->LoadCatalog(signature, NULL, fingerprint);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@ -255,12 +258,19 @@ BCatalogAddOn::CountItems() const
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BCatalogAddOn::SetNext(BCatalogAddOn *next)
|
||||
{
|
||||
fNext = next;
|
||||
}
|
||||
|
||||
|
||||
//#pragma mark - EditableCatalog
|
||||
namespace BPrivate {
|
||||
EditableCatalog::EditableCatalog(const char *type, const char *signature,
|
||||
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");
|
||||
#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 <UnicodeChar.h>
|
||||
#include <String.h>
|
||||
#include <Message.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <typeinfo>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <unicode/coll.h>
|
||||
#include <unicode/tblcoll.h>
|
||||
|
||||
|
||||
BCollator::BCollator()
|
||||
:
|
||||
fFallbackICUCollator(NULL),
|
||||
fStrength(B_COLLATE_PRIMARY),
|
||||
fDefaultStrength(B_COLLATE_PRIMARY),
|
||||
fIgnorePunctuation(true)
|
||||
{
|
||||
// TODO: the collator construction will have to change; the default
|
||||
@ -33,11 +34,9 @@ BCollator::BCollator()
|
||||
}
|
||||
|
||||
|
||||
BCollator::BCollator(const char *locale, int8 strength,
|
||||
bool ignorePunctuation)
|
||||
BCollator::BCollator(const char* locale, int8 strength, bool ignorePunctuation)
|
||||
:
|
||||
fFallbackICUCollator(NULL),
|
||||
fStrength(strength),
|
||||
fDefaultStrength(strength),
|
||||
fIgnorePunctuation(ignorePunctuation)
|
||||
{
|
||||
UErrorCode error = U_ZERO_ERROR;
|
||||
@ -45,57 +44,80 @@ BCollator::BCollator(const char *locale, int8 strength,
|
||||
}
|
||||
|
||||
|
||||
BCollator::BCollator(BMessage *archive)
|
||||
: BArchivable(archive),
|
||||
BCollator::BCollator(BMessage* archive)
|
||||
:
|
||||
BArchivable(archive),
|
||||
fICUCollator(NULL),
|
||||
fFallbackICUCollator(NULL),
|
||||
fDefaultStrength(B_COLLATE_PRIMARY),
|
||||
fIgnorePunctuation(true)
|
||||
{
|
||||
int32 data;
|
||||
if (archive->FindInt32("loc:strength", &data) == B_OK)
|
||||
fStrength = (uint8)data;
|
||||
fDefaultStrength = (uint8)data;
|
||||
else
|
||||
fStrength = B_COLLATE_PRIMARY;
|
||||
fDefaultStrength = B_COLLATE_PRIMARY;
|
||||
|
||||
if (archive->FindBool("loc:punctuation", &fIgnorePunctuation) != B_OK)
|
||||
fIgnorePunctuation = true;
|
||||
archive->FindBool("loc:punctuation", &fIgnorePunctuation);
|
||||
|
||||
UErrorCode error = U_ZERO_ERROR;
|
||||
fFallbackICUCollator = static_cast<RuleBasedCollator*>
|
||||
(Collator::createInstance(error));
|
||||
RuleBasedCollator* fallbackICUCollator
|
||||
= static_cast<RuleBasedCollator*>(Collator::createInstance(error));
|
||||
|
||||
ssize_t size;
|
||||
const void* buffer = NULL;
|
||||
if (archive->FindData("loc:collator", B_RAW_TYPE, &buffer, &size) == B_OK) {
|
||||
fICUCollator = new RuleBasedCollator((const uint8_t*)buffer, (int)size,
|
||||
fFallbackICUCollator, error);
|
||||
fallbackICUCollator, error);
|
||||
if (fICUCollator == NULL) {
|
||||
fICUCollator = fFallbackICUCollator;
|
||||
fICUCollator = fallbackICUCollator;
|
||||
// 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()
|
||||
{
|
||||
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
|
||||
BCollator::SetDefaultStrength(int8 strength)
|
||||
{
|
||||
fStrength = strength;
|
||||
fDefaultStrength = strength;
|
||||
}
|
||||
|
||||
|
||||
int8
|
||||
BCollator::DefaultStrength() const
|
||||
{
|
||||
return fStrength;
|
||||
return fDefaultStrength;
|
||||
}
|
||||
|
||||
|
||||
@ -114,31 +136,11 @@ BCollator::IgnorePunctuation() const
|
||||
|
||||
|
||||
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
|
||||
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);
|
||||
|
||||
@ -154,6 +156,7 @@ BCollator::GetSortKey(const char *string, BString *key, int8 strength)
|
||||
buffer = (uint8_t*)realloc(buffer, requiredSize);
|
||||
if (buffer == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
error = U_ZERO_ERROR;
|
||||
fICUCollator->getSortKey(UnicodeString(string, length, NULL, error),
|
||||
buffer, requiredSize);
|
||||
@ -164,50 +167,32 @@ BCollator::GetSortKey(const char *string, BString *key, int8 strength)
|
||||
|
||||
if (error == U_ZERO_ERROR)
|
||||
return B_OK;
|
||||
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
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;
|
||||
return fICUCollator->compare(a, b, error);
|
||||
return fICUCollator->compare(s1, s2, error);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BCollator::Archive(BMessage *archive, bool deep) const
|
||||
BCollator::Archive(BMessage* archive, bool deep) const
|
||||
{
|
||||
status_t status = BArchivable::Archive(archive, deep);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
if (status == B_OK)
|
||||
status = archive->AddInt32("loc:strength", fStrength);
|
||||
status = archive->AddInt32("loc:strength", fDefaultStrength);
|
||||
if (status == B_OK)
|
||||
status = archive->AddBool("loc:punctuation", fIgnorePunctuation);
|
||||
|
||||
@ -231,13 +216,42 @@ BCollator::Archive(BMessage *archive, bool deep) const
|
||||
}
|
||||
|
||||
|
||||
BArchivable *
|
||||
BCollator::Instantiate(BMessage *archive)
|
||||
BArchivable*
|
||||
BCollator::Instantiate(BMessage* archive)
|
||||
{
|
||||
if (validate_instantiation(archive, "BCollator"))
|
||||
return new BCollator(archive);
|
||||
return new(std::nothrow) BCollator(archive);
|
||||
|
||||
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;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
34
src/kits/locale/DateFormat.cpp
Normal file
34
src/kits/locale/DateFormat.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2010, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Oliver Tappe <zooey@hirschkaefer.de>
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
34
src/kits/locale/DateTimeFormat.cpp
Normal file
34
src/kits/locale/DateTimeFormat.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2010, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Oliver Tappe <zooey@hirschkaefer.de>
|
||||
*/
|
||||
|
||||
#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 <DefaultCatalog.h>
|
||||
#include <LocaleRoster.h>
|
||||
#include <MutableLocaleRoster.h>
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
@ -596,9 +596,9 @@ default_catalog_get_available_languages(BMessage* availableLanguages,
|
||||
BPath catalogPath(&appDir, catalogName.String());
|
||||
BEntry file(catalogPath.Path());
|
||||
BDirectory dir(&file);
|
||||
|
||||
|
||||
char fileName[B_FILE_NAME_LENGTH];
|
||||
while(dir.GetNextEntry(&file) == B_OK) {
|
||||
while(dir.GetNextEntry(&file) == B_OK) {
|
||||
file.GetName(fileName);
|
||||
BString langName(fileName);
|
||||
langName.Replace(kCatExtension,"",1);
|
||||
@ -616,16 +616,16 @@ default_catalog_get_available_languages(BMessage* availableLanguages,
|
||||
for (size_t i = 0; i < sizeof(which) / sizeof(which[0]); i++) {
|
||||
BPath path;
|
||||
if (find_directory(which[i], &path) == B_OK) {
|
||||
catalogName = BString("locale/")
|
||||
catalogName = BString("locale/")
|
||||
<< kCatFolder
|
||||
<< "/" << sigPattern;
|
||||
|
||||
|
||||
BPath catalogPath(path.Path(), catalogName.String());
|
||||
BEntry file(catalogPath.Path());
|
||||
BDirectory dir(&file);
|
||||
|
||||
|
||||
char fileName[B_FILE_NAME_LENGTH];
|
||||
while(dir.GetNextEntry(&file) == B_OK) {
|
||||
while(dir.GetNextEntry(&file) == B_OK) {
|
||||
file.GetName(fileName);
|
||||
BString langName(fileName);
|
||||
langName.Replace(kCatExtension,"",1);
|
||||
@ -633,6 +633,6 @@ default_catalog_get_available_languages(BMessage* availableLanguages,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
75
src/kits/locale/DurationFormat.cpp
Normal file
75
src/kits/locale/DurationFormat.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2010, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Oliver Tappe <zooey@hirschkaefer.de>
|
||||
*/
|
||||
|
||||
|
||||
#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
|
||||
Locale.cpp
|
||||
LocaleRoster.cpp
|
||||
MutableLocaleRoster.cpp
|
||||
TimeZone.cpp
|
||||
|
||||
# in progress
|
||||
DateFormat.cpp
|
||||
DateTimeFormat.cpp
|
||||
DurationFormat.cpp
|
||||
TimeFormat.cpp
|
||||
TimeUnitFormat.cpp
|
||||
|
||||
# old, needs investigation
|
||||
Currency.cpp
|
||||
FloatFormat.cpp
|
||||
FloatFormatImpl.cpp
|
||||
@ -36,7 +45,6 @@ local sources =
|
||||
NumberFormatImpl.cpp
|
||||
NumberFormatParameters.cpp
|
||||
PropertyFile.cpp
|
||||
TimeFormat.cpp
|
||||
UnicodeChar.cpp
|
||||
;
|
||||
|
||||
|
@ -6,6 +6,11 @@
|
||||
|
||||
#include <Language.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <Catalog.h>
|
||||
@ -15,11 +20,6 @@
|
||||
#include <String.h>
|
||||
#include <FindDirectory.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <ICUWrapper.h>
|
||||
|
||||
#include <unicode/locid.h>
|
||||
@ -28,91 +28,62 @@
|
||||
#define ICU_VERSION icu_44
|
||||
|
||||
|
||||
static const char *gBuiltInStrings[] = {
|
||||
"Yesterday",
|
||||
"Today",
|
||||
"Tomorrow",
|
||||
"Future",
|
||||
|
||||
"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()
|
||||
:
|
||||
fDirection(B_LEFT_TO_RIGHT),
|
||||
fICULocale(NULL)
|
||||
{
|
||||
SetTo(NULL);
|
||||
}
|
||||
|
||||
|
||||
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()
|
||||
{
|
||||
delete fICULocale;
|
||||
|
||||
for (int32 i = B_NUM_LANGUAGE_STRINGS;i-- > 0;)
|
||||
free(fStrings[i]);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BLanguage::Default()
|
||||
status_t
|
||||
BLanguage::SetTo(const char* language)
|
||||
{
|
||||
fICULocale = new ICU_VERSION::Locale("en");
|
||||
fDirection = B_LEFT_TO_RIGHT;
|
||||
delete fICULocale;
|
||||
fICULocale = new ICU_VERSION::Locale(language);
|
||||
if (fICULocale == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
for (int32 i = B_NUM_LANGUAGE_STRINGS;i-- > 0;) {
|
||||
free(fStrings[i]);
|
||||
fStrings[i] = strdup(gBuiltInStrings[i]);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
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 "Locale.h"
|
||||
#include "LocaleRoster.h"
|
||||
#include "MutableLocaleRoster.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
@ -25,7 +25,7 @@ CreateLocaleBackendInstance()
|
||||
|
||||
LibbeLocaleBackend::LibbeLocaleBackend()
|
||||
{
|
||||
be_locale_roster->GetSystemCatalog(&systemCatalog);
|
||||
mutable_locale_roster->GetSystemCatalog(&systemCatalog);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
*/
|
||||
@ -38,5 +38,5 @@ BLocale::GetString(uint32 id)
|
||||
|
||||
return "";
|
||||
}
|
||||
return fLanguage->GetString(id);
|
||||
return fLanguage.GetString(id);
|
||||
}
|
||||
|
@ -13,11 +13,10 @@
|
||||
#include <set>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h> // for debug only
|
||||
#include <syslog.h>
|
||||
|
||||
#include <AppFileInfo.h>
|
||||
#include <Autolock.h>
|
||||
#include <AppFileInfo.h>
|
||||
#include <Catalog.h>
|
||||
#include <Collator.h>
|
||||
#include <Country.h>
|
||||
@ -25,9 +24,9 @@
|
||||
#include <Directory.h>
|
||||
#include <Entry.h>
|
||||
#include <File.h>
|
||||
#include <FindDirectory.h>
|
||||
#include <Language.h>
|
||||
#include <Locale.h>
|
||||
#include <MutableLocaleRoster.h>
|
||||
#include <Node.h>
|
||||
#include <Path.h>
|
||||
#include <String.h>
|
||||
@ -40,19 +39,20 @@
|
||||
#include <unicode/timezone.h>
|
||||
|
||||
|
||||
using BPrivate::CatalogAddOnInfo;
|
||||
|
||||
|
||||
/*
|
||||
* 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
|
||||
const char *BLocaleRoster::kCatSigAttr = "BEOS:LOCALE_SIGNATURE";
|
||||
const char* BLocaleRoster::kCatSigAttr = "BEOS:LOCALE_SIGNATURE";
|
||||
// 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
|
||||
|
||||
const char *BLocaleRoster::kEmbeddedCatAttr = "BEOS:LOCALE_EMBEDDED_CATALOG";
|
||||
const char* BLocaleRoster::kEmbeddedCatAttr = "BEOS:LOCALE_EMBEDDED_CATALOG";
|
||||
// attribute which contains flattened data of embedded catalog
|
||||
// this may live in an app- or add-on-file
|
||||
int32 BLocaleRoster::kEmbeddedCatResId = 0xCADA;
|
||||
@ -61,340 +61,6 @@ int32 BLocaleRoster::kEmbeddedCatResId = 0xCADA;
|
||||
// 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()
|
||||
{
|
||||
}
|
||||
@ -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*
|
||||
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
|
||||
// status_t. Maybe it could throw exceptions ?
|
||||
@ -460,428 +295,3 @@ BLocaleRoster::GetCatalog(BCatalog* catalog, vint32* catalogInitStatus)
|
||||
|
||||
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;
|
||||
}
|
||||
|
861
src/kits/locale/MutableLocaleRoster.cpp
Normal file
861
src/kits/locale/MutableLocaleRoster.cpp
Normal file
@ -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.
|
||||
*
|
||||
* Authors:
|
||||
* Oliver Tappe <zooey@hirschkaefer.de>
|
||||
*/
|
||||
|
||||
#include <TimeFormat.h>
|
||||
|
||||
#include <unicode/format.h>
|
||||
#include <unicode/tmutfmt.h>
|
||||
#include <unicode/utypes.h>
|
||||
#include <ICUWrapper.h>
|
||||
|
||||
#define ICU_VERSION icu_44
|
||||
|
||||
status_t BTimeFormat::Format(int64 number, BString* buffer) const
|
||||
// copy constructor
|
||||
BTimeFormat::BTimeFormat(const BTimeFormat &other)
|
||||
: BDateTimeFormat(other)
|
||||
{
|
||||
// create time unit amount instance - a combination of Number and time unit
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
int64 days, hours, minutes, seconds, remainder;
|
||||
|
||||
days = number / (24 * 3600);
|
||||
remainder = number % (24 * 3600);
|
||||
|
||||
hours = remainder / 3600;
|
||||
remainder %= 3600;
|
||||
|
||||
minutes = remainder / 60;
|
||||
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;
|
||||
}
|
||||
|
||||
// destructor
|
||||
BTimeFormat::~BTimeFormat()
|
||||
{
|
||||
}
|
||||
|
||||
// Format
|
||||
status_t
|
||||
BTimeFormat::Format(bigtime_t value, BString* buffer) const
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
65
src/kits/locale/TimeUnitFormat.cpp
Normal file
65
src/kits/locale/TimeUnitFormat.cpp
Normal file
@ -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>
|
||||
|
||||
|
||||
const char* BTimeZone::kNameOfGmtZone = "GMT";
|
||||
|
||||
|
||||
BTimeZone::BTimeZone(const char* zoneCode)
|
||||
{
|
||||
_Init(zoneCode);
|
||||
SetTo(zoneCode);
|
||||
}
|
||||
|
||||
|
||||
@ -53,8 +56,8 @@ BTimeZone::InitCheck() const
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BTimeZone::_Init(const char* zoneCode)
|
||||
status_t
|
||||
BTimeZone::SetTo(const char* zoneCode)
|
||||
{
|
||||
TimeZone* icuTimeZone;
|
||||
if (zoneCode == NULL || zoneCode[0] == '\0')
|
||||
@ -86,4 +89,6 @@ BTimeZone::_Init(const char* zoneCode)
|
||||
// we want seconds, not ms (which ICU gives us)
|
||||
fInitStatus = B_OK;
|
||||
}
|
||||
|
||||
return fInitStatus;
|
||||
}
|
||||
|
@ -7,20 +7,21 @@
|
||||
#include "LocaleSettings.h"
|
||||
|
||||
#include <FindDirectory.h>
|
||||
#include <LocaleRoster.h>
|
||||
#include <MutableLocaleRoster.h>
|
||||
#include <Path.h>
|
||||
#include <Roster.h>
|
||||
#include <String.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
using BPrivate::mutable_locale_roster;
|
||||
|
||||
|
||||
static const uint32 kMsgLocaleSettings = 'LCst';
|
||||
|
||||
|
||||
LocaleSettings::LocaleSettings()
|
||||
:
|
||||
fMessage(kMsgLocaleSettings),
|
||||
fSaved(false)
|
||||
fMessage(kMsgLocaleSettings)
|
||||
{
|
||||
// Set default preferences
|
||||
fMessage.AddString("language", "en");
|
||||
@ -36,27 +37,14 @@ LocaleSettings::Load()
|
||||
err = _Open(&file, B_READ_ONLY);
|
||||
if (err != B_OK)
|
||||
return err;
|
||||
err = fMessage.Unflatten(&file);
|
||||
if (err == B_OK)
|
||||
fSaved = true;
|
||||
return err;
|
||||
return fMessage.Unflatten(&file);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
LocaleSettings::Save()
|
||||
{
|
||||
// Save on disk for next time we reboot
|
||||
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;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -86,33 +74,35 @@ LocaleSettings::UpdateFrom(BMessage* message)
|
||||
break;
|
||||
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) {
|
||||
fMessage.ReplaceString("country", messageContent);
|
||||
fMessage.RemoveName("shortTimeFormat");
|
||||
fMessage.RemoveName("longTimeFormat");
|
||||
fSaved = false;
|
||||
defaultCountry = BCountry(messageContent.String());
|
||||
countryChanged = true;
|
||||
}
|
||||
|
||||
if (message->FindString("shortTimeFormat", &messageContent) == B_OK) {
|
||||
fMessage.RemoveName("shortTimeFormat");
|
||||
fMessage.AddString("shortTimeFormat", messageContent);
|
||||
fSaved = false;
|
||||
defaultCountry.SetTimeFormat(messageContent, false);
|
||||
countryChanged = true;
|
||||
}
|
||||
|
||||
if (message->FindString("longTimeFormat", &messageContent) == B_OK) {
|
||||
fMessage.RemoveName("longTimeFormat");
|
||||
fMessage.AddString("longTimeFormat", messageContent);
|
||||
fSaved = false;
|
||||
defaultCountry.SetTimeFormat(messageContent, true);
|
||||
countryChanged = true;
|
||||
}
|
||||
|
||||
if (fSaved == false) {
|
||||
// Send to all running apps to notify them they should update their
|
||||
// settings
|
||||
fMessage.what = B_LOCALE_CHANGED;
|
||||
be_roster->Broadcast(&fMessage);
|
||||
}
|
||||
if (countryChanged)
|
||||
mutable_locale_roster->SetDefaultCountry(defaultCountry);
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,6 @@ class LocaleSettings {
|
||||
status_t Load();
|
||||
status_t Save();
|
||||
|
||||
bool Saved();
|
||||
bool operator==(const LocaleSettings& other);
|
||||
|
||||
void UpdateFrom(BMessage* message);
|
||||
@ -44,7 +43,6 @@ class LocaleSettings {
|
||||
status_t _Open(BFile* file, int32 mode);
|
||||
|
||||
BMessage fMessage;
|
||||
bool fSaved;
|
||||
};
|
||||
|
||||
|
||||
|
@ -47,10 +47,24 @@ static const uint32 kMsgPreferredLanguagesChanged = 'lang';
|
||||
static int
|
||||
compare_typed_list_items(const BListItem* _a, const BListItem* _b)
|
||||
{
|
||||
// TODO: sort them using collators.
|
||||
static BCollator collator;
|
||||
|
||||
LanguageListItem* a = (LanguageListItem*)_a;
|
||||
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
|
||||
| B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS)
|
||||
{
|
||||
BCountry* defaultCountry;
|
||||
BCountry defaultCountry;
|
||||
be_locale_roster->GetDefaultCountry(&defaultCountry);
|
||||
|
||||
SetLayout(new BGroupLayout(B_HORIZONTAL));
|
||||
@ -173,21 +187,26 @@ LocaleWindow::LocaleWindow()
|
||||
be_locale_roster->GetInstalledLanguages(&countryList);
|
||||
BString countryCode;
|
||||
|
||||
LanguageListItem* currentItem = NULL;
|
||||
for (int i = 0; countryList.FindString("langs", i, &countryCode) == B_OK;
|
||||
i++) {
|
||||
BCountry country(countryCode);
|
||||
BString countryName;
|
||||
|
||||
country.LocaleName(countryName);
|
||||
country.GetLocaleName(countryName);
|
||||
|
||||
LanguageListItem* item
|
||||
= new LanguageListItem(countryName, countryCode,
|
||||
NULL);
|
||||
listView->AddItem(item);
|
||||
if (!strcmp(countryCode, defaultCountry->Code()))
|
||||
listView->Select(listView->CountItems() - 1);
|
||||
if (!strcmp(countryCode, defaultCountry.Code()))
|
||||
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
|
||||
listView->SetExplicitMinSize(
|
||||
BSize(25 * be_plain_font->Size(), B_SIZE_UNSET));
|
||||
@ -341,7 +360,7 @@ LocaleWindow::MessageReceived(BMessage* message)
|
||||
be_app_messenger.SendMessage(&newMessage);
|
||||
SettingsChanged();
|
||||
|
||||
BCountry* country = new BCountry(item->ID());
|
||||
BCountry country(item->ID());
|
||||
fFormatView->SetCountry(country);
|
||||
break;
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include <GroupLayoutBuilder.h>
|
||||
#include <LayoutBuilder.h>
|
||||
#include <Locale.h>
|
||||
#include <LocaleRoster.h>
|
||||
#include <MutableLocaleRoster.h>
|
||||
#include <Message.h>
|
||||
#include <Menu.h>
|
||||
#include <MenuField.h>
|
||||
@ -34,6 +34,10 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
using BPrivate::mutable_locale_roster;
|
||||
|
||||
|
||||
#undef B_TRANSLATE_CONTEXT
|
||||
#define B_TRANSLATE_CONTEXT "TimeFormatSettings"
|
||||
@ -144,10 +148,10 @@ IsSpecialDateChar(char charToTest)
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
FormatView::FormatView(BCountry* country)
|
||||
FormatView::FormatView(const BCountry& country)
|
||||
:
|
||||
BView("WindowsSettingsView", B_FRAME_EVENTS),
|
||||
fCountry(*country)
|
||||
fCountry(country)
|
||||
{
|
||||
SetLayout(new BGroupLayout(B_HORIZONTAL));
|
||||
|
||||
@ -185,8 +189,8 @@ FormatView::FormatView(BCountry* country)
|
||||
f12HrRadioButton = new BRadioButton("", B_TRANSLATE("12 hour"),
|
||||
new BMessage(kClockFormatChange));
|
||||
|
||||
fCountry.TimeFormat(fOriginalTimeFormat, false);
|
||||
fCountry.TimeFormat(fOriginalLongTimeFormat, true);
|
||||
fCountry.GetTimeFormat(fOriginalTimeFormat, false);
|
||||
fCountry.GetTimeFormat(fOriginalLongTimeFormat, true);
|
||||
if (fOriginalTimeFormat.FindFirst("a") != B_ERROR) {
|
||||
f12HrRadioButton->SetValue(B_CONTROL_ON);
|
||||
fCountryIs24Hr = false;
|
||||
@ -356,7 +360,7 @@ FormatView::FormatView(BCountry* country)
|
||||
|
||||
FormatView::~FormatView()
|
||||
{
|
||||
be_locale_roster->SetDefaultCountry(&fCountry);
|
||||
mutable_locale_roster->SetDefaultCountry(fCountry);
|
||||
}
|
||||
|
||||
|
||||
@ -510,9 +514,9 @@ FormatView::SetDefaults()
|
||||
settings.SetClockTo24Hr(false);
|
||||
*/
|
||||
|
||||
BCountry* defaultCountry;
|
||||
BCountry defaultCountry;
|
||||
be_locale_roster->GetDefaultCountry(&defaultCountry);
|
||||
fCountry = *defaultCountry;
|
||||
fCountry = defaultCountry;
|
||||
// We work on a copy of the default country and set the changes when
|
||||
// closing the preflet
|
||||
_UpdateExamples();
|
||||
@ -551,14 +555,12 @@ FormatView::Revert()
|
||||
|
||||
|
||||
void
|
||||
FormatView::SetCountry(BCountry* country)
|
||||
FormatView::SetCountry(const BCountry& country)
|
||||
{
|
||||
fCountry = *country;
|
||||
fCountry = country;
|
||||
|
||||
fOriginalTimeFormat.Truncate(0);
|
||||
fCountry.TimeFormat(fOriginalTimeFormat, false);
|
||||
fOriginalLongTimeFormat.Truncate(0);
|
||||
fCountry.TimeFormat(fOriginalLongTimeFormat, true);
|
||||
fCountry.GetTimeFormat(fOriginalTimeFormat, false);
|
||||
fCountry.GetTimeFormat(fOriginalLongTimeFormat, true);
|
||||
|
||||
if (fOriginalTimeFormat.FindFirst("a") != B_ERROR) {
|
||||
f12HrRadioButton->SetValue(B_CONTROL_ON);
|
||||
@ -666,10 +668,12 @@ FormatView::_ParseDateFormat()
|
||||
{
|
||||
// TODO parse the short date too
|
||||
BString dateFormatString;
|
||||
fCountry.DateFormat(dateFormatString, true);
|
||||
fCountry.GetDateFormat(dateFormatString, true);
|
||||
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* fieldBegin = dateFormat;
|
||||
|
||||
@ -717,8 +721,7 @@ FormatView::_ParseDateFormat()
|
||||
}
|
||||
|
||||
// Short date is a bit more tricky, we want to extract the separator
|
||||
dateFormatString.Truncate(0);
|
||||
fCountry.DateFormat(dateFormatString, false);
|
||||
fCountry.GetDateFormat(dateFormatString, false);
|
||||
dateFormat = dateFormatString.String();
|
||||
|
||||
// Travel trough the string and parse it
|
||||
|
@ -37,7 +37,7 @@ const uint32 kMenuMessage = 'FRMT';
|
||||
|
||||
class FormatView : public BView {
|
||||
public:
|
||||
FormatView(BCountry* country);
|
||||
FormatView(const BCountry& country);
|
||||
~FormatView();
|
||||
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
@ -46,7 +46,7 @@ public:
|
||||
virtual void SetDefaults();
|
||||
virtual bool IsDefaultable() const;
|
||||
virtual void Revert();
|
||||
virtual void SetCountry(BCountry* country);
|
||||
virtual void SetCountry(const BCountry& country);
|
||||
virtual void RecordRevertSettings();
|
||||
virtual bool IsRevertable() const;
|
||||
|
||||
|
@ -105,9 +105,9 @@ TTimeEdit::DrawSection(uint32 index, bool hasFocus)
|
||||
int* fieldPositions;
|
||||
int fieldCount;
|
||||
|
||||
BCountry* country;
|
||||
BCountry 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
|
||||
|
||||
if (index * 2 + 1 > (uint32)fieldCount) {
|
||||
@ -148,10 +148,10 @@ TTimeEdit::DrawSeparator(uint32 index)
|
||||
int* fieldPositions;
|
||||
int fieldCount;
|
||||
|
||||
BCountry* country;
|
||||
BCountry country;
|
||||
be_locale_roster->GetDefaultCountry(&country);
|
||||
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
|
||||
|
||||
if (index * 2 + 2 > (uint32)fieldCount) {
|
||||
@ -265,9 +265,9 @@ TTimeEdit::BuildDispatch(BMessage* message)
|
||||
|
||||
BDateElement* dateFormat;
|
||||
int fieldCount;
|
||||
BCountry* here;
|
||||
BCountry here;
|
||||
be_locale_roster->GetDefaultCountry(&here);
|
||||
here->TimeFields(dateFormat, fieldCount, true);
|
||||
here.GetTimeFields(dateFormat, fieldCount, true);
|
||||
if (fFocus > fieldCount) {
|
||||
free(dateFormat);
|
||||
return;
|
||||
@ -303,9 +303,9 @@ TTimeEdit::_CheckRange()
|
||||
int32 value = fHoldValue;
|
||||
BDateElement* fields;
|
||||
int fieldCount;
|
||||
BCountry* here;
|
||||
BCountry here;
|
||||
be_locale_roster->GetDefaultCountry(&here);
|
||||
here->TimeFields(fields, fieldCount, true);
|
||||
here.GetTimeFields(fields, fieldCount, true);
|
||||
if (fFocus > fieldCount) {
|
||||
free(fields);
|
||||
return;
|
||||
@ -373,9 +373,9 @@ TTimeEdit::_IsValidDoubleDigi(int32 value)
|
||||
bool isInRange = false;
|
||||
BDateElement* fields;
|
||||
int fieldCount;
|
||||
BCountry* here;
|
||||
BCountry here;
|
||||
be_locale_roster->GetDefaultCountry(&here);
|
||||
here->TimeFields(fields, fieldCount, true);
|
||||
here.GetTimeFields(fields, fieldCount, true);
|
||||
if (fFocus > fieldCount) {
|
||||
free(fields);
|
||||
return false;
|
||||
@ -412,9 +412,9 @@ TTimeEdit::_SectionValue(int32 index) const
|
||||
int32 value;
|
||||
BDateElement* fields;
|
||||
int fieldCount;
|
||||
BCountry* here;
|
||||
BCountry here;
|
||||
be_locale_roster->GetDefaultCountry(&here);
|
||||
here->TimeFields(fields, fieldCount, true);
|
||||
here.GetTimeFields(fields, fieldCount, true);
|
||||
if (index > fieldCount) {
|
||||
free(fields);
|
||||
return 0;
|
||||
@ -487,9 +487,9 @@ TDateEdit::KeyDown(const char* bytes, int32 numBytes)
|
||||
|
||||
BDateElement* dateFormat;
|
||||
int fieldCount;
|
||||
BCountry* here;
|
||||
BCountry here;
|
||||
be_locale_roster->GetDefaultCountry(&here);
|
||||
here->DateFields(dateFormat, fieldCount, false);
|
||||
here.GetDateFields(dateFormat, fieldCount, false);
|
||||
|
||||
if (dateFormat[section] == B_DATE_ELEMENT_YEAR) {
|
||||
int32 oldCentury = int32(fHoldValue / 100) * 100;
|
||||
@ -541,9 +541,9 @@ TDateEdit::DrawSection(uint32 index, bool hasFocus)
|
||||
int* fieldPositions;
|
||||
int fieldCount;
|
||||
|
||||
BCountry* country;
|
||||
BCountry country;
|
||||
be_locale_roster->GetDefaultCountry(&country);
|
||||
country->FormatDate(&text, fieldPositions, fieldCount, dateTime.Time_t(),
|
||||
country.FormatDate(&text, fieldPositions, fieldCount, dateTime.Time_t(),
|
||||
false);
|
||||
// TODO : this should be cached somehow to not redo it for each field
|
||||
|
||||
@ -587,10 +587,10 @@ TDateEdit::DrawSeparator(uint32 index)
|
||||
int* fieldPositions;
|
||||
int fieldCount;
|
||||
|
||||
BCountry* country;
|
||||
BCountry country;
|
||||
be_locale_roster->GetDefaultCountry(&country);
|
||||
BDateTime dateTime(fDate, BTime());
|
||||
country->FormatDate(&text, fieldPositions, fieldCount, dateTime.Time_t(),
|
||||
country.FormatDate(&text, fieldPositions, fieldCount, dateTime.Time_t(),
|
||||
false);
|
||||
// TODO : this should be cached somehow to not redo it for each field
|
||||
|
||||
@ -716,9 +716,9 @@ TDateEdit::BuildDispatch(BMessage* message)
|
||||
|
||||
BDateElement* dateFormat;
|
||||
int fieldCount;
|
||||
BCountry* here;
|
||||
BCountry here;
|
||||
be_locale_roster->GetDefaultCountry(&here);
|
||||
here->DateFields(dateFormat, fieldCount, false);
|
||||
here.GetDateFields(dateFormat, fieldCount, false);
|
||||
if (fFocus > fieldCount) {
|
||||
free(dateFormat);
|
||||
return;
|
||||
@ -754,9 +754,9 @@ TDateEdit::_CheckRange()
|
||||
int32 value = fHoldValue;
|
||||
BDateElement* fields;
|
||||
int fieldCount;
|
||||
BCountry* here;
|
||||
BCountry here;
|
||||
be_locale_roster->GetDefaultCountry(&here);
|
||||
here->DateFields(fields, fieldCount, false);
|
||||
here.GetDateFields(fields, fieldCount, false);
|
||||
if (fFocus > fieldCount) {
|
||||
free(fields);
|
||||
return;
|
||||
@ -811,9 +811,9 @@ TDateEdit::_IsValidDoubleDigi(int32 value)
|
||||
bool isInRange = false;
|
||||
BDateElement* fields;
|
||||
int fieldCount;
|
||||
BCountry* here;
|
||||
BCountry here;
|
||||
be_locale_roster->GetDefaultCountry(&here);
|
||||
here->DateFields(fields, fieldCount, false);
|
||||
here.GetDateFields(fields, fieldCount, false);
|
||||
if (fFocus > fieldCount) {
|
||||
free(fields);
|
||||
return false;
|
||||
@ -852,9 +852,9 @@ TDateEdit::_SectionValue(int32 index) const
|
||||
int32 value = 0;
|
||||
BDateElement* fields;
|
||||
int fieldCount;
|
||||
BCountry* here;
|
||||
BCountry here;
|
||||
be_locale_roster->GetDefaultCountry(&here);
|
||||
here->DateFields(fields, fieldCount, false);
|
||||
here.GetDateFields(fields, fieldCount, false);
|
||||
if (index > fieldCount) {
|
||||
free(fields);
|
||||
return 0;
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include "TimeMessages.h"
|
||||
#include "TimeWindow.h"
|
||||
|
||||
|
||||
#include <CalendarView.h>
|
||||
#include <CheckBox.h>
|
||||
#include <DateTime.h>
|
||||
@ -28,22 +27,18 @@
|
||||
#include <String.h>
|
||||
#include <StringView.h>
|
||||
#include <Window.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <syscalls.h>
|
||||
|
||||
|
||||
using BPrivate::BCalendarView;
|
||||
using BPrivate::BDateTime;
|
||||
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)
|
||||
: BView(frame, "dateTimeView", B_FOLLOW_NONE, B_WILL_DRAW
|
||||
| B_NAVIGABLE_JUMP),
|
||||
@ -266,6 +261,7 @@ DateTimeView::_InitView()
|
||||
AddChild(fGmtTime);
|
||||
fGmtTime->ResizeToPreferred();
|
||||
|
||||
printf("fUseGmtTime=%d\n", fUseGmtTime);
|
||||
if (fUseGmtTime)
|
||||
fGmtTime->SetValue(B_CONTROL_ON);
|
||||
else
|
||||
@ -323,20 +319,6 @@ DateTimeView::_UpdateGmtSettings()
|
||||
{
|
||||
_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);
|
||||
}
|
||||
|
||||
|
@ -2,10 +2,10 @@ SubDir HAIKU_TOP src preferences time ;
|
||||
|
||||
SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||
|
||||
UsePrivateHeaders shared ;
|
||||
UsePrivateHeaders locale shared ;
|
||||
UsePrivateSystemHeaders ;
|
||||
|
||||
Preference Time :
|
||||
local sources =
|
||||
AnalogClock.cpp
|
||||
BaseView.cpp
|
||||
Bitmaps.cpp
|
||||
@ -18,6 +18,16 @@ Preference Time :
|
||||
TimeZoneListItem.cpp
|
||||
TZDisplay.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)
|
||||
: Time.rdef
|
||||
;
|
||||
|
@ -88,7 +88,7 @@ void
|
||||
TTZDisplay::SetLabel(const char* label)
|
||||
{
|
||||
fLabel.SetTo(label);
|
||||
Draw(Bounds());
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
|
||||
@ -103,7 +103,7 @@ void
|
||||
TTZDisplay::SetText(const char* text)
|
||||
{
|
||||
fText.SetTo(text);
|
||||
Draw(Bounds());
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
|
||||
@ -115,24 +115,9 @@ TTZDisplay::Time() const
|
||||
|
||||
|
||||
void
|
||||
TTZDisplay::SetTime(int32 hour, int32 minute)
|
||||
TTZDisplay::SetTime(const char* time)
|
||||
{
|
||||
int32 ahour = hour;
|
||||
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);
|
||||
|
||||
fTime.SetTo(time);
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
|
@ -33,12 +33,12 @@ public:
|
||||
void SetText(const char* text);
|
||||
|
||||
const char* Time() const;
|
||||
void SetTime(int32 hour, int32 minute);
|
||||
void SetTime(const char* time);
|
||||
|
||||
private:
|
||||
BString fLabel;
|
||||
BString fText;
|
||||
BString fTime;
|
||||
BString fLabel;
|
||||
BString fText;
|
||||
BString fTime;
|
||||
};
|
||||
|
||||
|
||||
|
@ -28,7 +28,8 @@ TimeZoneListItem::TimeZoneListItem(const char* text, BCountry* country,
|
||||
BTimeZone* timeZone)
|
||||
:
|
||||
BStringItem(text),
|
||||
fIcon(NULL)
|
||||
fIcon(NULL),
|
||||
fTimeZone(timeZone)
|
||||
{
|
||||
if (country != NULL) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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&
|
||||
TimeZoneListItem::Code() const
|
||||
{
|
||||
|
@ -27,6 +27,8 @@ public:
|
||||
void DrawItem(BView* owner, BRect frame,
|
||||
bool complete = false);
|
||||
|
||||
bool HasTimeZone() const;
|
||||
const BTimeZone& TimeZone() const;
|
||||
const BString& Code() const;
|
||||
const BString& Name() const;
|
||||
int OffsetFromGMT() const;
|
||||
|
@ -10,16 +10,14 @@
|
||||
* Oliver Tappe <zooey@hirschkaefer.de>
|
||||
*/
|
||||
|
||||
/*
|
||||
Exceptions:
|
||||
doesn't calc "Time in" time.
|
||||
*/
|
||||
|
||||
#include "ZoneView.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
#include <Button.h>
|
||||
#include <Collator.h>
|
||||
#include <Directory.h>
|
||||
@ -27,7 +25,7 @@
|
||||
#include <FindDirectory.h>
|
||||
#include <ListItem.h>
|
||||
#include <Locale.h>
|
||||
#include <LocaleRoster.h>
|
||||
#include <MutableLocaleRoster.h>
|
||||
#include <OutlineListView.h>
|
||||
#include <ScrollView.h>
|
||||
#include <StorageDefs.h>
|
||||
@ -38,21 +36,25 @@
|
||||
|
||||
#include <syscalls.h>
|
||||
|
||||
#include <unicode/datefmt.h>
|
||||
#include <unicode/utmscale.h>
|
||||
#include <ICUWrapper.h>
|
||||
|
||||
#include "TimeMessages.h"
|
||||
#include "TimeZoneListItem.h"
|
||||
#include "TZDisplay.h"
|
||||
#include "TimeWindow.h"
|
||||
|
||||
|
||||
static BCollator sCollator;
|
||||
// used to sort the timezone list
|
||||
using BPrivate::mutable_locale_roster;
|
||||
using BPrivate::ObjectDeleter;
|
||||
|
||||
|
||||
TimeZoneView::TimeZoneView(BRect frame)
|
||||
:
|
||||
BView(frame, "timeZoneView", B_FOLLOW_NONE, B_WILL_DRAW | B_NAVIGABLE_JUMP),
|
||||
fCurrentZone(NULL),
|
||||
fOldZone(NULL),
|
||||
fCurrentZoneItem(NULL),
|
||||
fOldZoneItem(NULL),
|
||||
fInitialized(false)
|
||||
{
|
||||
_InitView();
|
||||
@ -62,33 +64,30 @@ TimeZoneView::TimeZoneView(BRect frame)
|
||||
bool
|
||||
TimeZoneView::CheckCanRevert()
|
||||
{
|
||||
return fCurrentZone != fOldZone;
|
||||
return fCurrentZoneItem != fOldZoneItem;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TimeZoneView::_Revert()
|
||||
{
|
||||
fCurrentZone = fOldZone;
|
||||
int32 czone = 0;
|
||||
fCurrentZoneItem = fOldZoneItem;
|
||||
|
||||
if (fCurrentZone != NULL) {
|
||||
czone = fCityList->IndexOf(fCurrentZone);
|
||||
fCityList->Select(czone);
|
||||
}
|
||||
// TODO : else, select ??!
|
||||
if (fCurrentZoneItem != NULL) {
|
||||
int32 currentZoneIndex = fZoneList->IndexOf(fCurrentZoneItem);
|
||||
fZoneList->Select(currentZoneIndex);
|
||||
} else
|
||||
fZoneList->DeselectAll();
|
||||
fZoneList->ScrollToSelection();
|
||||
|
||||
fCityList->ScrollToSelection();
|
||||
fCurrent->SetText(((TimeZoneListItem*)fCityList->ItemAt(czone))->Text());
|
||||
_SetPreview();
|
||||
_SetTimeZone();
|
||||
_SetSystemTimeZone();
|
||||
_UpdatePreview();
|
||||
_UpdateCurrent();
|
||||
}
|
||||
|
||||
|
||||
TimeZoneView::~TimeZoneView()
|
||||
{
|
||||
delete fCurrentZone;
|
||||
delete fOldZone;
|
||||
}
|
||||
|
||||
|
||||
@ -102,23 +101,23 @@ TimeZoneView::AttachedToWindow()
|
||||
fInitialized = true;
|
||||
|
||||
fSetZone->SetTarget(this);
|
||||
fCityList->SetTarget(this);
|
||||
fZoneList->SetTarget(this);
|
||||
|
||||
// update displays
|
||||
int32 czone = 0;
|
||||
if (fCurrentZone != NULL) {
|
||||
czone = fCityList->IndexOf(fCurrentZone);
|
||||
if (fCurrentZoneItem != NULL) {
|
||||
czone = fZoneList->IndexOf(fCurrentZoneItem);
|
||||
} else {
|
||||
// TODO : else, select ??!
|
||||
fCurrentZone = (TimeZoneListItem*)fCityList->ItemAt(0);
|
||||
fCurrentZoneItem = (TimeZoneListItem*)fZoneList->ItemAt(0);
|
||||
}
|
||||
|
||||
fCityList->Select(czone);
|
||||
fZoneList->Select(czone);
|
||||
|
||||
fCityList->ScrollToSelection();
|
||||
fCurrent->SetText(fCurrentZone->Text());
|
||||
fZoneList->ScrollToSelection();
|
||||
fCurrent->SetText(fCurrentZoneItem->Text());
|
||||
}
|
||||
fCityList->ScrollToSelection();
|
||||
fZoneList->ScrollToSelection();
|
||||
}
|
||||
|
||||
|
||||
@ -144,7 +143,7 @@ TimeZoneView::MessageReceived(BMessage* message)
|
||||
|
||||
case H_SET_TIME_ZONE:
|
||||
{
|
||||
_SetTimeZone();
|
||||
_SetSystemTimeZone();
|
||||
((TTimeWindow*)Window())->SetRevertStatus();
|
||||
break;
|
||||
}
|
||||
@ -154,7 +153,7 @@ TimeZoneView::MessageReceived(BMessage* message)
|
||||
break;
|
||||
|
||||
case H_CITY_CHANGED:
|
||||
_SetPreview();
|
||||
_UpdatePreview();
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -167,20 +166,14 @@ TimeZoneView::MessageReceived(BMessage* message)
|
||||
void
|
||||
TimeZoneView::_UpdateDateTime(BMessage* message)
|
||||
{
|
||||
int32 hour;
|
||||
// only need to update once every minute
|
||||
int32 minute;
|
||||
if (message->FindInt32("minute", &minute) == B_OK) {
|
||||
if (fLastUpdateMinute != minute) {
|
||||
_UpdateCurrent();
|
||||
_UpdatePreview();
|
||||
|
||||
// only need hour and 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();
|
||||
fLastUpdateMinute = minute;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -195,14 +188,14 @@ TimeZoneView::_InitView()
|
||||
frameLeft.InsetBy(10.0f, 10.0f);
|
||||
|
||||
// City Listing
|
||||
fCityList = new BOutlineListView(frameLeft, "cityList",
|
||||
fZoneList = new BOutlineListView(frameLeft, "cityList",
|
||||
B_SINGLE_SELECTION_LIST);
|
||||
fCityList->SetSelectionMessage(new BMessage(H_CITY_CHANGED));
|
||||
fCityList->SetInvocationMessage(new BMessage(H_SET_TIME_ZONE));
|
||||
fZoneList->SetSelectionMessage(new BMessage(H_CITY_CHANGED));
|
||||
fZoneList->SetInvocationMessage(new BMessage(H_SET_TIME_ZONE));
|
||||
|
||||
_BuildRegionMenu();
|
||||
|
||||
BScrollView* scrollList = new BScrollView("scrollList", fCityList,
|
||||
BScrollView* scrollList = new BScrollView("scrollList", fZoneList,
|
||||
B_FOLLOW_ALL, 0, false, true);
|
||||
AddChild(scrollList);
|
||||
|
||||
@ -237,7 +230,7 @@ TimeZoneView::_InitView()
|
||||
void
|
||||
TimeZoneView::_BuildRegionMenu()
|
||||
{
|
||||
BTimeZone* defaultTimeZone = NULL;
|
||||
BTimeZone defaultTimeZone = NULL;
|
||||
be_locale_roster->GetDefaultTimeZone(&defaultTimeZone);
|
||||
|
||||
// Get a list of countries and, for each country, get all the timezones and
|
||||
@ -252,7 +245,7 @@ TimeZoneView::_BuildRegionMenu()
|
||||
== B_OK; i++) {
|
||||
BCountry country("", countryCode);
|
||||
BString fullName;
|
||||
country.Name(fullName);
|
||||
country.GetName(fullName);
|
||||
|
||||
// Now list the timezones for this country
|
||||
BList tzList;
|
||||
@ -269,24 +262,24 @@ TimeZoneView::_BuildRegionMenu()
|
||||
timeZone = (BTimeZone*)tzList.ItemAt(0);
|
||||
countryItem
|
||||
= new TimeZoneListItem(fullName, &country, timeZone);
|
||||
fCityList->AddItem(countryItem);
|
||||
if (timeZone->Code() == defaultTimeZone->Code())
|
||||
fCurrentZone = countryItem;
|
||||
fZoneList->AddItem(countryItem);
|
||||
if (timeZone->Code() == defaultTimeZone.Code())
|
||||
fCurrentZoneItem = countryItem;
|
||||
break;
|
||||
default:
|
||||
countryItem = new TimeZoneListItem(fullName, &country, NULL);
|
||||
countryItem->SetExpanded(false);
|
||||
fCityList->AddItem(countryItem);
|
||||
fZoneList->AddItem(countryItem);
|
||||
|
||||
for (int j = 0;
|
||||
(timeZone = (BTimeZone*)tzList.ItemAt(j)) != NULL;
|
||||
j++) {
|
||||
TimeZoneListItem* tzItem = new TimeZoneListItem(
|
||||
timeZone->Name(), NULL, timeZone);
|
||||
fCityList->AddUnder(tzItem, countryItem);
|
||||
if (timeZone->Code() == defaultTimeZone->Code())
|
||||
fZoneList->AddUnder(tzItem, countryItem);
|
||||
if (timeZone->Code() == defaultTimeZone.Code())
|
||||
{
|
||||
fCurrentZone = tzItem;
|
||||
fCurrentZoneItem = tzItem;
|
||||
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 {
|
||||
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());
|
||||
}
|
||||
};
|
||||
fCityList->SortItemsUnder(NULL, false, ListSorter::compare);
|
||||
|
||||
fZoneList->SortItemsUnder(NULL, false, ListSorter::compare);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TimeZoneView::_SetPreview()
|
||||
TimeZoneView::_UpdatePreview()
|
||||
{
|
||||
int32 selection = fCityList->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();
|
||||
int32 selection = fZoneList->CurrentSelection();
|
||||
if (selection < 0)
|
||||
return;
|
||||
|
||||
const BString& code
|
||||
= ((TimeZoneListItem*)fCityList->ItemAt(selection))->Code();
|
||||
_SetTimeZone(code.String());
|
||||
TimeZoneListItem* item = (TimeZoneListItem*)fZoneList->ItemAt(selection);
|
||||
if (!item->HasTimeZone())
|
||||
return;
|
||||
|
||||
// update display
|
||||
time_t current = time(NULL);
|
||||
struct tm localTime;
|
||||
localtime_r(¤t, &localTime);
|
||||
BString timeString = _FormatTime(item);
|
||||
fPreview->SetText(item->Text());
|
||||
fPreview->SetTime(timeString.String());
|
||||
|
||||
set_timezone(code.String());
|
||||
// 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());
|
||||
fSetZone->SetEnabled((strcmp(fCurrent->Text(), item->Text()) != 0));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TimeZoneView::_SetTimeZone(const char* zone)
|
||||
TimeZoneView::_UpdateCurrent()
|
||||
{
|
||||
putenv(BString("TZ=").Append(zone).String());
|
||||
tzset();
|
||||
if (fCurrentZoneItem == NULL)
|
||||
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:
|
||||
void _UpdateDateTime(BMessage* message);
|
||||
void _SetTimeZone();
|
||||
void _SetTimeZone(const char* zone);
|
||||
void _SetPreview();
|
||||
void _SetCurrent(const char* text);
|
||||
|
||||
void _SetSystemTimeZone();
|
||||
|
||||
void _UpdatePreview();
|
||||
void _UpdateCurrent();
|
||||
BString _FormatTime(TimeZoneListItem* zoneItem);
|
||||
|
||||
void _InitView();
|
||||
void _BuildRegionMenu();
|
||||
|
||||
void _Revert();
|
||||
|
||||
private:
|
||||
BOutlineListView* fCityList;
|
||||
BOutlineListView* fZoneList;
|
||||
BButton* fSetZone;
|
||||
TTZDisplay* fCurrent;
|
||||
TTZDisplay* fPreview;
|
||||
|
||||
int32 fHour;
|
||||
int32 fMinute;
|
||||
TimeZoneListItem* fCurrentZone;
|
||||
TimeZoneListItem* fOldZone;
|
||||
int32 fLastUpdateMinute;
|
||||
|
||||
TimeZoneListItem* fCurrentZoneItem;
|
||||
TimeZoneListItem* fOldZoneItem;
|
||||
bool fInitialized;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user