xkbconfig.c revision 8c9fbc29
1/* $Xorg: xkbconfig.c,v 1.4 2000/08/17 19:46:43 cpqbld Exp $ */ 2/************************************************************ 3 Copyright (c) 1995 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/lib/xkbfile/xkbconfig.c,v 3.7 2001/11/30 12:11:51 eich Exp $ */ 28 29#ifdef HAVE_DIX_CONFIG_H 30#include <dix-config.h> 31#elif defined(HAVE_CONFIG_H) 32#include <config.h> 33#endif 34 35#include <stdio.h> 36#include <ctype.h> 37#include <stdlib.h> 38 39#include <X11/Xfuncs.h> 40 41#include <X11/Xfuncs.h> 42 43#ifndef XKB_IN_SERVER 44 45#include <X11/Xos.h> 46#include <X11/Xlib.h> 47#include <X11/keysym.h> 48#include <X11/XKBlib.h> 49#include "XKBfileInt.h" 50 51#else 52 53#include <X11/X.h> 54#define NEED_EVENTS 55#include <X11/keysym.h> 56#include <X11/Xproto.h> 57#include "misc.h" 58#include "inputstr.h" 59#include "dix.h" 60#define XKBSRV_NEED_FILE_FUNCS 61#include <X11/extensions/XKBsrv.h> 62#endif 63 64#include <X11/extensions/XKBconfig.h> 65 66/***====================================================================***/ 67 68#define XKBCF_MAX_STR_LEN 100 69static char _XkbCF_rtrn[XKBCF_MAX_STR_LEN+1]; 70 71static int 72ScanIdent(FILE *file,int ch,XkbCFScanResultPtr val_rtrn) 73{ 74register int i; 75char * str; 76 77 val_rtrn->str= str= _XkbCF_rtrn; 78 for (i=0;(isalpha(ch)||isdigit(ch)||(ch=='_'));ch=getc(file)) { 79 if (i<XKBCF_MAX_STR_LEN) 80 str[i++]= ch; 81 } 82 if ((ch!=EOF)&&(ch!=' ')&&(ch!='\t')) 83 ungetc(ch,file); 84 str[i]= '\0'; 85 return XkbCF_Ident; 86} 87 88static int 89ScanString(FILE *file,int quote,XkbCFScanResultPtr val_rtrn) 90{ 91int ch,nInBuf; 92 93 nInBuf = 0; 94 while ( ((ch=getc(file))!=EOF) && (ch!='\n') && (ch!=quote) ) { 95 if ( ch == '\\' ) { 96 if ((ch = getc(file))!=EOF) { 97 if ( ch=='n' ) ch = '\n'; 98 else if ( ch == 't' ) ch = '\t'; 99 else if ( ch == 'v' ) ch = '\v'; 100 else if ( ch == 'b' ) ch = '\b'; 101 else if ( ch == 'r' ) ch = '\r'; 102 else if ( ch == 'f' ) ch = '\f'; 103 else if ( ch == 'e' ) ch = '\033'; 104 else if ( ch == '0' ) { 105 int tmp,stop; 106 ch = stop = 0; 107 if (((tmp=getc(file))!=EOF) && (isdigit(tmp)) && 108 (tmp!='8') && (tmp!='9')) { 109 ch= (ch*8)+(tmp-'0'); 110 } 111 else { 112 stop= 1; 113 ungetc(tmp,file); 114 } 115 if ((!stop) && ((tmp=getc(file))!=EOF) && (isdigit(tmp)) && 116 (tmp!='8') && (tmp!='9')) { 117 ch= (ch*8)+(tmp-'0'); 118 } 119 else { 120 stop= 1; 121 ungetc(tmp,file); 122 } 123 if ((!stop) && ((tmp=getc(file))!=EOF) && (isdigit(tmp)) && 124 (tmp!='8') && (tmp!='9')) { 125 ch= (ch*8)+(tmp-'0'); 126 } 127 else { 128 stop= 1; 129 ungetc(tmp,file); 130 } 131 } 132 } 133 else return XkbCF_EOF; 134 } 135 136 if ( nInBuf < XKBCF_MAX_STR_LEN-1 ) 137 _XkbCF_rtrn[nInBuf++] = ch; 138 } 139 if ( ch == quote ) { 140 _XkbCF_rtrn[nInBuf++] = '\0'; 141 val_rtrn->str= _XkbCF_rtrn; 142 return XkbCF_String; 143 } 144 return XkbCF_UnterminatedString; 145} 146 147static int 148ScanInteger(FILE *file,int ch,XkbCFScanResultPtr val_rtrn) 149{ 150int i; 151 152 if (isdigit(ch)) 153 ungetc(ch,file); 154 if (fscanf(file,"%i",&i)==1) { 155 val_rtrn->ival= i; 156 return XkbCF_Integer; 157 } 158 return XkbCF_Unknown; 159} 160 161int 162XkbCFScan(FILE *file,XkbCFScanResultPtr val_rtrn,XkbConfigRtrnPtr rtrn) 163{ 164int ch; 165 166 do { 167 ch= getc(file); 168 } while ((ch=='\t')||(ch==' ')); 169 if (isalpha(ch)) 170 return ScanIdent(file,ch,val_rtrn); 171 else if (isdigit(ch)) 172 return ScanInteger(file,ch,val_rtrn); 173 else if (ch=='"') 174 return ScanString(file,ch,val_rtrn); 175 else if (ch=='\n') { 176 rtrn->line++; 177 return XkbCF_EOL; 178 } 179 else if (ch==';') 180 return XkbCF_Semi; 181 else if (ch=='=') 182 return XkbCF_Equals; 183 else if (ch=='+') { 184 ch= getc(file); 185 if (ch=='=') 186 return XkbCF_PlusEquals; 187 if ((ch!=EOF)&&(ch!=' ')&&(ch!='\t')) 188 ungetc(ch,file); 189 return XkbCF_Plus; 190 } 191 else if (ch=='-') { 192 ch= getc(file); 193 if (ch=='=') 194 return XkbCF_MinusEquals; 195 if ((ch!=EOF)&&(ch!=' ')&&(ch!='\t')) 196 ungetc(ch,file); 197 return XkbCF_Minus; 198 } 199 else if (ch==EOF) 200 return XkbCF_EOF; 201 else if ((ch=='#')||((ch=='/')&&(getc(file)=='/'))) { 202 while ((ch!='\n')&&(ch!=EOF)) 203 ch= getc(file); 204 rtrn->line++; 205 return XkbCF_EOL; 206 } 207 return XkbCF_Unknown; 208} 209 210/***====================================================================***/ 211 212#define _XkbCF_Illegal 0 213#define _XkbCF_Keymap 1 214#define _XkbCF_Keycodes 2 215#define _XkbCF_Geometry 3 216#define _XkbCF_PhysSymbols 4 217#define _XkbCF_Symbols 5 218#define _XkbCF_Types 6 219#define _XkbCF_CompatMap 7 220 221#define _XkbCF_RulesFile 8 222#define _XkbCF_Model 9 223#define _XkbCF_Layout 10 224#define _XkbCF_Variant 11 225#define _XkbCF_Options 12 226 227#define _XkbCF_InitialMods 13 228#define _XkbCF_InitialCtrls 14 229 230#define _XkbCF_ClickVolume 15 231#define _XkbCF_BellVolume 16 232#define _XkbCF_BellPitch 17 233#define _XkbCF_BellDuration 18 234#define _XkbCF_RepeatDelay 19 235#define _XkbCF_RepeatInterval 20 236#define _XkbCF_SlowKeysDelay 21 237#define _XkbCF_DebounceDelay 22 238#define _XkbCF_MouseKeysDelay 23 239#define _XkbCF_MouseKeysInterval 24 240#define _XkbCF_MouseKeysTimeToMax 25 241#define _XkbCF_MouseKeysMaxSpeed 26 242#define _XkbCF_MouseKeysCurve 27 243#define _XkbCF_AccessXTimeout 28 244#define _XkbCF_AccessXTimeoutCtrlsOn 29 245#define _XkbCF_AccessXTimeoutCtrlsOff 30 246#define _XkbCF_AccessXTimeoutOptsOn 31 247#define _XkbCF_AccessXTimeoutOptsOff 32 248 249#define _XkbCF_IgnoreLockMods 33 250#define _XkbCF_IgnoreGroupLock 34 251#define _XkbCF_InternalMods 35 252 253#define _XkbCF_GroupsWrap 36 254#define _XkbCF_InitialFeedback 37 255 256static Bool 257AddCtrlByName(XkbConfigRtrnPtr rtrn,char *name,unsigned long *ctrls_rtrn) 258{ 259 if ((_XkbStrCaseCmp(name,"repeat")==0)|| 260 (_XkbStrCaseCmp(name,"repeatkeys")==0)) 261 *ctrls_rtrn= XkbRepeatKeysMask; 262 else if (_XkbStrCaseCmp(name,"slowkeys")==0) 263 *ctrls_rtrn= XkbSlowKeysMask; 264 else if (_XkbStrCaseCmp(name,"bouncekeys")==0) 265 *ctrls_rtrn= XkbBounceKeysMask; 266 else if (_XkbStrCaseCmp(name,"stickykeys")==0) 267 *ctrls_rtrn= XkbStickyKeysMask; 268 else if (_XkbStrCaseCmp(name,"mousekeys")==0) 269 *ctrls_rtrn= XkbMouseKeysMask; 270 else if (_XkbStrCaseCmp(name,"mousekeysaccel")==0) 271 *ctrls_rtrn= XkbMouseKeysAccelMask; 272 else if (_XkbStrCaseCmp(name,"accessxkeys")==0) 273 *ctrls_rtrn= XkbAccessXKeysMask; 274 else if (_XkbStrCaseCmp(name,"accessxtimeout")==0) 275 *ctrls_rtrn= XkbAccessXTimeoutMask; 276 else if (_XkbStrCaseCmp(name,"accessxfeedback")==0) 277 *ctrls_rtrn= XkbAccessXFeedbackMask; 278 else if (_XkbStrCaseCmp(name,"audiblebell")==0) 279 *ctrls_rtrn= XkbAudibleBellMask; 280 else if (_XkbStrCaseCmp(name,"overlay1")==0) 281 *ctrls_rtrn= XkbOverlay1Mask; 282 else if (_XkbStrCaseCmp(name,"overlay2")==0) 283 *ctrls_rtrn= XkbOverlay2Mask; 284 else if (_XkbStrCaseCmp(name,"ignoregrouplock")==0) 285 *ctrls_rtrn= XkbIgnoreGroupLockMask; 286 else { 287 rtrn->error= XkbCF_ExpectedControl; 288 return False; 289 } 290 return True; 291} 292 293static Bool 294AddAXTimeoutOptByName( XkbConfigRtrnPtr rtrn, 295 char * name, 296 unsigned short * opts_rtrn) 297{ 298 if (_XkbStrCaseCmp(name,"slowkeyspress")==0) 299 *opts_rtrn= XkbAX_SKPressFBMask; 300 else if (_XkbStrCaseCmp(name,"slowkeysaccept")==0) 301 *opts_rtrn= XkbAX_SKAcceptFBMask; 302 else if (_XkbStrCaseCmp(name,"feature")==0) 303 *opts_rtrn= XkbAX_FeatureFBMask; 304 else if (_XkbStrCaseCmp(name,"slowwarn")==0) 305 *opts_rtrn= XkbAX_SlowWarnFBMask; 306 else if (_XkbStrCaseCmp(name,"indicator")==0) 307 *opts_rtrn= XkbAX_IndicatorFBMask; 308 else if (_XkbStrCaseCmp(name,"stickykeys")==0) 309 *opts_rtrn= XkbAX_StickyKeysFBMask; 310 else if (_XkbStrCaseCmp(name,"twokeys")==0) 311 *opts_rtrn= XkbAX_TwoKeysMask; 312 else if (_XkbStrCaseCmp(name,"latchtolock")==0) 313 *opts_rtrn= XkbAX_LatchToLockMask; 314 else if (_XkbStrCaseCmp(name,"slowkeysrelease")==0) 315 *opts_rtrn= XkbAX_SKReleaseFBMask; 316 else if (_XkbStrCaseCmp(name,"slowkeysreject")==0) 317 *opts_rtrn= XkbAX_SKRejectFBMask; 318 else if (_XkbStrCaseCmp(name,"bouncekeysreject")==0) 319 *opts_rtrn= XkbAX_BKRejectFBMask; 320 else if (_XkbStrCaseCmp(name,"dumbbell")==0) 321 *opts_rtrn= XkbAX_DumbBellFBMask; 322 else { 323 rtrn->error= XkbCF_ExpectedControl; 324 return False; 325 } 326 return True; 327} 328 329XkbConfigUnboundModPtr 330XkbCFAddModByName( XkbConfigRtrnPtr rtrn, 331 int what, 332 char * name, 333 Bool merge, 334 XkbConfigUnboundModPtr last) 335{ 336 if (rtrn->num_unbound_mods>=rtrn->sz_unbound_mods) { 337 rtrn->sz_unbound_mods+= 5; 338 rtrn->unbound_mods= _XkbTypedRealloc(rtrn->unbound_mods, 339 rtrn->sz_unbound_mods, 340 XkbConfigUnboundModRec); 341 if (rtrn->unbound_mods==NULL) { 342 rtrn->error= XkbCF_BadAlloc; 343 return False; 344 } 345 } 346 if (last==NULL) { 347 last= &rtrn->unbound_mods[rtrn->num_unbound_mods++]; 348 last->what= what; 349 last->mods= 0; 350 last->vmods= 0; 351 last->merge= merge; 352 last->name= NULL; 353 } 354 if (_XkbStrCaseCmp(name,"shift")==0) 355 last->mods|= ShiftMask; 356 else if (_XkbStrCaseCmp(name,"lock")==0) 357 last->mods|= LockMask; 358 else if ((_XkbStrCaseCmp(name,"control")==0)|| 359 (_XkbStrCaseCmp(name,"ctrl")==0)) 360 last->mods|= ControlMask; 361 else if (_XkbStrCaseCmp(name,"mod1")==0) 362 last->mods|= Mod1Mask; 363 else if (_XkbStrCaseCmp(name,"mod2")==0) 364 last->mods|= Mod2Mask; 365 else if (_XkbStrCaseCmp(name,"mod3")==0) 366 last->mods|= Mod3Mask; 367 else if (_XkbStrCaseCmp(name,"mod4")==0) 368 last->mods|= Mod4Mask; 369 else if (_XkbStrCaseCmp(name,"mod5")==0) 370 last->mods|= Mod5Mask; 371 else { 372 if (last->name!=NULL) { 373 last= &rtrn->unbound_mods[rtrn->num_unbound_mods++]; 374 last->what= what; 375 last->mods= 0; 376 last->vmods= 0; 377 last->merge= merge; 378 last->name= NULL; 379 } 380 last->name= _XkbDupString(name); 381 } 382 return last; 383} 384 385int 386XkbCFBindMods(XkbConfigRtrnPtr rtrn,XkbDescPtr xkb) 387{ 388register int n,v; 389Atom name; 390XkbConfigUnboundModPtr mod; 391int missing; 392 393 if (rtrn->num_unbound_mods<1) 394 return 0; 395 if ((xkb==NULL) || (xkb->names==NULL)) 396 return -1; 397 398 missing= 0; 399 for (n=0,mod=rtrn->unbound_mods;n<rtrn->num_unbound_mods;n++,mod++) { 400 if (mod->name!=NULL) { 401 name= XkbInternAtom(xkb->dpy,mod->name,True); 402 if (name==None) 403 continue; 404 for (v=0;v<XkbNumVirtualMods;v++) { 405 if (xkb->names->vmods[v]==name) { 406 mod->vmods= (1<<v); 407 _XkbFree(mod->name); 408 mod->name= NULL; 409 break; 410 } 411 } 412 if (mod->name!=NULL) 413 missing++; 414 } 415 } 416 return missing; 417} 418 419Bool 420XkbCFApplyMods(XkbConfigRtrnPtr rtrn,int what,XkbConfigModInfoPtr info) 421{ 422register int n; 423XkbConfigUnboundModPtr mod; 424 425 if (rtrn->num_unbound_mods<1) 426 return True; 427 428 for (n=0,mod=rtrn->unbound_mods;n<rtrn->num_unbound_mods;n++,mod++) { 429 if (mod->what!=what) 430 continue; 431 if (mod->merge==XkbCF_MergeRemove) { 432 info->mods_clear|= mod->mods; 433 info->vmods_clear|= mod->vmods; 434 } 435 else { 436 if (mod->merge==XkbCF_MergeSet) 437 info->replace= True; 438 info->mods|= mod->mods; 439 info->vmods|= mod->vmods; 440 } 441 if (mod->name==NULL) { 442 mod->what= _XkbCF_Illegal; 443 } 444 else { 445 mod->mods= 0; 446 mod->vmods= 0; 447 } 448 } 449 return True; 450} 451 452/*ARGSUSED*/ 453static Bool 454DefaultParser( FILE * file, 455 XkbConfigFieldsPtr fields, 456 XkbConfigFieldPtr field, 457 XkbDescPtr xkb, 458 XkbConfigRtrnPtr rtrn) 459{ 460int tok; 461XkbCFScanResultRec val; 462char ** str; 463int merge; 464unsigned long * ctrls, ctrls_mask; 465unsigned short * opts, opts_mask; 466int * pival, sign; 467int onoff; 468XkbConfigUnboundModPtr last; 469unsigned what; 470 471 tok= XkbCFScan(file,&val,rtrn); 472 str= NULL; 473 onoff= 0; 474 pival= NULL; 475 switch (field->field_id) { 476 case _XkbCF_RulesFile: if (!str) str= &rtrn->rules_file; 477 case _XkbCF_Model: if (!str) str= &rtrn->model; 478 case _XkbCF_Layout: if (!str) str= &rtrn->layout; 479 case _XkbCF_Variant: if (!str) str= &rtrn->variant; 480 case _XkbCF_Options: if (!str) str= &rtrn->options; 481 case _XkbCF_Keymap: if (!str) str= &rtrn->keymap; 482 case _XkbCF_Keycodes: if (!str) str= &rtrn->keycodes; 483 case _XkbCF_Geometry: if (!str) str= &rtrn->geometry; 484 case _XkbCF_PhysSymbols:if (!str) str= &rtrn->phys_symbols; 485 case _XkbCF_Symbols: if (!str) str= &rtrn->symbols; 486 case _XkbCF_Types: if (!str) str= &rtrn->types; 487 case _XkbCF_CompatMap: if (!str) str= &rtrn->compat; 488 if (tok!=XkbCF_Equals) { 489 rtrn->error= XkbCF_MissingEquals; 490 goto BAILOUT; 491 } 492 tok= XkbCFScan(file,&val,rtrn); 493 if ((tok!=XkbCF_String)&&(tok!=XkbCF_Ident)) { 494 rtrn->error= XkbCF_ExpectedString; 495 return False; 496 } 497 tok= XkbCFScan(file,&val,rtrn); 498 if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) { 499 rtrn->error= XkbCF_ExpectedEOS; 500 return False; 501 } 502 if (*str!=NULL) 503 _XkbFree(*str); 504 *str= _XkbDupString(val.str); 505 break; 506 case _XkbCF_InitialMods: 507 case _XkbCF_IgnoreLockMods: 508 case _XkbCF_InternalMods: 509 what= XkbCF_InitialMods; 510 if (field->field_id==_XkbCF_InitialMods) 511 rtrn->defined|= (what=XkbCF_InitialMods); 512 else if (field->field_id==_XkbCF_InternalMods) 513 rtrn->defined|= (what=XkbCF_InternalMods); 514 else if (field->field_id==_XkbCF_IgnoreLockMods) 515 rtrn->defined|= (what=XkbCF_IgnoreLockMods); 516 if (tok==XkbCF_Equals) merge= XkbCF_MergeSet; 517 else if (tok==XkbCF_MinusEquals) merge= XkbCF_MergeRemove; 518 else if (tok==XkbCF_PlusEquals) merge= XkbCF_MergeAdd; 519 else { 520 rtrn->error= XkbCF_MissingEquals; 521 goto BAILOUT; 522 } 523 tok= XkbCFScan(file,&val,rtrn); 524 if ((tok==XkbCF_EOL)||(tok==XkbCF_Semi)||(tok==XkbCF_EOF)) { 525 rtrn->error= XkbCF_ExpectedModifier; 526 return False; 527 } 528 last= NULL; 529 while ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) { 530 if ((tok!=XkbCF_Ident)&&(tok!=XkbCF_String)) { 531 rtrn->error= XkbCF_ExpectedModifier; 532 return False; 533 } 534 last=XkbCFAddModByName(rtrn,what,val.str,merge,last); 535 if (last==NULL) 536 return False; 537 if (merge==XkbCF_MergeSet) 538 merge= XkbCF_MergeAdd; 539 tok= XkbCFScan(file,&val,rtrn); 540 if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_EOF)&&(tok!=XkbCF_Semi)) { 541 if (tok!=XkbCF_Plus) { 542 rtrn->error= XkbCF_ExpectedOperator; 543 return False; 544 } 545 tok= XkbCFScan(file,&val,rtrn); 546 } 547 } 548 break; 549 case _XkbCF_InitialCtrls: 550 rtrn->defined|= XkbCF_InitialCtrls; 551 ctrls= NULL; 552 if (tok==XkbCF_PlusEquals) 553 ctrls= &rtrn->initial_ctrls; 554 else if (tok==XkbCF_MinusEquals) 555 ctrls= &rtrn->initial_ctrls_clear; 556 else if (tok==XkbCF_Equals) { 557 ctrls= &rtrn->initial_ctrls; 558 rtrn->replace_initial_ctrls= True; 559 *ctrls= 0; 560 } 561 else { 562 rtrn->error= XkbCF_MissingEquals; 563 goto BAILOUT; 564 } 565 tok= XkbCFScan(file,&val,rtrn); 566 if ((tok==XkbCF_EOL)||(tok==XkbCF_Semi)||(tok==XkbCF_EOF)) { 567 rtrn->error= XkbCF_ExpectedControl; 568 return False; 569 } 570 while ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) { 571 if ((tok!=XkbCF_Ident)&&(tok!=XkbCF_String)) { 572 rtrn->error= XkbCF_ExpectedControl; 573 return False; 574 } 575 if (!AddCtrlByName(rtrn,val.str,&ctrls_mask)) { 576 return False; 577 } 578 *ctrls |= ctrls_mask; 579 tok= XkbCFScan(file,&val,rtrn); 580 if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_EOF)&&(tok!=XkbCF_Semi)) { 581 if (tok!=XkbCF_Plus) { 582 rtrn->error= XkbCF_ExpectedOperator; 583 return False; 584 } 585 tok= XkbCFScan(file,&val,rtrn); 586 } 587 } 588 break; 589 case _XkbCF_AccessXTimeoutCtrlsOn: 590 case _XkbCF_AccessXTimeoutCtrlsOff: 591 opts= NULL; 592 if (tok==XkbCF_MinusEquals) { 593 ctrls= &rtrn->axt_ctrls_ignore; 594 opts= &rtrn->axt_opts_ignore; 595 } 596 else if ((tok==XkbCF_PlusEquals)||(tok==XkbCF_Equals)) { 597 if (field->field_id==_XkbCF_AccessXTimeoutCtrlsOff) { 598 ctrls= &rtrn->axt_ctrls_off; 599 opts= &rtrn->axt_opts_off; 600 if (tok==XkbCF_Equals) 601 rtrn->replace_axt_ctrls_off= True; 602 } 603 else { 604 ctrls= &rtrn->axt_ctrls_on; 605 opts= &rtrn->axt_opts_on; 606 if (tok==XkbCF_Equals) 607 rtrn->replace_axt_ctrls_on= True; 608 } 609 *ctrls= 0; 610 } 611 else { 612 rtrn->error= XkbCF_MissingEquals; 613 goto BAILOUT; 614 } 615 tok= XkbCFScan(file,&val,rtrn); 616 if ((tok==XkbCF_EOL)||(tok==XkbCF_Semi)||(tok==XkbCF_EOF)) { 617 rtrn->error= XkbCF_ExpectedControl; 618 return False; 619 } 620 while ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) { 621 if ((tok!=XkbCF_Ident)&&(tok!=XkbCF_String)) { 622 rtrn->error= XkbCF_ExpectedControl; 623 return False; 624 } 625 if (!AddCtrlByName(rtrn,val.str,&ctrls_mask)) { 626 if (!AddAXTimeoutOptByName(rtrn,val.str,&opts_mask)) 627 return False; 628 *opts |= opts_mask; 629 if (field->field_id==_XkbCF_AccessXTimeoutCtrlsOff) { 630 rtrn->defined|= XkbCF_AccessXTimeoutOptsOff; 631 if (rtrn->replace_axt_ctrls_off) 632 rtrn->replace_axt_opts_off= True; 633 } 634 else { 635 rtrn->defined|= XkbCF_AccessXTimeoutOptsOn; 636 if (rtrn->replace_axt_ctrls_on) 637 rtrn->replace_axt_opts_on= True; 638 } 639 } 640 else 641 *ctrls |= ctrls_mask; 642 tok= XkbCFScan(file,&val,rtrn); 643 if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_EOF)&&(tok!=XkbCF_Semi)) { 644 if (tok!=XkbCF_Plus) { 645 rtrn->error= XkbCF_ExpectedOperator; 646 return False; 647 } 648 tok= XkbCFScan(file,&val,rtrn); 649 } 650 } 651 break; 652 case _XkbCF_InitialFeedback: 653 rtrn->defined|= XkbCF_InitialOpts; 654 opts= NULL; 655 if (tok==XkbCF_PlusEquals) 656 opts= &rtrn->initial_opts; 657 else if (tok==XkbCF_MinusEquals) 658 opts= &rtrn->initial_opts_clear; 659 else if (tok==XkbCF_Equals) { 660 opts= &rtrn->initial_opts; 661 rtrn->replace_initial_opts= True; 662 *opts= 0; 663 } 664 else { 665 rtrn->error= XkbCF_MissingEquals; 666 goto BAILOUT; 667 } 668 tok= XkbCFScan(file,&val,rtrn); 669 if ((tok==XkbCF_EOL)||(tok==XkbCF_Semi)||(tok==XkbCF_EOF)) { 670 rtrn->error= XkbCF_ExpectedAXOption; 671 return False; 672 } 673 while ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) { 674 if ((tok!=XkbCF_Ident)&&(tok!=XkbCF_String)) { 675 rtrn->error= XkbCF_ExpectedAXOption; 676 return False; 677 } 678 if (!AddAXTimeoutOptByName(rtrn,val.str,&opts_mask)) { 679 return False; 680 } 681 *opts |= opts_mask; 682 tok= XkbCFScan(file,&val,rtrn); 683 if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_EOF)&&(tok!=XkbCF_Semi)) { 684 if (tok!=XkbCF_Plus) { 685 rtrn->error= XkbCF_ExpectedOperator; 686 return False; 687 } 688 tok= XkbCFScan(file,&val,rtrn); 689 } 690 } 691 break; 692 case _XkbCF_AccessXTimeoutOptsOff: 693 case _XkbCF_AccessXTimeoutOptsOn: 694 opts= NULL; 695 if (tok==XkbCF_MinusEquals) 696 opts= &rtrn->axt_opts_ignore; 697 else if ((tok==XkbCF_PlusEquals)||(tok==XkbCF_Equals)) { 698 if (field->field_id==_XkbCF_AccessXTimeoutOptsOff) { 699 opts= &rtrn->axt_opts_off; 700 if (tok==XkbCF_Equals) 701 rtrn->replace_axt_opts_off= True; 702 } 703 else { 704 opts= &rtrn->axt_opts_on; 705 if (tok==XkbCF_Equals) 706 rtrn->replace_axt_opts_on= True; 707 } 708 *opts = 0; 709 } 710 else { 711 rtrn->error= XkbCF_MissingEquals; 712 goto BAILOUT; 713 } 714 tok= XkbCFScan(file,&val,rtrn); 715 if ((tok==XkbCF_EOL)||(tok==XkbCF_Semi)||(tok==XkbCF_EOF)) { 716 rtrn->error= XkbCF_ExpectedControl; 717 return False; 718 } 719 while ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) { 720 if ((tok!=XkbCF_Ident)&&(tok!=XkbCF_String)) { 721 rtrn->error= XkbCF_ExpectedControl; 722 return False; 723 } 724 if (!AddAXTimeoutOptByName(rtrn,val.str,&opts_mask)) 725 return False; 726 *opts |= opts_mask; 727 728 tok= XkbCFScan(file,&val,rtrn); 729 if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_EOF)&&(tok!=XkbCF_Semi)) { 730 if (tok!=XkbCF_Plus) { 731 rtrn->error= XkbCF_ExpectedOperator; 732 return False; 733 } 734 tok= XkbCFScan(file,&val,rtrn); 735 } 736 } 737 break; 738 case _XkbCF_ClickVolume: 739 if (!pival) { 740 pival= &rtrn->click_volume; 741 onoff= 100; 742 } 743 case _XkbCF_BellVolume: 744 if (!pival) { 745 pival= &rtrn->bell_volume; 746 onoff= 100; 747 } 748 case _XkbCF_BellPitch: 749 if (!pival) 750 pival= &rtrn->bell_pitch; 751 case _XkbCF_BellDuration: 752 if (!pival) 753 pival= &rtrn->bell_duration; 754 case _XkbCF_RepeatDelay: 755 if (!pival) 756 pival= &rtrn->repeat_delay; 757 case _XkbCF_RepeatInterval: 758 if (!pival) 759 pival= &rtrn->repeat_interval; 760 case _XkbCF_SlowKeysDelay: 761 if (!pival) 762 pival= &rtrn->slow_keys_delay; 763 case _XkbCF_DebounceDelay: 764 if (!pival) 765 pival= &rtrn->debounce_delay; 766 case _XkbCF_MouseKeysDelay: 767 if (!pival) 768 pival= &rtrn->mk_delay; 769 case _XkbCF_MouseKeysInterval: 770 if (!pival) 771 pival= &rtrn->mk_interval; 772 case _XkbCF_MouseKeysTimeToMax: 773 if (!pival) 774 pival= &rtrn->mk_time_to_max; 775 case _XkbCF_MouseKeysMaxSpeed: 776 if (!pival) 777 pival= &rtrn->mk_max_speed; 778 case _XkbCF_MouseKeysCurve: 779 if (!pival) 780 pival= &rtrn->mk_curve; 781 case _XkbCF_AccessXTimeout: 782 if (!pival) 783 pival= &rtrn->ax_timeout; 784 if (tok!=XkbCF_Equals) { 785 rtrn->error= XkbCF_MissingEquals; 786 goto BAILOUT; 787 } 788 tok= XkbCFScan(file,&val,rtrn); 789 if (tok == XkbCF_Minus && field->field_id == _XkbCF_MouseKeysCurve) { 790 /* This can be a negative value */ 791 tok = XkbCFScan(file,&val,rtrn); 792 sign = -1; 793 } 794 else 795 sign = 1; 796 if (tok!=XkbCF_Integer) { 797 Bool ok= False; 798 if ((onoff)&&(tok==XkbCF_Ident)&&(val.str!=NULL)) { 799 if (_XkbStrCaseCmp(val.str,"on")) { 800 val.ival= onoff; 801 ok= True; 802 } 803 else if (_XkbStrCaseCmp(val.str,"off")) { 804 val.ival= 0; 805 ok= True; 806 } 807 } 808 if (!ok) { 809 rtrn->error= XkbCF_ExpectedInteger; 810 goto BAILOUT; 811 } 812 } 813 *pival= val.ival * sign; 814 if (field->field_id == _XkbCF_AccessXTimeout) 815 rtrn->defined|=XkbCF_AccessXTimeout; 816 tok= XkbCFScan(file,&val,rtrn); 817 if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) { 818 rtrn->error= XkbCF_ExpectedEOS; 819 return False; 820 } 821 break; 822 case _XkbCF_GroupsWrap: 823 if (tok!=XkbCF_Equals) { 824 rtrn->error= XkbCF_MissingEquals; 825 goto BAILOUT; 826 } 827 tok= XkbCFScan(file,&val,rtrn); 828 if (tok==XkbCF_Ident) { 829 if (_XkbStrCaseCmp(val.str,"wrap")==0) { 830 rtrn->groups_wrap= XkbSetGroupInfo(0,XkbWrapIntoRange,0); 831 } 832 else if (_XkbStrCaseCmp(val.str,"clamp")==0) { 833 rtrn->groups_wrap= XkbSetGroupInfo(0,XkbClampIntoRange,0); 834 } 835 else { 836 rtrn->error= XkbCF_ExpectedOORGroupBehavior; 837 return False; 838 } 839 } 840 else if ((tok==XkbCF_Integer)&&(XkbIsLegalGroup(val.ival-1))) { 841 rtrn->groups_wrap= XkbSetGroupInfo(0,XkbRedirectIntoRange, 842 val.ival-1); 843 } 844 else { 845 rtrn->error= XkbCF_ExpectedOORGroupBehavior; 846 return False; 847 } 848 rtrn->defined|= XkbCF_GroupsWrap; 849 tok= XkbCFScan(file,&val,rtrn); 850 if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)&&(tok!=XkbCF_EOF)) { 851 rtrn->error= XkbCF_ExpectedEOS; 852 return False; 853 } 854 break; 855 default: 856 rtrn->error= XkbCF_ExpectedInteger; 857 goto BAILOUT; 858 859 } 860 return True; 861BAILOUT: 862 return False; 863} 864 865static Bool 866DefaultCleanUp(XkbConfigRtrnPtr rtrn) 867{ 868 if (rtrn->keymap) _XkbFree(rtrn->keymap); 869 if (rtrn->keycodes) _XkbFree(rtrn->keycodes); 870 if (rtrn->geometry) _XkbFree(rtrn->geometry); 871 if (rtrn->phys_symbols) _XkbFree(rtrn->phys_symbols); 872 if (rtrn->symbols) _XkbFree(rtrn->symbols); 873 if (rtrn->types) _XkbFree(rtrn->types); 874 if (rtrn->compat) _XkbFree(rtrn->compat); 875 rtrn->keycodes= rtrn->geometry= NULL; 876 rtrn->symbols= rtrn->phys_symbols= NULL; 877 rtrn->types= rtrn->compat= NULL; 878 if ((rtrn->unbound_mods!=NULL)&&(rtrn->num_unbound_mods>0)) { 879 register int i; 880 for (i=0;i<rtrn->num_unbound_mods;i++) { 881 if (rtrn->unbound_mods[i].name!=NULL) { 882 _XkbFree(rtrn->unbound_mods[i].name); 883 rtrn->unbound_mods[i].name= NULL; 884 } 885 } 886 _XkbFree(rtrn->unbound_mods); 887 rtrn->sz_unbound_mods= 0; 888 rtrn->num_unbound_mods= 0; 889 rtrn->unbound_mods= NULL; 890 } 891 return True; 892} 893 894static Bool 895DefaultApplyNames(XkbConfigRtrnPtr rtrn,XkbDescPtr xkb) 896{ 897char *str; 898 899 if (XkbAllocNames(xkb,XkbComponentNamesMask,0,0)!=Success) 900 return False; 901 if ((str=rtrn->keycodes)!=NULL) { 902 xkb->names->keycodes= XkbInternAtom(xkb->dpy,str,False); 903 _XkbFree(str); 904 rtrn->keycodes= NULL; 905 } 906 if ((str=rtrn->geometry)!=NULL) { 907 xkb->names->geometry= XkbInternAtom(xkb->dpy,str,False); 908 _XkbFree(str); 909 rtrn->geometry= NULL; 910 } 911 if ((str=rtrn->symbols)!=NULL) { 912 xkb->names->symbols= XkbInternAtom(xkb->dpy,str,False); 913 _XkbFree(str); 914 rtrn->symbols= NULL; 915 } 916 if ((str=rtrn->phys_symbols)!=NULL) { 917 xkb->names->phys_symbols= XkbInternAtom(xkb->dpy,str,False); 918 _XkbFree(str); 919 rtrn->phys_symbols= NULL; 920 } 921 if ((str=rtrn->types)!=NULL) { 922 xkb->names->types= XkbInternAtom(xkb->dpy,str,False); 923 _XkbFree(str); 924 rtrn->types= NULL; 925 } 926 if ((str=rtrn->compat)!=NULL) { 927 xkb->names->compat= XkbInternAtom(xkb->dpy,str,False); 928 _XkbFree(str); 929 rtrn->compat= NULL; 930 } 931 return True; 932} 933 934static Bool 935DefaultApplyControls(XkbConfigRtrnPtr rtrn,XkbDescPtr xkb) 936{ 937unsigned on,off; 938XkbControlsPtr ctrls; 939unsigned int mask; 940 941 if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success) 942 return False; 943 ctrls= xkb->ctrls; 944 if (rtrn->replace_initial_ctrls) 945 ctrls->enabled_ctrls= rtrn->initial_ctrls; 946 else ctrls->enabled_ctrls|= rtrn->initial_ctrls; 947 ctrls->enabled_ctrls&= ~rtrn->initial_ctrls_clear; 948 if (rtrn->internal_mods.replace) { 949 ctrls->internal.real_mods= rtrn->internal_mods.mods; 950 ctrls->internal.vmods= rtrn->internal_mods.vmods; 951 } 952 else { 953 ctrls->internal.real_mods&= ~rtrn->internal_mods.mods_clear; 954 ctrls->internal.vmods&= ~rtrn->internal_mods.vmods_clear; 955 ctrls->internal.real_mods|= rtrn->internal_mods.mods; 956 ctrls->internal.vmods|= rtrn->internal_mods.vmods; 957 } 958 mask= 0; 959 (void)XkbVirtualModsToReal(xkb,ctrls->internal.vmods,&mask); 960 ctrls->internal.mask= (ctrls->internal.real_mods|mask); 961 962 if (rtrn->ignore_lock_mods.replace) { 963 ctrls->ignore_lock.real_mods= rtrn->ignore_lock_mods.mods; 964 ctrls->ignore_lock.vmods= rtrn->ignore_lock_mods.vmods; 965 } 966 else { 967 ctrls->ignore_lock.real_mods&= ~rtrn->ignore_lock_mods.mods_clear; 968 ctrls->ignore_lock.vmods&= ~rtrn->ignore_lock_mods.vmods_clear; 969 ctrls->ignore_lock.real_mods|= rtrn->ignore_lock_mods.mods; 970 ctrls->ignore_lock.vmods|= rtrn->ignore_lock_mods.vmods; 971 } 972 mask= 0; 973 (void)XkbVirtualModsToReal(xkb,ctrls->ignore_lock.vmods,&mask); 974 ctrls->ignore_lock.mask= (ctrls->ignore_lock.real_mods|mask); 975 976 if (rtrn->repeat_delay>0) 977 ctrls->repeat_delay= rtrn->repeat_delay; 978 if (rtrn->repeat_interval>0) 979 ctrls->repeat_interval= rtrn->repeat_interval; 980 if (rtrn->slow_keys_delay>0) 981 ctrls->slow_keys_delay= rtrn->slow_keys_delay; 982 if (rtrn->debounce_delay>0) 983 ctrls->debounce_delay= rtrn->debounce_delay; 984 if (rtrn->mk_delay>0) 985 ctrls->mk_delay= rtrn->mk_delay; 986 if (rtrn->mk_interval>0) 987 ctrls->mk_interval= rtrn->mk_interval; 988 if (rtrn->mk_time_to_max>0) 989 ctrls->mk_time_to_max= rtrn->mk_time_to_max; 990 if (rtrn->mk_max_speed>0) 991 ctrls->mk_max_speed= rtrn->mk_max_speed; 992 if (rtrn->mk_curve>0) 993 ctrls->mk_curve= rtrn->mk_curve; 994 if (rtrn->defined&XkbCF_AccessXTimeout && rtrn->ax_timeout > 0) 995 ctrls->ax_timeout= rtrn->ax_timeout; 996 997 /* any value set to both off and on is reset to ignore */ 998 if ((off=(rtrn->axt_ctrls_on&rtrn->axt_ctrls_off))!=0) 999 rtrn->axt_ctrls_ignore|= off; 1000 1001 /* ignore takes priority over on and off */ 1002 rtrn->axt_ctrls_on&= ~rtrn->axt_ctrls_ignore; 1003 rtrn->axt_ctrls_off&= ~rtrn->axt_ctrls_ignore; 1004 1005 if (!rtrn->replace_axt_ctrls_off) { 1006 off= (ctrls->axt_ctrls_mask&(~ctrls->axt_ctrls_values)); 1007 off&= ~rtrn->axt_ctrls_on; 1008 off|= rtrn->axt_ctrls_off; 1009 } 1010 else off= rtrn->axt_ctrls_off; 1011 if (!rtrn->replace_axt_ctrls_on) { 1012 on= (ctrls->axt_ctrls_mask&ctrls->axt_ctrls_values); 1013 on&= ~rtrn->axt_ctrls_off; 1014 on|= rtrn->axt_ctrls_on; 1015 } 1016 else on= rtrn->axt_ctrls_on; 1017 ctrls->axt_ctrls_mask= (on|off)&~rtrn->axt_ctrls_ignore; 1018 ctrls->axt_ctrls_values= on&~rtrn->axt_ctrls_ignore; 1019 1020 /* any value set to both off and on is reset to ignore */ 1021 if ((off=(rtrn->axt_opts_on&rtrn->axt_opts_off))!=0) 1022 rtrn->axt_opts_ignore|= off; 1023 1024 /* ignore takes priority over on and off */ 1025 rtrn->axt_opts_on&= ~rtrn->axt_opts_ignore; 1026 rtrn->axt_opts_off&= ~rtrn->axt_opts_ignore; 1027 1028 if (rtrn->replace_axt_opts_off) { 1029 off= (ctrls->axt_opts_mask&(~ctrls->axt_opts_values)); 1030 off&= ~rtrn->axt_opts_on; 1031 off|= rtrn->axt_opts_off; 1032 } 1033 else off= rtrn->axt_opts_off; 1034 if (!rtrn->replace_axt_opts_on) { 1035 on= (ctrls->axt_opts_mask&ctrls->axt_opts_values); 1036 on&= ~rtrn->axt_opts_off; 1037 on|= rtrn->axt_opts_on; 1038 } 1039 else on= rtrn->axt_opts_on; 1040 ctrls->axt_opts_mask= (unsigned short)((on|off)&~rtrn->axt_ctrls_ignore); 1041 ctrls->axt_opts_values= (unsigned short)(on&~rtrn->axt_ctrls_ignore); 1042 1043 if (rtrn->defined&XkbCF_GroupsWrap) { 1044 int n; 1045 n= XkbNumGroups(ctrls->groups_wrap); 1046 rtrn->groups_wrap= XkbSetNumGroups(rtrn->groups_wrap,n); 1047 ctrls->groups_wrap= rtrn->groups_wrap; 1048 } 1049 return True; 1050} 1051 1052/*ARGSUSED*/ 1053static Bool 1054DefaultFinish( XkbConfigFieldsPtr fields, 1055 XkbDescPtr xkb, 1056 XkbConfigRtrnPtr rtrn, 1057 int what) 1058{ 1059 if ((what==XkbCF_Destroy)||(what==XkbCF_CleanUp)) 1060 return DefaultCleanUp(rtrn); 1061 if (what==XkbCF_Check) { 1062 if ((rtrn->symbols==NULL)&&(rtrn->phys_symbols!=NULL)) 1063 rtrn->symbols= _XkbDupString(rtrn->phys_symbols); 1064 } 1065 if ((what==XkbCF_Apply)||(what==XkbCF_Check)) { 1066 if (xkb && xkb->names && (rtrn->num_unbound_mods>0)) 1067 XkbCFBindMods(rtrn,xkb); 1068 XkbCFApplyMods(rtrn,XkbCF_InitialMods,&rtrn->initial_mods); 1069 XkbCFApplyMods(rtrn,XkbCF_InternalMods,&rtrn->internal_mods); 1070 XkbCFApplyMods(rtrn,XkbCF_IgnoreLockMods,&rtrn->ignore_lock_mods); 1071 } 1072 if (what==XkbCF_Apply) { 1073 if (xkb!=NULL) { 1074 DefaultApplyNames(rtrn,xkb); 1075 DefaultApplyControls(rtrn,xkb); 1076 XkbCFBindMods(rtrn,xkb); 1077 } 1078 } 1079 return True; 1080} 1081 1082static XkbConfigFieldRec _XkbCFDfltFields[] = { 1083 { "rules", _XkbCF_RulesFile }, 1084 { "model", _XkbCF_Model }, 1085 { "layout", _XkbCF_Layout }, 1086 { "variant", _XkbCF_Variant }, 1087 { "options", _XkbCF_Options }, 1088 { "keymap", _XkbCF_Keymap }, 1089 { "keycodes", _XkbCF_Keycodes }, 1090 { "geometry", _XkbCF_Geometry }, 1091 { "realsymbols",_XkbCF_PhysSymbols }, 1092 { "actualsymbols",_XkbCF_PhysSymbols }, 1093 { "symbols", _XkbCF_Symbols }, 1094 { "symbolstouse",_XkbCF_Symbols }, 1095 { "types", _XkbCF_Types }, 1096 { "compat", _XkbCF_CompatMap }, 1097 { "modifiers", _XkbCF_InitialMods }, 1098 { "controls", _XkbCF_InitialCtrls }, 1099 { "click", _XkbCF_ClickVolume }, 1100 { "clickvolume",_XkbCF_ClickVolume }, 1101 { "bell", _XkbCF_BellVolume }, 1102 { "bellvolume", _XkbCF_BellVolume }, 1103 { "bellpitch", _XkbCF_BellPitch }, 1104 { "bellduration",_XkbCF_BellDuration }, 1105 { "repeatdelay",_XkbCF_RepeatDelay }, 1106 { "repeatinterval",_XkbCF_RepeatInterval }, 1107 { "slowkeysdelay",_XkbCF_SlowKeysDelay }, 1108 { "debouncedelay",_XkbCF_DebounceDelay }, 1109 { "mousekeysdelay",_XkbCF_MouseKeysDelay }, 1110 { "mousekeysinterval",_XkbCF_MouseKeysInterval }, 1111 { "mousekeystimetomax",_XkbCF_MouseKeysTimeToMax }, 1112 { "mousekeysmaxspeed",_XkbCF_MouseKeysMaxSpeed }, 1113 { "mousekeyscurve",_XkbCF_MouseKeysCurve }, 1114 { "accessxtimeout",_XkbCF_AccessXTimeout }, 1115 { "axtimeout",_XkbCF_AccessXTimeout }, 1116 { "accessxtimeoutctrlson",_XkbCF_AccessXTimeoutCtrlsOn }, 1117 { "axtctrlson", _XkbCF_AccessXTimeoutCtrlsOn }, 1118 { "accessxtimeoutctrlsoff",_XkbCF_AccessXTimeoutCtrlsOff }, 1119 { "axtctrlsoff",_XkbCF_AccessXTimeoutCtrlsOff }, 1120 { "accessxtimeoutfeedbackon", _XkbCF_AccessXTimeoutOptsOn }, 1121 { "axtfeedbackon", _XkbCF_AccessXTimeoutOptsOn }, 1122 { "accessxtimeoutfeedbackoff", _XkbCF_AccessXTimeoutOptsOff }, 1123 { "axtfeedbackoff", _XkbCF_AccessXTimeoutOptsOff }, 1124 { "ignorelockmods",_XkbCF_IgnoreLockMods }, 1125 { "ignorelockmodifiers",_XkbCF_IgnoreLockMods }, 1126 { "ignoregrouplock",_XkbCF_IgnoreGroupLock }, 1127 { "internalmods",_XkbCF_InternalMods }, 1128 { "internalmodifiers",_XkbCF_InternalMods }, 1129 { "outofrangegroups",_XkbCF_GroupsWrap }, 1130 { "groups", _XkbCF_GroupsWrap }, 1131 { "feedback", _XkbCF_InitialFeedback }, 1132}; 1133#define _XkbCFNumDfltFields (sizeof(_XkbCFDfltFields)/sizeof(XkbConfigFieldRec)) 1134 1135static XkbConfigFieldsRec _XkbCFDflts = { 1136 0, /* cfg_id */ 1137 _XkbCFNumDfltFields, /* num_fields */ 1138 _XkbCFDfltFields, /* fields */ 1139 DefaultParser, /* parser */ 1140 DefaultFinish, /* finish */ 1141 NULL, /* priv */ 1142 NULL /* next */ 1143}; 1144 1145XkbConfigFieldsPtr XkbCFDflts= &_XkbCFDflts; 1146 1147/***====================================================================***/ 1148 1149XkbConfigFieldsPtr 1150XkbCFDup(XkbConfigFieldsPtr fields) 1151{ 1152XkbConfigFieldsPtr pNew; 1153 1154 pNew= _XkbTypedAlloc(XkbConfigFieldsRec); 1155 if (pNew!=NULL) { 1156 memcpy(pNew,fields,sizeof(XkbConfigFieldsRec)); 1157 if ((pNew->fields!=NULL)&&(pNew->num_fields>0)) { 1158 pNew->fields= _XkbTypedCalloc(pNew->num_fields,XkbConfigFieldRec); 1159 if (pNew->fields) { 1160 memcpy(fields->fields,pNew->fields, 1161 (pNew->num_fields*sizeof(XkbConfigFieldRec))); 1162 } 1163 else { 1164 _XkbFree(pNew); 1165 return NULL; 1166 } 1167 } 1168 else { 1169 pNew->num_fields= 0; 1170 pNew->fields= NULL; 1171 } 1172 pNew->next= NULL; 1173 } 1174 return pNew; 1175} 1176 1177XkbConfigFieldsPtr 1178XkbCFFree(XkbConfigFieldsPtr fields,Bool all) 1179{ 1180XkbConfigFieldsPtr next; 1181 1182 next= NULL; 1183 while (fields!=NULL) { 1184 next= fields->next; 1185 if (fields!=XkbCFDflts) { 1186 if (fields->fields) { 1187 _XkbFree(fields->fields); 1188 fields->fields= NULL; 1189 fields->num_fields= 0; 1190 } 1191 _XkbFree(fields); 1192 } 1193 fields= (all?next:NULL); 1194 } 1195 return next; 1196} 1197 1198Bool 1199XkbCFApplyRtrnValues( XkbConfigRtrnPtr rtrn, 1200 XkbConfigFieldsPtr fields, 1201 XkbDescPtr xkb) 1202{ 1203Bool ok; 1204 1205 if ((fields==NULL)||(rtrn==NULL)||(xkb==NULL)) 1206 return False; 1207 for (ok=True;fields!=NULL;fields=fields->next) { 1208 if (fields->finish!=NULL) 1209 ok= (*fields->finish)(fields,xkb,rtrn,XkbCF_Apply)&&ok; 1210 } 1211 return ok; 1212} 1213 1214XkbConfigRtrnPrivPtr 1215XkbCFAddPrivate( XkbConfigRtrnPtr rtrn, 1216 XkbConfigFieldsPtr fields, 1217 XPointer ptr) 1218{ 1219XkbConfigRtrnPrivPtr priv; 1220 1221 if ((rtrn==NULL)||(fields==NULL)) 1222 return NULL; 1223 priv= _XkbTypedAlloc(XkbConfigRtrnPrivRec); 1224 if (priv!=NULL) { 1225 priv->cfg_id= fields->cfg_id; 1226 priv->priv= ptr; 1227 priv->next= rtrn->priv; 1228 rtrn->priv= priv; 1229 } 1230 return priv; 1231} 1232 1233void 1234XkbCFFreeRtrn( XkbConfigRtrnPtr rtrn, 1235 XkbConfigFieldsPtr fields, 1236 XkbDescPtr xkb) 1237{ 1238XkbConfigRtrnPrivPtr tmp,next; 1239 1240 if ((fields==NULL)||(rtrn==NULL)) 1241 return; 1242 while (fields!=NULL) { 1243 if (fields->finish!=NULL) 1244 (*fields->finish)(fields,xkb,rtrn,XkbCF_Destroy); 1245 fields= fields->next; 1246 } 1247 for (tmp=rtrn->priv;tmp!=NULL;tmp=next) { 1248 next= tmp->next; 1249 bzero((char *)tmp,sizeof(XkbConfigRtrnPrivRec)); 1250 _XkbFree(tmp); 1251 } 1252 bzero((char *)rtrn,sizeof(XkbConfigRtrnRec)); 1253 return; 1254} 1255 1256Bool 1257XkbCFParse( FILE * file, 1258 XkbConfigFieldsPtr fields, 1259 XkbDescPtr xkb, 1260 XkbConfigRtrnPtr rtrn) 1261{ 1262int tok; 1263XkbCFScanResultRec val; 1264XkbConfigFieldsPtr tmp; 1265 1266 if ((file==NULL)||(fields==NULL)||(rtrn==NULL)) 1267 return False; 1268 for (tok=0,tmp=fields;tmp!=NULL;tmp=tmp->next,tok++) { 1269 fields->cfg_id= tok; 1270 } 1271 bzero((char *)rtrn,sizeof(XkbConfigRtrnRec)); 1272 rtrn->line= 1; 1273 rtrn->click_volume= -1; 1274 rtrn->bell_volume= -1; 1275 while ((tok=XkbCFScan(file,&val,rtrn))!=XkbCF_EOF) { 1276 if (tok==XkbCF_Ident) { 1277 Bool done; 1278 for (tmp=fields,done=False;(tmp!=NULL)&&(!done);tmp=tmp->next) { 1279 register int i; 1280 XkbConfigFieldPtr f; 1281 1282 for (i=0,f=tmp->fields;(i<tmp->num_fields)&&(!done);i++,f++) { 1283 if (_XkbStrCaseCmp(val.str,f->field)!=0) 1284 continue; 1285 if ((*tmp->parser)(file,tmp,f,xkb,rtrn)) 1286 done= True; 1287 else goto BAILOUT; 1288 } 1289 } 1290 } 1291 else if ((tok!=XkbCF_EOL)&&(tok!=XkbCF_Semi)) { 1292 rtrn->error= XkbCF_MissingIdent; 1293 goto BAILOUT; 1294 } 1295 } 1296 for (tmp=fields;tmp!=NULL;tmp=tmp->next) { 1297 if ((tmp->finish)&&(!(*tmp->finish)(tmp,xkb,rtrn,XkbCF_Check))) 1298 goto BAILOUT; 1299 } 1300 return True; 1301BAILOUT: 1302 for (tmp=fields;tmp!=NULL;tmp=tmp->next) { 1303 if (tmp->finish) 1304 (*tmp->finish)(tmp,xkb,rtrn,XkbCF_CleanUp); 1305 } 1306 return False; 1307} 1308 1309/*ARGSUSED*/ 1310void 1311XkbCFReportError(FILE *file,char *name,int error,int line) 1312{ 1313char * msg; 1314 1315 switch(error) { 1316 case XkbCF_BadAlloc: 1317 msg= "allocation failed\n"; break; 1318 case XkbCF_UnterminatedString: 1319 msg= "unterminated string on line %d"; break; 1320 case XkbCF_MissingIdent: 1321 msg= "expected identifier on line %d"; break; 1322 case XkbCF_MissingEquals: 1323 msg= "expected '=' on line %d"; break; 1324 case XkbCF_ExpectedEOS: 1325 msg= "expected ';' or newline on line %d"; break; 1326 case XkbCF_ExpectedBoolean: 1327 msg= "expected a boolean value on line %d"; break; 1328 case XkbCF_ExpectedInteger: 1329 msg= "expected a numeric value on line %d"; break; 1330 case XkbCF_ExpectedString: 1331 msg= "expected a string on line %d"; break; 1332 case XkbCF_ExpectedModifier: 1333 msg= "expected a modifier name on line %d"; break; 1334 case XkbCF_ExpectedControl: 1335 msg= "expected a control name on line %d"; break; 1336 case XkbCF_ExpectedAXOption: 1337 msg= "expected an AccessX option on line %d"; break; 1338 case XkbCF_ExpectedOperator: 1339 msg= "expected '+' or '-' on line %d"; break; 1340 case XkbCF_ExpectedOORGroupBehavior: 1341 msg= "expected wrap, clamp or group number on line %d"; break; 1342 default: 1343 msg= "unknown error on line %d"; break; 1344 } 1345#ifndef XKB_IN_SERVER 1346 fprintf(file,msg,line); 1347 if (name) fprintf(file," of %s\n",name); 1348 else fprintf(file,"\n"); 1349#else 1350 ErrorF(msg,line); 1351 if (name) ErrorF(" of %s\n",name); 1352 else ErrorF("\n"); 1353#endif 1354 return; 1355} 1356