indicators.c revision f46a6179
1/* $Xorg: indicators.c,v 1.3 2000/08/17 19:54:31 cpqbld Exp $ */ 2/************************************************************ 3 Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. 4 5 Permission to use, copy, modify, and distribute this 6 software and its documentation for any purpose and without 7 fee is hereby granted, provided that the above copyright 8 notice appear in all copies and that both that copyright 9 notice and this permission notice appear in supporting 10 documentation, and that the name of Silicon Graphics not be 11 used in advertising or publicity pertaining to distribution 12 of the software without specific prior written permission. 13 Silicon Graphics makes no representation about the suitability 14 of this software for any purpose. It is provided "as is" 15 without any express or implied warranty. 16 17 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 18 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 19 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 20 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 21 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 22 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 23 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 24 THE USE OR PERFORMANCE OF THIS SOFTWARE. 25 26 ********************************************************/ 27/* $XFree86: xc/programs/xkbcomp/indicators.c,v 1.4 2001/01/17 23:45:43 dawes Exp $ */ 28 29#include "xkbcomp.h" 30#include "misc.h" 31#include "tokens.h" 32#include "expr.h" 33#include "vmod.h" 34#include "indicators.h" 35#include "action.h" 36#include "compat.h" 37 38/***====================================================================***/ 39 40#define ReportIndicatorBadType(d,l,f,w) \ 41 ReportBadType("indicator map",(f),\ 42 XkbAtomText((d),(l)->name,XkbMessage),(w)) 43#define ReportIndicatorNotArray(d,l,f) \ 44 ReportNotArray("indicator map",(f),\ 45 XkbAtomText((d),(l)->name,XkbMessage)) 46 47/***====================================================================***/ 48 49void 50ClearIndicatorMapInfo(Display *dpy,LEDInfo *info) 51{ 52 info->name= XkbInternAtom(dpy,"default",False); 53 info->indicator= _LED_NotBound; 54 info->flags= info->which_mods= info->real_mods= 0; 55 info->vmods= 0; 56 info->which_groups= info->groups= 0; 57 info->ctrls= 0; 58 return; 59} 60 61LEDInfo * 62AddIndicatorMap(LEDInfo *oldLEDs,LEDInfo *new) 63{ 64LEDInfo *old,*last; 65unsigned collide; 66 67 last= NULL; 68 for (old=oldLEDs;old!=NULL;old=(LEDInfo *)old->defs.next) { 69 if (old->name==new->name) { 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 old->defs.defined|= new->defs.defined; 77 return oldLEDs; 78 } 79 if (new->defs.merge==MergeReplace) { 80 CommonInfo *next= old->defs.next; 81 if (((old->defs.fileID==new->defs.fileID)&&(warningLevel>0))|| 82 (warningLevel>9)) { 83 WARN1("Map for indicator %s redefined\n", 84 XkbAtomText(NULL,old->name,XkbMessage)); 85 ACTION("Earlier definition ignored\n"); 86 } 87 *old= *new; 88 old->defs.next= next; 89 return oldLEDs; 90 } 91 collide= 0; 92 if (UseNewField(_LED_Index,&old->defs,&new->defs,&collide)) { 93 old->indicator= new->indicator; 94 old->defs.defined|= _LED_Index; 95 } 96 if (UseNewField(_LED_Mods,&old->defs,&new->defs,&collide)) { 97 old->which_mods= new->which_mods; 98 old->real_mods= new->real_mods; 99 old->vmods= new->vmods; 100 old->defs.defined|= _LED_Mods; 101 } 102 if (UseNewField(_LED_Groups,&old->defs,&new->defs,&collide)) { 103 old->which_groups= new->which_groups; 104 old->groups= new->groups; 105 old->defs.defined|= _LED_Groups; 106 } 107 if (UseNewField(_LED_Ctrls,&old->defs,&new->defs,&collide)) { 108 old->ctrls= new->ctrls; 109 old->defs.defined|= _LED_Ctrls; 110 } 111 if (UseNewField(_LED_Explicit,&old->defs,&new->defs,&collide)) { 112 old->flags&= ~XkbIM_NoExplicit; 113 old->flags|= (new->flags&XkbIM_NoExplicit); 114 old->defs.defined|= _LED_Explicit; 115 } 116 if (UseNewField(_LED_Automatic,&old->defs,&new->defs,&collide)) { 117 old->flags&= ~XkbIM_NoAutomatic; 118 old->flags|= (new->flags&XkbIM_NoAutomatic); 119 old->defs.defined|= _LED_Automatic; 120 } 121 if (UseNewField(_LED_DrivesKbd,&old->defs,&new->defs,&collide)) { 122 old->flags&= ~XkbIM_LEDDrivesKB; 123 old->flags|= (new->flags&XkbIM_LEDDrivesKB); 124 old->defs.defined|= _LED_DrivesKbd; 125 } 126 if (collide) { 127 WARN1("Map for indicator %s redefined\n", 128 XkbAtomText(NULL,old->name,XkbMessage)); 129 ACTION1("Using %s definition for duplicate fields\n", 130 (new->defs.merge==MergeAugment?"first":"last")); 131 } 132 return oldLEDs; 133 } 134 if (old->defs.next==NULL) 135 last= old; 136 } 137 /* new definition */ 138 old= uTypedAlloc(LEDInfo); 139 if (!old) { 140 WSGO("Couldn't allocate indicator map\n"); 141 ACTION1("Map for indicator %s not compiled\n", 142 XkbAtomText(NULL,new->name,XkbMessage)); 143 return False; 144 } 145 *old= *new; 146 old->defs.next= NULL; 147 if (last) { 148 last->defs.next= &old->defs; 149 return oldLEDs; 150 } 151 return old; 152} 153 154LookupEntry modComponentNames[] = { 155 { "base", XkbIM_UseBase }, 156 { "latched", XkbIM_UseLatched }, 157 { "locked", XkbIM_UseLocked }, 158 { "effective", XkbIM_UseEffective }, 159 { "compat", XkbIM_UseCompat }, 160 { "any", XkbIM_UseAnyMods }, 161 { "none", 0 }, 162 { NULL, 0 } 163}; 164LookupEntry groupComponentNames[] = { 165 { "base", XkbIM_UseBase }, 166 { "latched", XkbIM_UseLatched }, 167 { "locked", XkbIM_UseLocked }, 168 { "effective", XkbIM_UseEffective }, 169 { "any", XkbIM_UseAnyGroup }, 170 { "none", 0 }, 171 { NULL, 0 } 172}; 173 174int 175SetIndicatorMapField( LEDInfo * led, 176 XkbDescPtr xkb, 177 char * field, 178 ExprDef * arrayNdx, 179 ExprDef * value) 180{ 181ExprResult rtrn; 182Bool ok; 183 184 ok= True; 185 if ((uStrCaseCmp(field,"modifiers")==0)||(uStrCaseCmp(field,"mods")==0)) { 186 if (arrayNdx!=NULL) 187 return ReportIndicatorNotArray(xkb->dpy,led,field); 188 if (!ExprResolveModMask(value,&rtrn,LookupVModMask,(XPointer)xkb)) 189 return ReportIndicatorBadType(xkb->dpy,led,field,"modifier mask"); 190 led->real_mods= rtrn.uval&0xff; 191 led->vmods= (rtrn.uval>>8)&0xff; 192 led->defs.defined|= _LED_Mods; 193 } 194 else if (uStrCaseCmp(field,"groups")==0) { 195 if (arrayNdx!=NULL) 196 return ReportIndicatorNotArray(xkb->dpy,led,field); 197 if (!ExprResolveMask(value,&rtrn,SimpleLookup,(XPointer)groupNames)) 198 return ReportIndicatorBadType(xkb->dpy,led,field,"group mask"); 199 led->groups= rtrn.uval; 200 led->defs.defined|= _LED_Groups; 201 } 202 else if ((uStrCaseCmp(field,"controls")==0)|| 203 (uStrCaseCmp(field,"ctrls")==0)) { 204 if (arrayNdx!=NULL) 205 return ReportIndicatorNotArray(xkb->dpy,led,field); 206 if (!ExprResolveMask(value,&rtrn,SimpleLookup,(XPointer)ctrlNames)) 207 return ReportIndicatorBadType(xkb->dpy,led,field,"controls mask"); 208 led->ctrls= rtrn.uval; 209 led->defs.defined|= _LED_Ctrls; 210 } 211 else if (uStrCaseCmp(field,"allowexplicit")==0) { 212 if (arrayNdx!=NULL) 213 return ReportIndicatorNotArray(xkb->dpy,led,field); 214 if (!ExprResolveBoolean(value,&rtrn,NULL,NULL)) 215 return ReportIndicatorBadType(xkb->dpy,led,field,"boolean"); 216 if (rtrn.uval) led->flags&= ~XkbIM_NoExplicit; 217 else led->flags|= XkbIM_NoExplicit; 218 led->defs.defined|= _LED_Explicit; 219 } 220 else if ((uStrCaseCmp(field,"whichmodstate")==0)|| 221 (uStrCaseCmp(field,"whichmodifierstate")==0)) { 222 if (arrayNdx!=NULL) 223 return ReportIndicatorNotArray(xkb->dpy,led,field); 224 if (!ExprResolveMask(value,&rtrn,SimpleLookup, 225 (XPointer)modComponentNames)) { 226 return ReportIndicatorBadType(xkb->dpy,led,field, 227 "mask of modifier state components"); 228 } 229 led->which_mods= rtrn.uval; 230 } 231 else if (uStrCaseCmp(field,"whichgroupstate")==0) { 232 if (arrayNdx!=NULL) 233 return ReportIndicatorNotArray(xkb->dpy,led,field); 234 if (!ExprResolveMask(value,&rtrn,SimpleLookup, 235 (XPointer)groupComponentNames)){ 236 return ReportIndicatorBadType(xkb->dpy,led,field, 237 "mask of group state components"); 238 } 239 led->which_groups= rtrn.uval; 240 } 241 else if ((uStrCaseCmp(field,"driveskbd")==0)|| 242 (uStrCaseCmp(field,"driveskeyboard")==0)|| 243 (uStrCaseCmp(field,"leddriveskbd")==0)|| 244 (uStrCaseCmp(field,"leddriveskeyboard")==0)|| 245 (uStrCaseCmp(field,"indicatordriveskbd")==0)|| 246 (uStrCaseCmp(field,"indicatordriveskeyboard")==0)) { 247 if (arrayNdx!=NULL) 248 return ReportIndicatorNotArray(xkb->dpy,led,field); 249 if (!ExprResolveBoolean(value,&rtrn,NULL,NULL)) 250 return ReportIndicatorBadType(xkb->dpy,led,field,"boolean"); 251 if (rtrn.uval) led->flags|= XkbIM_LEDDrivesKB; 252 else led->flags&= ~XkbIM_LEDDrivesKB; 253 led->defs.defined|= _LED_DrivesKbd; 254 } 255 else if (uStrCaseCmp(field,"index")==0) { 256 if (arrayNdx!=NULL) 257 return ReportIndicatorNotArray(xkb->dpy,led,field); 258 if (!ExprResolveInteger(value,&rtrn,NULL,NULL)) 259 return ReportIndicatorBadType(xkb->dpy,led,field,"indicator index"); 260 if ((rtrn.uval<1)||(rtrn.uval>32)) { 261 ERROR2("Illegal indicator index %d (range 1..%d)\n",rtrn.uval, 262 XkbNumIndicators); 263 ACTION1("Index definition for %s indicator ignored\n", 264 XkbAtomText(NULL,led->name,XkbMessage)); 265 return False; 266 } 267 led->indicator= rtrn.uval; 268 led->defs.defined|= _LED_Index; 269 } 270 else { 271 ERROR2("Unknown field %s in map for %s indicator\n",field, 272 XkbAtomText(NULL,led->name,XkbMessage)); 273 ACTION("Definition ignored\n"); 274 ok= False; 275 } 276 return ok; 277} 278 279LEDInfo * 280HandleIndicatorMapDef( IndicatorMapDef * def, 281 XkbDescPtr xkb, 282 LEDInfo * dflt, 283 LEDInfo * oldLEDs, 284 unsigned merge) 285{ 286LEDInfo led,*rtrn; 287VarDef * var; 288Bool ok; 289 290 if (def->merge!=MergeDefault) 291 merge= def->merge; 292 293 led= *dflt; 294 led.defs.merge= merge; 295 led.name= def->name; 296 297 ok= True; 298 for (var= def->body;var!=NULL;var= (VarDef *)var->common.next) { 299 ExprResult elem,field; 300 ExprDef * arrayNdx; 301 if (!ExprResolveLhs(var->name,&elem,&field,&arrayNdx)) { 302 ok= False; 303 continue; 304 } 305 if (elem.str!=NULL) { 306 ERROR1("Cannot set defaults for \"%s\" element in indicator map\n", 307 elem.str); 308 ACTION2("Assignment to %s.%s ignored\n",elem.str,field.str); 309 ok= False; 310 } 311 else { 312 ok=SetIndicatorMapField(&led,xkb,field.str,arrayNdx,var->value)&&ok; 313 } 314 } 315 if (ok) { 316 rtrn= AddIndicatorMap(oldLEDs,&led); 317 return rtrn; 318 } 319 return NULL; 320} 321 322Bool 323CopyIndicatorMapDefs(XkbFileInfo *result,LEDInfo *leds,LEDInfo **unboundRtrn) 324{ 325LEDInfo * led,*next; 326LEDInfo * unbound,*last; 327XkbDescPtr xkb; 328 329 xkb= result->xkb; 330 if (XkbAllocNames(xkb,XkbIndicatorNamesMask,0,0)!=Success) { 331 WSGO("Couldn't allocate names\n"); 332 ACTION("Indicator names may be incorrect\n"); 333 } 334 if (XkbAllocIndicatorMaps(xkb)!=Success) { 335 WSGO("Can't allocate indicator maps\n"); 336 ACTION("Indicator map definitions may be lost\n"); 337 return False; 338 } 339 last= unbound= (unboundRtrn?*unboundRtrn:NULL); 340 while ((last!=NULL) && (last->defs.next!=NULL)) { 341 last= (LEDInfo *)last->defs.next; 342 } 343 for (led=leds;led!=NULL;led=next) { 344 next= (LEDInfo *)led->defs.next; 345 if ((led->groups!=0)&&(led->which_groups==0)) 346 led->which_groups= XkbIM_UseEffective; 347 if ((led->which_mods==0)&&((led->real_mods)||(led->vmods))) 348 led->which_mods= XkbIM_UseEffective; 349 if ((led->indicator==_LED_NotBound)||(!xkb->indicators)) { 350 if (unboundRtrn!=NULL) { 351 led->defs.next= NULL; 352 if (last!=NULL) last->defs.next= (CommonInfo *)led; 353 else unbound= led; 354 last= led; 355 } 356 else uFree(led); 357 } 358 else { 359 register XkbIndicatorMapPtr im; 360 im= &xkb->indicators->maps[led->indicator-1]; 361 im->flags= led->flags; 362 im->which_groups= led->which_groups; 363 im->groups= led->groups; 364 im->which_mods= led->which_mods; 365 im->mods.mask= led->real_mods; 366 im->mods.real_mods= led->real_mods; 367 im->mods.vmods= led->vmods; 368 im->ctrls= led->ctrls; 369 if (xkb->names!=NULL) 370 xkb->names->indicators[led->indicator-1]= led->name; 371 uFree(led); 372 } 373 } 374 if (unboundRtrn!=NULL) { 375 *unboundRtrn= unbound; 376 } 377 return True; 378} 379 380Bool 381BindIndicators( XkbFileInfo * result, 382 Bool force, 383 LEDInfo * unbound, 384 LEDInfo ** unboundRtrn) 385{ 386XkbDescPtr xkb; 387register int i; 388register LEDInfo *led,*next,*last; 389 390 xkb= result->xkb; 391 if (xkb->names!=NULL) { 392 for (led=unbound;led!=NULL;led= (LEDInfo *)led->defs.next) { 393 if (led->indicator==_LED_NotBound) { 394 for (i=0;i<XkbNumIndicators;i++) { 395 if (xkb->names->indicators[i]==led->name) { 396 led->indicator= i+1; 397 break; 398 } 399 } 400 } 401 } 402 if (force) { 403 for (led=unbound;led!=NULL;led= (LEDInfo *)led->defs.next) { 404 if (led->indicator==_LED_NotBound) { 405 for (i=0;i<XkbNumIndicators;i++) { 406 if (xkb->names->indicators[i]==None) { 407 xkb->names->indicators[i]= led->name; 408 led->indicator= i+1; 409 xkb->indicators->phys_indicators&= ~(1<<i); 410 break; 411 } 412 } 413 if (led->indicator==_LED_NotBound) { 414 ERROR("No unnamed indicators found\n"); 415 ACTION1("Virtual indicator map \"%s\" not bound\n", 416 XkbAtomGetString(xkb->dpy,led->name)); 417 continue; 418 } 419 } 420 } 421 } 422 } 423 for (last=NULL,led=unbound;led!=NULL;led= next) { 424 next= (LEDInfo *)led->defs.next; 425 if (led->indicator==_LED_NotBound) { 426 if (force) { 427 unbound= next; 428 uFree(led); 429 } 430 else { 431 if (last) 432 last->defs.next= &led->defs; 433 else unbound= led; 434 last= led; 435 } 436 } 437 else { 438 if ((xkb->names!=NULL)&& 439 (xkb->names->indicators[led->indicator-1]!=led->name)) { 440 Atom old= xkb->names->indicators[led->indicator-1]; 441 ERROR1("Multiple names bound to indicator %d\n",(unsigned int)led->indicator); 442 ACTION2("Using %s, ignoring %s\n", 443 XkbAtomGetString(xkb->dpy,old), 444 XkbAtomGetString(xkb->dpy,led->name)); 445 led->indicator= _LED_NotBound; 446 if (force) { 447 uFree(led); 448 unbound= next; 449 } 450 else { 451 if (last) 452 last->defs.next= &led->defs; 453 else unbound= led; 454 last= led; 455 } 456 } 457 else { 458 XkbIndicatorMapPtr map; 459 map= &xkb->indicators->maps[led->indicator-1]; 460 map->flags= led->flags; 461 map->which_groups= led->which_groups; 462 map->groups= led->groups; 463 map->which_mods= led->which_mods; 464 map->mods.mask= led->real_mods; 465 map->mods.real_mods= led->real_mods; 466 map->mods.vmods= led->vmods; 467 map->ctrls= led->ctrls; 468 if (last) last->defs.next= &next->defs; 469 else unbound= next; 470 led->defs.next= NULL; 471 uFree(led); 472 } 473 } 474 } 475 if (unboundRtrn) { 476 *unboundRtrn= unbound; 477 } 478 else if (unbound) { 479 for (led=unbound;led!=NULL;led=next) { 480 next= (LEDInfo *)led->defs.next; 481 uFree(led); 482 } 483 } 484 return True; 485} 486