1
2
3 #include "tw/stringtable.h"
4 // #include "tw/message.h"
5 //#include "tfilepath.h"
6 #include "tfilepath_io.h"
7 #include "tenv.h"
8 //#include "texception.h"
9 #include "tsystem.h"
10 #include "tstream.h"
11 #include "tconvert.h"
12
13 namespace {
14
15 //-------------------------------------------------------------------
16
17 class TStringTableImp final : public TStringTable {
18 public:
19 bool m_initialized;
20
21 std::map<std::string, Item> m_table;
22 std::pair<std::string, int> m_defaultFontNameAndSize;
23 std::string m_defaultMacFontName;
24
25 TStringTableImp();
26 ~TStringTableImp();
27
28 void init();
29
30 void load(const TFilePath &);
31
32 void loadCoded(const TFilePath &);
33 void saveCoded(const TFilePath &);
34
35 const Item *getItem(std::string name) const override;
getDefaultFontNameAndSize() const36 std::pair<std::string, int> getDefaultFontNameAndSize() const override {
37 return m_defaultFontNameAndSize;
38 }
39 std::string getDefaultMacFontName() const override;
40 };
41
42 //-------------------------------------------------------------------
43
TStringTableImp()44 TStringTableImp::TStringTableImp()
45 : m_initialized(false)
46 , m_defaultFontNameAndSize("", 0)
47 , m_defaultMacFontName("") {}
48
49 //-------------------------------------------------------------------
50
~TStringTableImp()51 TStringTableImp::~TStringTableImp() {}
52
53 //-------------------------------------------------------------------
54
init()55 void TStringTableImp::init() {
56 if (m_initialized) return;
57
58 m_initialized = true;
59
60 TFilePath plainFp = TEnv::getConfigDir() + "current.txt";
61
62 try {
63 load(plainFp);
64 } catch (...) {
65 }
66 }
67
68 //-------------------------------------------------------------------
69
getDefaultMacFontName() const70 std::string TStringTableImp::getDefaultMacFontName() const {
71 return m_defaultMacFontName;
72 }
73
74 //-------------------------------------------------------------------
75
writeShort(Tofstream & os,int x)76 void writeShort(Tofstream &os, int x) {
77 os.put(x & 0xff);
78 os.put((x >> 8) & 0xff);
79 }
80
81 //-------------------------------------------------------------------
82
readShort(Tifstream & is)83 int readShort(Tifstream &is) {
84 char hi = 0, lo = 0;
85 is.get(lo);
86 is.get(hi);
87 return (unsigned char)hi << 8 | (unsigned char)lo;
88 }
89
90 //-------------------------------------------------------------------
91
writeString(Tofstream & os,std::string s)92 void writeString(Tofstream &os, std::string s) {
93 int len = s.length();
94 writeShort(os, len);
95 os.write(s.c_str(), len);
96 if (len & 0x3) {
97 os.write("____", 4 - (len & 0x3));
98 }
99 }
100
101 //-------------------------------------------------------------------
102
readString(Tifstream & is)103 std::string readString(Tifstream &is) {
104 int len = readShort(is);
105 int len2 = len;
106 if (len2 & 0x3) len2 += 4 - (len2 & 0x3);
107 char buffer[1204];
108 assert(len2 <= (int)(sizeof(buffer)));
109 is.read(buffer, len2);
110 return std::string(buffer, len);
111 }
112
113 //-------------------------------------------------------------------
114
writeStringW(Tofstream & os,std::wstring s)115 void writeStringW(Tofstream &os, std::wstring s) {
116 int len = s.length();
117 writeShort(os, len);
118 os.write(reinterpret_cast<const char *>(s.c_str()), sizeof(wchar_t) * len);
119 }
120
121 //-------------------------------------------------------------------
122
readStringW(Tifstream & is)123 std::wstring readStringW(Tifstream &is) {
124 int len = readShort(is);
125 wchar_t buffer[1204];
126 assert(len <= (int)(sizeof(buffer)));
127 is.read(reinterpret_cast<char *>(buffer), sizeof(wchar_t) * len);
128 return std::wstring(buffer, len);
129 }
130
131 //-------------------------------------------------------------------
132 #ifdef MACOSX
133 class TMagic // singleton
134 {
135 public:
136 std::string m_magic;
137
138 private:
TMagic()139 TMagic() : m_magic("stab.001") {}
140
141 public:
instance()142 static TMagic *instance() {
143 static TMagic inst;
144 ;
145 return &inst;
146 }
147 };
148
149 #else
150 const std::string magic = "stab.001";
151 #endif
152
loadCoded(const TFilePath & fp)153 void TStringTableImp::loadCoded(const TFilePath &fp) {
154 try {
155 Tifstream is(fp);
156 char buffer[1024];
157
158 #ifdef MACOSX
159 is.read(buffer, TMagic::instance()->m_magic.length());
160 #else
161 is.read(buffer, magic.length());
162 #endif
163
164 m_defaultFontNameAndSize.first = readString(is);
165 m_defaultFontNameAndSize.second = readShort(is);
166 int count = readShort(is);
167 for (int i = 0; i < count; i++) {
168 int m = readShort(is);
169 assert(1 <= m && m <= 3);
170 std::string id = readString(is);
171 Item &item = m_table[id];
172 item.m_name = readStringW(is);
173 if (m >= 2) {
174 item.m_help = readStringW(is);
175 if (m == 3) item.m_tip = readStringW(is);
176 }
177 }
178 int check = readShort(is);
179 assert(check == 12345);
180 // if(check != 12345)
181 // throw;
182 } catch (...) {
183 // TMessage::error("Error reading StringTable file: ", fp);
184 }
185 }
186
187 //-------------------------------------------------------------------
188
189 /*
190 void TStringTableImp::saveCoded(const TFilePath &fp)
191 {
192 try {
193 Tofstream os(fp);
194
195 #ifdef MACOSX
196 os.write(TMagic::instance()->m_magic.c_str(),
197 TMagic::instance()->m_magic.length());
198 #else
199 os.write(magic.c_str(), magic.length());
200 #endif
201 writeString(os, m_defaultFontNameAndSize.first);
202 writeShort(os, m_defaultFontNameAndSize.second);
203 writeShort(os, m_table.size());
204 for(std::map<std::string, Item>::iterator it = m_table.begin();
205 it != m_table.end(); ++it)
206 {
207 Item &item = it->second;
208 int m = 1;
209 if(item.m_tip != L"") m = 3;
210 else if(item.m_help != L"") m = 2;
211 writeShort(os, m);
212 writeString(os, it->first);
213 writeStringW(os, item.m_name);
214 if(m>=2)
215 {
216 writeStringW(os, item.m_help);
217 if(m==3)
218 writeStringW(os, item.m_tip);
219 }
220 }
221 writeShort(os, 12345);
222 } catch(...) {
223 TMessage::error("Unable to save StringTable file: ", fp);
224 }
225 }
226 */
227 //-------------------------------------------------------------------
228
load(const TFilePath & fp)229 void TStringTableImp::load(const TFilePath &fp) {
230 if (!TFileStatus(fp).doesExist()) throw TException("file not found");
231
232 TIStream is(fp);
233 if (!is) throw TException("can't read string table ");
234
235 std::string tagName;
236 if (!is.matchTag(tagName) || tagName != "stringtable")
237 throw TException("not a string table file");
238
239 while (!is.matchEndTag()) {
240 if (!is.matchTag(tagName)) throw TException("expected tag");
241 if (tagName == "item") {
242 std::string id, name, help, tip;
243 is >> id >> name;
244 if (!is.matchEndTag()) {
245 is >> help;
246 if (!is.matchEndTag()) {
247 is >> tip;
248 if (!is.matchEndTag()) throw TException("Expected end tag");
249 }
250 }
251 Item &item = m_table[id];
252 item.m_name = ::to_wstring(name);
253 item.m_help = ::to_wstring(help);
254 item.m_tip = ::to_wstring(tip);
255 } else if (tagName == "defaultFont") {
256 std::string fontName;
257 int fontSize = 0;
258 is >> fontName >> fontSize;
259 if (!is.matchEndTag()) throw TException("Expected end tag");
260 m_defaultFontNameAndSize = std::make_pair(fontName, fontSize);
261 } else if (tagName == "defaultMacFont") {
262 std::string macFontName;
263 is >> macFontName;
264 if (!is.matchEndTag()) throw TException("Expected end tag");
265 m_defaultMacFontName = macFontName;
266 } else
267 throw TException("unexpected tag /" + tagName + "/");
268 }
269 // m_valid =true;
270 }
271
272 //-------------------------------------------------------------------
273
getItem(std::string name) const274 const TStringTable::Item *TStringTableImp::getItem(std::string name) const {
275 std::map<std::string, Item>::const_iterator it;
276 it = m_table.find(name);
277 if (it == m_table.end())
278 return 0;
279 else
280 return &(it->second);
281 }
282
283 //-------------------------------------------------------------------
284
285 } // namespace
286
287 //-------------------------------------------------------------------
288
TStringTable()289 TStringTable::TStringTable() {}
290
291 //-------------------------------------------------------------------
292
~TStringTable()293 TStringTable::~TStringTable() {}
294
295 //-------------------------------------------------------------------
296
translate(std::string name)297 std::wstring TStringTable::translate(std::string name) {
298 const TStringTable::Item *item = instance()->getItem(name);
299 if (item)
300 return item->m_name;
301 else
302 return ::to_wstring(name);
303 }
304
305 //-------------------------------------------------------------------
306
instance()307 const TStringTable *TStringTable::instance() {
308 // may hurt MacOsX
309 static TStringTableImp *instance = 0;
310 if (!instance) instance = new TStringTableImp;
311
312 instance->init();
313
314 return instance;
315 }
316