]> git.lyx.org Git - lyx.git/blob - src/kbsequence.C
Angus patch, + allow to set cursor color + constify more local variables
[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-2000 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         if (length < 0) {
65                 length = 0;
66                 sequence.clear();
67                 modifiers.clear();
68         }
69
70         modifiers.push_back(mod + (nmod << 16));
71         sequence.push_back(key);
72         ++length;
73
74         if (curmap)
75                 return curmap->lookup(key, mod, this);
76         
77         return -1;
78 }
79
80
81 /* ---F+------------------------------------------------------------------ *\
82     Function  : kb_sequence::parse
83     Called by : [user]
84     Purpose   : parse a string that holds a key sequence and add the keys
85     Parameters: s - string holding the key sequence
86     Returns   : 0 - if ok, error pos if error
87     Note      : Keys must be separated with whitespace;
88                 Use the keysym names used by XStringToKeysym
89                 Prefixes are S-, C-, M- for shift, control, meta
90 \* ---F------------------------------------------------------------------- */
91
92 int kb_sequence::parse(string const & s)
93 {
94         if (s.empty()) return 1;
95
96         string::size_type i = 0;
97         unsigned int mod = 0, nmod = 0;
98         while (i < s.length()) {
99                 if (s[i] && (s[i]) <= ' ') ++i;
100                 if (i >= s.length()) break;
101                 
102                 if (s[i + 1] == '-')    { // is implicit that s[i] == true
103                         switch (s[i]) {
104                         case 's': case 'S':
105                                 mod |= ShiftMask;
106                                 i += 2;
107                                 continue;
108                         case 'c': case 'C':
109                                 mod |= ControlMask;
110                                 i += 2;
111                                 continue;
112                         case 'm': case 'M':
113                                 mod |= Mod1Mask;
114                                 i += 2;
115                                 continue;
116                         default:
117                                 return i + 1;
118                         }
119                 } else if (s[i] == '~' && s[i + 1] && s[i + 2] == '-') {
120                         switch (s[i + 1]) {
121                         case 's': case 'S':
122                                 nmod |= ShiftMask;
123                                 i += 3;
124                                 continue;
125                         case 'c': case 'C':
126                                 nmod |= ControlMask;
127                                 i += 3;
128                                 continue;
129                         case 'm': case 'M':
130                                 nmod |= Mod1Mask;
131                                 i += 3;
132                                 continue;
133                         default:
134                                 return i + 2;
135                         }
136                 } else {
137                         string tbuf;
138                         string::size_type j = i;
139                         for (; j < s.length() && s[j] > ' '; ++j)
140                                 tbuf += s[j];    // (!!!check bounds :-)
141                         
142                         KeySym key = XStringToKeysym(tbuf.c_str());
143                         if (key == NoSymbol) {
144                                 lyxerr[Debug::KBMAP]
145                                         << "kbmap.C: No such keysym: "
146                                         << tbuf << endl;
147                                 return j;
148                         }
149                         i = j;
150                         
151                         addkey(key, mod, nmod);
152                         mod = 0;
153                         nmod = 0;
154                 }
155         }
156         return 0;
157 }
158
159
160 /* ---F+------------------------------------------------------------------ *\
161     Function  : kb_sequence::print
162     Called by : [user]
163     Purpose   : print the currently defined sequence into a string
164     Parameters: buf           - string where the result goes
165                 maxlen        - length of string (including '\0')
166                 when_defined  - only  print when sequence is real: length > 0.
167     Returns   : 0, if ok, -1 if string too long
168 \* ---F------------------------------------------------------------------- */
169
170 int kb_sequence::print(string & buf, bool when_defined) const
171 {
172         KeySym key;
173         unsigned int mod;
174         int l = length;
175         if (l < 0 && !when_defined ) l = -l;
176         
177         for (int i = 0; i < l; ++i) {
178                 key = sequence[i];
179                 mod = modifiers[i] & 0xffff;
180
181                 printKeysym(key, mod, buf);  // RVDK_PATCH_5
182
183                 if (i + 1 < l) {  // append a blank
184                         buf += ' ';
185                 }
186         }
187         return 0;
188 }
189
190
191 /* ---F+------------------------------------------------------------------ *\
192     Function  : kb_sequence::printOptions
193     Called by : [user]
194     Purpose   : print the available key options from the current state in the
195                 sequence. RVDK_PATCH_5
196     Parameters: buf    - string where the result goes
197                 maxlen - length of string (including '\0')
198     Returns   : 0, if ok, -1 if string too long
199 \* ---F------------------------------------------------------------------- */
200
201 int kb_sequence::printOptions(string & buf) const
202 {
203         print(buf, true);
204         
205         if (!curmap) return -1;
206         buf += _("   options: ");
207         curmap->print(buf);
208         return 0;
209 }
210
211
212 /* ---F+------------------------------------------------------------------ *\
213     Function  : kb_sequence::delseq
214     Called by : [user]
215     Purpose   : mark the sequence as deleted
216     Parameters: none
217     Returns   : nothing
218 \* ---F------------------------------------------------------------------- */
219
220 void kb_sequence::delseq()
221 {
222         // negative length marks sequence as deleted, but we can still
223         // print() it or retrieve the last char using getiso()
224         length = -length;
225 }
226
227
228 /* ---F+------------------------------------------------------------------ *\
229    Function  : kb_sequence::getsym
230    Called by : [user], getiso
231    Purpose   : get the keysym of the last key in sequence
232    Parameters: none
233    Returns   : keysym
234 \* ---F------------------------------------------------------------------- */
235
236 unsigned int kb_sequence::getsym() const
237 {
238         int l = length;
239         if (l == 0) return NoSymbol;
240         if (l < 0) l = -l;
241         return sequence[l - 1];
242 }
243
244
245 /* ---F+------------------------------------------------------------------ *\
246     Function  : kb_sequence::getiso
247     Called by : [user]
248     Purpose   : return iso character code of last key, if any
249     Parameters: none
250     Returns   : iso code or 0 if none
251 \* ---F------------------------------------------------------------------- */
252
253 char kb_sequence::getiso() const
254 {
255         int const c = getsym();
256         
257         if (c > 0xff)
258                 return '\0';
259         return c;
260 }
261
262
263 /* ---F+------------------------------------------------------------------ *\
264     Function  : kb_sequence::reset
265     Called by : [user]
266     Purpose   : reset sequence to initial state. RVDK_PATCH_5
267     Parameters: none
268     Returns   : void
269 \* ---F------------------------------------------------------------------- */
270
271 void kb_sequence::reset()
272 {
273         delseq();
274         curmap = stdmap;
275         if (length > 0) length = -length;
276 }
277
278 /* === End of File: kbmap.C ============================================== */