action.c revision c82dfdfb
1/************************************************************ 2 Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. 3 4 Permission to use, copy, modify, and distribute this 5 software and its documentation for any purpose and without 6 fee is hereby granted, provided that the above copyright 7 notice appear in all copies and that both that copyright 8 notice and this permission notice appear in supporting 9 documentation, and that the name of Silicon Graphics not be 10 used in advertising or publicity pertaining to distribution 11 of the software without specific prior written permission. 12 Silicon Graphics makes no representation about the suitability 13 of this software for any purpose. It is provided "as is" 14 without any express or implied warranty. 15 16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23 THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 25 ********************************************************/ 26 27#include "xkbcomp.h" 28#include "tokens.h" 29#include "expr.h" 30 31#include "keycodes.h" 32#include "vmod.h" 33#include "misc.h" 34#include "action.h" 35#include "misc.h" 36 37static Bool actionsInitialized; 38static ExprDef constTrue; 39static ExprDef constFalse; 40 41/***====================================================================***/ 42 43static Bool 44stringToAction(const char *str, unsigned *type_rtrn) 45{ 46 if (str == NULL) 47 return False; 48 49 if (uStrCaseCmp(str, "noaction") == 0) 50 *type_rtrn = XkbSA_NoAction; 51 else if (uStrCaseCmp(str, "setmods") == 0) 52 *type_rtrn = XkbSA_SetMods; 53 else if (uStrCaseCmp(str, "latchmods") == 0) 54 *type_rtrn = XkbSA_LatchMods; 55 else if (uStrCaseCmp(str, "lockmods") == 0) 56 *type_rtrn = XkbSA_LockMods; 57 else if (uStrCaseCmp(str, "setgroup") == 0) 58 *type_rtrn = XkbSA_SetGroup; 59 else if (uStrCaseCmp(str, "latchgroup") == 0) 60 *type_rtrn = XkbSA_LatchGroup; 61 else if (uStrCaseCmp(str, "lockgroup") == 0) 62 *type_rtrn = XkbSA_LockGroup; 63 else if (uStrCaseCmp(str, "moveptr") == 0) 64 *type_rtrn = XkbSA_MovePtr; 65 else if (uStrCaseCmp(str, "movepointer") == 0) 66 *type_rtrn = XkbSA_MovePtr; 67 else if (uStrCaseCmp(str, "ptrbtn") == 0) 68 *type_rtrn = XkbSA_PtrBtn; 69 else if (uStrCaseCmp(str, "pointerbutton") == 0) 70 *type_rtrn = XkbSA_PtrBtn; 71 else if (uStrCaseCmp(str, "lockptrbtn") == 0) 72 *type_rtrn = XkbSA_LockPtrBtn; 73 else if (uStrCaseCmp(str, "lockpointerbutton") == 0) 74 *type_rtrn = XkbSA_LockPtrBtn; 75 else if (uStrCaseCmp(str, "lockptrbutton") == 0) 76 *type_rtrn = XkbSA_LockPtrBtn; 77 else if (uStrCaseCmp(str, "lockpointerbtn") == 0) 78 *type_rtrn = XkbSA_LockPtrBtn; 79 else if (uStrCaseCmp(str, "setptrdflt") == 0) 80 *type_rtrn = XkbSA_SetPtrDflt; 81 else if (uStrCaseCmp(str, "setpointerdefault") == 0) 82 *type_rtrn = XkbSA_SetPtrDflt; 83 else if (uStrCaseCmp(str, "isolock") == 0) 84 *type_rtrn = XkbSA_ISOLock; 85 else if (uStrCaseCmp(str, "terminate") == 0) 86 *type_rtrn = XkbSA_Terminate; 87 else if (uStrCaseCmp(str, "terminateserver") == 0) 88 *type_rtrn = XkbSA_Terminate; 89 else if (uStrCaseCmp(str, "switchscreen") == 0) 90 *type_rtrn = XkbSA_SwitchScreen; 91 else if (uStrCaseCmp(str, "setcontrols") == 0) 92 *type_rtrn = XkbSA_SetControls; 93 else if (uStrCaseCmp(str, "lockcontrols") == 0) 94 *type_rtrn = XkbSA_LockControls; 95 else if (uStrCaseCmp(str, "actionmessage") == 0) 96 *type_rtrn = XkbSA_ActionMessage; 97 else if (uStrCaseCmp(str, "messageaction") == 0) 98 *type_rtrn = XkbSA_ActionMessage; 99 else if (uStrCaseCmp(str, "message") == 0) 100 *type_rtrn = XkbSA_ActionMessage; 101 else if (uStrCaseCmp(str, "redirect") == 0) 102 *type_rtrn = XkbSA_RedirectKey; 103 else if (uStrCaseCmp(str, "redirectkey") == 0) 104 *type_rtrn = XkbSA_RedirectKey; 105 else if (uStrCaseCmp(str, "devbtn") == 0) 106 *type_rtrn = XkbSA_DeviceBtn; 107 else if (uStrCaseCmp(str, "devicebtn") == 0) 108 *type_rtrn = XkbSA_DeviceBtn; 109 else if (uStrCaseCmp(str, "devbutton") == 0) 110 *type_rtrn = XkbSA_DeviceBtn; 111 else if (uStrCaseCmp(str, "devicebutton") == 0) 112 *type_rtrn = XkbSA_DeviceBtn; 113 else if (uStrCaseCmp(str, "lockdevbtn") == 0) 114 *type_rtrn = XkbSA_DeviceBtn; 115 else if (uStrCaseCmp(str, "lockdevicebtn") == 0) 116 *type_rtrn = XkbSA_LockDeviceBtn; 117 else if (uStrCaseCmp(str, "lockdevbutton") == 0) 118 *type_rtrn = XkbSA_LockDeviceBtn; 119 else if (uStrCaseCmp(str, "lockdevicebutton") == 0) 120 *type_rtrn = XkbSA_LockDeviceBtn; 121 else if (uStrCaseCmp(str, "devval") == 0) 122 *type_rtrn = XkbSA_DeviceValuator; 123 else if (uStrCaseCmp(str, "deviceval") == 0) 124 *type_rtrn = XkbSA_DeviceValuator; 125 else if (uStrCaseCmp(str, "devvaluator") == 0) 126 *type_rtrn = XkbSA_DeviceValuator; 127 else if (uStrCaseCmp(str, "devicevaluator") == 0) 128 *type_rtrn = XkbSA_DeviceValuator; 129 else if (uStrCaseCmp(str, "private") == 0) 130 *type_rtrn = PrivateAction; 131 else 132 return False; 133 return True; 134} 135 136static Bool 137stringToField(const char *str, unsigned *field_rtrn) 138{ 139 140 if (str == NULL) 141 return False; 142 143 if (uStrCaseCmp(str, "clearlocks") == 0) 144 *field_rtrn = F_ClearLocks; 145 else if (uStrCaseCmp(str, "latchtolock") == 0) 146 *field_rtrn = F_LatchToLock; 147 else if (uStrCaseCmp(str, "genkeyevent") == 0) 148 *field_rtrn = F_GenKeyEvent; 149 else if (uStrCaseCmp(str, "generatekeyevent") == 0) 150 *field_rtrn = F_GenKeyEvent; 151 else if (uStrCaseCmp(str, "report") == 0) 152 *field_rtrn = F_Report; 153 else if (uStrCaseCmp(str, "default") == 0) 154 *field_rtrn = F_Default; 155 else if (uStrCaseCmp(str, "affect") == 0) 156 *field_rtrn = F_Affect; 157 else if (uStrCaseCmp(str, "increment") == 0) 158 *field_rtrn = F_Increment; 159 else if (uStrCaseCmp(str, "mods") == 0) 160 *field_rtrn = F_Modifiers; 161 else if (uStrCaseCmp(str, "modifiers") == 0) 162 *field_rtrn = F_Modifiers; 163 else if (uStrCaseCmp(str, "group") == 0) 164 *field_rtrn = F_Group; 165 else if (uStrCaseCmp(str, "x") == 0) 166 *field_rtrn = F_X; 167 else if (uStrCaseCmp(str, "y") == 0) 168 *field_rtrn = F_Y; 169 else if (uStrCaseCmp(str, "accel") == 0) 170 *field_rtrn = F_Accel; 171 else if (uStrCaseCmp(str, "accelerate") == 0) 172 *field_rtrn = F_Accel; 173 else if (uStrCaseCmp(str, "repeat") == 0) 174 *field_rtrn = F_Accel; 175 else if (uStrCaseCmp(str, "button") == 0) 176 *field_rtrn = F_Button; 177 else if (uStrCaseCmp(str, "value") == 0) 178 *field_rtrn = F_Value; 179 else if (uStrCaseCmp(str, "controls") == 0) 180 *field_rtrn = F_Controls; 181 else if (uStrCaseCmp(str, "ctrls") == 0) 182 *field_rtrn = F_Controls; 183 else if (uStrCaseCmp(str, "type") == 0) 184 *field_rtrn = F_Type; 185 else if (uStrCaseCmp(str, "count") == 0) 186 *field_rtrn = F_Count; 187 else if (uStrCaseCmp(str, "screen") == 0) 188 *field_rtrn = F_Screen; 189 else if (uStrCaseCmp(str, "same") == 0) 190 *field_rtrn = F_Same; 191 else if (uStrCaseCmp(str, "sameserver") == 0) 192 *field_rtrn = F_Same; 193 else if (uStrCaseCmp(str, "data") == 0) 194 *field_rtrn = F_Data; 195 else if (uStrCaseCmp(str, "device") == 0) 196 *field_rtrn = F_Device; 197 else if (uStrCaseCmp(str, "dev") == 0) 198 *field_rtrn = F_Device; 199 else if (uStrCaseCmp(str, "key") == 0) 200 *field_rtrn = F_Keycode; 201 else if (uStrCaseCmp(str, "keycode") == 0) 202 *field_rtrn = F_Keycode; 203 else if (uStrCaseCmp(str, "kc") == 0) 204 *field_rtrn = F_Keycode; 205 else if (uStrCaseCmp(str, "clearmods") == 0) 206 *field_rtrn = F_ModsToClear; 207 else if (uStrCaseCmp(str, "clearmodifiers") == 0) 208 *field_rtrn = F_ModsToClear; 209 else 210 return False; 211 return True; 212} 213 214static char * 215fieldText(unsigned field) 216{ 217 static char buf[32]; 218 219 switch (field) 220 { 221 case F_ClearLocks: 222 strcpy(buf, "clearLocks"); 223 break; 224 case F_LatchToLock: 225 strcpy(buf, "latchToLock"); 226 break; 227 case F_GenKeyEvent: 228 strcpy(buf, "genKeyEvent"); 229 break; 230 case F_Report: 231 strcpy(buf, "report"); 232 break; 233 case F_Default: 234 strcpy(buf, "default"); 235 break; 236 case F_Affect: 237 strcpy(buf, "affect"); 238 break; 239 case F_Increment: 240 strcpy(buf, "increment"); 241 break; 242 case F_Modifiers: 243 strcpy(buf, "modifiers"); 244 break; 245 case F_Group: 246 strcpy(buf, "group"); 247 break; 248 case F_X: 249 strcpy(buf, "x"); 250 break; 251 case F_Y: 252 strcpy(buf, "y"); 253 break; 254 case F_Accel: 255 strcpy(buf, "accel"); 256 break; 257 case F_Button: 258 strcpy(buf, "button"); 259 break; 260 case F_Value: 261 strcpy(buf, "value"); 262 break; 263 case F_Controls: 264 strcpy(buf, "controls"); 265 break; 266 case F_Type: 267 strcpy(buf, "type"); 268 break; 269 case F_Count: 270 strcpy(buf, "count"); 271 break; 272 case F_Screen: 273 strcpy(buf, "screen"); 274 break; 275 case F_Same: 276 strcpy(buf, "sameServer"); 277 break; 278 case F_Data: 279 strcpy(buf, "data"); 280 break; 281 case F_Device: 282 strcpy(buf, "device"); 283 break; 284 case F_Keycode: 285 strcpy(buf, "keycode"); 286 break; 287 case F_ModsToClear: 288 strcpy(buf, "clearmods"); 289 break; 290 default: 291 strcpy(buf, "unknown"); 292 break; 293 } 294 return buf; 295} 296 297/***====================================================================***/ 298 299static Bool 300ReportMismatch(unsigned action, unsigned field, const char *type) 301{ 302 ERROR2("Value of %s field must be of type %s\n", fieldText(field), type); 303 ACTION1("Action %s definition ignored\n", 304 XkbActionTypeText(action, XkbMessage)); 305 return False; 306} 307 308static Bool 309ReportIllegal(unsigned action, unsigned field) 310{ 311 ERROR2("Field %s is not defined for an action of type %s\n", 312 fieldText(field), XkbActionTypeText(action, XkbMessage)); 313 ACTION("Action definition ignored\n"); 314 return False; 315} 316 317static Bool 318ReportActionNotArray(unsigned action, unsigned field) 319{ 320 ERROR2("The %s field in the %s action is not an array\n", 321 fieldText(field), XkbActionTypeText(action, XkbMessage)); 322 ACTION("Action definition ignored\n"); 323 return False; 324} 325 326static Bool 327ReportNotFound(unsigned action, unsigned field, const char *what, char *bad) 328{ 329 ERROR2("%s named %s not found\n", what, bad); 330 ACTION2("Ignoring the %s field of an %s action\n", fieldText(field), 331 XkbActionTypeText(action, XkbMessage)); 332 return False; 333} 334 335static Bool 336HandleNoAction(XkbDescPtr xkb, 337 XkbAnyAction * action, 338 unsigned field, ExprDef * array_ndx, ExprDef * value) 339{ 340 return ReportIllegal(action->type, field); 341} 342 343static Bool 344CheckLatchLockFlags(unsigned action, 345 unsigned field, ExprDef * value, unsigned *flags_inout) 346{ 347 unsigned tmp; 348 ExprResult result; 349 350 if (field == F_ClearLocks) 351 tmp = XkbSA_ClearLocks; 352 else if (field == F_LatchToLock) 353 tmp = XkbSA_LatchToLock; 354 else 355 return False; /* WSGO! */ 356 if (!ExprResolveBoolean(value, &result, NULL, NULL)) 357 return ReportMismatch(action, field, "boolean"); 358 if (result.uval) 359 *flags_inout |= tmp; 360 else 361 *flags_inout &= ~tmp; 362 return True; 363} 364 365static Bool 366CheckModifierField(XkbDescPtr xkb, 367 unsigned action, 368 ExprDef * value, 369 unsigned *flags_inout, unsigned *mods_rtrn) 370{ 371 ExprResult rtrn; 372 373 if (value->op == ExprIdent) 374 { 375 register char *valStr; 376 valStr = XkbAtomGetString(NULL, value->value.str); 377 if (valStr && ((uStrCaseCmp(valStr, "usemodmapmods") == 0) || 378 (uStrCaseCmp(valStr, "modmapmods") == 0))) 379 { 380 381 *mods_rtrn = 0; 382 *flags_inout |= XkbSA_UseModMapMods; 383 return True; 384 } 385 } 386 if (!ExprResolveModMask(value, &rtrn, LookupVModMask, (XPointer) xkb)) 387 return ReportMismatch(action, F_Modifiers, "modifier mask"); 388 *mods_rtrn = rtrn.uval; 389 *flags_inout &= ~XkbSA_UseModMapMods; 390 return True; 391} 392 393static Bool 394HandleSetLatchMods(XkbDescPtr xkb, 395 XkbAnyAction * action, 396 unsigned field, ExprDef * array_ndx, ExprDef * value) 397{ 398 XkbModAction *act; 399 unsigned rtrn; 400 unsigned t1, t2; 401 402 act = (XkbModAction *) action; 403 if (array_ndx != NULL) 404 { 405 switch (field) 406 { 407 case F_ClearLocks: 408 case F_LatchToLock: 409 case F_Modifiers: 410 return ReportActionNotArray(action->type, field); 411 } 412 } 413 switch (field) 414 { 415 case F_ClearLocks: 416 case F_LatchToLock: 417 rtrn = act->flags; 418 if (CheckLatchLockFlags(action->type, field, value, &rtrn)) 419 { 420 act->flags = rtrn; 421 return True; 422 } 423 return False; 424 case F_Modifiers: 425 t1 = act->flags; 426 if (CheckModifierField(xkb, action->type, value, &t1, &t2)) 427 { 428 act->flags = t1; 429 act->real_mods = act->mask = (t2 & 0xff); 430 t2 = (t2 >> 8) & 0xffff; 431 XkbSetModActionVMods(act, t2); 432 return True; 433 } 434 return False; 435 } 436 return ReportIllegal(action->type, field); 437} 438 439static Bool 440HandleLockMods(XkbDescPtr xkb, 441 XkbAnyAction * action, 442 unsigned field, ExprDef * array_ndx, ExprDef * value) 443{ 444 XkbModAction *act; 445 unsigned t1, t2; 446 447 act = (XkbModAction *) action; 448 if ((array_ndx != NULL) && (field == F_Modifiers)) 449 return ReportActionNotArray(action->type, field); 450 switch (field) 451 { 452 case F_Modifiers: 453 t1 = act->flags; 454 if (CheckModifierField(xkb, action->type, value, &t1, &t2)) 455 { 456 act->flags = t1; 457 act->real_mods = act->mask = (t2 & 0xff); 458 t2 = (t2 >> 8) & 0xffff; 459 XkbSetModActionVMods(act, t2); 460 return True; 461 } 462 return False; 463 } 464 return ReportIllegal(action->type, field); 465} 466 467static LookupEntry groupNames[] = { 468 {"group1", 1}, 469 {"group2", 2}, 470 {"group3", 3}, 471 {"group4", 4}, 472 {"group5", 5}, 473 {"group6", 6}, 474 {"group7", 7}, 475 {"group8", 8}, 476 {NULL, 0}, 477}; 478 479static Bool 480CheckGroupField(unsigned action, 481 ExprDef * value, unsigned *flags_inout, int *grp_rtrn) 482{ 483 ExprDef *spec; 484 ExprResult rtrn; 485 486 if ((value->op == OpNegate) || (value->op == OpUnaryPlus)) 487 { 488 *flags_inout &= ~XkbSA_GroupAbsolute; 489 spec = value->value.child; 490 } 491 else 492 { 493 *flags_inout |= XkbSA_GroupAbsolute; 494 spec = value; 495 } 496 497 if (!ExprResolveInteger(spec, &rtrn, SimpleLookup, (XPointer) groupNames)) 498 return ReportMismatch(action, F_Group, "integer (range 1..8)"); 499 if ((rtrn.ival < 1) || (rtrn.ival > XkbNumKbdGroups)) 500 { 501 ERROR2("Illegal group %d (must be in the range 1..%d)\n", rtrn.ival, 502 XkbNumKbdGroups); 503 ACTION1("Action %s definition ignored\n", 504 XkbActionTypeText(action, XkbMessage)); 505 return False; 506 } 507 if (value->op == OpNegate) 508 *grp_rtrn = -rtrn.ival; 509 else if (value->op == OpUnaryPlus) 510 *grp_rtrn = rtrn.ival; 511 else 512 *grp_rtrn = rtrn.ival - 1; 513 return True; 514} 515 516static Bool 517HandleSetLatchGroup(XkbDescPtr xkb, 518 XkbAnyAction * action, 519 unsigned field, ExprDef * array_ndx, ExprDef * value) 520{ 521 XkbGroupAction *act; 522 unsigned rtrn; 523 unsigned t1; 524 int t2; 525 526 act = (XkbGroupAction *) action; 527 if (array_ndx != NULL) 528 { 529 switch (field) 530 { 531 case F_ClearLocks: 532 case F_LatchToLock: 533 case F_Group: 534 return ReportActionNotArray(action->type, field); 535 } 536 } 537 switch (field) 538 { 539 case F_ClearLocks: 540 case F_LatchToLock: 541 rtrn = act->flags; 542 if (CheckLatchLockFlags(action->type, field, value, &rtrn)) 543 { 544 act->flags = rtrn; 545 return True; 546 } 547 return False; 548 case F_Group: 549 t1 = act->flags; 550 if (CheckGroupField(action->type, value, &t1, &t2)) 551 { 552 act->flags = t1; 553 XkbSASetGroup(act, t2); 554 return True; 555 } 556 return False; 557 } 558 return ReportIllegal(action->type, field); 559} 560 561static Bool 562HandleLockGroup(XkbDescPtr xkb, 563 XkbAnyAction * action, 564 unsigned field, ExprDef * array_ndx, ExprDef * value) 565{ 566 XkbGroupAction *act; 567 unsigned t1; 568 int t2; 569 570 act = (XkbGroupAction *) action; 571 if ((array_ndx != NULL) && (field == F_Group)) 572 return ReportActionNotArray(action->type, field); 573 if (field == F_Group) 574 { 575 t1 = act->flags; 576 if (CheckGroupField(action->type, value, &t1, &t2)) 577 { 578 act->flags = t1; 579 XkbSASetGroup(act, t2); 580 return True; 581 } 582 return False; 583 } 584 return ReportIllegal(action->type, field); 585} 586 587static Bool 588HandleMovePtr(XkbDescPtr xkb, 589 XkbAnyAction * action, 590 unsigned field, ExprDef * array_ndx, ExprDef * value) 591{ 592 ExprResult rtrn; 593 XkbPtrAction *act; 594 Bool absolute; 595 596 act = (XkbPtrAction *) action; 597 if ((array_ndx != NULL) && ((field == F_X) || (field == F_Y))) 598 return ReportActionNotArray(action->type, field); 599 600 if ((field == F_X) || (field == F_Y)) 601 { 602 if ((value->op == OpNegate) || (value->op == OpUnaryPlus)) 603 absolute = False; 604 else 605 absolute = True; 606 if (!ExprResolveInteger(value, &rtrn, NULL, NULL)) 607 return ReportMismatch(action->type, field, "integer"); 608 if (field == F_X) 609 { 610 if (absolute) 611 act->flags |= XkbSA_MoveAbsoluteX; 612 XkbSetPtrActionX(act, rtrn.ival); 613 } 614 else 615 { 616 if (absolute) 617 act->flags |= XkbSA_MoveAbsoluteY; 618 XkbSetPtrActionY(act, rtrn.ival); 619 } 620 return True; 621 } 622 else if (field == F_Accel) 623 { 624 if (!ExprResolveBoolean(value, &rtrn, NULL, NULL)) 625 return ReportMismatch(action->type, field, "boolean"); 626 if (rtrn.uval) 627 act->flags &= ~XkbSA_NoAcceleration; 628 else 629 act->flags |= XkbSA_NoAcceleration; 630 } 631 return ReportIllegal(action->type, field); 632} 633 634static LookupEntry btnNames[] = { 635 {"button1", 1}, 636 {"button2", 2}, 637 {"button3", 3}, 638 {"button4", 4}, 639 {"button5", 5}, 640 {"default", 0}, 641 {NULL, 0} 642}; 643 644static LookupEntry lockWhich[] = { 645 {"both", 0}, 646 {"lock", XkbSA_LockNoUnlock}, 647 {"neither", (XkbSA_LockNoLock | XkbSA_LockNoUnlock)}, 648 {"unlock", XkbSA_LockNoLock}, 649 {NULL, 0} 650}; 651 652static Bool 653HandlePtrBtn(XkbDescPtr xkb, 654 XkbAnyAction * action, 655 unsigned field, ExprDef * array_ndx, ExprDef * value) 656{ 657 ExprResult rtrn; 658 XkbPtrBtnAction *act; 659 660 act = (XkbPtrBtnAction *) action; 661 if (field == F_Button) 662 { 663 if (array_ndx != NULL) 664 return ReportActionNotArray(action->type, field); 665 if (!ExprResolveInteger 666 (value, &rtrn, SimpleLookup, (XPointer) btnNames)) 667 return ReportMismatch(action->type, field, 668 "integer (range 1..5)"); 669 if ((rtrn.ival < 0) || (rtrn.ival > 5)) 670 { 671 ERROR("Button must specify default or be in the range 1..5\n"); 672 ACTION1("Illegal button value %d ignored\n", rtrn.ival); 673 return False; 674 } 675 act->button = rtrn.ival; 676 return True; 677 } 678 else if ((action->type == XkbSA_LockPtrBtn) && (field == F_Affect)) 679 { 680 if (array_ndx != NULL) 681 return ReportActionNotArray(action->type, field); 682 if (!ExprResolveEnum(value, &rtrn, lockWhich)) 683 return ReportMismatch(action->type, field, "lock or unlock"); 684 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock); 685 act->flags |= rtrn.ival; 686 return True; 687 } 688 else if (field == F_Count) 689 { 690 if (array_ndx != NULL) 691 return ReportActionNotArray(action->type, field); 692 if (!ExprResolveInteger 693 (value, &rtrn, SimpleLookup, (XPointer) btnNames)) 694 return ReportMismatch(action->type, field, "integer"); 695 if ((rtrn.ival < 0) || (rtrn.ival > 255)) 696 { 697 ERROR("The count field must have a value in the range 0..255\n"); 698 ACTION1("Illegal count %d ignored\n", rtrn.ival); 699 return False; 700 } 701 act->count = rtrn.ival; 702 return True; 703 } 704 return ReportIllegal(action->type, field); 705} 706 707static LookupEntry ptrDflts[] = { 708 {"dfltbtn", XkbSA_AffectDfltBtn}, 709 {"defaultbutton", XkbSA_AffectDfltBtn}, 710 {"button", XkbSA_AffectDfltBtn}, 711 {NULL, 0} 712}; 713 714static Bool 715HandleSetPtrDflt(XkbDescPtr xkb, 716 XkbAnyAction * action, 717 unsigned field, ExprDef * array_ndx, ExprDef * value) 718{ 719 ExprResult rtrn; 720 XkbPtrDfltAction *act; 721 722 act = (XkbPtrDfltAction *) action; 723 if (field == F_Affect) 724 { 725 if (array_ndx != NULL) 726 return ReportActionNotArray(action->type, field); 727 if (!ExprResolveEnum(value, &rtrn, ptrDflts)) 728 return ReportMismatch(action->type, field, "pointer component"); 729 act->affect = rtrn.uval; 730 return True; 731 } 732 else if ((field == F_Button) || (field == F_Value)) 733 { 734 ExprDef *btn; 735 if (array_ndx != NULL) 736 return ReportActionNotArray(action->type, field); 737 if ((value->op == OpNegate) || (value->op == OpUnaryPlus)) 738 { 739 act->flags &= ~XkbSA_DfltBtnAbsolute; 740 btn = value->value.child; 741 } 742 else 743 { 744 act->flags |= XkbSA_DfltBtnAbsolute; 745 btn = value; 746 } 747 748 if (!ExprResolveInteger 749 (btn, &rtrn, SimpleLookup, (XPointer) btnNames)) 750 return ReportMismatch(action->type, field, 751 "integer (range 1..5)"); 752 if ((rtrn.ival < 0) || (rtrn.ival > 5)) 753 { 754 ERROR("New default button value must be in the range 1..5\n"); 755 ACTION1("Illegal default button value %d ignored\n", rtrn.ival); 756 return False; 757 } 758 if (rtrn.ival == 0) 759 { 760 ERROR("Cannot set default pointer button to \"default\"\n"); 761 ACTION("Illegal default button setting ignored\n"); 762 return False; 763 } 764 if (value->op == OpNegate) 765 XkbSASetPtrDfltValue(act, -rtrn.ival); 766 else 767 XkbSASetPtrDfltValue(act, rtrn.ival); 768 return True; 769 } 770 return ReportIllegal(action->type, field); 771} 772 773static LookupEntry isoNames[] = { 774 {"mods", XkbSA_ISONoAffectMods}, 775 {"modifiers", XkbSA_ISONoAffectMods}, 776 {"group", XkbSA_ISONoAffectGroup}, 777 {"groups", XkbSA_ISONoAffectGroup}, 778 {"ptr", XkbSA_ISONoAffectPtr}, 779 {"pointer", XkbSA_ISONoAffectPtr}, 780 {"ctrls", XkbSA_ISONoAffectCtrls}, 781 {"controls", XkbSA_ISONoAffectCtrls}, 782 {"all", ~((unsigned) 0)}, 783 {"none", 0}, 784 {NULL, 0}, 785}; 786 787static Bool 788HandleISOLock(XkbDescPtr xkb, 789 XkbAnyAction * action, 790 unsigned field, ExprDef * array_ndx, ExprDef * value) 791{ 792 ExprResult rtrn; 793 XkbISOAction *act; 794 unsigned flags, mods; 795 int group; 796 797 act = (XkbISOAction *) action; 798 switch (field) 799 { 800 case F_Modifiers: 801 if (array_ndx != NULL) 802 return ReportActionNotArray(action->type, field); 803 flags = act->flags; 804 if (CheckModifierField(xkb, action->type, value, &flags, &mods)) 805 { 806 act->flags = flags & (~XkbSA_ISODfltIsGroup); 807 act->real_mods = mods & 0xff; 808 mods = (mods >> 8) & 0xff; 809 XkbSetModActionVMods(act, mods); 810 return True; 811 } 812 return False; 813 case F_Group: 814 if (array_ndx != NULL) 815 return ReportActionNotArray(action->type, field); 816 flags = act->flags; 817 if (CheckGroupField(action->type, value, &flags, &group)) 818 { 819 act->flags = flags | XkbSA_ISODfltIsGroup; 820 XkbSASetGroup(act, group); 821 return True; 822 } 823 return False; 824 case F_Affect: 825 if (array_ndx != NULL) 826 return ReportActionNotArray(action->type, field); 827 if (!ExprResolveMask(value, &rtrn, SimpleLookup, (XPointer) isoNames)) 828 return ReportMismatch(action->type, field, "keyboard component"); 829 act->affect = (~rtrn.uval) & XkbSA_ISOAffectMask; 830 return True; 831 } 832 return ReportIllegal(action->type, field); 833} 834 835static Bool 836HandleSwitchScreen(XkbDescPtr xkb, 837 XkbAnyAction * action, 838 unsigned field, ExprDef * array_ndx, ExprDef * value) 839{ 840 ExprResult rtrn; 841 XkbSwitchScreenAction *act; 842 843 act = (XkbSwitchScreenAction *) action; 844 if (field == F_Screen) 845 { 846 ExprDef *scrn; 847 if (array_ndx != NULL) 848 return ReportActionNotArray(action->type, field); 849 if ((value->op == OpNegate) || (value->op == OpUnaryPlus)) 850 { 851 act->flags &= ~XkbSA_SwitchAbsolute; 852 scrn = value->value.child; 853 } 854 else 855 { 856 act->flags |= XkbSA_SwitchAbsolute; 857 scrn = value; 858 } 859 860 if (!ExprResolveInteger(scrn, &rtrn, NULL, NULL)) 861 return ReportMismatch(action->type, field, "integer (0..255)"); 862 if ((rtrn.ival < 0) || (rtrn.ival > 255)) 863 { 864 ERROR("Screen index must be in the range 1..255\n"); 865 ACTION1("Illegal screen value %d ignored\n", rtrn.ival); 866 return False; 867 } 868 if (value->op == OpNegate) 869 XkbSASetScreen(act, -rtrn.ival); 870 else 871 XkbSASetScreen(act, rtrn.ival); 872 return True; 873 } 874 else if (field == F_Same) 875 { 876 if (array_ndx != NULL) 877 return ReportActionNotArray(action->type, field); 878 if (!ExprResolveBoolean(value, &rtrn, NULL, NULL)) 879 return ReportMismatch(action->type, field, "boolean"); 880 if (rtrn.uval) 881 act->flags &= ~XkbSA_SwitchApplication; 882 else 883 act->flags |= XkbSA_SwitchApplication; 884 return True; 885 } 886 return ReportIllegal(action->type, field); 887} 888 889LookupEntry ctrlNames[] = { 890 {"repeatkeys", XkbRepeatKeysMask} 891 , 892 {"repeat", XkbRepeatKeysMask} 893 , 894 {"autorepeat", XkbRepeatKeysMask} 895 , 896 {"slowkeys", XkbSlowKeysMask} 897 , 898 {"bouncekeys", XkbBounceKeysMask} 899 , 900 {"stickykeys", XkbStickyKeysMask} 901 , 902 {"mousekeys", XkbMouseKeysMask} 903 , 904 {"mousekeysaccel", XkbMouseKeysAccelMask} 905 , 906 {"accessxkeys", XkbAccessXKeysMask} 907 , 908 {"accessxtimeout", XkbAccessXTimeoutMask} 909 , 910 {"accessxfeedback", XkbAccessXFeedbackMask} 911 , 912 {"audiblebell", XkbAudibleBellMask} 913 , 914 {"overlay1", XkbOverlay1Mask} 915 , 916 {"overlay2", XkbOverlay2Mask} 917 , 918 {"ignoregrouplock", XkbIgnoreGroupLockMask} 919 , 920 {"all", XkbAllBooleanCtrlsMask} 921 , 922 {"none", 0} 923 , 924 {NULL, 0} 925}; 926 927static Bool 928HandleSetLockControls(XkbDescPtr xkb, 929 XkbAnyAction * action, 930 unsigned field, ExprDef * array_ndx, ExprDef * value) 931{ 932 ExprResult rtrn; 933 XkbCtrlsAction *act; 934 935 act = (XkbCtrlsAction *) action; 936 if (field == F_Controls) 937 { 938 if (array_ndx != NULL) 939 return ReportActionNotArray(action->type, field); 940 if (!ExprResolveMask 941 (value, &rtrn, SimpleLookup, (XPointer) ctrlNames)) 942 return ReportMismatch(action->type, field, "controls mask"); 943 XkbActionSetCtrls(act, rtrn.uval); 944 return True; 945 } 946 return ReportIllegal(action->type, field); 947} 948 949static LookupEntry evNames[] = { 950 {"press", XkbSA_MessageOnPress}, 951 {"keypress", XkbSA_MessageOnPress}, 952 {"release", XkbSA_MessageOnRelease}, 953 {"keyrelease", XkbSA_MessageOnRelease}, 954 {"all", XkbSA_MessageOnPress | XkbSA_MessageOnRelease}, 955 {"none", 0}, 956 {NULL, 0} 957}; 958 959static Bool 960HandleActionMessage(XkbDescPtr xkb, 961 XkbAnyAction * action, 962 unsigned field, ExprDef * array_ndx, ExprDef * value) 963{ 964 ExprResult rtrn; 965 XkbMessageAction *act; 966 967 act = (XkbMessageAction *) action; 968 switch (field) 969 { 970 case F_Report: 971 if (array_ndx != NULL) 972 return ReportActionNotArray(action->type, field); 973 if (!ExprResolveMask(value, &rtrn, SimpleLookup, (XPointer) evNames)) 974 return ReportMismatch(action->type, field, "key event mask"); 975 act->flags &= ~(XkbSA_MessageOnPress | XkbSA_MessageOnRelease); 976 act->flags = 977 rtrn.uval & (XkbSA_MessageOnPress | XkbSA_MessageOnRelease); 978 return True; 979 case F_GenKeyEvent: 980 if (array_ndx != NULL) 981 return ReportActionNotArray(action->type, field); 982 if (!ExprResolveBoolean(value, &rtrn, NULL, NULL)) 983 return ReportMismatch(action->type, field, "boolean"); 984 if (rtrn.uval) 985 act->flags |= XkbSA_MessageGenKeyEvent; 986 else 987 act->flags &= ~XkbSA_MessageGenKeyEvent; 988 return True; 989 case F_Data: 990 if (array_ndx == NULL) 991 { 992 if (!ExprResolveString(value, &rtrn, NULL, NULL)) 993 return ReportMismatch(action->type, field, "string"); 994 else 995 { 996 int len = strlen(rtrn.str); 997 if ((len < 1) || (len > 6)) 998 { 999 WARN("An action message can hold only 6 bytes\n"); 1000 ACTION1("Extra %d bytes ignored\n", len - 6); 1001 } 1002 strncpy((char *) act->message, rtrn.str, 6); 1003 } 1004 return True; 1005 } 1006 else 1007 { 1008 unsigned ndx; 1009 if (!ExprResolveInteger(array_ndx, &rtrn, NULL, NULL)) 1010 { 1011 ERROR("Array subscript must be integer\n"); 1012 ACTION("Illegal subscript ignored\n"); 1013 return False; 1014 } 1015 ndx = rtrn.uval; 1016 if (ndx > 5) 1017 { 1018 ERROR("An action message is at most 6 bytes long\n"); 1019 ACTION1("Attempt to use data[%d] ignored\n", ndx); 1020 return False; 1021 } 1022 if (!ExprResolveInteger(value, &rtrn, NULL, NULL)) 1023 return ReportMismatch(action->type, field, "integer"); 1024 if ((rtrn.ival < 0) || (rtrn.ival > 255)) 1025 { 1026 ERROR("Message data must be in the range 0..255\n"); 1027 ACTION1("Illegal datum %d ignored\n", rtrn.ival); 1028 return False; 1029 } 1030 act->message[ndx] = rtrn.uval; 1031 } 1032 return True; 1033 } 1034 return ReportIllegal(action->type, field); 1035} 1036 1037static Bool 1038HandleRedirectKey(XkbDescPtr xkb, 1039 XkbAnyAction * action, 1040 unsigned field, ExprDef * array_ndx, ExprDef * value) 1041{ 1042 ExprResult rtrn; 1043 XkbRedirectKeyAction *act; 1044 unsigned t1, t2, vmods, vmask; 1045 unsigned long tmp; 1046 1047 if (array_ndx != NULL) 1048 return ReportActionNotArray(action->type, field); 1049 1050 act = (XkbRedirectKeyAction *) action; 1051 switch (field) 1052 { 1053 case F_Keycode: 1054 if (!ExprResolveKeyName(value, &rtrn, NULL, NULL)) 1055 return ReportMismatch(action->type, field, "key name"); 1056 tmp = KeyNameToLong(rtrn.keyName.name); 1057 if (!FindNamedKey(xkb, tmp, &t1, True, CreateKeyNames(xkb), 0)) 1058 { 1059 return ReportNotFound(action->type, field, "Key", 1060 XkbKeyNameText(rtrn.keyName.name, 1061 XkbMessage)); 1062 } 1063 act->new_key = t1; 1064 return True; 1065 case F_ModsToClear: 1066 case F_Modifiers: 1067 t1 = 0; 1068 if (CheckModifierField(xkb, action->type, value, &t1, &t2)) 1069 { 1070 act->mods_mask |= (t2 & 0xff); 1071 if (field == F_Modifiers) 1072 act->mods |= (t2 & 0xff); 1073 else 1074 act->mods &= ~(t2 & 0xff); 1075 1076 t2 = (t2 >> 8) & 0xffff; 1077 vmods = XkbSARedirectVMods(act); 1078 vmask = XkbSARedirectVModsMask(act); 1079 vmask |= t2; 1080 if (field == F_Modifiers) 1081 vmods |= t2; 1082 else 1083 vmods &= ~t2; 1084 XkbSARedirectSetVMods(act, vmods); 1085 XkbSARedirectSetVModsMask(act, vmask); 1086 return True; 1087 } 1088 return True; 1089 } 1090 return ReportIllegal(action->type, field); 1091} 1092 1093static Bool 1094HandleDeviceBtn(XkbDescPtr xkb, 1095 XkbAnyAction * action, 1096 unsigned field, ExprDef * array_ndx, ExprDef * value) 1097{ 1098 ExprResult rtrn; 1099 XkbDeviceBtnAction *act; 1100 1101 act = (XkbDeviceBtnAction *) action; 1102 if (field == F_Button) 1103 { 1104 if (array_ndx != NULL) 1105 return ReportActionNotArray(action->type, field); 1106 if (!ExprResolveInteger(value, &rtrn, NULL, NULL)) 1107 return ReportMismatch(action->type, field, 1108 "integer (range 1..255)"); 1109 if ((rtrn.ival < 0) || (rtrn.ival > 255)) 1110 { 1111 ERROR("Button must specify default or be in the range 1..255\n"); 1112 ACTION1("Illegal button value %d ignored\n", rtrn.ival); 1113 return False; 1114 } 1115 act->button = rtrn.ival; 1116 return True; 1117 } 1118 else if ((action->type == XkbSA_LockDeviceBtn) && (field == F_Affect)) 1119 { 1120 if (array_ndx != NULL) 1121 return ReportActionNotArray(action->type, field); 1122 if (!ExprResolveEnum(value, &rtrn, lockWhich)) 1123 return ReportMismatch(action->type, field, "lock or unlock"); 1124 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock); 1125 act->flags |= rtrn.ival; 1126 return True; 1127 } 1128 else if (field == F_Count) 1129 { 1130 if (array_ndx != NULL) 1131 return ReportActionNotArray(action->type, field); 1132 if (!ExprResolveInteger 1133 (value, &rtrn, SimpleLookup, (XPointer) btnNames)) 1134 return ReportMismatch(action->type, field, "integer"); 1135 if ((rtrn.ival < 0) || (rtrn.ival > 255)) 1136 { 1137 ERROR("The count field must have a value in the range 0..255\n"); 1138 ACTION1("Illegal count %d ignored\n", rtrn.ival); 1139 return False; 1140 } 1141 act->count = rtrn.ival; 1142 return True; 1143 } 1144 else if (field == F_Device) 1145 { 1146 if (array_ndx != NULL) 1147 return ReportActionNotArray(action->type, field); 1148 if (!ExprResolveInteger(value, &rtrn, NULL, NULL)) 1149 return ReportMismatch(action->type, field, 1150 "integer (range 1..255)"); 1151 if ((rtrn.ival < 0) || (rtrn.ival > 255)) 1152 { 1153 ERROR("Device must specify default or be in the range 1..255\n"); 1154 ACTION1("Illegal device value %d ignored\n", rtrn.ival); 1155 return False; 1156 } 1157 act->device = rtrn.ival; 1158 return True; 1159 } 1160 return ReportIllegal(action->type, field); 1161} 1162 1163static Bool 1164HandleDeviceValuator(XkbDescPtr xkb, 1165 XkbAnyAction * action, 1166 unsigned field, ExprDef * array_ndx, ExprDef * value) 1167{ 1168#if 0 1169 ExprResult rtrn; 1170 XkbDeviceValuatorAction *act; 1171 1172 act = (XkbDeviceValuatorAction *) action; 1173 /* XXX - Not yet implemented */ 1174#endif 1175 return False; 1176} 1177 1178static Bool 1179HandlePrivate(XkbDescPtr xkb, 1180 XkbAnyAction * action, 1181 unsigned field, ExprDef * array_ndx, ExprDef * value) 1182{ 1183 ExprResult rtrn; 1184 1185 switch (field) 1186 { 1187 case F_Type: 1188 if (!ExprResolveInteger(value, &rtrn, NULL, NULL)) 1189 return ReportMismatch(PrivateAction, field, "integer"); 1190 if ((rtrn.ival < 0) || (rtrn.ival > 255)) 1191 { 1192 ERROR("Private action type must be in the range 0..255\n"); 1193 ACTION1("Illegal type %d ignored\n", rtrn.ival); 1194 return False; 1195 } 1196 action->type = rtrn.uval; 1197 return True; 1198 case F_Data: 1199 if (array_ndx == NULL) 1200 { 1201 if (!ExprResolveString(value, &rtrn, NULL, NULL)) 1202 return ReportMismatch(action->type, field, "string"); 1203 else 1204 { 1205 int len = strlen(rtrn.str); 1206 if ((len < 1) || (len > 7)) 1207 { 1208 WARN("A private action has 7 data bytes\n"); 1209 ACTION1("Extra %d bytes ignored\n", len - 6); 1210 return False; 1211 } 1212 strncpy((char *) action->data, rtrn.str, 7); 1213 } 1214 return True; 1215 } 1216 else 1217 { 1218 unsigned ndx; 1219 if (!ExprResolveInteger(array_ndx, &rtrn, NULL, NULL)) 1220 { 1221 ERROR("Array subscript must be integer\n"); 1222 ACTION("Illegal subscript ignored\n"); 1223 return False; 1224 } 1225 ndx = rtrn.uval; 1226 if (ndx > 6) 1227 { 1228 ERROR("The data for a private action is 7 bytes long\n"); 1229 ACTION1("Attempt to use data[%d] ignored\n", ndx); 1230 return False; 1231 } 1232 if (!ExprResolveInteger(value, &rtrn, NULL, NULL)) 1233 return ReportMismatch(action->type, field, "integer"); 1234 if ((rtrn.ival < 0) || (rtrn.ival > 255)) 1235 { 1236 ERROR("All data for a private action must be 0..255\n"); 1237 ACTION1("Illegal datum %d ignored\n", rtrn.ival); 1238 return False; 1239 } 1240 action->data[ndx] = rtrn.uval; 1241 return True; 1242 } 1243 } 1244 return ReportIllegal(PrivateAction, field); 1245} 1246 1247typedef Bool(*actionHandler) (XkbDescPtr /* xkb */ , 1248 XkbAnyAction * /* action */ , 1249 unsigned /* field */ , 1250 ExprDef * /* array_ndx */ , 1251 ExprDef * /* value */ 1252 ); 1253 1254static actionHandler handleAction[XkbSA_NumActions + 1] = { 1255 HandleNoAction /* NoAction */ , 1256 HandleSetLatchMods /* SetMods */ , 1257 HandleSetLatchMods /* LatchMods */ , 1258 HandleLockMods /* LockMods */ , 1259 HandleSetLatchGroup /* SetGroup */ , 1260 HandleSetLatchGroup /* LatchGroup */ , 1261 HandleLockGroup /* LockGroup */ , 1262 HandleMovePtr /* MovePtr */ , 1263 HandlePtrBtn /* PtrBtn */ , 1264 HandlePtrBtn /* LockPtrBtn */ , 1265 HandleSetPtrDflt /* SetPtrDflt */ , 1266 HandleISOLock /* ISOLock */ , 1267 HandleNoAction /* Terminate */ , 1268 HandleSwitchScreen /* SwitchScreen */ , 1269 HandleSetLockControls /* SetControls */ , 1270 HandleSetLockControls /* LockControls */ , 1271 HandleActionMessage /* ActionMessage */ , 1272 HandleRedirectKey /* RedirectKey */ , 1273 HandleDeviceBtn /* DeviceBtn */ , 1274 HandleDeviceBtn /* LockDeviceBtn */ , 1275 HandleDeviceValuator /* DeviceValuatr */ , 1276 HandlePrivate /* Private */ 1277}; 1278 1279/***====================================================================***/ 1280 1281static void 1282ApplyActionFactoryDefaults(XkbAction * action) 1283{ 1284 if (action->type == XkbSA_SetPtrDflt) 1285 { /* increment default button */ 1286 action->dflt.affect = XkbSA_AffectDfltBtn; 1287 action->dflt.flags = 0; 1288 XkbSASetPtrDfltValue(&action->dflt, 1); 1289 } 1290 else if (action->type == XkbSA_ISOLock) 1291 { 1292 action->iso.real_mods = LockMask; 1293 } 1294 return; 1295} 1296 1297 1298int 1299HandleActionDef(ExprDef * def, 1300 XkbDescPtr xkb, 1301 XkbAnyAction * action, unsigned mergeMode, ActionInfo * info) 1302{ 1303 ExprDef *arg; 1304 register char *str; 1305 unsigned tmp, hndlrType; 1306 1307 if (!actionsInitialized) 1308 ActionsInit(); 1309 1310 if (def->op != ExprActionDecl) 1311 { 1312 ERROR1("Expected an action definition, found %s\n", 1313 exprOpText(def->op)); 1314 return False; 1315 } 1316 str = XkbAtomGetString(NULL, def->value.action.name); 1317 if (!str) 1318 { 1319 WSGO("Missing name in action definition!!\n"); 1320 return False; 1321 } 1322 if (!stringToAction(str, &tmp)) 1323 { 1324 ERROR1("Unknown action %s\n", str); 1325 return False; 1326 } 1327 action->type = hndlrType = tmp; 1328 if (action->type != XkbSA_NoAction) 1329 { 1330 ApplyActionFactoryDefaults((XkbAction *) action); 1331 while (info) 1332 { 1333 if ((info->action == XkbSA_NoAction) 1334 || (info->action == hndlrType)) 1335 { 1336 if (!(*handleAction[hndlrType]) (xkb, action, 1337 info->field, 1338 info->array_ndx, 1339 info->value)) 1340 { 1341 return False; 1342 } 1343 } 1344 info = info->next; 1345 } 1346 } 1347 for (arg = def->value.action.args; arg != NULL; 1348 arg = (ExprDef *) arg->common.next) 1349 { 1350 ExprDef *field, *value, *arrayRtrn; 1351 ExprResult elemRtrn, fieldRtrn; 1352 unsigned fieldNdx; 1353 1354 if (arg->op == OpAssign) 1355 { 1356 field = arg->value.binary.left; 1357 value = arg->value.binary.right; 1358 } 1359 else 1360 { 1361 if ((arg->op == OpNot) || (arg->op == OpInvert)) 1362 { 1363 field = arg->value.child; 1364 value = &constFalse; 1365 } 1366 else 1367 { 1368 field = arg; 1369 value = &constTrue; 1370 } 1371 } 1372 if (!ExprResolveLhs(field, &elemRtrn, &fieldRtrn, &arrayRtrn)) 1373 return False; /* internal error -- already reported */ 1374 1375 if (elemRtrn.str != NULL) 1376 { 1377 ERROR("Cannot change defaults in an action definition\n"); 1378 ACTION2("Ignoring attempt to change %s.%s\n", elemRtrn.str, 1379 fieldRtrn.str); 1380 return False; 1381 } 1382 if (!stringToField(fieldRtrn.str, &fieldNdx)) 1383 { 1384 ERROR1("Unknown field name %s\n", uStringText(fieldRtrn.str)); 1385 return False; 1386 } 1387 if (!(*handleAction[hndlrType]) 1388 (xkb, action, fieldNdx, arrayRtrn, value)) 1389 { 1390 return False; 1391 } 1392 } 1393 return True; 1394} 1395 1396/***====================================================================***/ 1397 1398int 1399SetActionField(XkbDescPtr xkb, 1400 const char *elem, 1401 const char *field, 1402 ExprDef * array_ndx, ExprDef * value, ActionInfo ** info_rtrn) 1403{ 1404 ActionInfo *new, *old; 1405 1406 if (!actionsInitialized) 1407 ActionsInit(); 1408 1409 new = uTypedAlloc(ActionInfo); 1410 if (new == NULL) 1411 { 1412 WSGO("Couldn't allocate space for action default\n"); 1413 return False; 1414 } 1415 if (uStrCaseCmp(elem, "action") == 0) 1416 new->action = XkbSA_NoAction; 1417 else 1418 { 1419 if (!stringToAction(elem, &new->action)) 1420 return False; 1421 if (new->action == XkbSA_NoAction) 1422 { 1423 ERROR1("\"%s\" is not a valid field in a NoAction action\n", 1424 field); 1425 return False; 1426 } 1427 } 1428 if (!stringToField(field, &new->field)) 1429 { 1430 ERROR1("\"%s\" is not a legal field name\n", field); 1431 return False; 1432 } 1433 new->array_ndx = array_ndx; 1434 new->value = value; 1435 new->next = NULL; 1436 old = *info_rtrn; 1437 while ((old) && (old->next)) 1438 old = old->next; 1439 if (old == NULL) 1440 *info_rtrn = new; 1441 else 1442 old->next = new; 1443 return True; 1444} 1445 1446/***====================================================================***/ 1447 1448void 1449ActionsInit(void) 1450{ 1451 if (!actionsInitialized) 1452 { 1453 bzero((char *) &constTrue, sizeof(constTrue)); 1454 bzero((char *) &constFalse, sizeof(constFalse)); 1455 constTrue.common.stmtType = StmtExpr; 1456 constTrue.common.next = NULL; 1457 constTrue.op = ExprIdent; 1458 constTrue.type = TypeBoolean; 1459 constTrue.value.str = XkbInternAtom(NULL, "true", False); 1460 constFalse.common.stmtType = StmtExpr; 1461 constFalse.common.next = NULL; 1462 constFalse.op = ExprIdent; 1463 constFalse.type = TypeBoolean; 1464 constFalse.value.str = XkbInternAtom(NULL, "false", False); 1465 actionsInitialized = 1; 1466 } 1467 return; 1468} 1469