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