indicators.c revision a57d84fe
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 "misc.h" 29#include "tokens.h" 30#include "expr.h" 31#include "vmod.h" 32#include "indicators.h" 33#include "action.h" 34#include "compat.h" 35 36/***====================================================================***/ 37 38#define ReportIndicatorBadType(d,l,f,w) \ 39 ReportBadType("indicator map",(f),\ 40 XkbAtomText((d),(l)->name,XkbMessage),(w)) 41#define ReportIndicatorNotArray(d,l,f) \ 42 ReportNotArray("indicator map",(f),\ 43 XkbAtomText((d),(l)->name,XkbMessage)) 44 45/***====================================================================***/ 46 47void 48ClearIndicatorMapInfo(Display * dpy, LEDInfo * info) 49{ 50 info->name = XkbInternAtom(dpy, "default", False); 51 info->indicator = _LED_NotBound; 52 info->flags = info->which_mods = info->real_mods = 0; 53 info->vmods = 0; 54 info->which_groups = info->groups = 0; 55 info->ctrls = 0; 56 return; 57} 58 59LEDInfo * 60AddIndicatorMap(LEDInfo * oldLEDs, LEDInfo * new) 61{ 62 LEDInfo *old, *last; 63 unsigned collide; 64 65 last = NULL; 66 for (old = oldLEDs; old != NULL; old = (LEDInfo *) old->defs.next) 67 { 68 if (old->name == new->name) 69 { 70 if ((old->real_mods == new->real_mods) && 71 (old->vmods == new->vmods) && 72 (old->groups == new->groups) && 73 (old->ctrls == new->ctrls) && 74 (old->which_mods == new->which_mods) && 75 (old->which_groups == new->which_groups)) 76 { 77 old->defs.defined |= new->defs.defined; 78 return oldLEDs; 79 } 80 if (new->defs.merge == MergeReplace) 81 { 82 CommonInfo *next = old->defs.next; 83 if (((old->defs.fileID == new->defs.fileID) 84 && (warningLevel > 0)) || (warningLevel > 9)) 85 { 86 WARN("Map for indicator %s redefined\n", 87 XkbAtomText(NULL, old->name, XkbMessage)); 88 ACTION("Earlier definition ignored\n"); 89 } 90 *old = *new; 91 old->defs.next = next; 92 return oldLEDs; 93 } 94 collide = 0; 95 if (UseNewField(_LED_Index, &old->defs, &new->defs, &collide)) 96 { 97 old->indicator = new->indicator; 98 old->defs.defined |= _LED_Index; 99 } 100 if (UseNewField(_LED_Mods, &old->defs, &new->defs, &collide)) 101 { 102 old->which_mods = new->which_mods; 103 old->real_mods = new->real_mods; 104 old->vmods = new->vmods; 105 old->defs.defined |= _LED_Mods; 106 } 107 if (UseNewField(_LED_Groups, &old->defs, &new->defs, &collide)) 108 { 109 old->which_groups = new->which_groups; 110 old->groups = new->groups; 111 old->defs.defined |= _LED_Groups; 112 } 113 if (UseNewField(_LED_Ctrls, &old->defs, &new->defs, &collide)) 114 { 115 old->ctrls = new->ctrls; 116 old->defs.defined |= _LED_Ctrls; 117 } 118 if (UseNewField(_LED_Explicit, &old->defs, &new->defs, &collide)) 119 { 120 old->flags &= ~XkbIM_NoExplicit; 121 old->flags |= (new->flags & XkbIM_NoExplicit); 122 old->defs.defined |= _LED_Explicit; 123 } 124 if (UseNewField(_LED_Automatic, &old->defs, &new->defs, &collide)) 125 { 126 old->flags &= ~XkbIM_NoAutomatic; 127 old->flags |= (new->flags & XkbIM_NoAutomatic); 128 old->defs.defined |= _LED_Automatic; 129 } 130 if (UseNewField(_LED_DrivesKbd, &old->defs, &new->defs, &collide)) 131 { 132 old->flags &= ~XkbIM_LEDDrivesKB; 133 old->flags |= (new->flags & XkbIM_LEDDrivesKB); 134 old->defs.defined |= _LED_DrivesKbd; 135 } 136 if (collide && (warningLevel > 0)) 137 { 138 WARN("Map for indicator %s redefined\n", 139 XkbAtomText(NULL, old->name, XkbMessage)); 140 ACTION("Using %s definition for duplicate fields\n", 141 (new->defs.merge == MergeAugment ? "first" : "last")); 142 } 143 return oldLEDs; 144 } 145 if (old->defs.next == NULL) 146 last = old; 147 } 148 /* new definition */ 149 old = uTypedAlloc(LEDInfo); 150 if (!old) 151 { 152 WSGO("Couldn't allocate indicator map\n"); 153 ACTION("Map for indicator %s not compiled\n", 154 XkbAtomText(NULL, new->name, XkbMessage)); 155 return NULL; 156 } 157 *old = *new; 158 old->defs.next = NULL; 159 if (last) 160 { 161 last->defs.next = &old->defs; 162 return oldLEDs; 163 } 164 return old; 165} 166 167static LookupEntry modComponentNames[] = { 168 {"base", XkbIM_UseBase} 169 , 170 {"latched", XkbIM_UseLatched} 171 , 172 {"locked", XkbIM_UseLocked} 173 , 174 {"effective", XkbIM_UseEffective} 175 , 176 {"compat", XkbIM_UseCompat} 177 , 178 {"any", XkbIM_UseAnyMods} 179 , 180 {"none", 0} 181 , 182 {NULL, 0} 183}; 184static LookupEntry groupComponentNames[] = { 185 {"base", XkbIM_UseBase} 186 , 187 {"latched", XkbIM_UseLatched} 188 , 189 {"locked", XkbIM_UseLocked} 190 , 191 {"effective", XkbIM_UseEffective} 192 , 193 {"any", XkbIM_UseAnyGroup} 194 , 195 {"none", 0} 196 , 197 {NULL, 0} 198}; 199 200int 201SetIndicatorMapField(LEDInfo * led, 202 XkbDescPtr xkb, 203 const char *field, ExprDef *arrayNdx, ExprDef *value) 204{ 205 ExprResult rtrn; 206 Bool ok; 207 208 ok = True; 209 if ((uStrCaseCmp(field, "modifiers") == 0) 210 || (uStrCaseCmp(field, "mods") == 0)) 211 { 212 if (arrayNdx != NULL) 213 return ReportIndicatorNotArray(xkb->dpy, led, field); 214 if (!ExprResolveModMask(value, &rtrn, LookupVModMask, (XPointer) xkb)) 215 return ReportIndicatorBadType(xkb->dpy, led, field, 216 "modifier mask"); 217 led->real_mods = rtrn.uval & 0xff; 218 led->vmods = (rtrn.uval >> 8) & 0xff; 219 led->defs.defined |= _LED_Mods; 220 } 221 else if (uStrCaseCmp(field, "groups") == 0) 222 { 223 if (arrayNdx != NULL) 224 return ReportIndicatorNotArray(xkb->dpy, led, field); 225 if (!ExprResolveMask 226 (value, &rtrn, SimpleLookup, (XPointer) groupNames)) 227 return ReportIndicatorBadType(xkb->dpy, led, field, "group mask"); 228 led->groups = rtrn.uval; 229 led->defs.defined |= _LED_Groups; 230 } 231 else if ((uStrCaseCmp(field, "controls") == 0) || 232 (uStrCaseCmp(field, "ctrls") == 0)) 233 { 234 if (arrayNdx != NULL) 235 return ReportIndicatorNotArray(xkb->dpy, led, field); 236 if (!ExprResolveMask 237 (value, &rtrn, SimpleLookup, (XPointer) ctrlNames)) 238 return ReportIndicatorBadType(xkb->dpy, led, field, 239 "controls mask"); 240 led->ctrls = rtrn.uval; 241 led->defs.defined |= _LED_Ctrls; 242 } 243 else if (uStrCaseCmp(field, "allowexplicit") == 0) 244 { 245 if (arrayNdx != NULL) 246 return ReportIndicatorNotArray(xkb->dpy, led, field); 247 if (!ExprResolveBoolean(value, &rtrn, NULL, NULL)) 248 return ReportIndicatorBadType(xkb->dpy, led, field, "boolean"); 249 if (rtrn.uval) 250 led->flags &= ~XkbIM_NoExplicit; 251 else 252 led->flags |= XkbIM_NoExplicit; 253 led->defs.defined |= _LED_Explicit; 254 } 255 else if ((uStrCaseCmp(field, "whichmodstate") == 0) || 256 (uStrCaseCmp(field, "whichmodifierstate") == 0)) 257 { 258 if (arrayNdx != NULL) 259 return ReportIndicatorNotArray(xkb->dpy, led, field); 260 if (!ExprResolveMask(value, &rtrn, SimpleLookup, 261 (XPointer) modComponentNames)) 262 { 263 return ReportIndicatorBadType(xkb->dpy, led, field, 264 "mask of modifier state components"); 265 } 266 led->which_mods = rtrn.uval; 267 } 268 else if (uStrCaseCmp(field, "whichgroupstate") == 0) 269 { 270 if (arrayNdx != NULL) 271 return ReportIndicatorNotArray(xkb->dpy, led, field); 272 if (!ExprResolveMask(value, &rtrn, SimpleLookup, 273 (XPointer) groupComponentNames)) 274 { 275 return ReportIndicatorBadType(xkb->dpy, led, field, 276 "mask of group state components"); 277 } 278 led->which_groups = rtrn.uval; 279 } 280 else if ((uStrCaseCmp(field, "driveskbd") == 0) || 281 (uStrCaseCmp(field, "driveskeyboard") == 0) || 282 (uStrCaseCmp(field, "leddriveskbd") == 0) || 283 (uStrCaseCmp(field, "leddriveskeyboard") == 0) || 284 (uStrCaseCmp(field, "indicatordriveskbd") == 0) || 285 (uStrCaseCmp(field, "indicatordriveskeyboard") == 0)) 286 { 287 if (arrayNdx != NULL) 288 return ReportIndicatorNotArray(xkb->dpy, led, field); 289 if (!ExprResolveBoolean(value, &rtrn, NULL, NULL)) 290 return ReportIndicatorBadType(xkb->dpy, led, field, "boolean"); 291 if (rtrn.uval) 292 led->flags |= XkbIM_LEDDrivesKB; 293 else 294 led->flags &= ~XkbIM_LEDDrivesKB; 295 led->defs.defined |= _LED_DrivesKbd; 296 } 297 else if (uStrCaseCmp(field, "index") == 0) 298 { 299 if (arrayNdx != NULL) 300 return ReportIndicatorNotArray(xkb->dpy, led, field); 301 if (!ExprResolveInteger(value, &rtrn, NULL, NULL)) 302 return ReportIndicatorBadType(xkb->dpy, led, field, 303 "indicator index"); 304 if ((rtrn.uval < 1) || (rtrn.uval > 32)) 305 { 306 ERROR("Illegal indicator index %d (range 1..%d)\n", 307 rtrn.uval, XkbNumIndicators); 308 ACTION("Index definition for %s indicator ignored\n", 309 XkbAtomText(NULL, led->name, XkbMessage)); 310 return False; 311 } 312 led->indicator = rtrn.uval; 313 led->defs.defined |= _LED_Index; 314 } 315 else 316 { 317 ERROR("Unknown field %s in map for %s indicator\n", field, 318 XkbAtomText(NULL, led->name, XkbMessage)); 319 ACTION("Definition ignored\n"); 320 ok = False; 321 } 322 return ok; 323} 324 325LEDInfo * 326HandleIndicatorMapDef(IndicatorMapDef * def, 327 XkbDescPtr xkb, 328 LEDInfo * dflt, LEDInfo * oldLEDs, unsigned merge) 329{ 330 LEDInfo led, *rtrn; 331 VarDef *var; 332 Bool ok; 333 334 if (def->merge != MergeDefault) 335 merge = def->merge; 336 337 led = *dflt; 338 led.defs.merge = merge; 339 led.name = def->name; 340 341 ok = True; 342 for (var = def->body; var != NULL; var = (VarDef *) var->common.next) 343 { 344 ExprResult elem, field; 345 ExprDef *arrayNdx; 346 if (!ExprResolveLhs(var->name, &elem, &field, &arrayNdx)) 347 { 348 ok = False; 349 continue; 350 } 351 if (elem.str != NULL) 352 { 353 ERROR 354 ("Cannot set defaults for \"%s\" element in indicator map\n", 355 elem.str); 356 ACTION("Assignment to %s.%s ignored\n", elem.str, field.str); 357 ok = False; 358 } 359 else 360 { 361 ok = SetIndicatorMapField(&led, xkb, field.str, arrayNdx, 362 var->value) && ok; 363 } 364 } 365 if (ok) 366 { 367 rtrn = AddIndicatorMap(oldLEDs, &led); 368 return rtrn; 369 } 370 return NULL; 371} 372 373Bool 374CopyIndicatorMapDefs(XkbFileInfo * result, LEDInfo * leds, 375 LEDInfo ** unboundRtrn) 376{ 377 LEDInfo *led, *next; 378 LEDInfo *unbound, *last; 379 XkbDescPtr xkb; 380 381 xkb = result->xkb; 382 if (XkbAllocNames(xkb, XkbIndicatorNamesMask, 0, 0) != Success) 383 { 384 WSGO("Couldn't allocate names\n"); 385 ACTION("Indicator names may be incorrect\n"); 386 } 387 if (XkbAllocIndicatorMaps(xkb) != Success) 388 { 389 WSGO("Can't allocate indicator maps\n"); 390 ACTION("Indicator map definitions may be lost\n"); 391 return False; 392 } 393 last = unbound = (unboundRtrn ? *unboundRtrn : NULL); 394 while ((last != NULL) && (last->defs.next != NULL)) 395 { 396 last = (LEDInfo *) last->defs.next; 397 } 398 for (led = leds; led != NULL; led = next) 399 { 400 next = (LEDInfo *) led->defs.next; 401 if ((led->groups != 0) && (led->which_groups == 0)) 402 led->which_groups = XkbIM_UseEffective; 403 if ((led->which_mods == 0) && ((led->real_mods) || (led->vmods))) 404 led->which_mods = XkbIM_UseEffective; 405 if ((led->indicator == _LED_NotBound) || (!xkb->indicators)) 406 { 407 if (unboundRtrn != NULL) 408 { 409 led->defs.next = NULL; 410 if (last != NULL) 411 last->defs.next = (CommonInfo *) led; 412 else 413 unbound = led; 414 last = led; 415 } 416 else 417 uFree(led); 418 } 419 else 420 { 421 register XkbIndicatorMapPtr im; 422 im = &xkb->indicators->maps[led->indicator - 1]; 423 im->flags = led->flags; 424 im->which_groups = led->which_groups; 425 im->groups = led->groups; 426 im->which_mods = led->which_mods; 427 im->mods.mask = led->real_mods; 428 im->mods.real_mods = led->real_mods; 429 im->mods.vmods = led->vmods; 430 im->ctrls = led->ctrls; 431 if (xkb->names != NULL) 432 xkb->names->indicators[led->indicator - 1] = led->name; 433 uFree(led); 434 } 435 } 436 if (unboundRtrn != NULL) 437 { 438 *unboundRtrn = unbound; 439 } 440 return True; 441} 442 443Bool 444BindIndicators(XkbFileInfo * result, 445 Bool force, LEDInfo * unbound, LEDInfo ** unboundRtrn) 446{ 447 XkbDescPtr xkb; 448 register int i; 449 register LEDInfo *led, *next, *last; 450 451 xkb = result->xkb; 452 if (xkb->names != NULL) 453 { 454 for (led = unbound; led != NULL; led = (LEDInfo *) led->defs.next) 455 { 456 if (led->indicator == _LED_NotBound) 457 { 458 for (i = 0; i < XkbNumIndicators; i++) 459 { 460 if (xkb->names->indicators[i] == led->name) 461 { 462 led->indicator = i + 1; 463 break; 464 } 465 } 466 } 467 } 468 if (force) 469 { 470 for (led = unbound; led != NULL; led = (LEDInfo *) led->defs.next) 471 { 472 if (led->indicator == _LED_NotBound) 473 { 474 for (i = 0; i < XkbNumIndicators; i++) 475 { 476 if (xkb->names->indicators[i] == None) 477 { 478 xkb->names->indicators[i] = led->name; 479 led->indicator = i + 1; 480 xkb->indicators->phys_indicators &= ~(1 << i); 481 break; 482 } 483 } 484 if (led->indicator == _LED_NotBound) 485 { 486 ERROR("No unnamed indicators found\n"); 487 ACTION 488 ("Virtual indicator map \"%s\" not bound\n", 489 XkbAtomGetString(xkb->dpy, led->name)); 490 continue; 491 } 492 } 493 } 494 } 495 } 496 for (last = NULL, led = unbound; led != NULL; led = next) 497 { 498 next = (LEDInfo *) led->defs.next; 499 if (led->indicator == _LED_NotBound) 500 { 501 if (force) 502 { 503 unbound = next; 504 uFree(led); 505 } 506 else 507 { 508 if (last) 509 last->defs.next = &led->defs; 510 else 511 unbound = led; 512 last = led; 513 } 514 } 515 else 516 { 517 if ((xkb->names != NULL) && 518 (xkb->names->indicators[led->indicator - 1] != led->name)) 519 { 520 Atom old = xkb->names->indicators[led->indicator - 1]; 521 ERROR("Multiple names bound to indicator %d\n", 522 (unsigned int) led->indicator); 523 ACTION("Using %s, ignoring %s\n", 524 XkbAtomGetString(xkb->dpy, old), 525 XkbAtomGetString(xkb->dpy, led->name)); 526 led->indicator = _LED_NotBound; 527 if (force) 528 { 529 uFree(led); 530 unbound = next; 531 } 532 else 533 { 534 if (last) 535 last->defs.next = &led->defs; 536 else 537 unbound = led; 538 last = led; 539 } 540 } 541 else 542 { 543 XkbIndicatorMapPtr map; 544 map = &xkb->indicators->maps[led->indicator - 1]; 545 map->flags = led->flags; 546 map->which_groups = led->which_groups; 547 map->groups = led->groups; 548 map->which_mods = led->which_mods; 549 map->mods.mask = led->real_mods; 550 map->mods.real_mods = led->real_mods; 551 map->mods.vmods = led->vmods; 552 map->ctrls = led->ctrls; 553 if (last) 554 last->defs.next = &next->defs; 555 else 556 unbound = next; 557 led->defs.next = NULL; 558 uFree(led); 559 } 560 } 561 } 562 if (unboundRtrn) 563 { 564 *unboundRtrn = unbound; 565 } 566 else if (unbound) 567 { 568 for (led = unbound; led != NULL; led = next) 569 { 570 next = (LEDInfo *) led->defs.next; 571 uFree(led); 572 } 573 } 574 return True; 575} 576