mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
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:
parent
101a8c470b
commit
3e1fa2490c
6 changed files with 120 additions and 54 deletions
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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; ]]
|
||||
|
|
@ -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; ]]
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue