]> git.lyx.org Git - lyx.git/blob - src/kbmap.C
fix drawing of double quotes; fix input of cyrillic and greek characters
[lyx.git] / src / kbmap.C
1 /**
2  * \file kbmap.C
3  * Copyright 1995-2002 the LyX Team
4  * Read the file COPYING
5  *
6  * \author unknown
7  * \author John Levon <moz@compsoc.man.ac.uk>
8  */
9
10 #include <config.h>
11
12 #ifdef __GNUG__
13 #pragma implementation
14 #endif
15
16 #include "kbmap.h"
17 #include "commandtags.h"
18 #include "kbsequence.h"
19 #include "debug.h"
20
21 #include <X11/Xlib.h>
22
23 using std::endl;
24
25 // The only modifiers that we handle. We want to throw away things
26 // like NumLock.
27 enum { ModsMask = ShiftMask | ControlMask | Mod1Mask };
28
29
30 string const kb_keymap::printKeysym(unsigned int key, key_modifier::state mod)
31 {
32         string buf;
33
34         char const * const s = XKeysymToString(key);
35
36         if (mod & key_modifier::shift) buf += "S-";
37         if (mod & key_modifier::ctrl) buf += "C-";
38         if (mod & key_modifier::alt) buf += "M-";
39         if (s) buf += s;
40         return buf;
41 }
42
43
44 char kb_keymap::getiso(unsigned int c)
45 {
46         switch (c & 0x0000FF00) {
47                 // latin 1 byte 3 = 0
48         case 0x00000000: break;
49                 // latin 2 byte 3 = 1
50         case 0x00000100:
51                 // latin 3 byte 3 = 2
52         case 0x00000200:
53                 // latin 4 byte 3 = 3
54         case 0x00000300:
55                 // cyrillic KOI8 & Co
56         case 0x00000600:
57                 // greek
58         case 0x00000700:
59                 // latin 8 byte 3 = 18 (0x12)
60         case 0x00001200:
61                 // latin 9 byte 3 = 19 (0x13)
62         case 0x00001300:
63                 c &= 0x000000FF;
64                 break;
65         default:
66                 c = 0;
67         }
68         return c;
69 }
70
71 string const kb_keymap::printKey(kb_key const & key) const
72 {
73         return printKeysym(key.code, key.mod.first);
74 }
75
76
77 string::size_type kb_keymap::bind(string const & seq, int action)
78 {
79         if (lyxerr.debugging(Debug::KBMAP)) {
80                 lyxerr << "BIND: Sequence `"
81                        << seq << "' Action `"
82                        << action << "'" << endl;
83         }
84
85         kb_sequence k(0, 0);
86
87         string::size_type const res = k.parse(seq);
88         if (res == string::npos) {
89                 defkey(&k, action);
90         } else {
91                 lyxerr[Debug::KBMAP] << "Parse error at position " << res
92                                      << " in key sequence '" << seq << "'."
93                                      << endl;
94         }
95
96         return res;
97 }
98
99
100 int kb_keymap::lookup(unsigned int key,
101                       key_modifier::state mod, kb_sequence * seq) const
102 {
103         if (table.empty()) {
104                 seq->curmap = seq->stdmap;
105                 seq->mark_deleted();
106                 return LFUN_UNKNOWN_ACTION;
107         }
108
109         for (Table::const_iterator cit = table.begin();
110              cit != table.end(); ++cit) {
111                 key_modifier::state mask(cit->mod.second);
112                 key_modifier::state check =
113                         static_cast<key_modifier::state>(mod & ~mask);
114  
115                 if (cit->code == key && cit->mod.first == check) {
116                         // match found
117                         if (cit->table.get()) {
118                                 // this is a prefix key - set new map
119                                 seq->curmap = cit->table.get();
120                                 return LFUN_PREFIX;
121                         } else {
122                                 // final key - reset map
123                                 seq->curmap = seq->stdmap;
124                                 seq->mark_deleted();
125                                 return cit->action;
126                         }
127                 }
128         }
129
130         // error - key not found:
131         seq->curmap = seq->stdmap;
132         seq->mark_deleted();
133         return LFUN_UNKNOWN_ACTION;
134 }
135
136
137 string const kb_keymap::print() const
138 {
139         string buf;
140         for (Table::const_iterator cit = table.begin();
141              cit != table.end(); ++cit) {
142                 buf += printKey((*cit));
143                 buf += ' ';
144         }
145         return buf;
146 }
147
148
149 void kb_keymap::defkey(kb_sequence * seq, int action, unsigned int r)
150 {
151         unsigned int const code = seq->sequence[r];
152         if (code == NoSymbol) return;
153
154         key_modifier::state const mod1 = seq->modifiers[r].first;
155         key_modifier::state const mod2 = seq->modifiers[r].second;
156
157         // check if key is already there
158         for (Table::iterator it = table.begin(); it != table.end(); ++it) {
159                 if (code == it->code && mod1 == it->mod.first && mod2 == it->mod.second) {
160                         // overwrite binding
161                         if (r + 1 == seq->length()) {
162                                 lyxerr[Debug::KBMAP]
163                                         << "Warning: New binding for '"
164                                         << seq->print()
165                                         << "' is overriding old binding..."
166                                         << endl;
167                                 if (it->table.get()) {
168                                         it->table.reset();
169                                 }
170                                 it->action = action;
171                                 return;
172                         } else if (!it->table.get()) {
173                                 lyxerr << "Error: New binding for '" << seq->print()
174                                        << "' is overriding old binding..."
175                                                << endl;
176                                 return;
177                         } else {
178                                 it->table->defkey(seq, action, r + 1);
179                                 return;
180                         }
181                 }
182         }
183
184         Table::iterator newone = table.insert(table.end(), kb_key());
185         newone->code = code;
186         newone->mod = seq->modifiers[r];
187         if (r + 1 == seq->length()) {
188                 newone->action = action;
189                 newone->table.reset();
190                 return;
191         } else {
192                 newone->table.reset(new kb_keymap);
193                 newone->table->defkey(seq, action, r + 1);
194                 return;
195         }
196 }
197
198
199 string const kb_keymap::findbinding(int act, string const & prefix) const
200 {
201         string res;
202         if (table.empty()) return res;
203
204         Table::const_iterator end = table.end();
205         for (Table::const_iterator cit = table.begin();
206             cit != end; ++cit) {
207                 if (cit->table.get()) {
208                         res += cit->table->findbinding(act,
209                                                        prefix
210                                                        + printKey((*cit))
211                                                        + " ");
212                 } else if (cit->action == act) {
213                         res += "[";
214                         res += prefix + printKey((*cit));
215                         res += "] ";
216                 }
217         }
218         return res;
219 }