]> git.lyx.org Git - lyx.git/blob - src/kbmap.C
use more std::functors add some of my own, some change to fl_display etc. read the...
[lyx.git] / src / kbmap.C
1 /* This file is part of
2  * ====================================================== 
3  * 
4  *           LyX, The Document Processor
5  *       
6  *           Copyright 1995 Matthias Ettrich
7  *           Copyright 1995-2000 The LyX Team.
8  *
9  * ====================================================== */
10
11 #include <config.h>
12
13 #include <cstring>
14 #include <X11/Xlib.h>
15
16 #ifdef __GNUG__
17 #pragma implementation
18 #endif
19
20 #include "kbmap.h"
21 #include "kbsequence.h"
22 #include "debug.h"
23
24 using std::endl;
25
26 // The only modifiers that we handle. We want to throw away things
27 // like NumLock. 
28 enum { ModsMask = ShiftMask | ControlMask | Mod1Mask };
29
30
31 // === static functions =================================================== 
32
33
34 /* ---F+------------------------------------------------------------------ *\
35    Function  : printKeysym
36    Called by : kb_sequence::print and printKeyMap. RVDK_PATCH_5
37    Purpose   : prints a keysym, including modifiers.
38    Parameters: key    - keysym
39                mod    - modifiers
40                buf    - string where the result goes
41                maxlen - length of string (including '\0')
42    Returns   : length of printed string if ok, 0 otherwise.
43 \* ---F------------------------------------------------------------------- */
44 void printKeysym(unsigned int key, unsigned int mod, string & buf)
45 {
46         mod &= ModsMask;
47
48         char * s = XKeysymToString(key);
49         
50         if (mod & ShiftMask) buf += "S-";
51         if (mod & ControlMask) buf += "C-";
52         if (mod & Mod1Mask) buf += "M-";
53         if (s) buf += s;
54 }
55
56
57 /* ---F+------------------------------------------------------------------ *\
58    Function  : printKeyTab
59    Called by : kb_keymap::print
60    Purpose   : print the keysyms found in the given key table. RVDK_PATCH_5
61    Parameters: tabPt  - keytable pointer
62                buf    - string where the result goes
63                maxLen - length of string (including '\0')
64    Returns   : length of printed string.
65 \* ---F------------------------------------------------------------------- */
66
67 void kb_keymap::printKey(kb_key const & key, string & buf)
68 {
69         printKeysym(key.code, key.mod & 0xffff, buf);
70 }
71
72
73 // This binds a key to an action
74 int kb_keymap::bind(string const & seq, int action)
75 {
76         kb_sequence k;
77
78         int res = k.parse(seq);
79         if (!res) {
80                 defkey(&k, action);
81         } else
82                 lyxerr[Debug::KBMAP] << "Parse error at position " << res
83                                      << " in key sequence '" << seq << "'."
84                                      << endl;
85         return res;
86 }
87
88
89 /* ---F+------------------------------------------------------------------ *\
90     Function  : kb_keymap::lookup
91     Called by : [user], kb_sequence::add()
92     Purpose   : look up a key press in a given keymap
93     Parameters: key - the keysym of the key press
94                 mod - the modifier mask of the keypress
95                 seq - the key-sequence retrieved so far
96     Returns   : user defined action; 0 for prefix key, -1 if key not found
97 \* ---F------------------------------------------------------------------- */
98
99 int kb_keymap::lookup(unsigned int key,
100                       unsigned int mod, kb_sequence * seq) const
101 {
102         if (table.empty()) {
103                 seq->curmap = seq->stdmap;
104                 seq->delseq();
105                 return -1;
106         }
107
108         unsigned int msk1, msk0;
109         //suppress modifier bits we do not handle
110         mod &= ModsMask;
111
112         for (Table::const_iterator cit = table.begin();
113              cit != table.end(); ++cit) {
114                 msk1 = (*cit).mod & 0xffff;
115                 msk0 = ((*cit).mod >> 16) & 0xffff;
116                 if ((*cit).code == key && (mod & ~msk0) == msk1) {
117                         // math found:
118                         if ((*cit).table) {
119                                 // this is a prefix key - set new map
120                                 seq->curmap = (*cit).table;
121                                 return 0;
122                         } else {
123                                 // final key - reset map
124                                 seq->curmap = seq->stdmap;
125                                 seq->delseq();
126                                 return (*cit).action;
127                         }
128                 }
129         }
130
131         // error - key not found:
132         seq->curmap = seq->stdmap;
133         seq->delseq();
134         return -1;
135 }
136
137
138 /* ---F+------------------------------------------------------------------ *\
139     Function  : kb_keymap::print
140     Called by : [user]
141     Purpose   : Prints all the available keysyms. RVDK_PATCH_5
142     Parameters: buf    - string where output goes.
143                maxLen - available length in string, including `\0'.
144     Returns   : updated maxLen.
145 \* ---F------------------------------------------------------------------- */
146
147 void kb_keymap::print(string & buf) const
148 {
149         for (Table::const_iterator cit = table.begin();
150              cit != table.end(); ++cit) {
151                 printKey((*cit), buf);
152                 buf += ' ';
153         }
154 }
155
156
157 /* ---F+------------------------------------------------------------------ *\
158     Function  : kb_keymap::defkey
159     Called by : [user]
160     Purpose   : define an action for a key sequence
161     Parameters: seq    - the key sequence
162                 action - the action to be defined
163                 idx    - recursion depth
164     Returns   : 0 if ok.
165 \* ---F------------------------------------------------------------------- */
166
167 int kb_keymap::defkey(kb_sequence * seq, int action, int idx /*= 0*/)
168 {
169         unsigned int code = seq->sequence[idx];
170         if(code == NoSymbol) return -1;
171
172         unsigned int modmsk = seq->modifiers[idx];
173
174         // --- check if key is already there --------------------------------
175         if (table.size() != 0) { // without this I get strange crashes
176                 Table::iterator end = table.end();
177         for (Table::iterator it = table.begin(); it != end; ++it) {
178                 if (code == (*it).code && modmsk == (*it).mod) {
179                         // overwrite binding
180                         if (idx + 1 == seq->length) {
181                                 string buf;
182                                 seq->print(buf, true);
183                                 lyxerr[Debug::KBMAP]
184                                         << "Warning: New binding for '"
185                                         << buf
186                                         << "' is overriding old binding..."
187                                         << endl;
188                                 if((*it).table) {
189                                         delete (*it).table;
190                                         (*it).table = 0;
191                                 }
192                                 (*it).action = action;
193                                 return 0;
194                         } else if (!(*it).table) {
195                                 string buf;
196                                 seq->print(buf, true);
197                                 lyxerr << "Error: New binding for '" << buf
198                                        << "' is overriding old binding..."
199                                        << endl;
200                                 return -1;
201                         } else {
202                                 return (*it).table->defkey(seq, action,
203                                                            idx + 1);
204                         }
205                 }
206         }
207         }
208         
209         Table::iterator newone = table.insert(table.end(), kb_key());
210         (*newone).code = code;
211         (*newone).mod = modmsk;
212         if (idx + 1 == seq->length) {
213                 (*newone).action = action;
214                 (*newone).table = 0;
215                 return 0;
216         } else {
217                 (*newone).table = new kb_keymap;
218                 return (*newone).table->defkey(seq, action, idx + 1);
219         }
220 }
221
222
223 /* ---F+------------------------------------------------------------------ *\
224     Function  : kb_keymap::~kb_keymap
225     Called by : [destructor]
226     Purpose   : free keymap and its descendents
227     Parameters: none
228     Returns   : nothing
229 \* ---F------------------------------------------------------------------- */
230
231 kb_keymap::~kb_keymap()
232 {
233         // This could be done by a destructor in kb_key.
234         Table::iterator end = table.end();
235         for (Table::iterator it = table.begin(); it != end; ++it) {
236                 delete (*it).table;
237         }
238 }
239
240
241 string const kb_keymap::keyname(kb_key const & k)
242 {
243         string buf;
244         printKeysym(k.code, k.mod, buf);
245         return buf;
246 }
247
248
249 // Finds a key for a keyaction, if possible
250 string const kb_keymap::findbinding(int act) const
251 {
252         string res;
253         if (table.empty()) return res;
254
255         Table::const_iterator end = table.end();
256         for (Table::const_iterator cit = table.begin();
257             cit != end; ++cit) {
258                 if ((*cit).table) {
259                         string suffix = (*cit).table->findbinding(act);
260                         suffix = strip(suffix, ' ');
261                         suffix = strip(suffix, ']');
262                         suffix = frontStrip(suffix, '[');
263                         if (!suffix.empty()) {
264                                 res += "[" + keyname((*cit)) + " "
265                                         + suffix + "] ";
266                         }
267                 } else if ((*cit).action == act) {
268                         res += "[";
269                         res += keyname((*cit));
270                         res += "] ";
271                 }
272         }
273         return res;
274 }
275
276 /* === End of File: kbmap.C ============================================== */