File: | handle.c |
Location: | line 672, column 24 |
Description: | Potential leak of memory pointed to by 'kcs' |
1 | /* | |||
2 | ||||
3 | Copyright 1988, 1998 The Open Group | |||
4 | ||||
5 | Permission to use, copy, modify, distribute, and sell this software and its | |||
6 | documentation for any purpose is hereby granted without fee, provided that | |||
7 | the above copyright notice appear in all copies and that both that | |||
8 | copyright notice and this permission notice appear in supporting | |||
9 | documentation. | |||
10 | ||||
11 | The above copyright notice and this permission notice shall be included | |||
12 | in all copies or substantial portions of the Software. | |||
13 | ||||
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |||
15 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
17 | IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR | |||
18 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |||
19 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |||
20 | OTHER DEALINGS IN THE SOFTWARE. | |||
21 | ||||
22 | Except as contained in this notice, the name of The Open Group shall | |||
23 | not be used in advertising or otherwise to promote the sale, use or | |||
24 | other dealings in this Software without prior written authorization | |||
25 | from The Open Group. | |||
26 | ||||
27 | */ | |||
28 | ||||
29 | #ifdef HAVE_CONFIG_H1 | |||
30 | #include "config.h" | |||
31 | #endif | |||
32 | ||||
33 | #include <X11/Xos.h> | |||
34 | #include <X11/Xlib.h> | |||
35 | #include <stdio.h> | |||
36 | #include <ctype.h> | |||
37 | #include "xmodmap.h" | |||
38 | #include "wq.h" | |||
39 | #include <stdlib.h> | |||
40 | ||||
41 | #ifdef HAVE_STRNCASECMP1 | |||
42 | #include <strings.h> | |||
43 | #endif | |||
44 | ||||
45 | static XModifierKeymap *map = NULL((void*)0); | |||
46 | ||||
47 | ||||
48 | /* | |||
49 | * The routines in this file manipulate a queue of intructions. Instead of | |||
50 | * executing each line as it is entered, we build up a list of actions to | |||
51 | * take and execute them all at the end. This allows us to find all errors | |||
52 | * at once, and to preserve the context in which we are looking up keysyms. | |||
53 | */ | |||
54 | ||||
55 | struct wq work_queue = {NULL((void*)0), NULL((void*)0)}; | |||
56 | ||||
57 | ||||
58 | /* | |||
59 | * common utility routines | |||
60 | */ | |||
61 | ||||
62 | static KeyCode * | |||
63 | KeysymToKeycodes(Display *dpy, KeySym keysym, int *pnum_kcs) | |||
64 | { | |||
65 | KeyCode *kcs = NULL((void*)0); | |||
66 | int i, j; | |||
67 | ||||
68 | *pnum_kcs = 0; | |||
69 | for (i = min_keycode; i <= max_keycode; i++) { | |||
70 | for (j = 0; j < 8; j++) { | |||
71 | if (XKeycodeToKeysym(dpy, (KeyCode) i, j) == keysym) { | |||
72 | if (!kcs) | |||
73 | kcs = malloc(sizeof(KeyCode)); | |||
74 | else | |||
75 | kcs = realloc(kcs, sizeof(KeyCode) * (*pnum_kcs + 1)); | |||
76 | kcs[*pnum_kcs] = i; | |||
77 | *pnum_kcs += 1; | |||
78 | break; | |||
79 | } | |||
80 | } | |||
81 | } | |||
82 | return kcs; | |||
83 | } | |||
84 | ||||
85 | static char * | |||
86 | copy_to_scratch(const char *s, int len) | |||
87 | { | |||
88 | static char *buf = NULL((void*)0); | |||
89 | static int buflen = 0; | |||
90 | ||||
91 | if (len < 0) | |||
92 | len = 0; | |||
93 | ||||
94 | if (len >= buflen) { | |||
95 | if (buf) free (buf); | |||
96 | buflen = (len < 40) ? 80 : (len * 2); | |||
97 | buf = malloc (buflen+1); | |||
98 | if (!buf) { | |||
99 | fprintf (stderr__stderrp, "attempt to allocate %d byte scratch buffer\n", buflen + 1); | |||
100 | return NULL((void*)0); | |||
101 | } | |||
102 | } | |||
103 | ||||
104 | strncpy (buf, s, len)__builtin___strncpy_chk (buf, s, len, __builtin_object_size ( buf, 2 > 1 ? 1 : 0)); | |||
105 | buf[len] = '\0'; | |||
106 | ||||
107 | return (buf); | |||
108 | } | |||
109 | ||||
110 | static void | |||
111 | badheader(void) | |||
112 | { | |||
113 | fprintf (stderr__stderrp, "%s: %s:%d: bad ", ProgramName, inputFilename, lineno+1); | |||
114 | parse_errors++; | |||
115 | } | |||
116 | ||||
117 | #define badmsg0(what){ badheader(); fprintf (__stderrp, what); putc ('\n', __stderrp ); } { badheader(); fprintf (stderr__stderrp, what); \ | |||
118 | putc ('\n', stderr__stderrp); } | |||
119 | ||||
120 | #define badmsg(what,arg){ badheader(); fprintf (__stderrp, what, arg); putc ('\n', __stderrp ); } { badheader(); fprintf (stderr__stderrp, what, arg); \ | |||
121 | putc ('\n', stderr__stderrp); } | |||
122 | ||||
123 | #define badmsgn(what,s,len){ badheader(); fprintf (__stderrp, what, copy_to_scratch (s, len )); putc ('\n', __stderrp); } badmsg (what, copy_to_scratch (s, len)){ badheader(); fprintf (__stderrp, what, copy_to_scratch (s, len )); putc ('\n', __stderrp); } | |||
124 | ||||
125 | void | |||
126 | initialize_map (void) | |||
127 | { | |||
128 | map = XGetModifierMapping (dpy); | |||
129 | return; | |||
130 | } | |||
131 | ||||
132 | static void do_keycode ( char *line, int len ); | |||
133 | static void do_keysym ( char *line, int len ); | |||
134 | static void finish_keycodes ( const char *line, int len, KeyCode *keycodes, | |||
135 | int count ); | |||
136 | static void do_add ( char *line, int len ); | |||
137 | static void do_remove ( char *line, int len ); | |||
138 | static void do_clear ( char *line, int len ); | |||
139 | static void do_pointer ( char *line, int len ); | |||
140 | static int get_keysym_list ( const char *line, int len, int *np, KeySym **kslistp ); | |||
141 | ||||
142 | static void print_opcode(union op *op); | |||
143 | ||||
144 | static int skip_word ( const char *s, int len ); | |||
145 | static int skip_chars ( const char *s, int len ); | |||
146 | static int skip_space ( const char *s, int len ); | |||
147 | ||||
148 | static struct dt { | |||
149 | const char *command; /* name of input command */ | |||
150 | int length; /* length of command */ | |||
151 | void (*proc)(char *, int); /* handler */ | |||
152 | } dispatch_table[] = { | |||
153 | { "keycode", 7, do_keycode }, | |||
154 | { "keysym", 6, do_keysym }, | |||
155 | { "add", 3, do_add }, | |||
156 | { "remove", 6, do_remove }, | |||
157 | { "clear", 5, do_clear }, | |||
158 | { "pointer", 7, do_pointer }, | |||
159 | { NULL((void*)0), 0, NULL((void*)0) }}; | |||
160 | ||||
161 | /* | |||
162 | * handle_line - this routine parses the input line (which has had all leading | |||
163 | * and trailing whitespace removed) and builds up the work queue. | |||
164 | */ | |||
165 | ||||
166 | void | |||
167 | handle_line(char *line, /* string to parse */ | |||
168 | int len) /* length of line */ | |||
169 | { | |||
170 | int n; | |||
171 | struct dt *dtp; | |||
172 | ||||
173 | n = skip_chars (line, len); | |||
174 | if (n < 0) { | |||
175 | badmsg ("input line '%s'", line){ badheader(); fprintf (__stderrp, "input line '%s'", line); putc ('\n', __stderrp); }; | |||
176 | return; | |||
177 | } | |||
178 | ||||
179 | for (dtp = dispatch_table; dtp->command != NULL((void*)0); dtp++) { | |||
180 | if (n == dtp->length && | |||
181 | strncmp (line, dtp->command, dtp->length) == 0) { | |||
182 | ||||
183 | n += skip_space (line+n, len-n); | |||
184 | line += n, len -= n; | |||
185 | ||||
186 | (*(dtp->proc)) (line, len); | |||
187 | return; | |||
188 | } | |||
189 | } | |||
190 | ||||
191 | fprintf (stderr__stderrp, "%s: unknown command on line %s:%d\n", | |||
192 | ProgramName, inputFilename, lineno+1); | |||
193 | parse_errors++; | |||
194 | } | |||
195 | ||||
196 | /* | |||
197 | * the following routines are useful for parsing | |||
198 | */ | |||
199 | ||||
200 | static int | |||
201 | skip_word (const char *s, int len) | |||
202 | { | |||
203 | register int n; | |||
204 | ||||
205 | n = skip_chars (s, len); | |||
206 | return (n + skip_space (s+n, len-n)); | |||
207 | } | |||
208 | ||||
209 | static int | |||
210 | skip_chars(const char *s, int len) | |||
211 | { | |||
212 | register int i; | |||
213 | ||||
214 | if (len <= 0 || !s || *s == '\0') return (0); | |||
215 | ||||
216 | for (i = 0; i < len; i++) { | |||
217 | if (isspace(s[i])) break; | |||
218 | } | |||
219 | return (i); | |||
220 | } | |||
221 | ||||
222 | static int | |||
223 | skip_space(const char *s, int len) | |||
224 | { | |||
225 | register int i; | |||
226 | ||||
227 | if (len <= 0 || !s || *s == '\0') return (0); | |||
228 | ||||
229 | for (i = 0; i < len; i++) { | |||
230 | if (!s[i] || !isspace(s[i])) break; | |||
231 | } | |||
232 | return (i); | |||
233 | } | |||
234 | ||||
235 | ||||
236 | static int | |||
237 | skip_until_char(const char *s, int len, char c) | |||
238 | { | |||
239 | register int i; | |||
240 | ||||
241 | for (i = 0; i < len; i++) { | |||
242 | if (s[i] == c) break; | |||
243 | } | |||
244 | return (i); | |||
245 | } | |||
246 | ||||
247 | ||||
248 | /* | |||
249 | * The action routines. | |||
250 | * | |||
251 | * This is where the real work gets done. Each routine is responsible for | |||
252 | * parsing its input (note that the command keyword has been stripped off) | |||
253 | * and adding to the work queue. They are also in charge of outputting | |||
254 | * error messages and returning non-zero if there is a problem. | |||
255 | * | |||
256 | * The following global variables are available: | |||
257 | * dpy the display descriptor | |||
258 | * work_queue linked list of opcodes | |||
259 | * inputFilename name of the file being processed | |||
260 | * lineno line number of current line in input file | |||
261 | */ | |||
262 | static void | |||
263 | add_to_work_queue(union op *p) /* this can become a macro someday */ | |||
264 | { | |||
265 | if (work_queue.head == NULL((void*)0)) { /* nothing on the list */ | |||
266 | work_queue.head = work_queue.tail = p; /* head, tail, no prev */ | |||
267 | } else { | |||
268 | work_queue.tail->generic.next = p; /* head okay, prev */ | |||
269 | work_queue.tail = p; /* tail */ | |||
270 | } | |||
271 | p->generic.next = NULL((void*)0); | |||
272 | ||||
273 | if (verbose) { | |||
274 | print_opcode (p); | |||
275 | } | |||
276 | return; | |||
277 | } | |||
278 | ||||
279 | static Boolint | |||
280 | parse_number(const char *str, unsigned long *val) | |||
281 | { | |||
282 | const char *fmt = "%ld"; | |||
283 | ||||
284 | if (*str == '0') { | |||
285 | str++; | |||
286 | while (isspace(*str)) | |||
287 | str++; | |||
288 | fmt = "%lo"; | |||
289 | if (*str == '\0') { | |||
290 | *val = 0; | |||
291 | return 1; | |||
292 | } | |||
293 | if (*str == 'x' || *str == 'X') { | |||
294 | str++; | |||
295 | fmt = "%lx"; | |||
296 | } | |||
297 | } | |||
298 | return (sscanf (str, fmt, val) == 1); | |||
299 | } | |||
300 | ||||
301 | static Boolint | |||
302 | parse_keysym(const char *line, int n, char **name, KeySym *keysym) | |||
303 | { | |||
304 | *name = copy_to_scratch (line, n); | |||
305 | if (!strcmp(*name, "NoSymbol")) { | |||
306 | *keysym = NoSymbol0L; | |||
307 | return (True1); | |||
308 | } | |||
309 | *keysym = XStringToKeysym (*name); | |||
310 | if (*keysym == NoSymbol0L && '0' <= **name && **name <= '9') | |||
311 | return parse_number(*name, keysym); | |||
312 | return (*keysym != NoSymbol0L); | |||
313 | } | |||
314 | ||||
315 | /* | |||
316 | * do_keycode - parse off lines of the form | |||
317 | * | |||
318 | * "keycode" number "=" [keysym ...] | |||
319 | * ^ | |||
320 | * | |||
321 | * where number is in decimal, hex, or octal. Any number of keysyms may be | |||
322 | * listed. | |||
323 | */ | |||
324 | ||||
325 | static void | |||
326 | do_keycode(char *line, int len) | |||
327 | { | |||
328 | int dummy; | |||
329 | const char *fmt = "%d"; | |||
330 | KeyCode keycode; | |||
331 | ||||
332 | if (len < 3 || !line || *line == '\0') { /* 5=a minimum */ | |||
333 | badmsg0 ("keycode input line"){ badheader(); fprintf (__stderrp, "keycode input line"); putc ('\n', __stderrp); }; | |||
334 | return; | |||
335 | } | |||
336 | ||||
337 | /* | |||
338 | * We need not bother to advance line/len past the | |||
339 | * number (or the string 'any') as finish_keycodes() will | |||
340 | * first advance past the '='. | |||
341 | */ | |||
342 | if (!strncmp("any", line, 3)) { | |||
343 | keycode = 0; | |||
344 | } else { | |||
345 | if (*line == '0') line++, len--, fmt = "%o"; | |||
346 | if (*line == 'x' || *line == 'X') line++, len--, fmt = "%x"; | |||
347 | ||||
348 | dummy = 0; | |||
349 | if (sscanf (line, fmt, &dummy) != 1 || dummy == 0) { | |||
350 | badmsg0 ("keycode value"){ badheader(); fprintf (__stderrp, "keycode value"); putc ('\n' , __stderrp); }; | |||
351 | return; | |||
352 | } | |||
353 | keycode = (KeyCode) dummy; | |||
354 | if ((int)keycode < min_keycode || (int)keycode > max_keycode) { | |||
355 | badmsg0 ("keycode value (out of range)"){ badheader(); fprintf (__stderrp, "keycode value (out of range)" ); putc ('\n', __stderrp); }; | |||
356 | return; | |||
357 | } | |||
358 | } | |||
359 | ||||
360 | finish_keycodes (line, len, &keycode, 1); | |||
361 | } | |||
362 | ||||
363 | ||||
364 | /* | |||
365 | * do_keysym - parse off lines of the form | |||
366 | * | |||
367 | * "keysym" keysym "=" [keysym ...] | |||
368 | * ^ | |||
369 | * | |||
370 | * The left keysyms has to be checked for validity and evaluated. | |||
371 | */ | |||
372 | ||||
373 | static void | |||
374 | do_keysym(char *line, int len) | |||
375 | { | |||
376 | int n; | |||
377 | KeyCode *keycodes; | |||
378 | KeySym keysym; | |||
379 | char *tmpname; | |||
380 | ||||
381 | if (len < 3 || !line || *line == '\0') { /* a=b minimum */ | |||
382 | badmsg0 ("keysym input line"){ badheader(); fprintf (__stderrp, "keysym input line"); putc ('\n', __stderrp); }; | |||
383 | return; | |||
384 | } | |||
385 | ||||
386 | n = skip_chars (line, len); | |||
387 | if (n < 1) { | |||
388 | badmsg0 ("target keysym name"){ badheader(); fprintf (__stderrp, "target keysym name"); putc ('\n', __stderrp); }; | |||
389 | return; | |||
390 | } | |||
391 | if (!parse_keysym(line, n, &tmpname, &keysym)) { | |||
392 | badmsg ("keysym target key symbol '%s'", tmpname){ badheader(); fprintf (__stderrp, "keysym target key symbol '%s'" , tmpname); putc ('\n', __stderrp); }; | |||
393 | return; | |||
394 | } | |||
395 | ||||
396 | keycodes = KeysymToKeycodes (dpy, keysym, &n); | |||
397 | if (n == 0) { | |||
398 | badmsg ("keysym target keysym '%s', no corresponding keycodes",{ badheader(); fprintf (__stderrp, "keysym target keysym '%s', no corresponding keycodes" , tmpname); putc ('\n', __stderrp); } | |||
399 | tmpname){ badheader(); fprintf (__stderrp, "keysym target keysym '%s', no corresponding keycodes" , tmpname); putc ('\n', __stderrp); }; | |||
400 | return; | |||
401 | } | |||
402 | if (verbose) { | |||
403 | int i; | |||
404 | printf ("! Keysym %s (0x%lx) corresponds to keycode(s)", | |||
405 | tmpname, (long) keysym); | |||
406 | for (i = 0; i < n; i++) | |||
407 | printf (" 0x%x", keycodes[i]); | |||
408 | printf("\n"); | |||
409 | } | |||
410 | ||||
411 | finish_keycodes (line, len, keycodes, n); | |||
412 | } | |||
413 | ||||
414 | static void | |||
415 | finish_keycodes(const char *line, int len, KeyCode *keycodes, int count) | |||
416 | { | |||
417 | int n; | |||
418 | KeySym *kslist; | |||
419 | union op *uop; | |||
420 | struct op_keycode *opk; | |||
421 | ||||
422 | n = skip_until_char (line, len, '='); | |||
423 | line += n, len -= n; | |||
424 | ||||
425 | if (len < 1 || *line != '=') { /* = minimum */ | |||
426 | badmsg0 ("keycode command (missing keysym list),"){ badheader(); fprintf (__stderrp, "keycode command (missing keysym list)," ); putc ('\n', __stderrp); }; | |||
427 | return; | |||
428 | } | |||
429 | line++, len--; /* skip past the = */ | |||
430 | ||||
431 | n = skip_space (line, len); | |||
432 | line += n, len -= n; | |||
433 | ||||
434 | /* allow empty list */ | |||
435 | if (get_keysym_list (line, len, &n, &kslist) < 0) | |||
436 | return; | |||
437 | ||||
438 | while (--count >= 0) { | |||
439 | uop = AllocStruct (union op)(malloc (sizeof (union op))); | |||
440 | if (!uop) { | |||
441 | badmsg ("attempt to allocate a %ld byte keycode opcode",{ badheader(); fprintf (__stderrp, "attempt to allocate a %ld byte keycode opcode" , (long) sizeof (struct op_keycode)); putc ('\n', __stderrp); } | |||
442 | (long) sizeof (struct op_keycode)){ badheader(); fprintf (__stderrp, "attempt to allocate a %ld byte keycode opcode" , (long) sizeof (struct op_keycode)); putc ('\n', __stderrp); }; | |||
443 | return; | |||
444 | } | |||
445 | opk = &uop->keycode; | |||
446 | ||||
447 | opk->type = doKeycode; | |||
448 | opk->target_keycode = keycodes[count]; | |||
449 | opk->count = n; | |||
450 | opk->keysyms = kslist; | |||
451 | ||||
452 | add_to_work_queue (uop); | |||
453 | } | |||
454 | ||||
455 | #ifdef later | |||
456 | /* make sure we handle any special keys */ | |||
457 | check_special_keys (keycode, n, kslist); | |||
458 | #endif | |||
459 | } | |||
460 | ||||
461 | ||||
462 | /* | |||
463 | * parse_modifier - convert a modifier string name to its index | |||
464 | */ | |||
465 | ||||
466 | struct modtab modifier_table[] = { /* keep in order so it can be index */ | |||
467 | { "shift", 5, 0 }, | |||
468 | { "lock", 4, 1 }, | |||
469 | { "control", 7, 2 }, | |||
470 | { "mod1", 4, 3 }, | |||
471 | { "mod2", 4, 4 }, | |||
472 | { "mod3", 4, 5 }, | |||
473 | { "mod4", 4, 6 }, | |||
474 | { "mod5", 4, 7 }, | |||
475 | { "ctrl", 4, 2 }, | |||
476 | { NULL((void*)0), 0, 0 }}; | |||
477 | ||||
478 | static int | |||
479 | parse_modifier(char *line, int n) | |||
480 | { | |||
481 | register int i; | |||
482 | struct modtab *mt; | |||
483 | ||||
484 | /* lowercase for comparison against table */ | |||
485 | for (i = 0; i < n; i++) { | |||
486 | if (isupper (line[i])) line[i] = tolower (line[i]); | |||
487 | } | |||
488 | ||||
489 | for (mt = modifier_table; mt->name; mt++) { | |||
490 | if (n == mt->length && strncmp (line, mt->name, n) == 0) | |||
491 | return (mt->value); | |||
492 | } | |||
493 | return (-1); | |||
494 | } | |||
495 | ||||
496 | ||||
497 | /* | |||
498 | * do_add - parse off lines of the form | |||
499 | * | |||
500 | * add MODIFIER = keysym ... | |||
501 | * ^ | |||
502 | * where the MODIFIER is one of Shift, Lock, Control, Mod[1-5] where case | |||
503 | * is not important. There should also be an alias Ctrl for control. | |||
504 | */ | |||
505 | ||||
506 | static void | |||
507 | do_add(char *line, int len) | |||
508 | { | |||
509 | int n; | |||
510 | int modifier; | |||
511 | KeySym *kslist; | |||
512 | union op *uop; | |||
513 | struct op_addmodifier *opam; | |||
514 | ||||
515 | if (len < 6 || !line || *line == '\0') { /* Lock=a minimum */ | |||
516 | badmsg0 ("add modifier input line"){ badheader(); fprintf (__stderrp, "add modifier input line") ; putc ('\n', __stderrp); }; | |||
517 | return; | |||
518 | } | |||
519 | ||||
520 | n = skip_chars (line, len); | |||
521 | if (n < 1) { | |||
522 | badmsg ("add modifier name %s", line){ badheader(); fprintf (__stderrp, "add modifier name %s", line ); putc ('\n', __stderrp); }; | |||
523 | return; | |||
524 | } | |||
525 | ||||
526 | modifier = parse_modifier (line, n); | |||
527 | if (modifier < 0) { | |||
528 | badmsgn ("add modifier name '%s', not allowed", line, n){ badheader(); fprintf (__stderrp, "add modifier name '%s', not allowed" , copy_to_scratch (line, n)); putc ('\n', __stderrp); }; | |||
529 | return; | |||
530 | } | |||
531 | ||||
532 | line += n, len -= n; | |||
533 | n = skip_until_char (line, len, '='); | |||
534 | if (n < 0) { | |||
535 | badmsg0 ("add modifier = keysym"){ badheader(); fprintf (__stderrp, "add modifier = keysym"); putc ('\n', __stderrp); }; | |||
536 | return; | |||
537 | } | |||
538 | ||||
539 | n++; /* skip = */ | |||
540 | n += skip_space (line+n, len-n); | |||
541 | line += n, len -= n; | |||
542 | ||||
543 | if (get_keysym_list (line, len, &n, &kslist) < 0) | |||
544 | return; | |||
545 | if (n == 0) { | |||
546 | badmsg0 ("add modifier keysym list (empty)"){ badheader(); fprintf (__stderrp, "add modifier keysym list (empty)" ); putc ('\n', __stderrp); }; | |||
547 | return; | |||
548 | } | |||
549 | ||||
550 | uop = AllocStruct (union op)(malloc (sizeof (union op))); | |||
551 | if (!uop) { | |||
552 | badmsg ("attempt to allocate %ld byte addmodifier opcode",{ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte addmodifier opcode" , (long) sizeof (struct op_addmodifier)); putc ('\n', __stderrp ); } | |||
553 | (long) sizeof (struct op_addmodifier)){ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte addmodifier opcode" , (long) sizeof (struct op_addmodifier)); putc ('\n', __stderrp ); }; | |||
554 | return; | |||
555 | } | |||
556 | opam = &uop->addmodifier; | |||
557 | ||||
558 | opam->type = doAddModifier; | |||
559 | opam->modifier = modifier; | |||
560 | opam->count = n; | |||
561 | opam->keysyms = kslist; | |||
562 | ||||
563 | add_to_work_queue (uop); | |||
564 | } | |||
565 | ||||
566 | #ifdef AUTO_ADD_REMOVE | |||
567 | /* | |||
568 | * make_add - stick a single add onto the queue | |||
569 | */ | |||
570 | static void | |||
571 | make_add(int modifier, KeySym keysym) | |||
572 | { | |||
573 | union op *uop; | |||
574 | struct op_addmodifier *opam; | |||
575 | ||||
576 | uop = AllocStruct (union op)(malloc (sizeof (union op))); | |||
577 | if (!uop) { | |||
578 | badmsg ("attempt to allocate %ld byte addmodifier opcode",{ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte addmodifier opcode" , (long) sizeof (struct op_addmodifier)); putc ('\n', __stderrp ); } | |||
579 | (long) sizeof (struct op_addmodifier)){ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte addmodifier opcode" , (long) sizeof (struct op_addmodifier)); putc ('\n', __stderrp ); }; | |||
580 | return; | |||
581 | } | |||
582 | opam = &uop->addmodifier; | |||
583 | ||||
584 | opam->type = doAddModifier; | |||
585 | opam->modifier = modifier; | |||
586 | opam->count = 1; | |||
587 | opam->keysyms = malloc (sizeof (KeySym)); | |||
588 | if (!opam->keysyms) { | |||
589 | badmsg ("attempt to allocate %ld byte KeySym", (long) sizeof (KeySym)){ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte KeySym" , (long) sizeof (KeySym)); putc ('\n', __stderrp); }; | |||
590 | free (opam); | |||
591 | return; | |||
592 | } | |||
593 | opam->keysyms[0] = keysym; | |||
594 | ||||
595 | add_to_work_queue (uop); | |||
596 | return; | |||
597 | } | |||
598 | #endif /* AUTO_ADD_REMOVE */ | |||
599 | ||||
600 | ||||
601 | /* | |||
602 | * do_remove - parse off lines of the form | |||
603 | * | |||
604 | * remove MODIFIER = oldkeysym ... | |||
605 | * ^ | |||
606 | * where the MODIFIER is one of Shift, Lock, Control, Mod[1-5] where case | |||
607 | * is not important. There should also be an alias Ctrl for control. | |||
608 | */ | |||
609 | ||||
610 | static void | |||
611 | do_remove(char *line, int len) | |||
612 | { | |||
613 | int n; | |||
614 | int nc; | |||
615 | int i; | |||
616 | int tot; | |||
617 | int modifier; | |||
618 | KeySym *kslist; | |||
619 | KeyCode *kclist; | |||
620 | union op *uop; | |||
621 | struct op_removemodifier *oprm; | |||
622 | ||||
623 | if (len < 6 || !line || *line == '\0') { /* Lock=a minimum */ | |||
| ||||
624 | badmsg0 ("remove modifier input line"){ badheader(); fprintf (__stderrp, "remove modifier input line" ); putc ('\n', __stderrp); }; | |||
625 | return; | |||
626 | } | |||
627 | ||||
628 | n = skip_chars (line, len); | |||
629 | if (n < 1) { | |||
630 | badmsg ("remove modifier name %s", line){ badheader(); fprintf (__stderrp, "remove modifier name %s", line); putc ('\n', __stderrp); }; | |||
631 | return; | |||
632 | } | |||
633 | ||||
634 | modifier = parse_modifier (line, n); | |||
635 | if (modifier < 0) { | |||
636 | badmsgn ("remove modifier name '%s', not allowed", line, n){ badheader(); fprintf (__stderrp, "remove modifier name '%s', not allowed" , copy_to_scratch (line, n)); putc ('\n', __stderrp); }; | |||
637 | return; | |||
638 | } | |||
639 | ||||
640 | line += n, len -= n; | |||
641 | n = skip_until_char (line, len, '='); | |||
642 | if (n < 0) { | |||
643 | badmsg0 ("remove modifier = keysym"){ badheader(); fprintf (__stderrp, "remove modifier = keysym" ); putc ('\n', __stderrp); }; | |||
644 | return; | |||
645 | } | |||
646 | ||||
647 | n++; | |||
648 | n += skip_space (line+n, len-n); | |||
649 | line += n, len -= n; | |||
650 | ||||
651 | if (get_keysym_list (line, len, &n, &kslist) < 0) | |||
652 | return; | |||
653 | if (n == 0) { | |||
654 | badmsg0 ("remove modifier keysym list (empty)"){ badheader(); fprintf (__stderrp, "remove modifier keysym list (empty)" ); putc ('\n', __stderrp); }; | |||
655 | return; | |||
656 | } | |||
657 | ||||
658 | /* | |||
659 | * unlike the add command, we have to now evaluate the keysyms | |||
660 | */ | |||
661 | ||||
662 | kclist = malloc (n * sizeof (KeyCode)); | |||
663 | if (!kclist) { | |||
664 | badmsg ("attempt to allocate %ld byte keycode list",{ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte keycode list" , (long) (n * sizeof (KeyCode))); putc ('\n', __stderrp); } | |||
665 | (long) (n * sizeof (KeyCode))){ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte keycode list" , (long) (n * sizeof (KeyCode))); putc ('\n', __stderrp); }; | |||
666 | free (kslist); | |||
667 | return; | |||
668 | } | |||
669 | ||||
670 | tot = n; | |||
671 | nc = 0; | |||
672 | for (i = 0; i < n; i++) { | |||
| ||||
673 | int num_kcs; | |||
674 | KeyCode *kcs; | |||
675 | kcs = KeysymToKeycodes (dpy, kslist[i], &num_kcs); | |||
676 | if (num_kcs == 0) { | |||
677 | char *tmpname = XKeysymToString (kslist[i]); | |||
678 | badmsg ("keysym in remove modifier list '%s', no corresponding keycodes",{ badheader(); fprintf (__stderrp, "keysym in remove modifier list '%s', no corresponding keycodes" , tmpname ? tmpname : "?"); putc ('\n', __stderrp); } | |||
679 | tmpname ? tmpname : "?"){ badheader(); fprintf (__stderrp, "keysym in remove modifier list '%s', no corresponding keycodes" , tmpname ? tmpname : "?"); putc ('\n', __stderrp); }; | |||
680 | continue; | |||
681 | } | |||
682 | if (verbose) { | |||
683 | int j; | |||
684 | char *tmpname = XKeysymToString (kslist[i]); | |||
685 | printf ("! Keysym %s (0x%lx) corresponds to keycode(s)", | |||
686 | tmpname ? tmpname : "?", (long) kslist[i]); | |||
687 | for (j = 0; j < num_kcs; j++) | |||
688 | printf(" 0x%x", kcs[j]); | |||
689 | printf("\n"); | |||
690 | } | |||
691 | if (nc + num_kcs > tot) { | |||
692 | tot = nc + num_kcs; | |||
693 | kclist = realloc(kclist, tot * sizeof(KeyCode)); | |||
694 | if (!kclist) { | |||
695 | badmsg ("attempt to allocate %ld byte keycode list",{ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte keycode list" , (long) (tot * sizeof (KeyCode))); putc ('\n', __stderrp); } | |||
696 | (long) (tot * sizeof (KeyCode))){ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte keycode list" , (long) (tot * sizeof (KeyCode))); putc ('\n', __stderrp); }; | |||
697 | free (kslist); | |||
698 | return; | |||
699 | } | |||
700 | } | |||
701 | while (--num_kcs >= 0) | |||
702 | kclist[nc++] = *kcs++; /* okay, add it to list */ | |||
703 | } | |||
704 | ||||
705 | free (kslist); /* all done with it */ | |||
706 | ||||
707 | uop = AllocStruct (union op)(malloc (sizeof (union op))); | |||
708 | if (!uop) { | |||
709 | badmsg ("attempt to allocate %ld byte removemodifier opcode",{ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte removemodifier opcode" , (long) sizeof (struct op_removemodifier)); putc ('\n', __stderrp ); } | |||
710 | (long) sizeof (struct op_removemodifier)){ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte removemodifier opcode" , (long) sizeof (struct op_removemodifier)); putc ('\n', __stderrp ); }; | |||
711 | return; | |||
712 | } | |||
713 | oprm = &uop->removemodifier; | |||
714 | ||||
715 | oprm->type = doRemoveModifier; | |||
716 | oprm->modifier = modifier; | |||
717 | oprm->count = nc; | |||
718 | oprm->keycodes = kclist; | |||
719 | ||||
720 | add_to_work_queue (uop); | |||
721 | } | |||
722 | ||||
723 | #ifdef AUTO_ADD_REMOVE | |||
724 | /* | |||
725 | * make_remove - stick a single remove onto the queue | |||
726 | */ | |||
727 | static void | |||
728 | make_remove(int modifier, KeyCode keycode) | |||
729 | { | |||
730 | union op *uop; | |||
731 | struct op_removemodifier *oprm; | |||
732 | ||||
733 | uop = AllocStruct (union op)(malloc (sizeof (union op))); | |||
734 | if (!uop) { | |||
735 | badmsg ("attempt to allocate %ld byte removemodifier opcode",{ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte removemodifier opcode" , (long) sizeof (struct op_removemodifier)); putc ('\n', __stderrp ); } | |||
736 | (long) sizeof (struct op_removemodifier)){ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte removemodifier opcode" , (long) sizeof (struct op_removemodifier)); putc ('\n', __stderrp ); }; | |||
737 | return; | |||
738 | } | |||
739 | oprm = &uop->removemodifier; | |||
740 | ||||
741 | oprm->type = doRemoveModifier; | |||
742 | oprm->modifier = modifier; | |||
743 | oprm->count = 1; | |||
744 | oprm->keycodes = malloc (sizeof (KeyCode)); | |||
745 | if (!oprm->keycodes) { | |||
746 | badmsg ("attempt to allocate %ld byte KeyCode",{ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte KeyCode" , (long) sizeof (KeyCode)); putc ('\n', __stderrp); } | |||
747 | (long) sizeof (KeyCode)){ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte KeyCode" , (long) sizeof (KeyCode)); putc ('\n', __stderrp); }; | |||
748 | free (oprm); | |||
749 | return; | |||
750 | } | |||
751 | oprm->keycodes[0] = keycode; | |||
752 | ||||
753 | add_to_work_queue (uop); | |||
754 | return; | |||
755 | } | |||
756 | #endif /* AUTO_ADD_REMOVE */ | |||
757 | ||||
758 | ||||
759 | /* | |||
760 | * do_clear - parse off lines of the form | |||
761 | * | |||
762 | * clear MODIFIER | |||
763 | * ^ | |||
764 | */ | |||
765 | ||||
766 | static void | |||
767 | do_clear(char *line, int len) | |||
768 | { | |||
769 | int n; | |||
770 | int modifier; | |||
771 | union op *uop; | |||
772 | struct op_clearmodifier *opcm; | |||
773 | ||||
774 | if (len < 4 || !line || *line == '\0') { /* Lock minimum */ | |||
775 | badmsg0 ("clear modifier input line"){ badheader(); fprintf (__stderrp, "clear modifier input line" ); putc ('\n', __stderrp); }; | |||
776 | return; | |||
777 | } | |||
778 | ||||
779 | n = skip_chars (line, len); | |||
780 | ||||
781 | modifier = parse_modifier (line, n); | |||
782 | if (modifier < 0) { | |||
783 | badmsgn ("clear modifier name '%s'", line, n){ badheader(); fprintf (__stderrp, "clear modifier name '%s'" , copy_to_scratch (line, n)); putc ('\n', __stderrp); }; | |||
784 | return; | |||
785 | } | |||
786 | n += skip_space (line+n, len-n); | |||
787 | if (n != len) { | |||
788 | badmsgn ("extra argument '%s' to clear modifier", line+n, len-n){ badheader(); fprintf (__stderrp, "extra argument '%s' to clear modifier" , copy_to_scratch (line+n, len-n)); putc ('\n', __stderrp); }; | |||
789 | /* okay to continue */ | |||
790 | } | |||
791 | ||||
792 | uop = AllocStruct (union op)(malloc (sizeof (union op))); | |||
793 | if (!uop) { | |||
794 | badmsg ("attempt to allocate %ld byte clearmodifier opcode",{ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte clearmodifier opcode" , (long) sizeof (struct op_clearmodifier)); putc ('\n', __stderrp ); } | |||
795 | (long) sizeof (struct op_clearmodifier)){ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte clearmodifier opcode" , (long) sizeof (struct op_clearmodifier)); putc ('\n', __stderrp ); }; | |||
796 | return; | |||
797 | } | |||
798 | opcm = &uop->clearmodifier; | |||
799 | ||||
800 | opcm->type = doClearModifier; | |||
801 | opcm->modifier = modifier; | |||
802 | ||||
803 | add_to_work_queue (uop); | |||
804 | } | |||
805 | ||||
806 | #ifndef HAVE_STRNCASECMP1 | |||
807 | static int | |||
808 | strncasecmp(const char *a, const char *b, int n) | |||
809 | { | |||
810 | int i; | |||
811 | int a1, b1; | |||
812 | ||||
813 | for (i = 0; i < n; i++, a++, b++) { | |||
814 | if (!*a) return -1; | |||
815 | if (!*b) return 1; | |||
816 | ||||
817 | if (*a != *b) { | |||
818 | a1 = (isascii(*a) && isupper(*a)) ? tolower(*a) : *a; | |||
819 | b1 = (isascii(*b) && isupper(*b)) ? tolower(*b) : *b; | |||
820 | if (a1 != b1) return b1 - a1; | |||
821 | } | |||
822 | } | |||
823 | return 0; | |||
824 | } | |||
825 | #endif | |||
826 | ||||
827 | /* | |||
828 | * do_pointer = get list of numbers of the form | |||
829 | * | |||
830 | * buttons = NUMBER ... | |||
831 | * ^ | |||
832 | */ | |||
833 | ||||
834 | static void | |||
835 | do_pointer(char *line, int len) | |||
836 | { | |||
837 | int n; | |||
838 | int i; | |||
839 | unsigned long val; | |||
840 | union op *uop; | |||
841 | struct op_pointer *opp; | |||
842 | unsigned char buttons[MAXBUTTONCODES256]; | |||
843 | int nbuttons; | |||
844 | char *strval; | |||
845 | Boolint ok; | |||
846 | ||||
847 | if (len < 2 || !line || *line == '\0') { /* =1 minimum */ | |||
848 | badmsg0 ("buttons input line"){ badheader(); fprintf (__stderrp, "buttons input line"); putc ('\n', __stderrp); }; | |||
849 | return; | |||
850 | } | |||
851 | ||||
852 | nbuttons = XGetPointerMapping (dpy, buttons, MAXBUTTONCODES256); | |||
853 | ||||
854 | n = skip_space (line, len); | |||
855 | line += n, len -= n; | |||
856 | ||||
857 | if (line[0] != '=') { | |||
858 | badmsg0 ("buttons pointer code list, missing equal sign"){ badheader(); fprintf (__stderrp, "buttons pointer code list, missing equal sign" ); putc ('\n', __stderrp); }; | |||
859 | return; | |||
860 | } | |||
861 | ||||
862 | line++, len--; /* skip = */ | |||
863 | n = skip_space (line, len); | |||
864 | line += n, len -= n; | |||
865 | ||||
866 | i = 0; | |||
867 | if (len < 7 || strncasecmp (line, "default", 7) != 0) { | |||
868 | while (len > 0) { | |||
869 | n = skip_space (line, len); | |||
870 | line += n, len -= n; | |||
871 | if (line[0] == '\0') break; | |||
872 | n = skip_word (line, len); | |||
873 | if (n < 1) { | |||
874 | badmsg ("skip of word in buttons line: %s", line){ badheader(); fprintf (__stderrp, "skip of word in buttons line: %s" , line); putc ('\n', __stderrp); }; | |||
875 | return; | |||
876 | } | |||
877 | strval = copy_to_scratch(line, n); | |||
878 | if (strval == NULL((void*)0)) | |||
879 | /* copy_to_scratch already printed error message */ | |||
880 | return; | |||
881 | ok = parse_number (strval, &val); | |||
882 | if (!ok || val >= MAXBUTTONCODES256) { | |||
883 | badmsg ("value %s given for buttons list", strval){ badheader(); fprintf (__stderrp, "value %s given for buttons list" , strval); putc ('\n', __stderrp); }; | |||
884 | return; | |||
885 | } | |||
886 | buttons[i++] = (unsigned char) val; | |||
887 | line += n, len -= n; | |||
888 | } | |||
889 | } | |||
890 | ||||
891 | if (i > 0 && i != nbuttons) { | |||
892 | fprintf (stderr__stderrp, "Warning: Only changing the first %d of %d buttons.\n", | |||
893 | i, nbuttons); | |||
894 | i = nbuttons; | |||
895 | } | |||
896 | ||||
897 | uop = AllocStruct (union op)(malloc (sizeof (union op))); | |||
898 | if (!uop) { | |||
899 | badmsg ("attempt to allocate a %ld byte pointer opcode",{ badheader(); fprintf (__stderrp, "attempt to allocate a %ld byte pointer opcode" , (long) sizeof (struct op_pointer)); putc ('\n', __stderrp); } | |||
900 | (long) sizeof (struct op_pointer)){ badheader(); fprintf (__stderrp, "attempt to allocate a %ld byte pointer opcode" , (long) sizeof (struct op_pointer)); putc ('\n', __stderrp); }; | |||
901 | return; | |||
902 | } | |||
903 | opp = &uop->pointer; | |||
904 | ||||
905 | opp->type = doPointer; | |||
906 | opp->count = i; | |||
907 | for (i = 0; i < opp->count; i++) { | |||
908 | opp->button_codes[i] = buttons[i]; | |||
909 | } | |||
910 | ||||
911 | add_to_work_queue (uop); | |||
912 | } | |||
913 | ||||
914 | ||||
915 | /* | |||
916 | * get_keysym_list - parses the rest of the line into a keysyms assumes | |||
917 | * that the = sign has been parsed off but there may be leading whitespace | |||
918 | * | |||
919 | * keysym ... | |||
920 | * ^ | |||
921 | * | |||
922 | * this involves getting the word containing the keysym, checking its range, | |||
923 | * and adding it to the list. | |||
924 | */ | |||
925 | ||||
926 | static int | |||
927 | get_keysym_list(const char *line, int len, int *np, KeySym **kslistp) | |||
928 | { | |||
929 | int havesofar, maxcanhave; | |||
930 | KeySym *keysymlist; | |||
931 | ||||
932 | *np = 0; | |||
933 | *kslistp = NULL((void*)0); | |||
934 | ||||
935 | if (len == 0) return (0); /* empty list */ | |||
936 | ||||
937 | havesofar = 0; | |||
938 | maxcanhave = 4; /* most lists are small */ | |||
939 | keysymlist = malloc (maxcanhave * sizeof (KeySym)); | |||
940 | if (!keysymlist) { | |||
941 | badmsg ("attempt to allocate %ld byte initial keysymlist",{ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte initial keysymlist" , (long) (maxcanhave * sizeof (KeySym))); putc ('\n', __stderrp ); } | |||
942 | (long) (maxcanhave * sizeof (KeySym))){ badheader(); fprintf (__stderrp, "attempt to allocate %ld byte initial keysymlist" , (long) (maxcanhave * sizeof (KeySym))); putc ('\n', __stderrp ); }; | |||
943 | return (-1); | |||
944 | } | |||
945 | ||||
946 | while (len > 0) { | |||
947 | KeySym keysym; | |||
948 | int n; | |||
949 | char *tmpname; | |||
950 | Boolint ok; | |||
951 | ||||
952 | n = skip_space (line, len); | |||
953 | line += n, len -= n; | |||
954 | ||||
955 | n = skip_chars (line, len); | |||
956 | if (n < 0) { | |||
957 | badmsg0 ("keysym name list"){ badheader(); fprintf (__stderrp, "keysym name list"); putc ( '\n', __stderrp); }; | |||
958 | free(keysymlist); | |||
959 | return (-1); | |||
960 | } | |||
961 | ||||
962 | ok = parse_keysym (line, n, &tmpname, &keysym); | |||
963 | line += n, len -= n; | |||
964 | if (!ok) { | |||
965 | badmsg ("keysym name '%s' in keysym list", tmpname){ badheader(); fprintf (__stderrp, "keysym name '%s' in keysym list" , tmpname); putc ('\n', __stderrp); }; | |||
966 | /* do NOT return here, look for others */ | |||
967 | continue; | |||
968 | } | |||
969 | ||||
970 | /* | |||
971 | * Do NOT test to see if the keysym translates to a keycode or you | |||
972 | * won't be able to assign new ones.... | |||
973 | */ | |||
974 | ||||
975 | /* grow the list bigger if necessary */ | |||
976 | if (havesofar >= maxcanhave) { | |||
977 | KeySym *origkeysymlist = keysymlist; | |||
978 | maxcanhave *= 2; | |||
979 | keysymlist = realloc (keysymlist, maxcanhave * sizeof (KeySym)); | |||
980 | if (!keysymlist) { | |||
981 | badmsg ("attempt to grow keysym list to %ld bytes",{ badheader(); fprintf (__stderrp, "attempt to grow keysym list to %ld bytes" , (long) (maxcanhave * sizeof (KeySym))); putc ('\n', __stderrp ); } | |||
982 | (long) (maxcanhave * sizeof (KeySym))){ badheader(); fprintf (__stderrp, "attempt to grow keysym list to %ld bytes" , (long) (maxcanhave * sizeof (KeySym))); putc ('\n', __stderrp ); }; | |||
983 | free(origkeysymlist); | |||
984 | return (-1); | |||
985 | } | |||
986 | } | |||
987 | ||||
988 | /* and add it to the list */ | |||
989 | keysymlist[havesofar++] = keysym; | |||
990 | } | |||
991 | ||||
992 | *kslistp = keysymlist; | |||
993 | *np = havesofar; | |||
994 | return (0); | |||
995 | } | |||
996 | ||||
997 | ||||
998 | #ifdef later | |||
999 | /* | |||
1000 | * check_special_keys - run through list of keysyms and generate "add" or | |||
1001 | * "remove" commands for for any of the key syms that appear in the modifier | |||
1002 | * list. this involves running down the modifier map which is an array of | |||
1003 | * 8 by map->max_keypermod keycodes. | |||
1004 | */ | |||
1005 | ||||
1006 | static void | |||
1007 | check_special_keys(KeyCode keycode, int n, KeySym *kslist) | |||
1008 | { | |||
1009 | int i; /* iterator variable */ | |||
1010 | KeyCode *kcp; /* keycode pointer */ | |||
1011 | ||||
1012 | /* | |||
1013 | * walk the modifiermap array. since its dimensions are not known at | |||
1014 | * compile time, we have to walk it by hand instead of indexing. this | |||
1015 | * is why it is initialized outside the loop, but incremented inside the | |||
1016 | * second loop. | |||
1017 | */ | |||
1018 | ||||
1019 | kcp = map->modifiermap; /* start at beginning and iterate */ | |||
1020 | for (i = 0; i < 8; i++) { /* there are 8 modifier keys */ | |||
1021 | int j; | |||
1022 | ||||
1023 | for (j = 0; j < map->max_keypermod; j++, kcp++) { | |||
1024 | KeySym keysym; | |||
1025 | int k; | |||
1026 | ||||
1027 | if (!*kcp) continue; /* only non-zero entries significant */ | |||
1028 | ||||
1029 | /* | |||
1030 | * check to see if the target keycode is already a modifier; if so, | |||
1031 | * then we have to remove it | |||
1032 | */ | |||
1033 | if (keycode == *kcp) { | |||
1034 | make_remove (i, keycode); | |||
1035 | } | |||
1036 | ||||
1037 | /* | |||
1038 | * now, check to see if any of the keysyms map to keycodes | |||
1039 | * that are in the modifier list | |||
1040 | */ | |||
1041 | for (k = 0; k < n; k++) { | |||
1042 | KeyCodes kc; | |||
1043 | ||||
1044 | kc = XKeysymToKeycode (dpy, kslist[k]); | |||
1045 | if (kc == *kcp) { /* yup, found one */ | |||
1046 | /* | |||
1047 | * have to generate a remove of the CURRENT keycode | |||
1048 | * and then an add of the new KEYCODE | |||
1049 | */ | |||
1050 | make_remove (i, kc); /* modifier, keycode */ | |||
1051 | make_add (i, kslist[k]); /* modifier, keysym */ | |||
1052 | } | |||
1053 | } | |||
1054 | } | |||
1055 | } | |||
1056 | return; | |||
1057 | } | |||
1058 | #endif | |||
1059 | ||||
1060 | /* | |||
1061 | * print_work_queue - disassemble the work queue and print it on stdout | |||
1062 | */ | |||
1063 | ||||
1064 | void | |||
1065 | print_work_queue(void) | |||
1066 | { | |||
1067 | union op *op; | |||
1068 | ||||
1069 | printf ("! dump of work queue\n"); | |||
1070 | for (op = work_queue.head; op; op = op->generic.next) { | |||
1071 | print_opcode (op); | |||
1072 | } | |||
1073 | return; | |||
1074 | } | |||
1075 | ||||
1076 | static void | |||
1077 | print_opcode(union op *op) | |||
1078 | { | |||
1079 | int i; | |||
1080 | ||||
1081 | printf (" "); | |||
1082 | switch (op->generic.type) { | |||
1083 | case doKeycode: | |||
1084 | if (op->keycode.target_keycode) | |||
1085 | printf ("keycode 0x%lx =", (long) op->keycode.target_keycode); | |||
1086 | else | |||
1087 | printf ("keycode any ="); | |||
1088 | for (i = 0; i < op->keycode.count; i++) { | |||
1089 | char *name = XKeysymToString (op->keycode.keysyms[i]); | |||
1090 | ||||
1091 | printf (" %s", name ? name : "BADKEYSYM"); | |||
1092 | } | |||
1093 | printf ("\n"); | |||
1094 | break; | |||
1095 | case doAddModifier: | |||
1096 | printf ("add %s =", modifier_table[op->addmodifier.modifier].name); | |||
1097 | for (i = 0; i < op->addmodifier.count; i++) { | |||
1098 | char *name = XKeysymToString (op->addmodifier.keysyms[i]); | |||
1099 | printf (" %s", name ? name : "BADKEYSYM"); | |||
1100 | } | |||
1101 | printf ("\n"); | |||
1102 | break; | |||
1103 | case doRemoveModifier: | |||
1104 | printf ("remove %s = ", | |||
1105 | modifier_table[op->removemodifier.modifier].name); | |||
1106 | for (i = 0; i < op->removemodifier.count; i++) { | |||
1107 | printf (" 0x%lx", (long) op->removemodifier.keycodes[i]); | |||
1108 | } | |||
1109 | printf ("\n"); | |||
1110 | break; | |||
1111 | case doClearModifier: | |||
1112 | printf ("clear %s\n", modifier_table[op->clearmodifier.modifier].name); | |||
1113 | break; | |||
1114 | case doPointer: | |||
1115 | printf ("pointer = "); | |||
1116 | if (op->pointer.count == 0) | |||
1117 | printf(" default"); | |||
1118 | else for (i=0; i < op->pointer.count; i++) | |||
1119 | printf(" %d", op->pointer.button_codes[i]); | |||
1120 | printf ("\n"); | |||
1121 | break; | |||
1122 | default: | |||
1123 | printf ("! unknown opcode %d\n", op->generic.type); | |||
1124 | break; | |||
1125 | } /* end switch */ | |||
1126 | return; | |||
1127 | } | |||
1128 | ||||
1129 | /* | |||
1130 | * execute_work_queue - do the real meat and potatoes now that we know what | |||
1131 | * we need to do and that all of the input is correct. | |||
1132 | */ | |||
1133 | static int exec_keycode ( struct op_keycode *opk ); | |||
1134 | static int exec_add ( struct op_addmodifier *opam ); | |||
1135 | static int exec_remove ( struct op_removemodifier *oprm ); | |||
1136 | static int exec_clear ( struct op_clearmodifier *opcm ); | |||
1137 | static int exec_pointer ( struct op_pointer *opp ); | |||
1138 | ||||
1139 | ||||
1140 | int | |||
1141 | execute_work_queue (void) | |||
1142 | { | |||
1143 | union op *op; | |||
1144 | int errors; | |||
1145 | Boolint update_map = False0; | |||
1146 | int dosync; | |||
1147 | ||||
1148 | if (verbose) { | |||
1149 | printf ("!\n"); | |||
1150 | printf ("! executing work queue\n"); | |||
1151 | printf ("!\n"); | |||
1152 | } | |||
1153 | ||||
1154 | errors = 0; | |||
1155 | dosync = 0; | |||
1156 | ||||
1157 | for (op = work_queue.head; op; op = op->generic.next) { | |||
1158 | if (verbose) print_opcode (op); | |||
1159 | ||||
1160 | /* check to see if we have to update the keyboard mapping */ | |||
1161 | if (dosync && | |||
1162 | (dosync < 0 || | |||
1163 | op->generic.type != doKeycode || | |||
1164 | !op->keycode.target_keycode)) { | |||
1165 | XSync (dpy, 0); | |||
1166 | while (XEventsQueued (dpy, QueuedAlready0) > 0) { | |||
1167 | XEvent event; | |||
1168 | XNextEvent (dpy, &event); | |||
1169 | if (event.type == MappingNotify34) { | |||
1170 | /* read all MappingNotify events */ | |||
1171 | while (XCheckTypedEvent (dpy, MappingNotify34, &event)) ; | |||
1172 | XRefreshKeyboardMapping (&event.xmapping); | |||
1173 | } else { | |||
1174 | fprintf (stderr__stderrp, "%s: unknown event %ld\n", | |||
1175 | ProgramName, (long) event.type); | |||
1176 | } | |||
1177 | } | |||
1178 | } | |||
1179 | dosync = 0; | |||
1180 | switch (op->generic.type) { | |||
1181 | case doKeycode: | |||
1182 | if (exec_keycode (&op->keycode) < 0) errors++; | |||
1183 | if (op->keycode.target_keycode) | |||
1184 | dosync = 1; | |||
1185 | else | |||
1186 | dosync = -1; | |||
1187 | break; | |||
1188 | case doAddModifier: | |||
1189 | if (exec_add (&op->addmodifier) < 0) errors++; | |||
1190 | else update_map = True1; | |||
1191 | break; | |||
1192 | case doRemoveModifier: | |||
1193 | if (exec_remove (&op->removemodifier) < 0) errors++; | |||
1194 | else update_map = True1; | |||
1195 | break; | |||
1196 | case doClearModifier: | |||
1197 | if (exec_clear (&op->clearmodifier) < 0) errors++; | |||
1198 | else update_map = True1; | |||
1199 | break; | |||
1200 | case doPointer: | |||
1201 | if (exec_pointer (&op->pointer) < 0) errors++; | |||
1202 | break; | |||
1203 | default: | |||
1204 | fprintf (stderr__stderrp, "%s: unknown opcode %d\n", | |||
1205 | ProgramName, op->generic.type); | |||
1206 | break; | |||
1207 | } | |||
1208 | } | |||
1209 | ||||
1210 | if (update_map) { | |||
1211 | if (UpdateModifierMapping (map) < 0) errors++; | |||
1212 | } | |||
1213 | ||||
1214 | return (errors > 0 ? -1 : 0); | |||
1215 | } | |||
1216 | ||||
1217 | static int | |||
1218 | exec_keycode(struct op_keycode *opk) | |||
1219 | { | |||
1220 | if (!opk->target_keycode) { | |||
1221 | int i, j; | |||
1222 | KeyCode free; | |||
1223 | if (!opk->count) | |||
1224 | return (0); | |||
1225 | free = 0; | |||
1226 | for (i = min_keycode; i <= max_keycode; i++) { | |||
1227 | for (j = 0; j < opk->count; j++) { | |||
1228 | if (XKeycodeToKeysym(dpy, (KeyCode) i, j) != opk->keysyms[j]) | |||
1229 | break; | |||
1230 | } | |||
1231 | if (j >= opk->count) | |||
1232 | return (0); | |||
1233 | if (free) | |||
1234 | continue; | |||
1235 | for (j = 0; j < 8; j++) { | |||
1236 | if (XKeycodeToKeysym(dpy, (KeyCode) i, j) != None0L) | |||
1237 | break; | |||
1238 | } | |||
1239 | if (j >= 8) | |||
1240 | free = i; | |||
1241 | } | |||
1242 | if (!free) { | |||
1243 | fprintf(stderr__stderrp, "%s: no available keycode for assignment\n", | |||
1244 | ProgramName); | |||
1245 | return (-1); | |||
1246 | } | |||
1247 | XChangeKeyboardMapping (dpy, free, opk->count, opk->keysyms, 1); | |||
1248 | } else if (opk->count == 0) { | |||
1249 | KeySym dummy = NoSymbol0L; | |||
1250 | XChangeKeyboardMapping (dpy, opk->target_keycode, 1, | |||
1251 | &dummy, 1); | |||
1252 | } else { | |||
1253 | XChangeKeyboardMapping (dpy, opk->target_keycode, opk->count, | |||
1254 | opk->keysyms, 1); | |||
1255 | } | |||
1256 | return (0); | |||
1257 | } | |||
1258 | ||||
1259 | static int | |||
1260 | exec_add(struct op_addmodifier *opam) | |||
1261 | { | |||
1262 | int i; | |||
1263 | int status; | |||
1264 | ||||
1265 | status = 0; | |||
1266 | for (i = 0; i < opam->count; i++) { | |||
1267 | int num_kcs; | |||
1268 | KeyCode *kcs; | |||
1269 | ||||
1270 | kcs = KeysymToKeycodes (dpy, opam->keysyms[i], &num_kcs); | |||
1271 | if (num_kcs == 0) | |||
1272 | status = -1; | |||
1273 | while (--num_kcs >= 0) { | |||
1274 | if (AddModifier (&map, *kcs++, opam->modifier) < 0) | |||
1275 | status = -1; | |||
1276 | } | |||
1277 | } | |||
1278 | return (status); | |||
1279 | } | |||
1280 | ||||
1281 | static int | |||
1282 | exec_remove(struct op_removemodifier *oprm) | |||
1283 | { | |||
1284 | int i; | |||
1285 | int status; | |||
1286 | ||||
1287 | status = 0; | |||
1288 | for (i = 0; i < oprm->count; i++) { | |||
1289 | if (RemoveModifier (&map, oprm->keycodes[i], oprm->modifier) < 0) | |||
1290 | status = -1; | |||
1291 | } | |||
1292 | return (status); | |||
1293 | } | |||
1294 | ||||
1295 | static int | |||
1296 | exec_clear(struct op_clearmodifier *opcm) | |||
1297 | { | |||
1298 | return (ClearModifier (&map, opcm->modifier)); | |||
1299 | } | |||
1300 | ||||
1301 | ||||
1302 | static int | |||
1303 | exec_pointer(struct op_pointer *opp) | |||
1304 | { | |||
1305 | return (SetPointerMap (opp->button_codes, opp->count)); | |||
1306 | } | |||
1307 | ||||
1308 | void | |||
1309 | print_modifier_map(void) | |||
1310 | { | |||
1311 | PrintModifierMapping (map, stdout__stdoutp); | |||
1312 | return; | |||
1313 | } | |||
1314 | ||||
1315 | void | |||
1316 | print_key_table(Boolint exprs) | |||
1317 | { | |||
1318 | PrintKeyTable (exprs, stdout__stdoutp); | |||
1319 | return; | |||
1320 | } | |||
1321 | ||||
1322 | void | |||
1323 | print_pointer_map(void) | |||
1324 | { | |||
1325 | PrintPointerMap (stdout__stdoutp); | |||
1326 | return; | |||
1327 | } | |||
1328 | ||||
1329 |