action.c revision bfe6082c
11.11Sskrll/************************************************************ 21.4Schristos Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. 31.1Schristos 41.1Schristos Permission to use, copy, modify, and distribute this 51.1Schristos software and its documentation for any purpose and without 61.1Schristos fee is hereby granted, provided that the above copyright 71.1Schristos notice appear in all copies and that both that copyright 81.1Schristos notice and this permission notice appear in supporting 91.1Schristos documentation, and that the name of Silicon Graphics not be 101.1Schristos used in advertising or publicity pertaining to distribution 111.1Schristos of the software without specific prior written permission. 121.1Schristos Silicon Graphics makes no representation about the suitability 131.1Schristos of this software for any purpose. It is provided "as is" 141.1Schristos without any express or implied warranty. 151.1Schristos 161.1Schristos SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 171.1Schristos SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 181.1Schristos AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 191.1Schristos GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 201.1Schristos DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 211.1Schristos DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 221.1Schristos OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 231.1Schristos THE USE OR PERFORMANCE OF THIS SOFTWARE. 241.1Schristos 251.1Schristos ********************************************************/ 261.1Schristos 271.1Schristos#include "xkbcomp.h" 281.1Schristos#include "tokens.h" 291.1Schristos#include "expr.h" 301.1Schristos 311.1Schristos#include "keycodes.h" 321.1Schristos#include "vmod.h" 331.1Schristos#include "misc.h" 341.1Schristos#include "action.h" 351.1Schristos#include "misc.h" 361.1Schristos 371.1Schristosstatic Bool actionsInitialized; 381.5Schristosstatic ExprDef constTrue; 391.5Schristosstatic ExprDef constFalse; 401.5Schristos 411.5Schristos/***====================================================================***/ 421.11Sskrll 431.5Schristosstatic Bool 441.5SchristosstringToAction(const char *str, unsigned *type_rtrn) 451.11Sskrll{ 461.5Schristos if (str == NULL) 471.5Schristos return False; 481.5Schristos 491.11Sskrll if (uStrCaseCmp(str, "noaction") == 0) 501.11Sskrll *type_rtrn = XkbSA_NoAction; 511.5Schristos else if (uStrCaseCmp(str, "setmods") == 0) 521.5Schristos *type_rtrn = XkbSA_SetMods; 531.5Schristos else if (uStrCaseCmp(str, "latchmods") == 0) 541.5Schristos *type_rtrn = XkbSA_LatchMods; 551.5Schristos else if (uStrCaseCmp(str, "lockmods") == 0) 561.1Schristos *type_rtrn = XkbSA_LockMods; 571.1Schristos else if (uStrCaseCmp(str, "setgroup") == 0) 581.1Schristos *type_rtrn = XkbSA_SetGroup; 591.1Schristos else if (uStrCaseCmp(str, "latchgroup") == 0) 601.1Schristos *type_rtrn = XkbSA_LatchGroup; 611.3Schristos else if (uStrCaseCmp(str, "lockgroup") == 0) 621.3Schristos *type_rtrn = XkbSA_LockGroup; 631.3Schristos else if (uStrCaseCmp(str, "moveptr") == 0) 641.3Schristos *type_rtrn = XkbSA_MovePtr; 651.1Schristos else if (uStrCaseCmp(str, "movepointer") == 0) 661.1Schristos *type_rtrn = XkbSA_MovePtr; 671.1Schristos else if (uStrCaseCmp(str, "ptrbtn") == 0) 681.1Schristos *type_rtrn = XkbSA_PtrBtn; 691.1Schristos else if (uStrCaseCmp(str, "pointerbutton") == 0) 701.1Schristos *type_rtrn = XkbSA_PtrBtn; 711.1Schristos else if (uStrCaseCmp(str, "lockptrbtn") == 0) 721.1Schristos *type_rtrn = XkbSA_LockPtrBtn; 731.1Schristos else if (uStrCaseCmp(str, "lockpointerbutton") == 0) 741.1Schristos *type_rtrn = XkbSA_LockPtrBtn; 751.1Schristos else if (uStrCaseCmp(str, "lockptrbutton") == 0) 761.1Schristos *type_rtrn = XkbSA_LockPtrBtn; 771.1Schristos else if (uStrCaseCmp(str, "lockpointerbtn") == 0) 781.1Schristos *type_rtrn = XkbSA_LockPtrBtn; 791.1Schristos else if (uStrCaseCmp(str, "setptrdflt") == 0) 801.1Schristos *type_rtrn = XkbSA_SetPtrDflt; 811.1Schristos else if (uStrCaseCmp(str, "setpointerdefault") == 0) 821.1Schristos *type_rtrn = XkbSA_SetPtrDflt; 831.1Schristos else if (uStrCaseCmp(str, "isolock") == 0) 841.1Schristos *type_rtrn = XkbSA_ISOLock; 851.1Schristos else if (uStrCaseCmp(str, "terminate") == 0) 861.1Schristos *type_rtrn = XkbSA_Terminate; 871.1Schristos else if (uStrCaseCmp(str, "terminateserver") == 0) 881.1Schristos *type_rtrn = XkbSA_Terminate; 891.1Schristos else if (uStrCaseCmp(str, "switchscreen") == 0) 901.1Schristos *type_rtrn = XkbSA_SwitchScreen; 911.1Schristos else if (uStrCaseCmp(str, "setcontrols") == 0) 921.1Schristos *type_rtrn = XkbSA_SetControls; 931.1Schristos else if (uStrCaseCmp(str, "lockcontrols") == 0) 941.1Schristos *type_rtrn = XkbSA_LockControls; 951.1Schristos else if (uStrCaseCmp(str, "actionmessage") == 0) 961.1Schristos *type_rtrn = XkbSA_ActionMessage; 971.1Schristos else if (uStrCaseCmp(str, "messageaction") == 0) 981.1Schristos *type_rtrn = XkbSA_ActionMessage; 991.1Schristos else if (uStrCaseCmp(str, "message") == 0) 1001.1Schristos *type_rtrn = XkbSA_ActionMessage; 1011.1Schristos else if (uStrCaseCmp(str, "redirect") == 0) 1021.1Schristos *type_rtrn = XkbSA_RedirectKey; 1031.1Schristos else if (uStrCaseCmp(str, "redirectkey") == 0) 1041.1Schristos *type_rtrn = XkbSA_RedirectKey; 1051.1Schristos else if (uStrCaseCmp(str, "devbtn") == 0) 1061.1Schristos *type_rtrn = XkbSA_DeviceBtn; 1071.1Schristos else if (uStrCaseCmp(str, "devicebtn") == 0) 1081.1Schristos *type_rtrn = XkbSA_DeviceBtn; 1091.1Schristos else if (uStrCaseCmp(str, "devbutton") == 0) 1101.1Schristos *type_rtrn = XkbSA_DeviceBtn; 1111.1Schristos else if (uStrCaseCmp(str, "devicebutton") == 0) 1121.1Schristos *type_rtrn = XkbSA_DeviceBtn; 1131.1Schristos else if (uStrCaseCmp(str, "lockdevbtn") == 0) 1141.1Schristos *type_rtrn = XkbSA_LockDeviceBtn; 1151.1Schristos else if (uStrCaseCmp(str, "lockdevicebtn") == 0) 1161.1Schristos *type_rtrn = XkbSA_LockDeviceBtn; 1171.1Schristos else if (uStrCaseCmp(str, "lockdevbutton") == 0) 1181.1Schristos *type_rtrn = XkbSA_LockDeviceBtn; 1191.1Schristos else if (uStrCaseCmp(str, "lockdevicebutton") == 0) 1201.1Schristos *type_rtrn = XkbSA_LockDeviceBtn; 1211.1Schristos else if (uStrCaseCmp(str, "devval") == 0) 1221.1Schristos *type_rtrn = XkbSA_DeviceValuator; 1231.1Schristos else if (uStrCaseCmp(str, "deviceval") == 0) 1241.1Schristos *type_rtrn = XkbSA_DeviceValuator; 1251.1Schristos else if (uStrCaseCmp(str, "devvaluator") == 0) 1261.6Schristos *type_rtrn = XkbSA_DeviceValuator; 1271.6Schristos else if (uStrCaseCmp(str, "devicevaluator") == 0) 1281.9Smrg *type_rtrn = XkbSA_DeviceValuator; 1291.9Smrg else if (uStrCaseCmp(str, "private") == 0) 1301.9Smrg *type_rtrn = PrivateAction; 1311.9Smrg else 1321.9Smrg return False; 1331.9Smrg return True; 1341.10Swiz} 1351.10Swiz 1361.1Schristosstatic Bool 1371.3SchristosstringToField(const char *str, unsigned *field_rtrn) 1381.8Schristos{ 1391.1Schristos 1401.1Schristos if (str == NULL) 1411.5Schristos 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 ERROR("Value of %s field must be of type %s\n", fieldText(field), type); 303 ACTION("Action %s definition ignored\n", 304 XkbActionTypeText(action, XkbMessage)); 305 return False; 306} 307 308static Bool 309ReportIllegal(unsigned action, unsigned field) 310{ 311 ERROR("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 ERROR("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 ERROR("%s named %s not found\n", what, bad); 330 ACTION("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 LookupEntry lockWhich[] = { 440 {"both", 0}, 441 {"lock", XkbSA_LockNoUnlock}, 442 {"neither", (XkbSA_LockNoLock | XkbSA_LockNoUnlock)}, 443 {"unlock", XkbSA_LockNoLock}, 444 {NULL, 0} 445}; 446 447static Bool 448HandleLockMods(XkbDescPtr xkb, 449 XkbAnyAction * action, 450 unsigned field, ExprDef * array_ndx, ExprDef * value) 451{ 452 XkbModAction *act; 453 unsigned t1, t2; 454 ExprResult rtrn; 455 456 act = (XkbModAction *) action; 457 if ((array_ndx != NULL) && (field == F_Modifiers || field == F_Affect)) 458 return ReportActionNotArray(action->type, field); 459 switch (field) 460 { 461 case F_Affect: 462 if (!ExprResolveEnum(value, &rtrn, lockWhich)) 463 return ReportMismatch(action->type, field, "lock or unlock"); 464 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock); 465 act->flags |= rtrn.uval; 466 return True; 467 case F_Modifiers: 468 t1 = act->flags; 469 if (CheckModifierField(xkb, action->type, value, &t1, &t2)) 470 { 471 act->flags = t1; 472 act->real_mods = act->mask = (t2 & 0xff); 473 t2 = (t2 >> 8) & 0xffff; 474 XkbSetModActionVMods(act, t2); 475 return True; 476 } 477 return False; 478 } 479 return ReportIllegal(action->type, field); 480} 481 482static LookupEntry groupNames[] = { 483 {"group1", 1}, 484 {"group2", 2}, 485 {"group3", 3}, 486 {"group4", 4}, 487 {"group5", 5}, 488 {"group6", 6}, 489 {"group7", 7}, 490 {"group8", 8}, 491 {NULL, 0}, 492}; 493 494static Bool 495CheckGroupField(unsigned action, 496 ExprDef * value, unsigned *flags_inout, int *grp_rtrn) 497{ 498 ExprDef *spec; 499 ExprResult rtrn; 500 501 if ((value->op == OpNegate) || (value->op == OpUnaryPlus)) 502 { 503 *flags_inout &= ~XkbSA_GroupAbsolute; 504 spec = value->value.child; 505 } 506 else 507 { 508 *flags_inout |= XkbSA_GroupAbsolute; 509 spec = value; 510 } 511 512 if (!ExprResolveInteger(spec, &rtrn, SimpleLookup, (XPointer) groupNames)) 513 return ReportMismatch(action, F_Group, "integer (range 1..8)"); 514 if ((rtrn.ival < 1) || (rtrn.ival > XkbNumKbdGroups)) 515 { 516 ERROR("Illegal group %d (must be in the range 1..%d)\n", rtrn.ival, 517 XkbNumKbdGroups); 518 ACTION("Action %s definition ignored\n", 519 XkbActionTypeText(action, XkbMessage)); 520 return False; 521 } 522 if (value->op == OpNegate) 523 *grp_rtrn = -rtrn.ival; 524 else if (value->op == OpUnaryPlus) 525 *grp_rtrn = rtrn.ival; 526 else 527 *grp_rtrn = rtrn.ival - 1; 528 return True; 529} 530 531static Bool 532HandleSetLatchGroup(XkbDescPtr xkb, 533 XkbAnyAction * action, 534 unsigned field, ExprDef * array_ndx, ExprDef * value) 535{ 536 XkbGroupAction *act; 537 unsigned rtrn; 538 unsigned t1; 539 int t2; 540 541 act = (XkbGroupAction *) action; 542 if (array_ndx != NULL) 543 { 544 switch (field) 545 { 546 case F_ClearLocks: 547 case F_LatchToLock: 548 case F_Group: 549 return ReportActionNotArray(action->type, field); 550 } 551 } 552 switch (field) 553 { 554 case F_ClearLocks: 555 case F_LatchToLock: 556 rtrn = act->flags; 557 if (CheckLatchLockFlags(action->type, field, value, &rtrn)) 558 { 559 act->flags = rtrn; 560 return True; 561 } 562 return False; 563 case F_Group: 564 t1 = act->flags; 565 if (CheckGroupField(action->type, value, &t1, &t2)) 566 { 567 act->flags = t1; 568 XkbSASetGroup(act, t2); 569 return True; 570 } 571 return False; 572 } 573 return ReportIllegal(action->type, field); 574} 575 576static Bool 577HandleLockGroup(XkbDescPtr xkb, 578 XkbAnyAction * action, 579 unsigned field, ExprDef * array_ndx, ExprDef * value) 580{ 581 XkbGroupAction *act; 582 unsigned t1; 583 int t2; 584 585 act = (XkbGroupAction *) action; 586 if ((array_ndx != NULL) && (field == F_Group)) 587 return ReportActionNotArray(action->type, field); 588 if (field == F_Group) 589 { 590 t1 = act->flags; 591 if (CheckGroupField(action->type, value, &t1, &t2)) 592 { 593 act->flags = t1; 594 XkbSASetGroup(act, t2); 595 return True; 596 } 597 return False; 598 } 599 return ReportIllegal(action->type, field); 600} 601 602static Bool 603HandleMovePtr(XkbDescPtr xkb, 604 XkbAnyAction * action, 605 unsigned field, ExprDef * array_ndx, ExprDef * value) 606{ 607 ExprResult rtrn; 608 XkbPtrAction *act; 609 Bool absolute; 610 611 act = (XkbPtrAction *) action; 612 if ((array_ndx != NULL) && ((field == F_X) || (field == F_Y))) 613 return ReportActionNotArray(action->type, field); 614 615 if ((field == F_X) || (field == F_Y)) 616 { 617 if ((value->op == OpNegate) || (value->op == OpUnaryPlus)) 618 absolute = False; 619 else 620 absolute = True; 621 if (!ExprResolveInteger(value, &rtrn, NULL, NULL)) 622 return ReportMismatch(action->type, field, "integer"); 623 if (field == F_X) 624 { 625 if (absolute) 626 act->flags |= XkbSA_MoveAbsoluteX; 627 XkbSetPtrActionX(act, rtrn.ival); 628 } 629 else 630 { 631 if (absolute) 632 act->flags |= XkbSA_MoveAbsoluteY; 633 XkbSetPtrActionY(act, rtrn.ival); 634 } 635 return True; 636 } 637 else if (field == F_Accel) 638 { 639 if (!ExprResolveBoolean(value, &rtrn, NULL, NULL)) 640 return ReportMismatch(action->type, field, "boolean"); 641 if (rtrn.uval) 642 act->flags &= ~XkbSA_NoAcceleration; 643 else 644 act->flags |= XkbSA_NoAcceleration; 645 return True; 646 } 647 return ReportIllegal(action->type, field); 648} 649 650static LookupEntry btnNames[] = { 651 {"button1", 1}, 652 {"button2", 2}, 653 {"button3", 3}, 654 {"button4", 4}, 655 {"button5", 5}, 656 {"default", 0}, 657 {NULL, 0} 658}; 659 660static Bool 661HandlePtrBtn(XkbDescPtr xkb, 662 XkbAnyAction * action, 663 unsigned field, ExprDef * array_ndx, ExprDef * value) 664{ 665 ExprResult rtrn; 666 XkbPtrBtnAction *act; 667 668 act = (XkbPtrBtnAction *) action; 669 if (field == F_Button) 670 { 671 if (array_ndx != NULL) 672 return ReportActionNotArray(action->type, field); 673 if (!ExprResolveInteger 674 (value, &rtrn, SimpleLookup, (XPointer) btnNames)) 675 return ReportMismatch(action->type, field, 676 "integer (range 1..5)"); 677 if ((rtrn.ival < 0) || (rtrn.ival > 5)) 678 { 679 ERROR("Button must specify default or be in the range 1..5\n"); 680 ACTION("Illegal button value %d ignored\n", rtrn.ival); 681 return False; 682 } 683 act->button = rtrn.ival; 684 return True; 685 } 686 else if ((action->type == XkbSA_LockPtrBtn) && (field == F_Affect)) 687 { 688 if (array_ndx != NULL) 689 return ReportActionNotArray(action->type, field); 690 if (!ExprResolveEnum(value, &rtrn, lockWhich)) 691 return ReportMismatch(action->type, field, "lock or unlock"); 692 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock); 693 act->flags |= rtrn.uval; 694 return True; 695 } 696 else if (field == F_Count) 697 { 698 if (array_ndx != NULL) 699 return ReportActionNotArray(action->type, field); 700 if (!ExprResolveInteger 701 (value, &rtrn, SimpleLookup, (XPointer) btnNames)) 702 return ReportMismatch(action->type, field, "integer"); 703 if ((rtrn.ival < 0) || (rtrn.ival > 255)) 704 { 705 ERROR("The count field must have a value in the range 0..255\n"); 706 ACTION("Illegal count %d ignored\n", rtrn.ival); 707 return False; 708 } 709 act->count = rtrn.ival; 710 return True; 711 } 712 return ReportIllegal(action->type, field); 713} 714 715static LookupEntry ptrDflts[] = { 716 {"dfltbtn", XkbSA_AffectDfltBtn}, 717 {"defaultbutton", XkbSA_AffectDfltBtn}, 718 {"button", XkbSA_AffectDfltBtn}, 719 {NULL, 0} 720}; 721 722static Bool 723HandleSetPtrDflt(XkbDescPtr xkb, 724 XkbAnyAction * action, 725 unsigned field, ExprDef * array_ndx, ExprDef * value) 726{ 727 ExprResult rtrn; 728 XkbPtrDfltAction *act; 729 730 act = (XkbPtrDfltAction *) action; 731 if (field == F_Affect) 732 { 733 if (array_ndx != NULL) 734 return ReportActionNotArray(action->type, field); 735 if (!ExprResolveEnum(value, &rtrn, ptrDflts)) 736 return ReportMismatch(action->type, field, "pointer component"); 737 act->affect = rtrn.uval; 738 return True; 739 } 740 else if ((field == F_Button) || (field == F_Value)) 741 { 742 ExprDef *btn; 743 if (array_ndx != NULL) 744 return ReportActionNotArray(action->type, field); 745 if ((value->op == OpNegate) || (value->op == OpUnaryPlus)) 746 { 747 act->flags &= ~XkbSA_DfltBtnAbsolute; 748 btn = value->value.child; 749 } 750 else 751 { 752 act->flags |= XkbSA_DfltBtnAbsolute; 753 btn = value; 754 } 755 756 if (!ExprResolveInteger 757 (btn, &rtrn, SimpleLookup, (XPointer) btnNames)) 758 return ReportMismatch(action->type, field, 759 "integer (range 1..5)"); 760 if ((rtrn.ival < 0) || (rtrn.ival > 5)) 761 { 762 ERROR("New default button value must be in the range 1..5\n"); 763 ACTION("Illegal default button value %d ignored\n", rtrn.ival); 764 return False; 765 } 766 if (rtrn.ival == 0) 767 { 768 ERROR("Cannot set default pointer button to \"default\"\n"); 769 ACTION("Illegal default button setting ignored\n"); 770 return False; 771 } 772 if (value->op == OpNegate) 773 XkbSASetPtrDfltValue(act, -rtrn.ival); 774 else 775 XkbSASetPtrDfltValue(act, rtrn.ival); 776 return True; 777 } 778 return ReportIllegal(action->type, field); 779} 780 781static LookupEntry isoNames[] = { 782 {"mods", XkbSA_ISONoAffectMods}, 783 {"modifiers", XkbSA_ISONoAffectMods}, 784 {"group", XkbSA_ISONoAffectGroup}, 785 {"groups", XkbSA_ISONoAffectGroup}, 786 {"ptr", XkbSA_ISONoAffectPtr}, 787 {"pointer", XkbSA_ISONoAffectPtr}, 788 {"ctrls", XkbSA_ISONoAffectCtrls}, 789 {"controls", XkbSA_ISONoAffectCtrls}, 790 {"all", XkbSA_ISOAffectMask}, 791 {"none", 0}, 792 {"both", 0}, 793 {"lock", XkbSA_LockNoUnlock}, 794 {"neither", (XkbSA_LockNoLock | XkbSA_LockNoUnlock)}, 795 {"unlock", XkbSA_LockNoLock}, 796 {NULL, 0}, 797}; 798 799static Bool 800HandleISOLock(XkbDescPtr xkb, 801 XkbAnyAction * action, 802 unsigned field, ExprDef * array_ndx, ExprDef * value) 803{ 804 ExprResult rtrn; 805 XkbISOAction *act; 806 unsigned flags, mods; 807 int group; 808 809 act = (XkbISOAction *) action; 810 switch (field) 811 { 812 case F_Modifiers: 813 if (array_ndx != NULL) 814 return ReportActionNotArray(action->type, field); 815 flags = act->flags; 816 if (CheckModifierField(xkb, action->type, value, &flags, &mods)) 817 { 818 act->flags = flags & (~XkbSA_ISODfltIsGroup); 819 act->real_mods = act->mask = (mods & 0xff); 820 mods = (mods >> 8) & 0xffff; 821 XkbSetModActionVMods(act, mods); 822 return True; 823 } 824 return False; 825 case F_Group: 826 if (array_ndx != NULL) 827 return ReportActionNotArray(action->type, field); 828 flags = act->flags; 829 if (CheckGroupField(action->type, value, &flags, &group)) 830 { 831 act->flags = flags | XkbSA_ISODfltIsGroup; 832 XkbSASetGroup(act, group); 833 return True; 834 } 835 return False; 836 case F_Affect: 837 if (array_ndx != NULL) 838 return ReportActionNotArray(action->type, field); 839 if (!ExprResolveMask(value, &rtrn, SimpleLookup, (XPointer) isoNames)) 840 return ReportMismatch(action->type, field, "keyboard component"); 841 act->affect = (~rtrn.uval) & XkbSA_ISOAffectMask; 842 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock); 843 act->flags |= rtrn.uval & (XkbSA_LockNoLock | XkbSA_LockNoUnlock); 844 return True; 845 } 846 return ReportIllegal(action->type, field); 847} 848 849static Bool 850HandleSwitchScreen(XkbDescPtr xkb, 851 XkbAnyAction * action, 852 unsigned field, ExprDef * array_ndx, ExprDef * value) 853{ 854 ExprResult rtrn; 855 XkbSwitchScreenAction *act; 856 857 act = (XkbSwitchScreenAction *) action; 858 if (field == F_Screen) 859 { 860 ExprDef *scrn; 861 if (array_ndx != NULL) 862 return ReportActionNotArray(action->type, field); 863 if ((value->op == OpNegate) || (value->op == OpUnaryPlus)) 864 { 865 act->flags &= ~XkbSA_SwitchAbsolute; 866 scrn = value->value.child; 867 } 868 else 869 { 870 act->flags |= XkbSA_SwitchAbsolute; 871 scrn = value; 872 } 873 874 if (!ExprResolveInteger(scrn, &rtrn, NULL, NULL)) 875 return ReportMismatch(action->type, field, "integer (0..255)"); 876 if ((rtrn.ival < 0) || (rtrn.ival > 255)) 877 { 878 ERROR("Screen index must be in the range 1..255\n"); 879 ACTION("Illegal screen value %d ignored\n", rtrn.ival); 880 return False; 881 } 882 if (value->op == OpNegate) 883 XkbSASetScreen(act, -rtrn.ival); 884 else 885 XkbSASetScreen(act, rtrn.ival); 886 return True; 887 } 888 else if (field == F_Same) 889 { 890 if (array_ndx != NULL) 891 return ReportActionNotArray(action->type, field); 892 if (!ExprResolveBoolean(value, &rtrn, NULL, NULL)) 893 return ReportMismatch(action->type, field, "boolean"); 894 if (rtrn.uval) 895 act->flags &= ~XkbSA_SwitchApplication; 896 else 897 act->flags |= XkbSA_SwitchApplication; 898 return True; 899 } 900 return ReportIllegal(action->type, field); 901} 902 903LookupEntry ctrlNames[] = { 904 {"repeatkeys", XkbRepeatKeysMask} 905 , 906 {"repeat", XkbRepeatKeysMask} 907 , 908 {"autorepeat", XkbRepeatKeysMask} 909 , 910 {"slowkeys", XkbSlowKeysMask} 911 , 912 {"bouncekeys", XkbBounceKeysMask} 913 , 914 {"stickykeys", XkbStickyKeysMask} 915 , 916 {"mousekeys", XkbMouseKeysMask} 917 , 918 {"mousekeysaccel", XkbMouseKeysAccelMask} 919 , 920 {"accessxkeys", XkbAccessXKeysMask} 921 , 922 {"accessxtimeout", XkbAccessXTimeoutMask} 923 , 924 {"accessxfeedback", XkbAccessXFeedbackMask} 925 , 926 {"audiblebell", XkbAudibleBellMask} 927 , 928 {"overlay1", XkbOverlay1Mask} 929 , 930 {"overlay2", XkbOverlay2Mask} 931 , 932 {"ignoregrouplock", XkbIgnoreGroupLockMask} 933 , 934 {"all", XkbAllBooleanCtrlsMask} 935 , 936 {"none", 0} 937 , 938 {NULL, 0} 939}; 940 941static Bool 942HandleSetLockControls(XkbDescPtr xkb, 943 XkbAnyAction * action, 944 unsigned field, ExprDef * array_ndx, ExprDef * value) 945{ 946 ExprResult rtrn; 947 XkbCtrlsAction *act; 948 949 act = (XkbCtrlsAction *) action; 950 if (field == F_Controls) 951 { 952 if (array_ndx != NULL) 953 return ReportActionNotArray(action->type, field); 954 if (!ExprResolveMask 955 (value, &rtrn, SimpleLookup, (XPointer) ctrlNames)) 956 return ReportMismatch(action->type, field, "controls mask"); 957 XkbActionSetCtrls(act, rtrn.uval); 958 return True; 959 } 960 else if (field == F_Affect && action->type == XkbSA_LockControls) { 961 if (array_ndx != NULL) 962 return ReportActionNotArray(action->type, field); 963 if (!ExprResolveEnum(value, &rtrn, lockWhich)) 964 return ReportMismatch(action->type, field, "lock or unlock"); 965 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock); 966 act->flags |= rtrn.uval; 967 return True; 968 } 969 return ReportIllegal(action->type, field); 970} 971 972static LookupEntry evNames[] = { 973 {"press", XkbSA_MessageOnPress}, 974 {"keypress", XkbSA_MessageOnPress}, 975 {"release", XkbSA_MessageOnRelease}, 976 {"keyrelease", XkbSA_MessageOnRelease}, 977 {"all", XkbSA_MessageOnPress | XkbSA_MessageOnRelease}, 978 {"none", 0}, 979 {NULL, 0} 980}; 981 982static Bool 983HandleActionMessage(XkbDescPtr xkb, 984 XkbAnyAction * action, 985 unsigned field, ExprDef * array_ndx, ExprDef * value) 986{ 987 ExprResult rtrn; 988 XkbMessageAction *act; 989 990 act = (XkbMessageAction *) action; 991 switch (field) 992 { 993 case F_Report: 994 if (array_ndx != NULL) 995 return ReportActionNotArray(action->type, field); 996 if (!ExprResolveMask(value, &rtrn, SimpleLookup, (XPointer) evNames)) 997 return ReportMismatch(action->type, field, "key event mask"); 998 act->flags &= ~(XkbSA_MessageOnPress | XkbSA_MessageOnRelease); 999 act->flags = 1000 rtrn.uval & (XkbSA_MessageOnPress | XkbSA_MessageOnRelease); 1001 return True; 1002 case F_GenKeyEvent: 1003 if (array_ndx != NULL) 1004 return ReportActionNotArray(action->type, field); 1005 if (!ExprResolveBoolean(value, &rtrn, NULL, NULL)) 1006 return ReportMismatch(action->type, field, "boolean"); 1007 if (rtrn.uval) 1008 act->flags |= XkbSA_MessageGenKeyEvent; 1009 else 1010 act->flags &= ~XkbSA_MessageGenKeyEvent; 1011 return True; 1012 case F_Data: 1013 if (array_ndx == NULL) 1014 { 1015 if (!ExprResolveString(value, &rtrn, NULL, NULL)) 1016 return ReportMismatch(action->type, field, "string"); 1017 else 1018 { 1019 int len = strlen(rtrn.str); 1020 if ((len < 1) || (len > 6)) 1021 { 1022 WARN("An action message can hold only 6 bytes\n"); 1023 ACTION("Extra %d bytes ignored\n", len - 6); 1024 } 1025 strncpy((char *) act->message, rtrn.str, 6); 1026 } 1027 return True; 1028 } 1029 else 1030 { 1031 unsigned ndx; 1032 if (!ExprResolveInteger(array_ndx, &rtrn, NULL, NULL)) 1033 { 1034 ERROR("Array subscript must be integer\n"); 1035 ACTION("Illegal subscript ignored\n"); 1036 return False; 1037 } 1038 ndx = rtrn.uval; 1039 if (ndx > 5) 1040 { 1041 ERROR("An action message is at most 6 bytes long\n"); 1042 ACTION("Attempt to use data[%d] ignored\n", ndx); 1043 return False; 1044 } 1045 if (!ExprResolveInteger(value, &rtrn, NULL, NULL)) 1046 return ReportMismatch(action->type, field, "integer"); 1047 if ((rtrn.ival < 0) || (rtrn.ival > 255)) 1048 { 1049 ERROR("Message data must be in the range 0..255\n"); 1050 ACTION("Illegal datum %d ignored\n", rtrn.ival); 1051 return False; 1052 } 1053 act->message[ndx] = rtrn.uval; 1054 } 1055 return True; 1056 } 1057 return ReportIllegal(action->type, field); 1058} 1059 1060static Bool 1061HandleRedirectKey(XkbDescPtr xkb, 1062 XkbAnyAction * action, 1063 unsigned field, ExprDef * array_ndx, ExprDef * value) 1064{ 1065 ExprResult rtrn; 1066 XkbRedirectKeyAction *act; 1067 unsigned t1, t2, vmods, vmask; 1068 unsigned long tmp; 1069 1070 if (array_ndx != NULL) 1071 return ReportActionNotArray(action->type, field); 1072 1073 act = (XkbRedirectKeyAction *) action; 1074 switch (field) 1075 { 1076 case F_Keycode: 1077 if (!ExprResolveKeyName(value, &rtrn, NULL, NULL)) 1078 return ReportMismatch(action->type, field, "key name"); 1079 tmp = KeyNameToLong(rtrn.keyName.name); 1080 if (!FindNamedKey(xkb, tmp, &t1, True, CreateKeyNames(xkb), 0)) 1081 { 1082 return ReportNotFound(action->type, field, "Key", 1083 XkbKeyNameText(rtrn.keyName.name, 1084 XkbMessage)); 1085 } 1086 act->new_key = t1; 1087 return True; 1088 case F_ModsToClear: 1089 case F_Modifiers: 1090 t1 = 0; 1091 if (CheckModifierField(xkb, action->type, value, &t1, &t2)) 1092 { 1093 act->mods_mask |= (t2 & 0xff); 1094 if (field == F_Modifiers) 1095 act->mods |= (t2 & 0xff); 1096 else 1097 act->mods &= ~(t2 & 0xff); 1098 1099 t2 = (t2 >> 8) & 0xffff; 1100 vmods = XkbSARedirectVMods(act); 1101 vmask = XkbSARedirectVModsMask(act); 1102 vmask |= t2; 1103 if (field == F_Modifiers) 1104 vmods |= t2; 1105 else 1106 vmods &= ~t2; 1107 XkbSARedirectSetVMods(act, vmods); 1108 XkbSARedirectSetVModsMask(act, vmask); 1109 return True; 1110 } 1111 return True; 1112 } 1113 return ReportIllegal(action->type, field); 1114} 1115 1116static Bool 1117HandleDeviceBtn(XkbDescPtr xkb, 1118 XkbAnyAction * action, 1119 unsigned field, ExprDef * array_ndx, ExprDef * value) 1120{ 1121 ExprResult rtrn; 1122 XkbDeviceBtnAction *act; 1123 1124 act = (XkbDeviceBtnAction *) action; 1125 if (field == F_Button) 1126 { 1127 if (array_ndx != NULL) 1128 return ReportActionNotArray(action->type, field); 1129 if (!ExprResolveInteger(value, &rtrn, NULL, NULL)) 1130 return ReportMismatch(action->type, field, 1131 "integer (range 1..255)"); 1132 if ((rtrn.ival < 0) || (rtrn.ival > 255)) 1133 { 1134 ERROR("Button must specify default or be in the range 1..255\n"); 1135 ACTION("Illegal button value %d ignored\n", rtrn.ival); 1136 return False; 1137 } 1138 act->button = rtrn.ival; 1139 return True; 1140 } 1141 else if ((action->type == XkbSA_LockDeviceBtn) && (field == F_Affect)) 1142 { 1143 if (array_ndx != NULL) 1144 return ReportActionNotArray(action->type, field); 1145 if (!ExprResolveEnum(value, &rtrn, lockWhich)) 1146 return ReportMismatch(action->type, field, "lock or unlock"); 1147 act->flags &= ~(XkbSA_LockNoLock | XkbSA_LockNoUnlock); 1148 act->flags |= rtrn.uval; 1149 return True; 1150 } 1151 else if (field == F_Count) 1152 { 1153 if (array_ndx != NULL) 1154 return ReportActionNotArray(action->type, field); 1155 if (!ExprResolveInteger 1156 (value, &rtrn, SimpleLookup, (XPointer) btnNames)) 1157 return ReportMismatch(action->type, field, "integer"); 1158 if ((rtrn.ival < 0) || (rtrn.ival > 255)) 1159 { 1160 ERROR("The count field must have a value in the range 0..255\n"); 1161 ACTION("Illegal count %d ignored\n", rtrn.ival); 1162 return False; 1163 } 1164 act->count = rtrn.ival; 1165 return True; 1166 } 1167 else if (field == F_Device) 1168 { 1169 if (array_ndx != NULL) 1170 return ReportActionNotArray(action->type, field); 1171 if (!ExprResolveInteger(value, &rtrn, NULL, NULL)) 1172 return ReportMismatch(action->type, field, 1173 "integer (range 1..255)"); 1174 if ((rtrn.ival < 0) || (rtrn.ival > 255)) 1175 { 1176 ERROR("Device must specify default or be in the range 1..255\n"); 1177 ACTION("Illegal device value %d ignored\n", rtrn.ival); 1178 return False; 1179 } 1180 act->device = rtrn.ival; 1181 return True; 1182 } 1183 return ReportIllegal(action->type, field); 1184} 1185 1186static Bool 1187HandleDeviceValuator(XkbDescPtr xkb, 1188 XkbAnyAction * action, 1189 unsigned field, ExprDef * array_ndx, ExprDef * value) 1190{ 1191#if 0 1192 ExprResult rtrn; 1193 XkbDeviceValuatorAction *act; 1194 1195 act = (XkbDeviceValuatorAction *) action; 1196 /* XXX - Not yet implemented */ 1197#endif 1198 return False; 1199} 1200 1201static Bool 1202HandlePrivate(XkbDescPtr xkb, 1203 XkbAnyAction * action, 1204 unsigned field, ExprDef * array_ndx, ExprDef * value) 1205{ 1206 ExprResult rtrn; 1207 1208 switch (field) 1209 { 1210 case F_Type: 1211 if (!ExprResolveInteger(value, &rtrn, NULL, NULL)) 1212 return ReportMismatch(PrivateAction, field, "integer"); 1213 if ((rtrn.ival < 0) || (rtrn.ival > 255)) 1214 { 1215 ERROR("Private action type must be in the range 0..255\n"); 1216 ACTION("Illegal type %d ignored\n", rtrn.ival); 1217 return False; 1218 } 1219 action->type = rtrn.uval; 1220 return True; 1221 case F_Data: 1222 if (array_ndx == NULL) 1223 { 1224 if (!ExprResolveString(value, &rtrn, NULL, NULL)) 1225 return ReportMismatch(action->type, field, "string"); 1226 else 1227 { 1228 int len = strlen(rtrn.str); 1229 if ((len < 1) || (len > 7)) 1230 { 1231 WARN("A private action has 7 data bytes\n"); 1232 ACTION("Extra %d bytes ignored\n", len - 6); 1233 return False; 1234 } 1235 strncpy((char *) action->data, rtrn.str, 7); 1236 } 1237 return True; 1238 } 1239 else 1240 { 1241 unsigned ndx; 1242 if (!ExprResolveInteger(array_ndx, &rtrn, NULL, NULL)) 1243 { 1244 ERROR("Array subscript must be integer\n"); 1245 ACTION("Illegal subscript ignored\n"); 1246 return False; 1247 } 1248 ndx = rtrn.uval; 1249 if (ndx > 6) 1250 { 1251 ERROR("The data for a private action is 7 bytes long\n"); 1252 ACTION("Attempt to use data[%d] ignored\n", ndx); 1253 return False; 1254 } 1255 if (!ExprResolveInteger(value, &rtrn, NULL, NULL)) 1256 return ReportMismatch(action->type, field, "integer"); 1257 if ((rtrn.ival < 0) || (rtrn.ival > 255)) 1258 { 1259 ERROR("All data for a private action must be 0..255\n"); 1260 ACTION("Illegal datum %d ignored\n", rtrn.ival); 1261 return False; 1262 } 1263 action->data[ndx] = rtrn.uval; 1264 return True; 1265 } 1266 } 1267 return ReportIllegal(PrivateAction, field); 1268} 1269 1270typedef Bool(*actionHandler) (XkbDescPtr /* xkb */ , 1271 XkbAnyAction * /* action */ , 1272 unsigned /* field */ , 1273 ExprDef * /* array_ndx */ , 1274 ExprDef * /* value */ 1275 ); 1276 1277static actionHandler handleAction[XkbSA_NumActions + 1] = { 1278 HandleNoAction /* NoAction */ , 1279 HandleSetLatchMods /* SetMods */ , 1280 HandleSetLatchMods /* LatchMods */ , 1281 HandleLockMods /* LockMods */ , 1282 HandleSetLatchGroup /* SetGroup */ , 1283 HandleSetLatchGroup /* LatchGroup */ , 1284 HandleLockGroup /* LockGroup */ , 1285 HandleMovePtr /* MovePtr */ , 1286 HandlePtrBtn /* PtrBtn */ , 1287 HandlePtrBtn /* LockPtrBtn */ , 1288 HandleSetPtrDflt /* SetPtrDflt */ , 1289 HandleISOLock /* ISOLock */ , 1290 HandleNoAction /* Terminate */ , 1291 HandleSwitchScreen /* SwitchScreen */ , 1292 HandleSetLockControls /* SetControls */ , 1293 HandleSetLockControls /* LockControls */ , 1294 HandleActionMessage /* ActionMessage */ , 1295 HandleRedirectKey /* RedirectKey */ , 1296 HandleDeviceBtn /* DeviceBtn */ , 1297 HandleDeviceBtn /* LockDeviceBtn */ , 1298 HandleDeviceValuator /* DeviceValuatr */ , 1299 HandlePrivate /* Private */ 1300}; 1301 1302/***====================================================================***/ 1303 1304static void 1305ApplyActionFactoryDefaults(XkbAction * action) 1306{ 1307 if (action->type == XkbSA_SetPtrDflt) 1308 { /* increment default button */ 1309 action->dflt.affect = XkbSA_AffectDfltBtn; 1310 action->dflt.flags = 0; 1311 XkbSASetPtrDfltValue(&action->dflt, 1); 1312 } 1313 else if (action->type == XkbSA_ISOLock) 1314 { 1315 action->iso.real_mods = action->iso.mask = LockMask; 1316 } 1317 return; 1318} 1319 1320 1321int 1322HandleActionDef(ExprDef * def, 1323 XkbDescPtr xkb, 1324 XkbAnyAction * action, unsigned mergeMode, ActionInfo * info) 1325{ 1326 ExprDef *arg; 1327 register char *str; 1328 unsigned tmp, hndlrType; 1329 1330 if (!actionsInitialized) 1331 ActionsInit(); 1332 1333 if (def->op != ExprActionDecl) 1334 { 1335 ERROR("Expected an action definition, found %s\n", 1336 exprOpText(def->op)); 1337 return False; 1338 } 1339 str = XkbAtomGetString(NULL, def->value.action.name); 1340 if (!str) 1341 { 1342 WSGO("Missing name in action definition!!\n"); 1343 return False; 1344 } 1345 if (!stringToAction(str, &tmp)) 1346 { 1347 ERROR("Unknown action %s\n", str); 1348 return False; 1349 } 1350 action->type = hndlrType = tmp; 1351 if (action->type != XkbSA_NoAction) 1352 { 1353 ApplyActionFactoryDefaults((XkbAction *) action); 1354 while (info) 1355 { 1356 if ((info->action == XkbSA_NoAction) 1357 || (info->action == hndlrType)) 1358 { 1359 if (!(*handleAction[hndlrType]) (xkb, action, 1360 info->field, 1361 info->array_ndx, 1362 info->value)) 1363 { 1364 return False; 1365 } 1366 } 1367 info = info->next; 1368 } 1369 } 1370 for (arg = def->value.action.args; arg != NULL; 1371 arg = (ExprDef *) arg->common.next) 1372 { 1373 ExprDef *field, *value, *arrayRtrn; 1374 ExprResult elemRtrn, fieldRtrn; 1375 unsigned fieldNdx; 1376 1377 if (arg->op == OpAssign) 1378 { 1379 field = arg->value.binary.left; 1380 value = arg->value.binary.right; 1381 } 1382 else 1383 { 1384 if ((arg->op == OpNot) || (arg->op == OpInvert)) 1385 { 1386 field = arg->value.child; 1387 value = &constFalse; 1388 } 1389 else 1390 { 1391 field = arg; 1392 value = &constTrue; 1393 } 1394 } 1395 if (!ExprResolveLhs(field, &elemRtrn, &fieldRtrn, &arrayRtrn)) 1396 return False; /* internal error -- already reported */ 1397 1398 if (elemRtrn.str != NULL) 1399 { 1400 ERROR("Cannot change defaults in an action definition\n"); 1401 ACTION("Ignoring attempt to change %s.%s\n", elemRtrn.str, 1402 fieldRtrn.str); 1403 return False; 1404 } 1405 if (!stringToField(fieldRtrn.str, &fieldNdx)) 1406 { 1407 ERROR("Unknown field name %s\n", uStringText(fieldRtrn.str)); 1408 return False; 1409 } 1410 if (!(*handleAction[hndlrType]) 1411 (xkb, action, fieldNdx, arrayRtrn, value)) 1412 { 1413 return False; 1414 } 1415 } 1416 return True; 1417} 1418 1419/***====================================================================***/ 1420 1421int 1422SetActionField(XkbDescPtr xkb, 1423 const char *elem, 1424 const char *field, 1425 ExprDef * array_ndx, ExprDef * value, ActionInfo ** info_rtrn) 1426{ 1427 ActionInfo *new, *old; 1428 1429 if (!actionsInitialized) 1430 ActionsInit(); 1431 1432 new = uTypedAlloc(ActionInfo); 1433 if (new == NULL) 1434 { 1435 WSGO("Couldn't allocate space for action default\n"); 1436 return False; 1437 } 1438 if (uStrCaseCmp(elem, "action") == 0) 1439 new->action = XkbSA_NoAction; 1440 else 1441 { 1442 if (!stringToAction(elem, &new->action)) 1443 return False; 1444 if (new->action == XkbSA_NoAction) 1445 { 1446 ERROR("\"%s\" is not a valid field in a NoAction action\n", 1447 field); 1448 return False; 1449 } 1450 } 1451 if (!stringToField(field, &new->field)) 1452 { 1453 ERROR("\"%s\" is not a legal field name\n", field); 1454 return False; 1455 } 1456 new->array_ndx = array_ndx; 1457 new->value = value; 1458 new->next = NULL; 1459 old = *info_rtrn; 1460 while ((old) && (old->next)) 1461 old = old->next; 1462 if (old == NULL) 1463 *info_rtrn = new; 1464 else 1465 old->next = new; 1466 return True; 1467} 1468 1469/***====================================================================***/ 1470 1471void 1472ActionsInit(void) 1473{ 1474 if (!actionsInitialized) 1475 { 1476 bzero((char *) &constTrue, sizeof(constTrue)); 1477 bzero((char *) &constFalse, sizeof(constFalse)); 1478 constTrue.common.stmtType = StmtExpr; 1479 constTrue.common.next = NULL; 1480 constTrue.op = ExprIdent; 1481 constTrue.type = TypeBoolean; 1482 constTrue.value.str = XkbInternAtom(NULL, "true", False); 1483 constFalse.common.stmtType = StmtExpr; 1484 constFalse.common.next = NULL; 1485 constFalse.op = ExprIdent; 1486 constFalse.type = TypeBoolean; 1487 constFalse.value.str = XkbInternAtom(NULL, "false", False); 1488 actionsInitialized = 1; 1489 } 1490 return; 1491} 1492