3
*************************************************************************
5
ArmageTron -- Just another Tron Lightcycle Game in 3D.
6
Copyright (C) 2000 Manuel Moos (manuel@moosnet.de)
8
**************************************************************************
10
This program is free software; you can redistribute it and/or
11
modify it under the terms of the GNU General Public License
12
as published by the Free Software Foundation; either version 2
13
of the License, or (at your option) any later version.
15
This program is distributed in the hope that it will be useful,
16
but WITHOUT ANY WARRANTY; without even the implied warranty of
17
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
GNU General Public License for more details.
20
You should have received a copy of the GNU General Public License
21
along with this program; if not, write to the Free Software
22
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
***************************************************************************
28
#include "tMemManager.h"
31
#include "tDirectories.h"
38
class tLocaleSubItem; // identifies a single string in a single language
40
static tArray<tString> st_TemplateParameters;
42
static tString s_gameName("Armagetron"); // the official name of this game
44
class tLocaleItem: public tReferencable< tLocaleItem > // idendifies a string in all languages
46
friend class tLocaleSubItem;
48
tString identifier; // the cross-language identifier of this string
49
tLocaleSubItem *items; // the versions of various languages
50
bool istemplate; // does it contain \i-directives?
53
// static void Check(); // display warnings for all strings not defined in
54
// the favorite language
56
// operator tString() const; // return the version of this string in the favorite language
57
operator const char *() const;
59
tLocaleItem(const char *identifier); // constructor taking the string identifier
62
static void Load(const char *file, bool complete = true ); // load the language definitions from a file
64
static void Clear(); // clear all locale data on program exit
66
static tLocaleItem& Find(const char *identifier); // find identifier
70
static const tLanguage* st_firstLanguage = NULL;
71
static const tLanguage* st_secondLanguage = NULL;
73
static tLanguage* st_languageAnchor = NULL;
75
typedef std::map< std::string, tJUST_CONTROLLED_PTR< tLocaleItem > > tLocaleItemMap;
77
// static tLocaleItem* st_localeAnchor = NULL;
79
static tLanguage *currentLanguage = NULL;
82
class tLocaleSubItem: public tListItem<tLocaleSubItem>
85
const tLanguage *language; // the language this string is in
86
tString translation; // the string itself
88
tLocaleSubItem(tLocaleItem *item) // adds this SubItem to item
89
: tListItem<tLocaleSubItem>(item->items){}
94
tLanguage::tLanguage(const tString& n)
95
:tListItem<tLanguage>(st_languageAnchor),
101
tLanguage* tLanguage::FirstLanguage()
103
return st_languageAnchor;
106
void tLanguage::SetFirstLanguage() const
108
st_firstLanguage = this;
112
void tLanguage::SetSecondLanguage() const
114
st_secondLanguage = this;
118
void tLanguage::Load() const
122
tLocaleItem::Load( file );
127
void tLanguage::LoadLater( char const * file ) const
129
// store name for later loading
133
tLanguage* tLanguage::Find(tString const & name )
135
tLanguage *ret = FindSloppy( name );
140
return tNEW(tLanguage(name));
143
tLanguage* tLanguage::FindStrict(tString const & name )
145
tLanguage *ret = FindSloppy( name );
150
tERR_ERROR_INT("Language " << name << " not found.");
154
tLanguage* tLanguage::FindSloppy(tString const & name )
156
tLanguage *ret = st_languageAnchor;
159
if (ret->name == name)
169
void tLocaleItem::Check()
171
tLocaleItem *run = st_localeAnchor;
174
tLocaleSubItem *r = run->items;
178
if (r->language == currentLanguage)
185
// con << "Identifier " << run->identifier << " not translated.\n";
186
con << run->identifier << "\n";
193
tLocaleItem::operator const char *() const// return the version of this string in the favorite language
195
static tLanguage * english = tLanguage::FindStrict( tString("British English") );
197
tString *first = NULL, *second = NULL, *third = NULL, *fourth = NULL;
198
const tString *ret = NULL;
200
tLocaleSubItem *run = items;
203
if (st_firstLanguage && run->language == st_firstLanguage)
204
first = &run->translation;
206
if (st_secondLanguage && run->language == st_secondLanguage)
207
second = &run->translation;
209
if (run->language == english)
210
third = &run->translation;
212
fourth = &run->translation;
226
// load english and try again
227
static bool loadEnglish = true;
243
return *ret; // no template replacements need to be made
246
const tString& temp = *ret;
247
static tString replaced;
249
for(int i = 0; i < temp.Len(); i++)
254
else if (i < temp.Len() - 1)
258
replaced << s_gameName;
262
if (index > 0 && index < 10)
263
replaced << st_TemplateParameters[index];
264
else if (temp(i+1) == '\\')
276
tLocaleItem::tLocaleItem(const char *id) // constructor taking the string identifier
277
//:tListItem<tLocaleItem>(st_localeAnchor),
278
:identifier(id), items(NULL), istemplate(false)
282
tLocaleItem::~tLocaleItem()
289
void tLocaleItem::Clear()
291
//while (st_localeAnchor)
292
// delete (st_localeAnchor);
294
while (st_languageAnchor)
295
delete (st_languageAnchor);
299
tLocaleItem& tLocaleItem::Find(const char *nn)
302
tLocaleItem *ret = st_localeAnchor;
307
if (ret->identifier == n)
313
return *tNEW(tLocaleItem(n));
315
static tLocaleItemMap st_localeMap;
317
tJUST_CONTROLLED_PTR< tLocaleItem > & ret = st_localeMap[ nn ];
320
ret = tNEW(tLocaleItem(nn));
325
static const tString LANGUAGE("language");
326
static const tString INCLUDE("include");
327
// static const tString CHECK("check");
329
void tLocaleItem::Load(const char *file, bool complete) // load the language definitions from a file
331
// bool check = false;
335
f << "language/" << file;
338
if ( tDirectories::Data().Open( s, f ) )
340
while (!s.eof() && s.good())
361
currentLanguage = tLanguage::Find(lang);
366
currentLanguage->LoadLater(file);
390
// id is a true string identifier.
391
tLocaleItem &li = Find(id);
392
tLocaleSubItem *r = li.items;
396
if (r->language == currentLanguage)
398
// r->translation.ReadLine(s);
406
r = tNEW(tLocaleSubItem)(&li);
410
// con << "Locale item " << id << " defined twice in language "
411
// << currentLanguage->Name() << ".\n";
416
r->translation.Clear();
418
for (int i=0; i< pre.Len(); i++)
423
else if (i < pre.Len()-1)
427
r->translation += '\n';
441
r->translation += '\\';
442
li.istemplate = true;
447
r->translation << "\\\\";
452
r->translation += '\\';
457
r->language = currentLanguage;
458
// r->translation.ReadLine(s);
471
class tOutputItemLocale: public tOutputItemBase
473
const tLocaleItem *element;
475
tOutputItemLocale(tOutput& o, const tLocaleItem& e);
476
virtual void Print(tString& target) const;
477
virtual void Clone(tOutput& o) const;
480
class tOutputItemSpace: public tOutputItemBase
483
tOutputItemSpace(tOutput& o);
484
virtual void Print(tString& target) const;
485
virtual void Clone(tOutput& o) const;
489
class tOutputItemTemplate: public tOutputItemBase
494
tOutputItemTemplate(tOutput& o, int n, const char *p);
495
virtual void Print(tString& target) const;
496
virtual void Clone(tOutput& o) const;
500
tOutput::tOutput(): anchor(0){}
507
void tOutput::Clear()
514
static void getstring(tString &target, tOutputItemBase *item)
518
getstring(target, item->Next());
523
tOutput::operator tString() const
527
static bool recursion = false;
530
tERR_ERROR_INT("Locale Recursion!");
538
getstring(x, anchor);
550
tOutput::operator const char *() const
554
static bool recursion = false;
557
tERR_ERROR_INT("Locale Recursion!");
563
// get a relatively safe buffer to write to
564
static const int maxstrings = 5;
565
static int current = 0;
566
static tString buffers[maxstrings];
567
tString & x = buffers[current];
568
current = ( current + 1 ) % maxstrings;
571
getstring(x, anchor);
583
void tOutput::AddLiteral(const char *x)
585
tNEW(tOutputItem<tString>)(*this, tString(x));
588
void tOutput::AddSpace()
590
tNEW(tOutputItemSpace)(*this);
593
void tOutput::AddLocale(const char *x)
595
tNEW(tOutputItemLocale)(*this, tLocale::Find(x));
599
tOutput & tOutput::SetTemplateParameter(int num, const char *parameter)
601
tNEW(tOutputItemTemplate)(*this, num, parameter);
605
tOutput & tOutput::SetTemplateParameter(int num, int parameter)
609
tNEW(tOutputItemTemplate)(*this, num, p);
614
tOutput & tOutput::SetTemplateParameter(int num, float parameter)
618
tNEW(tOutputItemTemplate)(*this, num, p);
624
tOutput::tOutput(const tString& x)
627
tNEW(tOutputItem<tString>)(*this, x);
630
tOutput::tOutput(const char * x)
637
tOutput::tOutput(const tLocaleItem &locale)
640
tNEW(tOutputItemLocale)(*this, locale);
644
static void copyrec(tOutput &targ, tOutputItemBase *it)
649
copyrec(targ, it->Next());
653
tOutput::tOutput(const tOutput &o)
656
copyrec(*this, o.anchor);
659
tOutput& tOutput::operator=(const tOutput &o)
663
copyrec(*this, o.anchor);
668
void tOutput::Append(const tOutput &o)
670
copyrec(*this, o.anchor);
674
tOutputItemBase::tOutputItemBase(tOutput& o): tListItem<tOutputItemBase>(o.anchor){}
676
tOutputItemBase::~tOutputItemBase(){}
680
tOutputItemLocale::tOutputItemLocale(tOutput& o, const tLocaleItem& e)
686
void tOutputItemLocale::Print(tString& target) const
691
void tOutputItemLocale::Clone(tOutput& o) const
693
tNEW(tOutputItemLocale)(o, *element);
697
tOutputItemSpace::tOutputItemSpace(tOutput& o)
701
void tOutputItemSpace::Print(tString& target) const
706
void tOutputItemSpace::Clone(tOutput& o) const
708
tNEW(tOutputItemSpace)(o);
712
tOutputItemTemplate::tOutputItemTemplate(tOutput& o, int n, const char *p)
713
:tOutputItemBase(o), num(n), parameter(p)
716
void tOutputItemTemplate::Print(tString& target) const
718
st_TemplateParameters[num] = parameter;
721
void tOutputItemTemplate::Clone(tOutput& o) const
723
tNEW(tOutputItemTemplate)(o, num, parameter);
727
tOutput& operator << (tOutput &o, char *locale)
729
return operator<<(o, static_cast<const char *>(locale));
732
// and a special implementation for the locales and strings:
733
tOutput& operator << (tOutput &o, const char *locale){
734
int len = strlen(locale);
737
if (len == 1 && locale[0] == ' ')
738
tNEW(tOutputItemSpace)(o);
739
else if (locale[0] == '$')
740
tNEW(tOutputItemLocale)(o, tLocale::Find(locale+1));
742
tNEW(tOutputItem<tString>)(o, tString(locale));
748
std::ostream& operator<< (std::ostream& s, const tOutput& o)
750
return s << tString(o);
754
std::stringstream& operator<< (std::stringstream& s, const tOutput& o)
756
static_cast<std::ostream&>(s) << static_cast<const char *>(o);
761
tString& operator<< (tString& s, const tOutput& o)
769
// interface class for locale items
770
const tLocaleItem& tLocale::Find(const char* id)
772
return tLocaleItem::Find(id);
775
void tLocale::Load(const char* filename)
777
tLocaleItem::Load(filename, false);
779
// determine the name of the game
781
s_gameName << tOutput("$game_name");
784
void tLocale::Clear()
786
tLocaleItem::Clear();
790
std::stringstream& operator<<(std::stringstream& s, const tLocaleItem &t)
792
static_cast<std::ostream&>(s) << static_cast<const char*>(t);
797
std::ostream& operator<<(std::ostream& s, const tLocaleItem &t)
799
return s << static_cast<const char*>(t);
802
tString& operator<< (tString& s, const tLocaleItem& o)
804
s << static_cast<const char *>(o);