]> git.lyx.org Git - lyx.git/blob - src/trans.C
remove redundant lyxerr.debugging checks; macro LYXERR already checks whether the...
[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_type c,
52                             docstring 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, docstring const & keys)
111 {
112         KmodInfo tmp;
113         tmp.data = keys;
114         tmp.accent = accent;
115         kmod_list_[accent] = tmp;
116
117         for (docstring::size_type i = 0; i < keys.length(); ++i) {
118                 // FIXME This is a hack.
119                 // tmp is no valid UCS4 string, but misused to store the
120                 // accent.
121                 docstring tmp;
122                 tmp += char_type(0);
123                 tmp += char_type(accent);
124                 keymap_[keys[i]] = tmp;
125         }
126 }
127
128
129 int Trans::load(LyXLex & lex)
130 {
131         bool error = false;
132
133         while (lex.isOK() && !error) {
134                 switch (lex.lex()) {
135                 case KMOD:
136                 {
137                         if (lyxerr.debugging(Debug::KBMAP))
138                                 lyxerr << "KMOD:\t" << lex.getString() << endl;
139                         if (lex.next(true)) {
140                                 if (lyxerr.debugging(Debug::KBMAP))
141                                         lyxerr << "key\t`" << lex.getString()
142                                                << '\'' << endl;
143                         } else
144                                 return -1;
145
146                         docstring const keys = lex.getDocString();
147
148                         if (lex.next(true)) {
149                                 if (lyxerr.debugging(Debug::KBMAP))
150                                         lyxerr << "accent\t`" << lex.getString()
151                                                << '\'' << endl;
152                         } else
153                                 return -1;
154
155                         tex_accent accent = getkeymod(lex.getString());
156
157                         if (accent == TEX_NOACCENT)
158                                 return -1;
159
160 #if 1
161 //#warning This code should be removed...
162                         // But we need to fix up all the kmap files first
163                         // so that this field is not present anymore.
164                         if (lex.next(true)) {
165                                 if (lyxerr.debugging(Debug::KBMAP))
166                                         lyxerr << "allowed\t`" << lex.getString()
167                                                << '\'' << endl;
168                         } else
169                                 return -1;
170
171                         /* string const allowed = lex.getString(); */
172                         addDeadkey(accent, keys /*, allowed*/);
173 #else
174                         addDeadkey(accent, keys);
175 #endif
176                         break;
177                 }
178                 case KCOMB: {
179                         string str;
180
181                         LYXERR(Debug::KBMAP) << "KCOMB:" << endl;
182                         if (lex.next(true)) {
183                                 str = lex.getString();
184                                 LYXERR(Debug::KBMAP) << str << endl;
185                         } else
186                                 return -1;
187
188                         tex_accent accent_1 = getkeymod(str);
189                         if (accent_1 == TEX_NOACCENT) return -1;
190
191                         if (lex.next(true)) {
192                                 str = lex.getString();
193                                 LYXERR(Debug::KBMAP) << str << endl;
194                         } else
195                                 return -1;
196
197                         tex_accent accent_2= getkeymod(str);
198                         if (accent_2 == TEX_NOACCENT) return -1;
199
200                         map<tex_accent, KmodInfo>::iterator it1 =
201                                 kmod_list_.find(accent_1);
202                         map<tex_accent, KmodInfo>::iterator it2 =
203                                 kmod_list_.find(accent_2);
204                         if (it1 == kmod_list_.end()
205                             || it2 == kmod_list_.end()) {
206                                 return -1;
207                         }
208
209                         // Find what key accent_2 is on - should
210                         // check about accent_1 also
211                         map<char_type, docstring>::iterator it = keymap_.begin();
212                         map<char_type, docstring>::iterator end = keymap_.end();
213                         for (; it != end; ++it) {
214                                 if (!it->second.empty()
215                                     && it->second[0] == 0
216                                     && it->second[1] == accent_2)
217                                         break;
218                         }
219                         docstring allowed;
220                         if (lex.next()) {
221                                 allowed = lex.getDocString();
222                                 LYXERR(Debug::KBMAP) << "allowed: "
223                                                      << to_utf8(allowed) << endl;
224                         } else {
225                                 return -1;
226                         }
227
228                         insertException(kmod_list_[accent_1].exception_list,
229                                         it->first, allowed,
230                                         true, accent_2);
231                 }
232                 break;
233                 case KMAP: {
234                         unsigned char key_from;
235
236                         if (lyxerr.debugging(Debug::KBMAP))
237                                 lyxerr << "KMAP:\t" << lex.getString() << endl;
238                         if (lex.next(true)) {
239                                 key_from = lex.getString()[0];
240                                 if (lyxerr.debugging(Debug::KBMAP))
241                                         lyxerr << "\t`" << lex.getString() << '\''
242                                                << endl;
243                         } else
244                                 return -1;
245
246                         if (lex.next(true)) {
247                                 docstring const string_to = lex.getDocString();
248                                 keymap_[key_from] = string_to;
249                                 if (lyxerr.debugging(Debug::KBMAP))
250                                         lyxerr << "\t`" << to_utf8(string_to) << '\''
251                                                << endl;
252                         } else
253                                 return -1;
254
255                         break;
256                 }
257                 case KXMOD: {
258                         tex_accent accent;
259                         char_type key;
260                         docstring str;
261
262                         if (lyxerr.debugging(Debug::KBMAP))
263                                 lyxerr << "KXMOD:\t" << lex.getString() << endl;
264                         if (lex.next(true)) {
265                                 if (lyxerr.debugging(Debug::KBMAP))
266                                         lyxerr << "\t`" << lex.getString() << '\''
267                                                << endl;
268                                 accent = getkeymod(lex.getString());
269                         } else
270                                 return -1;
271
272                         if (lex.next(true)) {
273                                 if (lyxerr.debugging(Debug::KBMAP))
274                                         lyxerr << "\t`" << lex.getString() << '\''
275                                                << endl;
276                                 key = lex.getDocString()[0];
277                         } else
278                                 return -1;
279
280                         if (lex.next(true)) {
281                                 if (lyxerr.debugging(Debug::KBMAP))
282                                         lyxerr << "\t`" << lex.getString() << '\''
283                                                << endl;
284                                 str = lex.getDocString();
285                         } else
286                                 return -1;
287
288                         insertException(kmod_list_[accent].exception_list,
289                                         key, str);
290                         break;
291                 }
292                 case LyXLex::LEX_FEOF:
293                         LYXERR(Debug::PARSER) << "End of parsing" << endl;
294                         break;
295                 default:
296                         lex.printError("ParseKeymapFile: "
297                                        "Unknown tag: `$$Token'");
298                         return -1;
299                 }
300         }
301         return 0;
302 }
303
304
305 bool Trans::isAccentDefined(tex_accent accent, KmodInfo & i) const
306 {
307         map<tex_accent, KmodInfo>::const_iterator cit = kmod_list_.find(accent);
308         if (cit != kmod_list_.end()) {
309                 i = cit->second;
310                 return true;
311         }
312         return false;
313 }
314
315
316 docstring const Trans::process(char_type c, TransManager & k)
317 {
318         docstring const t = match(c);
319
320         if (t.empty() && c != 0) {
321                 return k.normalkey(c);
322         } else if (!t.empty() && t[0] != 0) {
323                 //return k.normalkey(c);
324                 return t;
325         } else {
326                 return k.deadkey(c,
327                                  kmod_list_[static_cast<tex_accent>(t[1])]);
328         }
329 }
330
331
332 int Trans::load(string const & language)
333 {
334         support::FileName const filename = libFileSearch("kbd", language, "kmap");
335         if (filename.empty())
336                 return -1;
337
338         freeKeymap();
339         LyXLex lex(kmapTags, K_LAST - 1);
340         lex.setFile(filename);
341
342         int const res = load(lex);
343
344         if (res == 0) {
345                 name_ = language;
346         } else
347                 name_.erase();
348
349         return res;
350 }
351
352
353 tex_accent getkeymod(string const & p)
354         /* return modifier - decoded from p and update p */
355 {
356         for (int i = 1; i <= TEX_MAX_ACCENT; ++i) {
357                 if (lyxerr.debugging(Debug::KBMAP))
358                         lyxerr << "p = " << p
359                                << ", lyx_accent_table[" << i
360                                << "].name = `" << lyx_accent_table[i].name
361                                << '\'' << endl;
362
363                 if (lyx_accent_table[i].name
364                      && contains(p, lyx_accent_table[i].name)) {
365                         LYXERR(Debug::KBMAP) << "Found it!" << endl;
366                         return static_cast<tex_accent>(i);
367                 }
368         }
369         return TEX_NOACCENT;
370 }
371
372
373 } // namespace lyx