1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 1995 Matthias Ettrich
7 * Copyright 1995-2000 The LyX Team.
9 * ====================================================== */
17 #pragma implementation
21 #include "kbsequence.h"
26 // The only modifiers that we handle. We want to throw away things
28 enum { ModsMask = ShiftMask | ControlMask | Mod1Mask };
31 // === static functions ===================================================
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
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)
48 char * s = XKeysymToString(key);
50 if (mod & ShiftMask) buf += "S-";
51 if (mod & ControlMask) buf += "C-";
52 if (mod & Mod1Mask) buf += "M-";
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------------------------------------------------------------------- */
67 void kb_keymap::printKey(kb_key const & key, string & buf)
69 printKeysym(key.code, key.mod & 0xffff, buf);
73 // This binds a key to an action
74 int kb_keymap::bind(char const * seq, int action)
78 int res = k.parse(seq);
82 lyxerr[Debug::KBMAP] << "Parse error at position " << res
83 << " in key sequence '" << seq << "'."
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------------------------------------------------------------------- */
99 int kb_keymap::lookup(unsigned int key,
100 unsigned int mod, kb_sequence * seq) const
103 seq->curmap = seq->stdmap;
108 unsigned int msk1, msk0;
109 //suppress modifier bits we do not handle
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) {
119 // this is a prefix key - set new map
120 seq->curmap = (*cit).table;
123 // final key - reset map
124 seq->curmap = seq->stdmap;
126 return (*cit).action;
131 // error - key not found:
132 seq->curmap = seq->stdmap;
138 /* ---F+------------------------------------------------------------------ *\
139 Function : kb_keymap::print
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------------------------------------------------------------------- */
147 void kb_keymap::print(string & buf) const
149 for (Table::const_iterator cit = table.begin();
150 cit != table.end(); ++cit) {
151 printKey((*cit), buf);
157 /* ---F+------------------------------------------------------------------ *\
158 Function : kb_keymap::defkey
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
165 \* ---F------------------------------------------------------------------- */
167 int kb_keymap::defkey(kb_sequence * seq, int action, int idx /*= 0*/)
169 unsigned int code = seq->sequence[idx];
170 if(code == NoSymbol) return -1;
172 unsigned int modmsk = seq->modifiers[idx];
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) {
180 if (idx + 1 == seq->length) {
182 seq->print(buf, true);
184 << "Warning: New binding for '"
186 << "' is overriding old binding..."
192 (*it).action = action;
194 } else if (!(*it).table) {
196 seq->print(buf, true);
197 lyxerr << "Error: New binding for '" << buf
198 << "' is overriding old binding..."
202 return (*it).table->defkey(seq, action,
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;
217 (*newone).table = new kb_keymap;
218 return (*newone).table->defkey(seq, action, idx + 1);
223 /* ---F+------------------------------------------------------------------ *\
224 Function : kb_keymap::~kb_keymap
225 Called by : [destructor]
226 Purpose : free keymap and its descendents
229 \* ---F------------------------------------------------------------------- */
231 kb_keymap::~kb_keymap()
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) {
241 string kb_keymap::keyname(kb_key const & k)
244 printKeysym(k.code, k.mod, buf);
249 // Finds a key for a keyaction, if possible
250 string kb_keymap::findbinding(int act) const
253 if (table.empty()) return res;
255 Table::const_iterator end = table.end();
256 for(Table::const_iterator cit = table.begin();
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)) + " "
267 } else if ((*cit).action == act) {
268 res += "[" + keyname((*cit)) + "] ";
274 /* === End of File: kbmap.C ============================================== */