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