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