Core: Language settings are now per-thread

git-svn-id: svn://ultimatepp.org/upp/trunk@5061 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2012-06-19 20:43:55 +00:00
parent 101a8c470b
commit 3e1fa2490c
6 changed files with 120 additions and 54 deletions

View file

@ -148,17 +148,9 @@ Convert& LNGConvert()
return Single<LangConvertClass>();
}
static int sCurrentLanguage = -1;
int GetCurrentLanguage() {
return sCurrentLanguage;
}
void SetLanguage(int lang) {
if(lang != LNG_CURRENT) {
sCurrentLanguage = lang;
if(lang != LNG_CURRENT)
SetDefaultCharset(GetLNGCharset(lang));
}
SetCurrentLanguage(lang);
}

View file

@ -67,30 +67,40 @@ String MonName(int i, int lang)
return i >= 0 && i < 12 ? Nvl(GetLngString(lang, month[i]), GetENUS(month[i])) : String();
}
static char s_date_format[64] = "%2:02d/%3:02d/%1:4d";
static thread__ char s_date_format_thread[64];
static char s_date_format_main[64] = "%2:02d/%3:02d/%1:4d";
void SetDateFormat(const char *fmt)
{
strncpy(s_date_format, fmt, 63);
strncpy(s_date_format_thread, fmt, 63);
#ifdef _MULTITHREADED
if(Thread::IsMain())
#endif
strncpy(s_date_format_main, fmt, 63);
}
String Format(Date date) {
String s;
if(IsNull(date))
return String();
return Format(s_date_format, date.year, date.month, date.day, DayOfWeek(date));
return Format(*s_date_format_thread ? s_date_format_thread : s_date_format_main, date.year, date.month, date.day, DayOfWeek(date));
}
static char s_date_scan[64] = "mdy";
static thread__ char s_date_scan_thread[64];
static char s_date_scan_main[64] = "mdy";
void SetDateScan(const char *scan)
{
strncpy(s_date_scan, scan, 63);
strncpy(s_date_scan_thread, scan, 63);
#ifdef _MULTITHREADED
if(Thread::IsMain())
#endif
strncpy(s_date_scan_main, scan, 63);
}
const char *StrToDate(Date& d, const char *s, Date def)
{
return StrToDate(s_date_scan, d, s, def);
return StrToDate(*s_date_scan_thread ? s_date_scan_thread : s_date_scan_main, d, s, def);
}
const char *StrToDate(const char *fmt, Date& d, const char *s, Date def)
@ -175,35 +185,39 @@ Date ScanDate(const char *s, Date def)
return def;
}
static bool s_date_letters = true, s_date_upper = true;
static char s_date_seps[64] = "A/\a .-";
static thread__ char s_date_seps_thread[64];
static char s_date_seps_main[64] = "A/\a .-";
void SetDateFilter(const char *seps)
{
s_date_letters = false;
s_date_upper = false;
if(*seps == 'a') {
s_date_letters = true;
seps++;
}
else
if(*seps == 'A') {
s_date_letters = true;
s_date_upper = true;
seps++;
}
strncpy(s_date_seps, seps, 63);
strncpy(s_date_seps_thread, seps, 63);
#ifdef _MULTITHREADED
if(Thread::IsMain())
#endif
strncpy(s_date_seps_main, seps, 63);
}
int CharFilterDate(int c)
{
if(IsDigit(c))
return c;
if(s_date_letters && IsLetter(c))
return s_date_upper ? ToUpper(c) : c;
const char *s = *s_date_seps_thread ? s_date_seps_thread : s_date_seps_main;
bool letters = false;
bool upper = false;
if(*s == 'a') {
letters = true;
s++;
}
else
if(*s == 'A') {
letters = true;
upper = true;
s++;
}
if(letters && IsLetter(c))
return upper ? ToUpper(c) : c;
;
int r = 0;
const char *s = s_date_seps;
while(*s) {
if(c == (byte)*s)
return c;
@ -468,7 +482,7 @@ const char *StrToTime(const char *datefmt, Time& d, const char *s)
const char *StrToTime(Time& d, const char *s)
{
return StrToTime(s_date_scan, d, s);
return StrToTime(*s_date_scan_thread ? s_date_scan_thread : s_date_scan_main, d, s);
}
Time ScanTime(const char *datefmt, const char *s, Time def)

View file

@ -52,5 +52,6 @@ void SaveLngFile(FileOut& out, int lang, int lang2 = 0);
bool LoadLngFile(const char *file);
void SetCurrentLanguage(int lang);
int GetCurrentLanguage();
void LngSetAdd(const char *id, int lang, const char *txt, bool addid);

View file

@ -81,14 +81,17 @@ function.&]
[s2; Sets formating string for dates. When used for formatting, there
are 3 integer arguments passed to [^topic`:`/`/Core`/src`/Format`$en`-us^ Format]
with this string. First is year, second is month and third is
day.&]
day. This is per`-thread setting with threads inheriting the
setting of main thread.&]
[s3; &]
[s4;%- &]
[s5;:SetDateScan`(const char`*`):%- [@(0.0.255) void]_[* SetDateScan]([@(0.0.255) const]_[@(0.0.255) c
har]_`*[*@3 scan])&]
[s2; Sets date scan string `- this string represents order of [* d]ay,
[* m]onth and [* y]ear for StrToDate function. Letters `'[* d]`', `'[* m]`'
and `'[* y]`' are used in [%-*@3 scan] to designate the order.&]
and `'[* y]`' are used in [%-*@3 scan] to designate the order. This
is per`-thread setting with threads inheriting the setting of
main thread.&]
[s2; Example:&]
[s2; [*C@3 ][*C `"mdy`"]&]
[s7; The month is first, day second and year third.&]
@ -102,11 +105,13 @@ string, letters are allowed. If there is `"A`", letters are allowed
and converted to upper`-case. After this optional character,
list of characters allowed as separator follows. `"`\r`" after
character designates `"replace`" character `- if used, all characters
up to next `"amend`" character or `'`\0`' are replaced by it.&]
up to next `"amend`" character or `'`\0`' are replaced by it.
This is per`-thread setting with threads inheriting the setting
of main thread.&]
[s2; Example:&]
[s2; [*C@3 ][*C `"a.][*C@3 `\r][*C@5 ,][*C@3 `\r][*C /][*C@3 `\r][*C@5 :;][*C `"]&]
[s2; CharFilterDate would allow letters but not convert them to uppercase,
it will allow characters `'[* .]`' and `'/`' and it will convert
`'[*@5 ,]`' to `'[* .]`' and `'[*@5 :]`' or `'[*@5 ;]`' to `'[* /]`'.&]
[s3; &]
[s0; ]
[s0; ]]

View file

@ -1,4 +1,4 @@
topic "";
topic "Utilities";
[2 $$0,0#00000000000000000000000000000000:Default]
[i448;a25;kKO9;2 $$1,0#37138531426314131252341829483380:class]
[l288;2 $$2,2#27521748481378242620020725143825:desc]
@ -25,4 +25,4 @@ ine]([_^Stream^ Stream][@(0.0.255) `&]_[*@3 s], [@(0.0.255) int]_[*@3 separator]
SV] input stream, using [%-*@3 separator] and converting from [%-*@3 charset]
to application default charset.&]
[s3; &]
[s0; ]
[s0; ]]

View file

@ -185,34 +185,88 @@ char *ZoneAlloc::Alloc(int sz)
return s;
}
int current_lang;
template<>
inline unsigned GetHashValue(const char * const &s)
{
return GetPtrHashValue(s);
}
static VectorMap<const char *, const char *>& sCurrentLangMap()
int main_current_lang;
static Index<int>& sLangIndex()
{
static VectorMap<const char *, const char *> m;
static Index<int> m;
return m;
}
static VectorMap<String, String>& sCurrentSLangMap()
static Array< VectorMap<const char *, const char *> >& sLangMap()
{
static VectorMap<String, String> m;
static Array< VectorMap<const char *, const char *> > m;
return m;
}
VectorMap<const char *, const char *> *sMainCurrentLangMapPtr;
thread__ VectorMap<const char *, const char *> *sCurrentLangMapPtr;
VectorMap<const char *, const char *>& sCurrentLangMap()
{
if(sCurrentLangMapPtr)
return *sCurrentLangMapPtr;
if(sMainCurrentLangMapPtr)
return *sMainCurrentLangMapPtr;
return sLangMap().At(0);
}
static Array< VectorMap<String, String> >& sSLangMap()
{
static Array< VectorMap<String, String> > m;
return m;
}
VectorMap<String, String> *sMainCurrentSLangMapPtr;
thread__ VectorMap<String, String> *sCurrentSLangMapPtr;
VectorMap<String, String>& sCurrentSLangMap()
{
if(sCurrentLangMapPtr)
return *sCurrentSLangMapPtr;
if(sMainCurrentSLangMapPtr)
return *sMainCurrentSLangMapPtr;
return sSLangMap().At(0);
}
thread__ int thread_current_lang;
int GetCurrentLanguage()
{
return thread_current_lang ? thread_current_lang : main_current_lang;
}
void SetCurrentLanguage(int lang)
{
{
CriticalSection::Lock __(slng);
current_lang = lang;
Single<ZoneAlloc>().Clear();
sCurrentLangMap().Clear();
sCurrentSLangMap().Clear();
thread_current_lang = lang;
int ii = sLangIndex().FindAdd(lang);
sCurrentLangMapPtr = &sLangMap().At(ii);
sCurrentSLangMapPtr = &sSLangMap().At(ii);
#ifdef _MULTITHREADED
if(Thread::IsMain())
#endif
{
main_current_lang = lang;
sMainCurrentSLangMapPtr = sCurrentSLangMapPtr;
sMainCurrentLangMapPtr = sCurrentLangMapPtr;
}
static int n = 1;
if(ii > n) { // protected against too many language/charset switches
n = 2 * n;
Single<ZoneAlloc>().Clear();
for(int i = 0; i < sLangIndex().GetCount(); i++) {
sSLangMap()[i].Clear();
sLangMap()[i].Clear();
}
}
}
SetDateFormat(t_("date-format\a%2:02d/%3:02d/%1:4d"));
SetDateScan(t_("date-scan\amdy"));
@ -225,9 +279,9 @@ const char *t_GetLngString_(const char *id)
int q = map.Find(id);
if(q >= 0)
return map[q];
const LngRec *r = sFindLngRec(id, current_lang);
const LngRec *r = sFindLngRec(id, GetCurrentLanguage());
if(r) {
int dch = GetLNGCharset(current_lang);
int dch = GetLNGCharset(GetCurrentLanguage());
if(dch == CHARSET_UTF8) {
map.Add(id, r->text);
return r->text;
@ -253,7 +307,7 @@ const char *t_GetLngString(const char *id)
String GetLngString_(int lang, const char *id)
{
if(!lang)
lang = current_lang;
lang = GetCurrentLanguage();
const LngRec *r = sFindLngRec(id, lang);
if(r) {
int dch = GetLNGCharset(lang);
@ -278,7 +332,7 @@ String GetLngString(const char *id)
int q = map.Find(id);
if(q >= 0)
return map[q];
String s = GetLngString_(current_lang, id);
String s = GetLngString_(GetCurrentLanguage(), id);
map.Add(id, s);
return s;
}