]> git.lyx.org Git - lyx.git/blob - src/kbmap.C
Painter and scrollbar API patches
[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                 // latin 8 byte 3 = 18 (0x12)
56         case 0x00001200:
57                 // latin 9 byte 3 = 19 (0x13)
58         case 0x00001300:
59                 c &= 0x000000FF;
60                 break;
61         default:
62                 c = 0;
63         }
64         return c;
65 }
66
67 string const kb_keymap::printKey(kb_key const & key) const
68 {
69         return printKeysym(key.code, key.mod.first);
70 }
71
72
73 string::size_type kb_keymap::bind(string const & seq, int action)
74 {
75         if (lyxerr.debugging(Debug::KBMAP)) {
76                 lyxerr << "BIND: Sequence `"
77                        << seq << "' Action `"
78                        << action << "'" << endl;
79         }
80
81         kb_sequence k(0, 0);
82
83         string::size_type const res = k.parse(seq);
84         if (res == string::npos) {
85                 defkey(&k, action);
86         } else {
87                 lyxerr[Debug::KBMAP] << "Parse error at position " << res
88                                      << " in key sequence '" << seq << "'."
89                                      << endl;
90         }
91
92         return res;
93 }
94
95
96 int kb_keymap::lookup(unsigned int key,
97                       key_modifier::state mod, kb_sequence * seq) const
98 {
99         if (table.empty()) {
100                 seq->curmap = seq->stdmap;
101                 seq->mark_deleted();
102                 return LFUN_UNKNOWN_ACTION;
103         }
104
105         for (Table::const_iterator cit = table.begin();
106              cit != table.end(); ++cit) {
107                 key_modifier::state mask(cit->mod.second);
108                 key_modifier::state check =
109                         static_cast<key_modifier::state>(mod & ~mask);
110  
111                 if (cit->code == key && cit->mod.first == check) {
112                         // match found
113                         if (cit->table.get()) {
114                                 // this is a prefix key - set new map
115                                 seq->curmap = cit->table.get();
116                                 return LFUN_PREFIX;
117                         } else {
118                                 // final key - reset map
119                                 seq->curmap = seq->stdmap;
120                                 seq->mark_deleted();
121                                 return cit->action;
122                         }
123                 }
124         }
125
126         // error - key not found:
127         seq->curmap = seq->stdmap;
128         seq->mark_deleted();
129         return LFUN_UNKNOWN_ACTION;
130 }
131
132
133 string const kb_keymap::print() const
134 {
135         string buf;
136         for (Table::const_iterator cit = table.begin();
137              cit != table.end(); ++cit) {
138                 buf += printKey((*cit));
139                 buf += ' ';
140         }
141         return buf;
142 }
143
144
145 void kb_keymap::defkey(kb_sequence * seq, int action, unsigned int r)
146 {
147         unsigned int const code = seq->sequence[r];
148         if (code == NoSymbol) return;
149
150         key_modifier::state const mod1 = seq->modifiers[r].first;
151         key_modifier::state const mod2 = seq->modifiers[r].second;
152
153         // check if key is already there
154         for (Table::iterator it = table.begin(); it != table.end(); ++it) {
155                 if (code == it->code && mod1 == it->mod.first && mod2 == it->mod.second) {
156                         // overwrite binding
157                         if (r + 1 == seq->length()) {
158                                 lyxerr[Debug::KBMAP]
159                                         << "Warning: New binding for '"
160                                         << seq->print()
161                                         << "' is overriding old binding..."
162                                         << endl;
163                                 if (it->table.get()) {
164                                         it->table.reset();
165                                 }
166                                 it->action = action;
167                                 return;
168                         } else if (!it->table.get()) {
169                                 lyxerr << "Error: New binding for '" << seq->print()
170                                        << "' is overriding old binding..."
171                                                << endl;
172                                 return;
173                         } else {
174                                 it->table->defkey(seq, action, r + 1);
175                                 return;
176                         }
177                 }
178         }
179
180         Table::iterator newone = table.insert(table.end(), kb_key());
181         newone->code = code;
182         newone->mod = seq->modifiers[r];
183         if (r + 1 == seq->length()) {
184                 newone->action = action;
185                 newone->table.reset();
186                 return;
187         } else {
188                 newone->table.reset(new kb_keymap);
189                 newone->table->defkey(seq, action, r + 1);
190                 return;
191         }
192 }
193
194
195 string const kb_keymap::findbinding(int act, string const & prefix) const
196 {
197         string res;
198         if (table.empty()) return res;
199
200         Table::const_iterator end = table.end();
201         for (Table::const_iterator cit = table.begin();
202             cit != end; ++cit) {
203                 if (cit->table.get()) {
204                         res += cit->table->findbinding(act,
205                                                        prefix
206                                                        + printKey((*cit))
207                                                        + " ");
208                 } else if (cit->action == act) {
209                         res += "[";
210                         res += prefix + printKey((*cit));
211                         res += "] ";
212                 }
213         }
214         return res;
215 }