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