| File: | handle.c |
| Location: | line 709, column 2 |
| Description: | Potential leak of memory pointed to by 'kclist' |
| 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 |