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