From 3e1fa2490c3857e7fa9fae43078f587696a37451 Mon Sep 17 00:00:00 2001 From: cxl Date: Tue, 19 Jun 2012 20:43:55 +0000 Subject: [PATCH] Core: Language settings are now per-thread git-svn-id: svn://ultimatepp.org/upp/trunk@5061 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/Core/Lang.cpp | 10 +--- uppsrc/Core/TimeDate.cpp | 64 +++++++++++++-------- uppsrc/Core/i18n.h | 1 + uppsrc/Core/src.tpp/DateFmt$en-us.tpp | 13 +++-- uppsrc/Core/src.tpp/Util$en-us.tpp | 4 +- uppsrc/Core/t.cpp | 82 ++++++++++++++++++++++----- 6 files changed, 120 insertions(+), 54 deletions(-) diff --git a/uppsrc/Core/Lang.cpp b/uppsrc/Core/Lang.cpp index 46210a9fa..d936d2c28 100644 --- a/uppsrc/Core/Lang.cpp +++ b/uppsrc/Core/Lang.cpp @@ -148,17 +148,9 @@ Convert& LNGConvert() return Single(); } -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); } diff --git a/uppsrc/Core/TimeDate.cpp b/uppsrc/Core/TimeDate.cpp index c2f4a35f1..da94dbed3 100644 --- a/uppsrc/Core/TimeDate.cpp +++ b/uppsrc/Core/TimeDate.cpp @@ -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) diff --git a/uppsrc/Core/i18n.h b/uppsrc/Core/i18n.h index 154fa3c66..1e9c1c213 100644 --- a/uppsrc/Core/i18n.h +++ b/uppsrc/Core/i18n.h @@ -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); diff --git a/uppsrc/Core/src.tpp/DateFmt$en-us.tpp b/uppsrc/Core/src.tpp/DateFmt$en-us.tpp index 687f562c0..b916f5755 100644 --- a/uppsrc/Core/src.tpp/DateFmt$en-us.tpp +++ b/uppsrc/Core/src.tpp/DateFmt$en-us.tpp @@ -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; ] \ No newline at end of file +[s0; ]] \ No newline at end of file diff --git a/uppsrc/Core/src.tpp/Util$en-us.tpp b/uppsrc/Core/src.tpp/Util$en-us.tpp index 448aba9d1..625476b75 100644 --- a/uppsrc/Core/src.tpp/Util$en-us.tpp +++ b/uppsrc/Core/src.tpp/Util$en-us.tpp @@ -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; ] \ No newline at end of file +[s0; ]] \ No newline at end of file diff --git a/uppsrc/Core/t.cpp b/uppsrc/Core/t.cpp index 601267de3..4458883a0 100644 --- a/uppsrc/Core/t.cpp +++ b/uppsrc/Core/t.cpp @@ -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& sCurrentLangMap() +int main_current_lang; + +static Index& sLangIndex() { - static VectorMap m; + static Index m; return m; } -static VectorMap& sCurrentSLangMap() +static Array< VectorMap >& sLangMap() { - static VectorMap m; + static Array< VectorMap > m; return m; } +VectorMap *sMainCurrentLangMapPtr; +thread__ VectorMap *sCurrentLangMapPtr; + +VectorMap& sCurrentLangMap() +{ + if(sCurrentLangMapPtr) + return *sCurrentLangMapPtr; + if(sMainCurrentLangMapPtr) + return *sMainCurrentLangMapPtr; + return sLangMap().At(0); +} + +static Array< VectorMap >& sSLangMap() +{ + static Array< VectorMap > m; + return m; +} + +VectorMap *sMainCurrentSLangMapPtr; +thread__ VectorMap *sCurrentSLangMapPtr; + +VectorMap& 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().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().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; }