]> git.lyx.org Git - lyx.git/blob - src/trans.C
introduce namespace lyx::support
[lyx.git] / src / trans.C
1 #include <config.h>
2
3 #include "trans.h"
4 #include "support/filetools.h"
5 #include "support/lstrings.h"
6 #include "tex-strings.h"
7 #include "lyxlex.h"
8 #include "debug.h"
9 #include "trans_mgr.h"
10
11 using namespace lyx::support;
12
13 using std::map;
14 using std::endl;
15
16
17 // KmodInfo
18 KmodInfo::KmodInfo()
19 {
20 }
21
22
23 // Trans class
24
25 Trans::Trans()
26 {
27 }
28
29
30 Trans::~Trans()
31 {
32         FreeKeymap();
33 }
34
35
36 void Trans::InsertException(KmodException & exclist, char c,
37                             string const & data, bool flag, tex_accent accent)
38 {
39         Keyexc p;
40         p.c = c;
41         p.data = data;
42         p.combined = flag;
43         p.accent = accent;
44         exclist.insert(exclist.begin(), p);
45         // or just
46         // exclist.push_back(p);
47 }
48
49
50 void Trans::FreeException(KmodException & exclist)
51 {
52         exclist.clear();
53 }
54
55
56 void Trans::FreeKeymap()
57 {
58         kmod_list_.clear();
59         keymap_.clear();
60 }
61
62
63 bool Trans::IsDefined() const
64 {
65         return !name_.empty();
66 }
67
68
69 string const & Trans::GetName() const
70 {
71         return name_;
72 }
73
74
75 enum kmaptags_ {
76         KCOMB = 1,
77         KMOD,
78         KMAP,
79         KXMOD,
80         K_LAST
81 };
82
83
84 struct keyword_item kmapTags[K_LAST - 1] = {
85         {"\\kcomb", KCOMB },
86         { "\\kmap", KMAP },
87         { "\\kmod", KMOD },
88         { "\\kxmod", KXMOD }
89 };
90
91
92 tex_accent getkeymod(string const &);
93
94
95 void Trans::AddDeadkey(tex_accent accent, string const & keys)
96 {
97         KmodInfo tmp;
98         tmp.data = keys;
99         tmp.accent = accent;
100         kmod_list_[accent] = tmp;
101
102         for (string::size_type i = 0; i < keys.length(); ++i) {
103                 string tmp;
104                 tmp += char(0);
105                 tmp += char(accent);
106                 keymap_[keys[i]] = tmp;
107         }
108 }
109
110
111 int Trans::Load(LyXLex & lex)
112 {
113         bool error = false;
114
115         while (lex.isOK() && !error) {
116                 switch (lex.lex()) {
117                 case KMOD:
118                 {
119                         if (lyxerr.debugging(Debug::KBMAP))
120                                 lyxerr << "KMOD:\t" << lex.getString() << endl;
121                         if (lex.next(true)) {
122                                 if (lyxerr.debugging(Debug::KBMAP))
123                                         lyxerr << "key\t`" << lex.getString()
124                                                << '\'' << endl;
125                         } else
126                                 return -1;
127
128                         string const keys = lex.getString();
129
130                         if (lex.next(true)) {
131                                 if (lyxerr.debugging(Debug::KBMAP))
132                                         lyxerr << "accent\t`" << lex.getString()
133                                                << '\'' << endl;
134                         } else
135                                 return -1;
136
137                         tex_accent accent = getkeymod(lex.getString());
138
139                         if (accent == TEX_NOACCENT)
140                                 return -1;
141
142 #if 1
143 //#warning This code should be removed...
144                         // But we need to fix up all the kmap files first
145                         // so that this field is not present anymore.
146                         if (lex.next(true)) {
147                                 if (lyxerr.debugging(Debug::KBMAP))
148                                         lyxerr << "allowed\t`" << lex.getString()
149                                                << '\'' << endl;
150                         } else
151                                 return -1;
152
153                         /* string const allowed = lex.getString(); */
154                         AddDeadkey(accent, keys /*, allowed*/);
155 #else
156                         AddDeadkey(accent, keys);
157 #endif
158                         break;
159                 }
160                 case KCOMB: {
161                         string str;
162
163                         lyxerr[Debug::KBMAP] << "KCOMB:" << endl;
164                         if (lex.next(true)) {
165                                 str = lex.getString();
166                                 lyxerr[Debug::KBMAP] << str << endl;
167                         } else
168                                 return -1;
169
170                         tex_accent accent_1 = getkeymod(str);
171                         if (accent_1 == TEX_NOACCENT) return -1;
172
173                         if (lex.next(true)) {
174                                 str = lex.getString();
175                                 lyxerr[Debug::KBMAP] << str << endl;
176                         } else
177                                 return -1;
178
179                         tex_accent accent_2= getkeymod(str);
180                         if (accent_2 == TEX_NOACCENT) return -1;
181
182                         map<int, KmodInfo>::iterator it1 =
183                                 kmod_list_.find(accent_1);
184                         map<int, KmodInfo>::iterator it2 =
185                                 kmod_list_.find(accent_2);
186                         if (it1 == kmod_list_.end()
187                             || it2 == kmod_list_.end()) {
188                                 return -1;
189                         }
190
191                         // Find what key accent_2 is on - should
192                         // check about accent_1 also
193                         map<int, string>::iterator it = keymap_.begin();
194                         map<int, string>::iterator end = keymap_.end();
195                         for (; it != end; ++it) {
196                                 if (!it->second.empty()
197                                     && it->second[0] == 0
198                                     && it->second[1] == accent_2)
199                                         break;
200                         }
201                         string allowed;
202                         if (lex.next()) {
203                                 allowed = lex.getString();
204                                 lyxerr[Debug::KBMAP] << "allowed: "
205                                                      << allowed << endl;
206                         } else {
207                                 return -1;
208                         }
209
210                         InsertException(kmod_list_[accent_1].exception_list,
211                                         static_cast<char>(it->first), allowed,
212                                         true, accent_2);
213                 }
214                 break;
215                 case KMAP: {
216                         unsigned char key_from;
217
218                         if (lyxerr.debugging(Debug::KBMAP))
219                                 lyxerr << "KMAP:\t" << lex.getString() << endl;
220                         if (lex.next(true)) {
221                                 key_from = lex.getString()[0];
222                                 if (lyxerr.debugging(Debug::KBMAP))
223                                         lyxerr << "\t`" << lex.getString() << '\''
224                                                << endl;
225                         } else
226                                 return -1;
227
228                         if (lex.next(true)) {
229                                 string const string_to = lex.getString();
230                                 keymap_[key_from] = string_to;
231                                 if (lyxerr.debugging(Debug::KBMAP))
232                                         lyxerr << "\t`" << string_to << '\''
233                                                << endl;
234                         } else
235                                 return -1;
236
237                         break;
238                 }
239                 case KXMOD: {
240                         tex_accent accent;
241                         char key;
242                         string str;
243
244                         if (lyxerr.debugging(Debug::KBMAP))
245                                 lyxerr << "KXMOD:\t" << lex.getString() << endl;
246                         if (lex.next(true)) {
247                                 if (lyxerr.debugging(Debug::KBMAP))
248                                         lyxerr << "\t`" << lex.getString() << '\''
249                                                << endl;
250                                 accent = getkeymod(lex.getString());
251                         } else
252                                 return -1;
253
254                         if (lex.next(true)) {
255                                 if (lyxerr.debugging(Debug::KBMAP))
256                                         lyxerr << "\t`" << lex.getString() << '\''
257                                                << endl;
258                                 key = lex.getString()[0];
259                         } else
260                                 return -1;
261
262                         if (lex.next(true)) {
263                                 if (lyxerr.debugging(Debug::KBMAP))
264                                         lyxerr << "\t`" << lex.getString() << '\''
265                                                << endl;
266                                 str = lex.getString();
267                         } else
268                                 return -1;
269
270                         InsertException(kmod_list_[accent].exception_list,
271                                         key, str);
272                         break;
273                 }
274                 case LyXLex::LEX_FEOF:
275                         lyxerr[Debug::PARSER] << "End of parsing" << endl;
276                         break;
277                 default:
278                         lex.printError("ParseKeymapFile: "
279                                        "Unknown tag: `$$Token'");
280                         return -1;
281                 }
282         }
283         return 0;
284 }
285
286
287 bool Trans::isAccentDefined(tex_accent accent, KmodInfo & i) const
288 {
289         map<int, KmodInfo>::const_iterator cit = kmod_list_.find(accent);
290         if (cit != kmod_list_.end()) {
291                 i = cit->second;
292                 return true;
293         }
294         return false;
295 }
296
297
298 string const Trans::process(char c, TransManager & k)
299 {
300         string const t = Match(static_cast<unsigned char>(c));
301
302         if (t.empty() && c != 0) {
303                 return k.normalkey(c);
304         } else if (!t.empty() && t[0] != char(0)) {
305                 //return k.normalkey(c);
306                 return t;
307         } else {
308                 return k.deadkey(c,
309                                  kmod_list_[static_cast<tex_accent>(t[1])]);
310         }
311 }
312
313
314 int Trans::Load(string const & language)
315 {
316         string const filename = LibFileSearch("kbd", language, "kmap");
317         if (filename.empty())
318                 return -1;
319
320         FreeKeymap();
321         LyXLex lex(kmapTags, K_LAST - 1);
322         lex.setFile(filename);
323
324         int const res = Load(lex);
325
326         if (res == 0) {
327                 name_ = language;
328         } else
329                 name_.erase();
330
331         return res;
332 }
333
334
335 tex_accent getkeymod(string const & p)
336         /* return modifier - decoded from p and update p */
337 {
338         for (int i = 1; i <= TEX_MAX_ACCENT; ++i) {
339                 if (lyxerr.debugging(Debug::KBMAP))
340                         lyxerr << "p = " << p
341                                << ", lyx_accent_table[" << i
342                                << "].name = `" << lyx_accent_table[i].name
343                                << '\'' << endl;
344
345                 if (lyx_accent_table[i].name
346                      && contains(p, lyx_accent_table[i].name)) {
347                         lyxerr[Debug::KBMAP] << "Found it!" << endl;
348                         return static_cast<tex_accent>(i);
349                 }
350         }
351         return TEX_NOACCENT;
352 }