xkbInit.c revision 05b261ec
1/************************************************************ 2Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. 3 4Permission to use, copy, modify, and distribute this 5software and its documentation for any purpose and without 6fee is hereby granted, provided that the above copyright 7notice appear in all copies and that both that copyright 8notice and this permission notice appear in supporting 9documentation, and that the name of Silicon Graphics not be 10used in advertising or publicity pertaining to distribution 11of the software without specific prior written permission. 12Silicon Graphics makes no representation about the suitability 13of this software for any purpose. It is provided "as is" 14without any express or implied warranty. 15 16SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 25********************************************************/ 26 27#ifdef HAVE_DIX_CONFIG_H 28#include <dix-config.h> 29#endif 30 31#ifdef HAVE_XKB_CONFIG_H 32#include <xkb-config.h> 33#endif 34 35#include <stdio.h> 36#include <stdlib.h> 37#include <ctype.h> 38#include <unistd.h> 39#include <math.h> 40#define NEED_EVENTS 1 41#include <X11/X.h> 42#include <X11/Xproto.h> 43#include <X11/keysym.h> 44#include <X11/Xatom.h> 45#include "misc.h" 46#include "inputstr.h" 47#include "opaque.h" 48#include "property.h" 49#define XKBSRV_NEED_FILE_FUNCS 50#include <xkbsrv.h> 51#include <X11/extensions/XKBgeom.h> 52#include <X11/extensions/XKMformat.h> 53#include <X11/extensions/XKBfile.h> 54#include "xkb.h" 55 56#define CREATE_ATOM(s) MakeAtom(s,sizeof(s)-1,1) 57 58#ifdef sgi 59#define LED_CAPS 5 60#define LED_NUM 6 61#define LED_SCROLL 7 62#define PHYS_LEDS 0x7f 63#define LED_COMPOSE 8 64#else 65#if defined(ultrix) || defined(__osf__) || defined(__alpha) || defined(__alpha__) 66#define LED_COMPOSE 2 67#define LED_CAPS 3 68#define LED_SCROLL 4 69#define LED_NUM 5 70#define PHYS_LEDS 0x1f 71#else 72#ifdef sun 73#define LED_NUM 1 74#define LED_SCROLL 2 75#define LED_COMPOSE 3 76#define LED_CAPS 4 77#define PHYS_LEDS 0x0f 78#else 79#define LED_CAPS 1 80#define LED_NUM 2 81#define LED_SCROLL 3 82#define PHYS_LEDS 0x07 83#endif 84#endif 85#endif 86 87#define MAX_TOC 16 88typedef struct _SrvXkmInfo { 89 DeviceIntPtr dev; 90 FILE * file; 91 XkbFileInfo xkbinfo; 92} SrvXkmInfo; 93 94 95/***====================================================================***/ 96 97#ifndef XKB_BASE_DIRECTORY 98#define XKB_BASE_DIRECTORY "/usr/lib/X11/xkb" 99#endif 100#ifndef XKB_BIN_DIRECTORY 101#define XKB_BIN_DIRECTORY XKB_BASE_DIRECTORY 102#endif 103#ifndef XKB_DFLT_RULES_FILE 104#define XKB_DFLT_RULES_FILE "rules" 105#endif 106#ifndef XKB_DFLT_KB_LAYOUT 107#define XKB_DFLT_KB_LAYOUT "us" 108#endif 109#ifndef XKB_DFLT_KB_MODEL 110#define XKB_DFLT_KB_MODEL "dflt" 111#endif 112#ifndef XKB_DFLT_KB_VARIANT 113#define XKB_DFLT_KB_VARIANT NULL 114#endif 115#ifndef XKB_DFLT_KB_OPTIONS 116#define XKB_DFLT_KB_OPTIONS NULL 117#endif 118#ifndef XKB_DFLT_DISABLED 119#define XKB_DFLT_DISABLED True 120#endif 121#ifndef XKB_DFLT_RULES_PROP 122#define XKB_DFLT_RULES_PROP True 123#endif 124 125char * XkbBaseDirectory= XKB_BASE_DIRECTORY; 126char * XkbBinDirectory= XKB_BIN_DIRECTORY; 127static int XkbWantAccessX= 0; 128static XkbFileInfo * _XkbInitFileInfo= NULL; 129 130static Bool rulesDefined= False; 131static char * XkbRulesFile= NULL; 132static char * XkbModelDflt= NULL; 133static char * XkbLayoutDflt= NULL; 134static char * XkbVariantDflt= NULL; 135static char * XkbOptionsDflt= NULL; 136 137static char * XkbModelUsed= NULL; 138static char * XkbLayoutUsed= NULL; 139static char * XkbVariantUsed= NULL; 140static char * XkbOptionsUsed= NULL; 141 142_X_EXPORT Bool noXkbExtension= XKB_DFLT_DISABLED; 143static Bool XkbWantRulesProp= XKB_DFLT_RULES_PROP; 144 145/***====================================================================***/ 146 147static char * 148XkbGetRulesDflts(XkbRF_VarDefsPtr defs) 149{ 150 if (XkbModelDflt) defs->model= XkbModelDflt; 151 else defs->model= XKB_DFLT_KB_MODEL; 152 if (XkbLayoutDflt) defs->layout= XkbLayoutDflt; 153 else defs->layout= XKB_DFLT_KB_LAYOUT; 154 if (XkbVariantDflt) defs->variant= XkbVariantDflt; 155 else defs->variant= XKB_DFLT_KB_VARIANT; 156 if (XkbOptionsDflt) defs->options= XkbOptionsDflt; 157 else defs->options= XKB_DFLT_KB_OPTIONS; 158 return (rulesDefined?XkbRulesFile:XKB_DFLT_RULES_FILE); 159} 160 161static Bool 162XkbWriteRulesProp(ClientPtr client, pointer closure) 163{ 164int len,out; 165Atom name; 166char * pval; 167 168 if (rulesDefined && (!XkbRulesFile)) 169 return False; 170 len= (XkbRulesFile?strlen(XkbRulesFile):strlen(XKB_DFLT_RULES_FILE)); 171 len+= (XkbModelUsed?strlen(XkbModelUsed):0); 172 len+= (XkbLayoutUsed?strlen(XkbLayoutUsed):0); 173 len+= (XkbVariantUsed?strlen(XkbVariantUsed):0); 174 len+= (XkbOptionsUsed?strlen(XkbOptionsUsed):0); 175 if (len<1) 176 return True; 177 178 len+= 5; /* trailing NULs */ 179 180 name= MakeAtom(_XKB_RF_NAMES_PROP_ATOM,strlen(_XKB_RF_NAMES_PROP_ATOM),1); 181 if (name==None) { 182 ErrorF("Atom error: %s not created\n",_XKB_RF_NAMES_PROP_ATOM); 183 return True; 184 } 185 pval= (char*) ALLOCATE_LOCAL(len); 186 if (!pval) { 187 ErrorF("Allocation error: %s proprerty not created\n", 188 _XKB_RF_NAMES_PROP_ATOM); 189 return True; 190 } 191 out= 0; 192 if (XkbRulesFile) { 193 strcpy(&pval[out],XkbRulesFile); 194 out+= strlen(XkbRulesFile); 195 } else { 196 strcpy(&pval[out],XKB_DFLT_RULES_FILE); 197 out+= strlen(XKB_DFLT_RULES_FILE); 198 } 199 pval[out++]= '\0'; 200 if (XkbModelUsed) { 201 strcpy(&pval[out],XkbModelUsed); 202 out+= strlen(XkbModelUsed); 203 } 204 pval[out++]= '\0'; 205 if (XkbLayoutUsed) { 206 strcpy(&pval[out],XkbLayoutUsed); 207 out+= strlen(XkbLayoutUsed); 208 } 209 pval[out++]= '\0'; 210 if (XkbVariantUsed) { 211 strcpy(&pval[out],XkbVariantUsed); 212 out+= strlen(XkbVariantUsed); 213 } 214 pval[out++]= '\0'; 215 if (XkbOptionsUsed) { 216 strcpy(&pval[out],XkbOptionsUsed); 217 out+= strlen(XkbOptionsUsed); 218 } 219 pval[out++]= '\0'; 220 if (out!=len) { 221 ErrorF("Internal Error! bad size (%d!=%d) for _XKB_RULES_NAMES\n", 222 out,len); 223 } 224 ChangeWindowProperty(WindowTable[0],name,XA_STRING,8,PropModeReplace, 225 len,pval,True); 226 DEALLOCATE_LOCAL(pval); 227 return True; 228} 229 230static void 231XkbSetRulesUsed(XkbRF_VarDefsPtr defs) 232{ 233 if (XkbModelUsed) 234 _XkbFree(XkbModelUsed); 235 XkbModelUsed= (defs->model?_XkbDupString(defs->model):NULL); 236 if (XkbLayoutUsed) 237 _XkbFree(XkbLayoutUsed); 238 XkbLayoutUsed= (defs->layout?_XkbDupString(defs->layout):NULL); 239 if (XkbVariantUsed) 240 _XkbFree(XkbVariantUsed); 241 XkbVariantUsed= (defs->variant?_XkbDupString(defs->variant):NULL); 242 if (XkbOptionsUsed) 243 _XkbFree(XkbOptionsUsed); 244 XkbOptionsUsed= (defs->options?_XkbDupString(defs->options):NULL); 245 if (XkbWantRulesProp) 246 QueueWorkProc(XkbWriteRulesProp,NULL,NULL); 247 return; 248} 249 250_X_EXPORT void 251XkbSetRulesDflts(char *rulesFile,char *model,char *layout, 252 char *variant,char *options) 253{ 254 if (XkbRulesFile) 255 _XkbFree(XkbRulesFile); 256 XkbRulesFile= _XkbDupString(rulesFile); 257 rulesDefined= True; 258 if (model) { 259 if (XkbModelDflt) 260 _XkbFree(XkbModelDflt); 261 XkbModelDflt= _XkbDupString(model); 262 } 263 if (layout) { 264 if (XkbLayoutDflt) 265 _XkbFree(XkbLayoutDflt); 266 XkbLayoutDflt= _XkbDupString(layout); 267 } 268 if (variant) { 269 if (XkbVariantDflt) 270 _XkbFree(XkbVariantDflt); 271 XkbVariantDflt= _XkbDupString(variant); 272 } 273 if (options) { 274 if (XkbOptionsDflt) 275 _XkbFree(XkbOptionsDflt); 276 XkbOptionsDflt= _XkbDupString(options); 277 } 278 return; 279} 280 281/***====================================================================***/ 282 283#if defined(luna) 284#define XKB_DDX_PERMANENT_LOCK 1 285#endif 286 287#include "xkbDflts.h" 288 289static Bool 290XkbInitKeyTypes(XkbDescPtr xkb,SrvXkmInfo *file) 291{ 292 if (file->xkbinfo.defined&XkmTypesMask) 293 return True; 294 initTypeNames(NULL); 295 if (XkbAllocClientMap(xkb,XkbKeyTypesMask,num_dflt_types)!=Success) 296 return False; 297 if (XkbCopyKeyTypes(dflt_types,xkb->map->types,num_dflt_types)!= 298 Success) { 299 return False; 300 } 301 xkb->map->size_types= xkb->map->num_types= num_dflt_types; 302 return True; 303} 304 305static void 306XkbInitRadioGroups(XkbSrvInfoPtr xkbi,SrvXkmInfo *file) 307{ 308 xkbi->nRadioGroups = 0; 309 xkbi->radioGroups = NULL; 310 return; 311} 312 313 314static Status 315XkbInitCompatStructs(XkbDescPtr xkb,SrvXkmInfo *file) 316{ 317register int i; 318XkbCompatMapPtr compat; 319 320 if (file->xkbinfo.defined&XkmCompatMapMask) 321 return Success; 322 if (XkbAllocCompatMap(xkb,XkbAllCompatMask,num_dfltSI)!=Success) 323 return BadAlloc; 324 compat = xkb->compat; 325 if (compat->sym_interpret) { 326 compat->num_si = num_dfltSI; 327 memcpy((char *)compat->sym_interpret,(char *)dfltSI,sizeof(dfltSI)); 328 } 329 for (i=0;i<XkbNumKbdGroups;i++) { 330 compat->groups[i]= compatMap.groups[i]; 331 if (compat->groups[i].vmods!=0) { 332 unsigned mask; 333 mask= XkbMaskForVMask(xkb,compat->groups[i].vmods); 334 compat->groups[i].mask= compat->groups[i].real_mods|mask; 335 } 336 else compat->groups[i].mask= compat->groups[i].real_mods; 337 } 338 return Success; 339} 340 341static void 342XkbInitSemantics(XkbDescPtr xkb,SrvXkmInfo *file) 343{ 344 XkbInitKeyTypes(xkb,file); 345 XkbInitCompatStructs(xkb,file); 346 return; 347} 348 349/***====================================================================***/ 350 351static Status 352XkbInitNames(XkbSrvInfoPtr xkbi,SrvXkmInfo *file) 353{ 354XkbDescPtr xkb; 355XkbNamesPtr names; 356Status rtrn; 357Atom unknown; 358 359 xkb= xkbi->desc; 360 if ((rtrn=XkbAllocNames(xkb,XkbAllNamesMask,0,0))!=Success) 361 return rtrn; 362 unknown= CREATE_ATOM("unknown"); 363 names = xkb->names; 364 if (names->keycodes==None) names->keycodes= unknown; 365 if (names->geometry==None) names->geometry= unknown; 366 if (names->phys_symbols==None) names->phys_symbols= unknown; 367 if (names->symbols==None) names->symbols= unknown; 368 if (names->types==None) names->types= unknown; 369 if (names->compat==None) names->compat= unknown; 370 if ((file->xkbinfo.defined&XkmVirtualModsMask)==0) { 371 if (names->vmods[vmod_NumLock]==None) 372 names->vmods[vmod_NumLock]= CREATE_ATOM("NumLock"); 373 if (names->vmods[vmod_Alt]==None) 374 names->vmods[vmod_Alt]= CREATE_ATOM("Alt"); 375 if (names->vmods[vmod_AltGr]==None) 376 names->vmods[vmod_AltGr]= CREATE_ATOM("ModeSwitch"); 377 } 378 379 if (((file->xkbinfo.defined&XkmIndicatorsMask)==0)|| 380 ((file->xkbinfo.defined&XkmGeometryMask)==0)) { 381 initIndicatorNames(NULL,xkb); 382 if (names->indicators[LED_CAPS-1]==None) 383 names->indicators[LED_CAPS-1] = CREATE_ATOM("Caps Lock"); 384 if (names->indicators[LED_NUM-1]==None) 385 names->indicators[LED_NUM-1] = CREATE_ATOM("Num Lock"); 386 if (names->indicators[LED_SCROLL-1]==None) 387 names->indicators[LED_SCROLL-1] = CREATE_ATOM("Scroll Lock"); 388#ifdef LED_COMPOSE 389 if (names->indicators[LED_COMPOSE-1]==None) 390 names->indicators[LED_COMPOSE-1] = CREATE_ATOM("Compose"); 391#endif 392 } 393#ifdef DEBUG_RADIO_GROUPS 394 if (names->num_rg<1) { 395 names->radio_groups= (Atom *)_XkbCalloc(RG_COUNT, sizeof(Atom)); 396 if (names->radio_groups) { 397 names->num_rg = RG_COUNT; 398 names->radio_groups[RG_BOGUS_FUNCTION_GROUP]= CREATE_ATOM("BOGUS"); 399 } 400 } 401#endif 402 if (xkb->geom!=NULL) 403 names->geometry= xkb->geom->name; 404 else names->geometry= unknown; 405 return Success; 406} 407 408static Status 409XkbInitIndicatorMap(XkbSrvInfoPtr xkbi,SrvXkmInfo *file) 410{ 411XkbDescPtr xkb; 412XkbIndicatorPtr map; 413XkbSrvLedInfoPtr sli; 414 415 xkb= xkbi->desc; 416 if (XkbAllocIndicatorMaps(xkb)!=Success) 417 return BadAlloc; 418 if ((file->xkbinfo.defined&XkmIndicatorsMask)==0) { 419 map= xkb->indicators; 420 map->phys_indicators = PHYS_LEDS; 421 map->maps[LED_CAPS-1].flags= XkbIM_NoExplicit; 422 map->maps[LED_CAPS-1].which_mods= XkbIM_UseLocked; 423 map->maps[LED_CAPS-1].mods.mask= LockMask; 424 map->maps[LED_CAPS-1].mods.real_mods= LockMask; 425 426 map->maps[LED_NUM-1].flags= XkbIM_NoExplicit; 427 map->maps[LED_NUM-1].which_mods= XkbIM_UseLocked; 428 map->maps[LED_NUM-1].mods.mask= 0; 429 map->maps[LED_NUM-1].mods.real_mods= 0; 430 map->maps[LED_NUM-1].mods.vmods= vmod_NumLockMask; 431 432/* Metro Link */ 433 map->maps[LED_SCROLL-1].flags= XkbIM_NoExplicit; 434 map->maps[LED_SCROLL-1].which_mods= XkbIM_UseLocked; 435 map->maps[LED_SCROLL-1].mods.mask= Mod3Mask; 436 map->maps[LED_SCROLL-1].mods.real_mods= Mod3Mask; 437/* Metro Link */ 438 } 439 sli= XkbFindSrvLedInfo(xkbi->device,XkbDfltXIClass,XkbDfltXIId,0); 440 if (sli) 441 XkbCheckIndicatorMaps(xkbi->device,sli,XkbAllIndicatorsMask); 442 return Success; 443} 444 445static Status 446XkbInitControls(DeviceIntPtr pXDev,XkbSrvInfoPtr xkbi,SrvXkmInfo *file) 447{ 448XkbDescPtr xkb; 449XkbControlsPtr ctrls; 450 451 xkb= xkbi->desc; 452 /* 12/31/94 (ef) -- XXX! Should check if controls loaded from file */ 453 if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success) 454 FatalError("Couldn't allocate keyboard controls\n"); 455 ctrls= xkb->ctrls; 456 if ((file->xkbinfo.defined&XkmSymbolsMask)==0) 457 ctrls->num_groups = 1; 458 ctrls->groups_wrap = XkbSetGroupInfo(1,XkbWrapIntoRange,0); 459 ctrls->internal.mask = 0; 460 ctrls->internal.real_mods = 0; 461 ctrls->internal.vmods = 0; 462 ctrls->ignore_lock.mask = 0; 463 ctrls->ignore_lock.real_mods = 0; 464 ctrls->ignore_lock.vmods = 0; 465 ctrls->enabled_ctrls = XkbAccessXTimeoutMask|XkbRepeatKeysMask| 466 XkbMouseKeysAccelMask|XkbAudibleBellMask| 467 XkbIgnoreGroupLockMask; 468 if (XkbWantAccessX) 469 ctrls->enabled_ctrls|= XkbAccessXKeysMask; 470 AccessXInit(pXDev); 471 return Success; 472} 473 474void 475XkbInitDevice(DeviceIntPtr pXDev) 476{ 477int i; 478XkbSrvInfoPtr xkbi; 479XkbChangesRec changes; 480SrvXkmInfo file; 481unsigned check; 482XkbEventCauseRec cause; 483 484 file.dev= pXDev; 485 file.file=NULL; 486 bzero(&file.xkbinfo,sizeof(XkbFileInfo)); 487 bzero(&changes,sizeof(XkbChangesRec)); 488 pXDev->key->xkbInfo= xkbi= _XkbTypedCalloc(1,XkbSrvInfoRec); 489 if ( xkbi ) { 490 XkbDescPtr xkb; 491 if ((_XkbInitFileInfo!=NULL)&&(_XkbInitFileInfo->xkb!=NULL)) { 492 file.xkbinfo= *_XkbInitFileInfo; 493 xkbi->desc= _XkbInitFileInfo->xkb; 494 _XkbInitFileInfo= NULL; 495 } 496 else { 497 xkbi->desc= XkbAllocKeyboard(); 498 if (!xkbi->desc) 499 FatalError("Couldn't allocate keyboard description\n"); 500 xkbi->desc->min_key_code = pXDev->key->curKeySyms.minKeyCode; 501 xkbi->desc->max_key_code = pXDev->key->curKeySyms.maxKeyCode; 502 } 503 xkb= xkbi->desc; 504 if (xkb->min_key_code == 0) 505 xkb->min_key_code = pXDev->key->curKeySyms.minKeyCode; 506 if (xkb->max_key_code == 0) 507 xkb->max_key_code = pXDev->key->curKeySyms.maxKeyCode; 508 if ((pXDev->key->curKeySyms.minKeyCode!=xkbi->desc->min_key_code)|| 509 (pXDev->key->curKeySyms.maxKeyCode!=xkbi->desc->max_key_code)) { 510 /* 12/9/95 (ef) -- XXX! Maybe we should try to fix up one or */ 511 /* the other here, but for now just complain */ 512 /* can't just update the core range without */ 513 /* reallocating the KeySymsRec (pain) */ 514 ErrorF("Internal Error!! XKB and core keymap have different range\n"); 515 } 516 if (XkbAllocClientMap(xkb,XkbAllClientInfoMask,0)!=Success) 517 FatalError("Couldn't allocate client map in XkbInitDevice\n"); 518 i= XkbNumKeys(xkb)/3+1; 519 if (XkbAllocServerMap(xkb,XkbAllServerInfoMask,i)!=Success) 520 FatalError("Couldn't allocate server map in XkbInitDevice\n"); 521 522 xkbi->dfltPtrDelta=1; 523 xkbi->device = pXDev; 524 525 file.xkbinfo.xkb= xkb; 526 XkbInitSemantics(xkb,&file); 527 XkbInitNames(xkbi,&file); 528 XkbInitRadioGroups(xkbi,&file); 529 530 /* 12/31/94 (ef) -- XXX! Should check if state loaded from file */ 531 bzero(&xkbi->state,sizeof(XkbStateRec)); 532 533 XkbInitControls(pXDev,xkbi,&file); 534 535 if (file.xkbinfo.defined&XkmSymbolsMask) 536 memcpy(pXDev->key->modifierMap,xkb->map->modmap,xkb->max_key_code+1); 537 else 538 memcpy(xkb->map->modmap,pXDev->key->modifierMap,xkb->max_key_code+1); 539 540 XkbInitIndicatorMap(xkbi,&file); 541 542 XkbDDXInitDevice(pXDev); 543 544 if (!(file.xkbinfo.defined&XkmSymbolsMask)) { 545 XkbUpdateKeyTypesFromCore(pXDev,xkb->min_key_code,XkbNumKeys(xkb), 546 &changes); 547 } 548 else { 549 XkbUpdateCoreDescription(pXDev,True); 550 } 551 XkbSetCauseUnknown(&cause); 552 XkbUpdateActions(pXDev,xkb->min_key_code, XkbNumKeys(xkb),&changes, 553 &check,&cause); 554 /* For sanity. The first time the connection 555 * is opened, the client side min and max are set 556 * using QueryMinMaxKeyCodes() which grabs them 557 * from pXDev. 558 */ 559 pXDev->key->curKeySyms.minKeyCode = xkb->min_key_code; 560 pXDev->key->curKeySyms.maxKeyCode = xkb->max_key_code; 561 } 562 if (file.file!=NULL) 563 fclose(file.file); 564 return; 565} 566 567#if MAP_LENGTH > XkbMaxKeyCount 568#undef XkbMaxKeyCount 569#define XkbMaxKeyCount MAP_LENGTH 570#endif 571 572_X_EXPORT Bool 573XkbInitKeyboardDeviceStruct( 574 DeviceIntPtr dev, 575 XkbComponentNamesPtr names, 576 KeySymsPtr pSymsIn, 577 CARD8 pModsIn[], 578 void (*bellProc)( 579 int /*percent*/, 580 DeviceIntPtr /*device*/, 581 pointer /*ctrl*/, 582 int), 583 void (*ctrlProc)( 584 DeviceIntPtr /*device*/, 585 KeybdCtrl * /*ctrl*/)) 586{ 587XkbFileInfo finfo; 588KeySymsRec tmpSyms,*pSyms; 589CARD8 tmpMods[XkbMaxLegalKeyCode+1],*pMods; 590char name[PATH_MAX],*rules; 591Bool ok=False; 592XkbRF_VarDefsRec defs; 593 594 if ((dev->key!=NULL)||(dev->kbdfeed!=NULL)) 595 return False; 596 pSyms= pSymsIn; 597 pMods= pModsIn; 598 bzero(&defs,sizeof(XkbRF_VarDefsRec)); 599 rules= XkbGetRulesDflts(&defs); 600 601 /* 602 * The strings are duplicated because it is not guaranteed that 603 * they are allocated, or that they are allocated for every server 604 * generation. Eventually they will be freed at the end of this 605 * function. 606 */ 607 if (names->keymap) names->keymap = _XkbDupString(names->keymap); 608 if (names->keycodes) names->keycodes = _XkbDupString(names->keycodes); 609 if (names->types) names->types = _XkbDupString(names->types); 610 if (names->compat) names->compat = _XkbDupString(names->compat); 611 if (names->geometry) names->geometry = _XkbDupString(names->geometry); 612 if (names->symbols) names->symbols = _XkbDupString(names->symbols); 613 614 if (defs.model && defs.layout && rules) { 615 XkbComponentNamesRec rNames; 616 bzero(&rNames,sizeof(XkbComponentNamesRec)); 617 if (XkbDDXNamesFromRules(dev,rules,&defs,&rNames)) { 618 if (rNames.keymap) { 619 if (!names->keymap) 620 names->keymap = rNames.keymap; 621 else _XkbFree(rNames.keymap); 622 } 623 if (rNames.keycodes) { 624 if (!names->keycodes) 625 names->keycodes = rNames.keycodes; 626 else 627 _XkbFree(rNames.keycodes); 628 } 629 if (rNames.types) { 630 if (!names->types) 631 names->types = rNames.types; 632 else _XkbFree(rNames.types); 633 } 634 if (rNames.compat) { 635 if (!names->compat) 636 names->compat = rNames.compat; 637 else _XkbFree(rNames.compat); 638 } 639 if (rNames.symbols) { 640 if (!names->symbols) 641 names->symbols = rNames.symbols; 642 else _XkbFree(rNames.symbols); 643 } 644 if (rNames.geometry) { 645 if (!names->geometry) 646 names->geometry = rNames.geometry; 647 else _XkbFree(rNames.geometry); 648 } 649 XkbSetRulesUsed(&defs); 650 } 651 } 652 653 if (names->keymap) { 654 XkbComponentNamesRec tmpNames; 655 bzero(&tmpNames,sizeof(XkbComponentNamesRec)); 656 tmpNames.keymap = names->keymap; 657 ok = (Bool) XkbDDXLoadKeymapByNames(dev,&tmpNames,XkmAllIndicesMask,0, 658 &finfo,name,PATH_MAX); 659 } 660 if (!(ok && (finfo.xkb!=NULL))) 661 ok = (Bool) XkbDDXLoadKeymapByNames(dev,names,XkmAllIndicesMask,0, 662 &finfo,name,PATH_MAX); 663 664 if (ok && (finfo.xkb!=NULL)) { 665 XkbDescPtr xkb; 666 KeyCode minKC,maxKC; 667 668 xkb= finfo.xkb; 669 minKC= xkb->min_key_code; 670 maxKC= xkb->max_key_code; 671 if (XkbIsLegalKeycode(minKC)&&XkbIsLegalKeycode(maxKC)&&(minKC<=maxKC)&& 672 ((minKC!=pSyms->minKeyCode)||(maxKC!=pSyms->maxKeyCode))) { 673 if (xkb->map!=NULL) { 674 KeySym *inSym,*outSym; 675 int width= pSymsIn->mapWidth; 676 677 tmpSyms.minKeyCode= minKC; 678 tmpSyms.maxKeyCode= maxKC; 679 680 if (minKC<pSymsIn->minKeyCode) 681 minKC= pSymsIn->minKeyCode; 682 if (maxKC>pSymsIn->maxKeyCode) 683 maxKC= pSymsIn->maxKeyCode; 684 685 tmpSyms.mapWidth= width; 686 tmpSyms.map= _XkbTypedCalloc(width*XkbNumKeys(xkb),KeySym); 687 inSym= &pSymsIn->map[(minKC-pSymsIn->minKeyCode)*width]; 688 outSym= &tmpSyms.map[(minKC-tmpSyms.minKeyCode)*width]; 689 memcpy(outSym,inSym,((maxKC-minKC+1)*width)*sizeof(KeySym)); 690 pSyms= &tmpSyms; 691 } 692 if ((xkb->map!=NULL)&&(xkb->map->modmap!=NULL)) { 693 bzero(tmpMods,XkbMaxKeyCount); 694 memcpy(tmpMods,xkb->map->modmap,maxKC+1); 695 pMods= tmpMods; 696 } 697 } 698 _XkbInitFileInfo= &finfo; 699 } 700 else { 701 LogMessage(X_WARNING, "Couldn't load XKB keymap, falling back to pre-XKB keymap\n"); 702 } 703 ok= InitKeyboardDeviceStruct((DevicePtr)dev,pSyms,pMods,bellProc,ctrlProc); 704 _XkbInitFileInfo= NULL; 705 if ((pSyms==&tmpSyms)&&(pSyms->map!=NULL)) { 706 _XkbFree(pSyms->map); 707 pSyms->map= NULL; 708 } 709 710 if (names->keymap) _XkbFree(names->keymap); 711 names->keymap = NULL; 712 if (names->keycodes) _XkbFree(names->keycodes); 713 names->keycodes = NULL; 714 if (names->types) _XkbFree(names->types); 715 names->types = NULL; 716 if (names->compat) _XkbFree(names->compat); 717 names->compat = NULL; 718 if (names->geometry) _XkbFree(names->geometry); 719 names->geometry = NULL; 720 if (names->symbols) _XkbFree(names->symbols); 721 names->symbols = NULL; 722 723 return ok; 724} 725 726/***====================================================================***/ 727 728 /* 729 * InitKeyClassDeviceStruct initializes the key class before it 730 * initializes the keyboard feedback class for a device. 731 * UpdateActions can't set up the correct autorepeat for keyboard 732 * initialization because the keyboard feedback isn't created yet. 733 * Instead, UpdateActions notes the "correct" autorepeat in the 734 * SrvInfo structure and InitKbdFeedbackClass calls UpdateAutoRepeat 735 * to apply the computed autorepeat once the feedback class exists. 736 * 737 * DIX will apply the changed autorepeat, so there's no need to 738 * do so here. This function returns True if both RepeatKeys and 739 * the core protocol autorepeat ctrls are set (i.e. should use 740 * software autorepeat), false otherwise. 741 * 742 * This function also computes the autorepeat accelerators for the 743 * default indicator feedback. 744 */ 745int 746XkbFinishDeviceInit(DeviceIntPtr pXDev) 747{ 748XkbSrvInfoPtr xkbi; 749XkbDescPtr xkb; 750int softRepeat; 751XkbSrvLedInfoPtr sli; 752 753 xkbi = NULL; 754 if (pXDev && pXDev->key && pXDev->key->xkbInfo && pXDev->kbdfeed) { 755 xkbi= pXDev->key->xkbInfo; 756 xkb= xkbi->desc; 757 if (pXDev->kbdfeed) { 758 xkbi->kbdProc= pXDev->kbdfeed->CtrlProc; 759 pXDev->kbdfeed->CtrlProc= XkbDDXKeybdCtrlProc; 760 } 761 if (pXDev->kbdfeed->ctrl.autoRepeat) 762 xkb->ctrls->enabled_ctrls|= XkbRepeatKeysMask; 763 softRepeat= (xkb->ctrls->enabled_ctrls&XkbRepeatKeysMask)!=0; 764 if (pXDev->kbdfeed) { 765 memcpy(pXDev->kbdfeed->ctrl.autoRepeats, 766 xkb->ctrls->per_key_repeat,XkbPerKeyBitArraySize); 767 softRepeat= softRepeat&&pXDev->kbdfeed->ctrl.autoRepeat; 768 } 769 } 770 else softRepeat= 0; 771 sli= XkbFindSrvLedInfo(pXDev,XkbDfltXIClass,XkbDfltXIId,0); 772 if (sli && xkbi) 773 XkbCheckIndicatorMaps(xkbi->device,sli,XkbAllIndicatorsMask); 774#ifdef DEBUG 775 else ErrorF("No indicator feedback in XkbFinishInit (shouldn't happen)!\n"); 776#endif 777 return softRepeat; 778} 779 780 /* 781 * Be very careful about what does and doesn't get freed by this 782 * function. To reduce fragmentation, XkbInitDevice allocates a 783 * single huge block per device and divides it up into most of the 784 * fixed-size structures for the device. Don't free anything that 785 * is part of this larger block. 786 */ 787void 788XkbFreeInfo(XkbSrvInfoPtr xkbi) 789{ 790 if (xkbi->radioGroups) { 791 _XkbFree(xkbi->radioGroups); 792 xkbi->radioGroups= NULL; 793 } 794 if (xkbi->mouseKeyTimer) { 795 TimerFree(xkbi->mouseKeyTimer); 796 xkbi->mouseKeyTimer= NULL; 797 } 798 if (xkbi->slowKeysTimer) { 799 TimerFree(xkbi->slowKeysTimer); 800 xkbi->slowKeysTimer= NULL; 801 } 802 if (xkbi->bounceKeysTimer) { 803 TimerFree(xkbi->bounceKeysTimer); 804 xkbi->bounceKeysTimer= NULL; 805 } 806 if (xkbi->repeatKeyTimer) { 807 TimerFree(xkbi->repeatKeyTimer); 808 xkbi->repeatKeyTimer= NULL; 809 } 810 if (xkbi->krgTimer) { 811 TimerFree(xkbi->krgTimer); 812 xkbi->krgTimer= NULL; 813 } 814 xkbi->beepType= _BEEP_NONE; 815 if (xkbi->beepTimer) { 816 TimerFree(xkbi->beepTimer); 817 xkbi->beepTimer= NULL; 818 } 819 if (xkbi->desc) { 820 XkbFreeKeyboard(xkbi->desc,XkbAllComponentsMask,True); 821 xkbi->desc= NULL; 822 } 823 _XkbFree(xkbi); 824 return; 825} 826 827/***====================================================================***/ 828 829extern int XkbDfltRepeatDelay; 830extern int XkbDfltRepeatInterval; 831 832extern unsigned short XkbDfltAccessXTimeout; 833extern unsigned int XkbDfltAccessXTimeoutMask; 834extern unsigned int XkbDfltAccessXFeedback; 835extern unsigned char XkbDfltAccessXOptions; 836 837int 838XkbProcessArguments(int argc,char *argv[],int i) 839{ 840 if (strcmp(argv[i],"-kb")==0) { 841 noXkbExtension= True; 842 return 1; 843 } 844 else if (strcmp(argv[i],"+kb")==0) { 845 noXkbExtension= False; 846 return 1; 847 } 848 else if (strncmp(argv[i], "-xkbdir", 7) == 0) { 849 if(++i < argc) { 850#if !defined(WIN32) && !defined(__CYGWIN__) 851 if (getuid() != geteuid()) { 852 LogMessage(X_WARNING, "-xkbdir is not available for setuid X servers\n"); 853 return -1; 854 } else 855#endif 856 { 857 if (strlen(argv[i]) < PATH_MAX) { 858 XkbBaseDirectory= argv[i]; 859 return 2; 860 } else { 861 LogMessage(X_ERROR, "-xkbdir pathname too long\n"); 862 return -1; 863 } 864 } 865 } 866 else { 867 return -1; 868 } 869 } 870 else if ((strncmp(argv[i],"-accessx",8)==0)|| 871 (strncmp(argv[i],"+accessx",8)==0)) { 872 int j=1; 873 if (argv[i][0]=='-') 874 XkbWantAccessX= 0; 875 else { 876 XkbWantAccessX= 1; 877 878 if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) { 879 XkbDfltAccessXTimeout = atoi(argv[++i]); 880 j++; 881 882 if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) { 883 /* 884 * presumption that the reasonably useful range of 885 * values fits in 0..MAXINT since SunOS 4 doesn't 886 * have strtoul. 887 */ 888 XkbDfltAccessXTimeoutMask=(unsigned int) 889 strtol(argv[++i],NULL,16); 890 j++; 891 } 892 if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) { 893 if (argv[++i][0] == '1' ) 894 XkbDfltAccessXFeedback=XkbAccessXFeedbackMask; 895 else 896 XkbDfltAccessXFeedback=0; 897 j++; 898 } 899 if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) { 900 XkbDfltAccessXOptions=(unsigned char) 901 strtol(argv[++i],NULL,16); 902 j++; 903 } 904 } 905 } 906 return j; 907 } 908 if ((strcmp(argv[i], "-ardelay") == 0) || 909 (strcmp (argv[i], "-ar1") == 0)) { /* -ardelay int */ 910 if (++i >= argc) UseMsg (); 911 XkbDfltRepeatDelay = (long)atoi(argv[i]); 912 return 2; 913 } 914 if ((strcmp(argv[i], "-arinterval") == 0) || 915 (strcmp (argv[i], "-ar2") == 0)) { /* -arinterval int */ 916 if (++i >= argc) UseMsg (); 917 XkbDfltRepeatInterval = (long)atoi(argv[i]); 918 return 2; 919 } 920 return 0; 921} 922 923void 924XkbUseMsg(void) 925{ 926 ErrorF("-kb disable the X Keyboard Extension\n"); 927 ErrorF("+kb enable the X Keyboard Extension\n"); 928 ErrorF("[+-]accessx [ timeout [ timeout_mask [ feedback [ options_mask] ] ] ]\n"); 929 ErrorF(" enable/disable accessx key sequences\n"); 930 ErrorF("-ardelay set XKB autorepeat delay\n"); 931 ErrorF("-arinterval set XKB autorepeat interval\n"); 932} 933