]> git.lyx.org Git - lyx.git/blob - src/kbsequence.C
7c661929c24b2dce3d9baa7c74cf1898a432cc4d
[lyx.git] / src / kbsequence.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 //#include <cstring>
13 #include <X11/Xlib.h>
14
15 #include "gettext.h"
16
17 #ifdef __GNUG__
18 #pragma implementation
19 #endif
20
21 #include "kbsequence.h"
22 #include "kbmap.h"
23 #include "debug.h"
24
25 using std::endl;
26
27 // The only modifiers that we handle. We want to throw away things
28 // like NumLock. 
29 enum { ModsMask = ShiftMask | ControlMask | Mod1Mask };
30
31
32 // === static functions =================================================== 
33
34
35 /* ---F+------------------------------------------------------------------ *\
36    Function  : printKeysym
37    Called by : kb_sequence::print and printKeyMap. RVDK_PATCH_5
38    Purpose   : prints a keysym, including modifiers.
39    Parameters: key    - keysym
40                mod    - modifiers
41                buf    - string where the result goes
42                maxlen - length of string (including '\0')
43    Returns   : length of printed string if ok, 0 otherwise.
44 \* ---F------------------------------------------------------------------- */
45 extern
46 void printKeysym(unsigned int key, unsigned int mod, string & buf);
47
48
49 // === kb_sequence methods ================================================ 
50
51 /* ---F+------------------------------------------------------------------ *\
52     Function  : kb_sequence::addkey
53     Called by : [user]
54     Purpose   : add a key to the sequence, look up in map and return action
55     Parameters: key  - keysym of key
56                 mod  - modifier mask
57                 nmod - modifier veto mask (unused now)
58     Returns   : action or -1 if error (no map defined or key not found)
59 \* ---F------------------------------------------------------------------- */
60
61 int kb_sequence::addkey(unsigned int key,
62                         unsigned int mod, unsigned int nmod /*= 0*/)
63 {
64         //lyxerr << "kb_sequence::addkey: length is [" << length << "]\n"
65         //       << "kb_sequence::addkey::key == [" << key << "]\n"
66         //       << "kb_sequence::addkey::mod == [" << mod << "]" << endl;
67         
68         if (length <= 0) {
69                 length = 0;
70                 sequence.clear();
71                 modifiers.clear();
72         }
73
74         modifiers.push_back(mod + (nmod << 16));
75         sequence.push_back(key);
76         ++length;
77
78         if (curmap)
79                 return curmap->lookup(key, mod, this);
80         
81         return -1;
82 }
83
84
85 /* ---F+------------------------------------------------------------------ *\
86     Function  : kb_sequence::parse
87     Called by : [user]
88     Purpose   : parse a string that holds a key sequence and add the keys
89     Parameters: s - string holding the key sequence
90     Returns   : string::npos if ok, error pos if error
91     Note      : Keys must be separated with whitespace;
92                 Use the keysym names used by XStringToKeysym
93                 Prefixes are S-, C-, M- for shift, control, meta
94 \* ---F------------------------------------------------------------------- */
95
96 string::size_type kb_sequence::parse(string const & s)
97 {
98         if (s.empty()) return 1;
99
100         string::size_type i = 0;
101         unsigned int mod = 0, nmod = 0;
102         while (i < s.length()) {
103                 if (s[i] == ' ')
104                         ++i;
105                 if (i >= s.length())
106                         break;
107                 
108                 if (i + 1 < s.length() && s[i + 1] == '-')      {
109                         switch (s[i]) {
110                         case 's': case 'S':
111                                 mod |= ShiftMask;
112                                 i += 2;
113                                 continue;
114                         case 'c': case 'C':
115                                 mod |= ControlMask;
116                                 i += 2;
117                                 continue;
118                         case 'm': case 'M':
119                                 mod |= Mod1Mask;
120                                 i += 2;
121                                 continue;
122                         default:
123                                 return i + 1;
124                         }
125                 } else if (i + 2 < s.length() && s[i] == '~'
126                            && s[i + 2] == '-') {
127                         switch (s[i + 1]) {
128                         case 's': case 'S':
129                                 nmod |= ShiftMask;
130                                 i += 3;
131                                 continue;
132                         case 'c': case 'C':
133                                 nmod |= ControlMask;
134                                 i += 3;
135                                 continue;
136                         case 'm': case 'M':
137                                 nmod |= Mod1Mask;
138                                 i += 3;
139                                 continue;
140                         default:
141                                 return i + 2;
142                         }
143                 } else {
144                         string tbuf;
145                         string::size_type j = i;
146                         for (; j < s.length() && s[j] != ' '; ++j)
147                                 tbuf += s[j];    // (!!!check bounds :-)
148                         
149                         KeySym key = XStringToKeysym(tbuf.c_str());
150                         if (key == NoSymbol) {
151                                 lyxerr[Debug::KBMAP]
152                                         << "kbmap.C: No such keysym: "
153                                         << tbuf << endl;
154                                 return j;
155                         }
156                         i = j;
157                         
158                         addkey(key, mod, nmod);
159                         mod = 0;
160                         nmod = 0;
161                 }
162         }
163         
164         // empty sequence?
165         if (!length)
166                 return 0;
167
168         // everything is fine
169         return string::npos;
170 }
171
172
173 /* ---F+------------------------------------------------------------------ *\
174     Function  : kb_sequence::print
175     Called by : [user]
176     Purpose   : print the currently defined sequence into a string
177     Parameters: buf           - string where the result goes
178                 when_defined  - only  print when sequence is real: length > 0.
179     Returns   : 0, if ok, -1 if string too long
180 \* ---F------------------------------------------------------------------- */
181
182 int kb_sequence::print(string & buf, bool when_defined) const
183 {
184         //lyxerr << "kb_sequence::print: length is [" << length << "]" << endl;
185         
186         KeySym key;
187         unsigned int mod;
188         int l = length;
189         if (l < 0 && !when_defined ) l = -l;
190         
191         for (int i = 0; i < l; ++i) {
192                 key = sequence[i];
193                 mod = modifiers[i] & 0xffff;
194                 //lyxerr << "kb_sequence::sequence[" << i << "] == [" << key << "]\n"
195                 //       << "kb_sequence::modifiers[" << i << "] == [" << mod << "]"
196                 //       << endl;
197
198                 printKeysym(key, mod, buf);  // RVDK_PATCH_5
199
200                 if (i + 1 < l) {  // append a blank
201                         buf += ' ';
202                 }
203         }
204         return 0;
205 }
206
207
208 /* ---F+------------------------------------------------------------------ *\
209     Function  : kb_sequence::printOptions
210     Called by : [user]
211     Purpose   : print the available key options from the current state in the
212                 sequence. RVDK_PATCH_5
213     Parameters: buf    - string where the result goes
214                 maxlen - length of string (including '\0')
215     Returns   : 0, if ok, -1 if string too long
216 \* ---F------------------------------------------------------------------- */
217
218 int kb_sequence::printOptions(string & buf) const
219 {
220         print(buf, true);
221         
222         if (!curmap) return -1;
223         buf += _("   options: ");
224         curmap->print(buf);
225         return 0;
226 }
227
228
229 /* ---F+------------------------------------------------------------------ *\
230     Function  : kb_sequence::delseq
231     Called by : [user]
232     Purpose   : mark the sequence as deleted
233     Parameters: none
234     Returns   : nothing
235 \* ---F------------------------------------------------------------------- */
236
237 void kb_sequence::delseq()
238 {
239         // negative length marks sequence as deleted, but we can still
240         // print() it or retrieve the last char using getiso()
241         length = -length;
242 }
243
244
245 /* ---F+------------------------------------------------------------------ *\
246    Function  : kb_sequence::getsym
247    Called by : [user], getiso
248    Purpose   : get the keysym of the last key in sequence
249    Parameters: none
250    Returns   : keysym
251 \* ---F------------------------------------------------------------------- */
252
253 unsigned int kb_sequence::getsym() const
254 {
255         int l = length;
256         if (l == 0) return NoSymbol;
257         if (l < 0) l = -l;
258         return sequence[l - 1];
259 }
260
261
262 /* ---F+------------------------------------------------------------------ *\
263     Function  : kb_sequence::getiso
264     Called by : [user]
265     Purpose   : return iso character code of last key, if any
266     Parameters: none
267     Returns   : iso code or 0 if none
268 \* ---F------------------------------------------------------------------- */
269
270 char kb_sequence::getiso() const
271 {
272         unsigned int const c = getsym();
273
274         lyxerr[Debug::KBMAP] << "Raw keysym: "
275                              << std::hex << c << std::dec << endl;
276         lyxerr[Debug::KBMAP] << "byte 3: "
277                              << std::hex << (c & 0x0000FF00) << std::dec
278                              << endl;
279         
280         switch (c & 0x0000FF00) {
281                 // latin 1 byte 3 = 0
282         case 0x00000000:
283                 return c;
284                 // latin 2 byte 3 = 1
285         case 0x00000100:
286                 // latin 3 byte 3 = 2
287         case 0x00000200:
288                 // latin 4 byte 3 = 3
289         case 0x00000300:
290                 // latin 8 byte 3 = 18 (0x12)
291         case 0x00001200:
292                 // latin 9 byte 3 = 19 (0x13)
293         case 0x00001300:
294                 return c & 0x000000FF;
295         default:
296                 return '\0';
297         }
298
299         // not a latin char we know of
300         // Yes but this is already handled above (JMarc)
301         //return '\0';
302 }
303
304
305 /* ---F+------------------------------------------------------------------ *\
306     Function  : kb_sequence::reset
307     Called by : [user]
308     Purpose   : reset sequence to initial state. RVDK_PATCH_5
309     Parameters: none
310     Returns   : void
311 \* ---F------------------------------------------------------------------- */
312
313 void kb_sequence::reset()
314 {
315         delseq();
316         curmap = stdmap;
317         if (length > 0) length = -length;
318 }
319
320 /* === End of File: kbmap.C ============================================== */