#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#ifdef HAVE_XKB_CONFIG_H
#include <xkb-config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <math.h>
#define NEED_EVENTS 1
#include <X11/X.h>
#include <X11/Xproto.h>
#include <X11/keysym.h>
#include <X11/Xatom.h>
#include "misc.h"
#include "inputstr.h"
#include "opaque.h"
#include "property.h"
#define XKBSRV_NEED_FILE_FUNCS
#include <xkbsrv.h>
#include <X11/extensions/XKBgeom.h>
#include <X11/extensions/XKMformat.h>
#include <X11/extensions/XKBfile.h>
#include "xkb.h"
#define CREATE_ATOM(s) MakeAtom(s,sizeof(s)-1,1)
#ifdef sgi
#define LED_CAPS 5
#define LED_NUM 6
#define LED_SCROLL 7
#define PHYS_LEDS 0x7f
#define LED_COMPOSE 8
#else
#if defined(ultrix) || defined(__osf__) || defined(__alpha) || defined(__alpha__)
#define LED_COMPOSE 2
#define LED_CAPS 3
#define LED_SCROLL 4
#define LED_NUM 5
#define PHYS_LEDS 0x1f
#else
#ifdef sun
#define LED_NUM 1
#define LED_SCROLL 2
#define LED_COMPOSE 3
#define LED_CAPS 4
#define PHYS_LEDS 0x0f
#else
#define LED_CAPS 1
#define LED_NUM 2
#define LED_SCROLL 3
#define PHYS_LEDS 0x07
#endif
#endif
#endif
#define MAX_TOC 16
typedef struct _SrvXkmInfo {
DeviceIntPtr dev;
FILE * file;
XkbFileInfo xkbinfo;
} SrvXkmInfo;
#ifndef XKB_BASE_DIRECTORY
#define XKB_BASE_DIRECTORY "/usr/lib/X11/xkb"
#endif
#ifndef XKB_BIN_DIRECTORY
#define XKB_BIN_DIRECTORY XKB_BASE_DIRECTORY
#endif
#ifndef XKB_DFLT_RULES_FILE
#define XKB_DFLT_RULES_FILE "rules"
#endif
#ifndef XKB_DFLT_KB_LAYOUT
#define XKB_DFLT_KB_LAYOUT "us"
#endif
#ifndef XKB_DFLT_KB_MODEL
#define XKB_DFLT_KB_MODEL "dflt"
#endif
#ifndef XKB_DFLT_KB_VARIANT
#define XKB_DFLT_KB_VARIANT NULL
#endif
#ifndef XKB_DFLT_KB_OPTIONS
#define XKB_DFLT_KB_OPTIONS NULL
#endif
#ifndef XKB_DFLT_DISABLED
#define XKB_DFLT_DISABLED True
#endif
#ifndef XKB_DFLT_RULES_PROP
#define XKB_DFLT_RULES_PROP True
#endif
char * XkbBaseDirectory= XKB_BASE_DIRECTORY;
char * XkbBinDirectory= XKB_BIN_DIRECTORY;
static int XkbWantAccessX= 0;
static XkbFileInfo * _XkbInitFileInfo= NULL;
static Bool rulesDefined= False;
static char * XkbRulesFile= NULL;
static char * XkbModelDflt= NULL;
static char * XkbLayoutDflt= NULL;
static char * XkbVariantDflt= NULL;
static char * XkbOptionsDflt= NULL;
static char * XkbModelUsed= NULL;
static char * XkbLayoutUsed= NULL;
static char * XkbVariantUsed= NULL;
static char * XkbOptionsUsed= NULL;
_X_EXPORT Bool noXkbExtension= XKB_DFLT_DISABLED;
static Bool XkbWantRulesProp= XKB_DFLT_RULES_PROP;
static char *
XkbGetRulesDflts(XkbRF_VarDefsPtr defs)
{
if (XkbModelDflt) defs->model= XkbModelDflt;
else defs->model= XKB_DFLT_KB_MODEL;
if (XkbLayoutDflt) defs->layout= XkbLayoutDflt;
else defs->layout= XKB_DFLT_KB_LAYOUT;
if (XkbVariantDflt) defs->variant= XkbVariantDflt;
else defs->variant= XKB_DFLT_KB_VARIANT;
if (XkbOptionsDflt) defs->options= XkbOptionsDflt;
else defs->options= XKB_DFLT_KB_OPTIONS;
return (rulesDefined?XkbRulesFile:XKB_DFLT_RULES_FILE);
}
static Bool
XkbWriteRulesProp(ClientPtr client, pointer closure)
{
int len,out;
Atom name;
char * pval;
if (rulesDefined && (!XkbRulesFile))
return False;
len= (XkbRulesFile?strlen(XkbRulesFile):strlen(XKB_DFLT_RULES_FILE));
len+= (XkbModelUsed?strlen(XkbModelUsed):0);
len+= (XkbLayoutUsed?strlen(XkbLayoutUsed):0);
len+= (XkbVariantUsed?strlen(XkbVariantUsed):0);
len+= (XkbOptionsUsed?strlen(XkbOptionsUsed):0);
if (len<1)
return True;
len+= 5;
name= MakeAtom(_XKB_RF_NAMES_PROP_ATOM,strlen(_XKB_RF_NAMES_PROP_ATOM),1);
if (name==None) {
ErrorF("Atom error: %s not created\n",_XKB_RF_NAMES_PROP_ATOM);
return True;
}
pval= (char*) ALLOCATE_LOCAL(len);
if (!pval) {
ErrorF("Allocation error: %s proprerty not created\n",
_XKB_RF_NAMES_PROP_ATOM);
return True;
}
out= 0;
if (XkbRulesFile) {
strcpy(&pval[out],XkbRulesFile);
out+= strlen(XkbRulesFile);
} else {
strcpy(&pval[out],XKB_DFLT_RULES_FILE);
out+= strlen(XKB_DFLT_RULES_FILE);
}
pval[out++]= '\0';
if (XkbModelUsed) {
strcpy(&pval[out],XkbModelUsed);
out+= strlen(XkbModelUsed);
}
pval[out++]= '\0';
if (XkbLayoutUsed) {
strcpy(&pval[out],XkbLayoutUsed);
out+= strlen(XkbLayoutUsed);
}
pval[out++]= '\0';
if (XkbVariantUsed) {
strcpy(&pval[out],XkbVariantUsed);
out+= strlen(XkbVariantUsed);
}
pval[out++]= '\0';
if (XkbOptionsUsed) {
strcpy(&pval[out],XkbOptionsUsed);
out+= strlen(XkbOptionsUsed);
}
pval[out++]= '\0';
if (out!=len) {
ErrorF("Internal Error! bad size (%d!=%d) for _XKB_RULES_NAMES\n",
out,len);
}
ChangeWindowProperty(WindowTable[0],name,XA_STRING,8,PropModeReplace,
len,pval,True);
DEALLOCATE_LOCAL(pval);
return True;
}
static void
XkbSetRulesUsed(XkbRF_VarDefsPtr defs)
{
if (XkbModelUsed)
_XkbFree(XkbModelUsed);
XkbModelUsed= (defs->model?_XkbDupString(defs->model):NULL);
if (XkbLayoutUsed)
_XkbFree(XkbLayoutUsed);
XkbLayoutUsed= (defs->layout?_XkbDupString(defs->layout):NULL);
if (XkbVariantUsed)
_XkbFree(XkbVariantUsed);
XkbVariantUsed= (defs->variant?_XkbDupString(defs->variant):NULL);
if (XkbOptionsUsed)
_XkbFree(XkbOptionsUsed);
XkbOptionsUsed= (defs->options?_XkbDupString(defs->options):NULL);
if (XkbWantRulesProp)
QueueWorkProc(XkbWriteRulesProp,NULL,NULL);
return;
}
_X_EXPORT void
XkbSetRulesDflts(char *rulesFile,char *model,char *layout,
char *variant,char *options)
{
if (XkbRulesFile)
_XkbFree(XkbRulesFile);
XkbRulesFile= _XkbDupString(rulesFile);
rulesDefined= True;
if (model) {
if (XkbModelDflt)
_XkbFree(XkbModelDflt);
XkbModelDflt= _XkbDupString(model);
}
if (layout) {
if (XkbLayoutDflt)
_XkbFree(XkbLayoutDflt);
XkbLayoutDflt= _XkbDupString(layout);
}
if (variant) {
if (XkbVariantDflt)
_XkbFree(XkbVariantDflt);
XkbVariantDflt= _XkbDupString(variant);
}
if (options) {
if (XkbOptionsDflt)
_XkbFree(XkbOptionsDflt);
XkbOptionsDflt= _XkbDupString(options);
}
return;
}
#if defined(luna)
#define XKB_DDX_PERMANENT_LOCK 1
#endif
#include "xkbDflts.h"
static Bool
XkbInitKeyTypes(XkbDescPtr xkb,SrvXkmInfo *file)
{
if (file->xkbinfo.defined&XkmTypesMask)
return True;
initTypeNames(NULL);
if (XkbAllocClientMap(xkb,XkbKeyTypesMask,num_dflt_types)!=Success)
return False;
if (XkbCopyKeyTypes(dflt_types,xkb->map->types,num_dflt_types)!=
Success) {
return False;
}
xkb->map->size_types= xkb->map->num_types= num_dflt_types;
return True;
}
static void
XkbInitRadioGroups(XkbSrvInfoPtr xkbi,SrvXkmInfo *file)
{
xkbi->nRadioGroups = 0;
xkbi->radioGroups = NULL;
return;
}
static Status
XkbInitCompatStructs(XkbDescPtr xkb,SrvXkmInfo *file)
{
register int i;
XkbCompatMapPtr compat;
if (file->xkbinfo.defined&XkmCompatMapMask)
return Success;
if (XkbAllocCompatMap(xkb,XkbAllCompatMask,num_dfltSI)!=Success)
return BadAlloc;
compat = xkb->compat;
if (compat->sym_interpret) {
compat->num_si = num_dfltSI;
memcpy((char *)compat->sym_interpret,(char *)dfltSI,sizeof(dfltSI));
}
for (i=0;i<XkbNumKbdGroups;i++) {
compat->groups[i]= compatMap.groups[i];
if (compat->groups[i].vmods!=0) {
unsigned mask;
mask= XkbMaskForVMask(xkb,compat->groups[i].vmods);
compat->groups[i].mask= compat->groups[i].real_mods|mask;
}
else compat->groups[i].mask= compat->groups[i].real_mods;
}
return Success;
}
static void
XkbInitSemantics(XkbDescPtr xkb,SrvXkmInfo *file)
{
XkbInitKeyTypes(xkb,file);
XkbInitCompatStructs(xkb,file);
return;
}
static Status
XkbInitNames(XkbSrvInfoPtr xkbi,SrvXkmInfo *file)
{
XkbDescPtr xkb;
XkbNamesPtr names;
Status rtrn;
Atom unknown;
xkb= xkbi->desc;
if ((rtrn=XkbAllocNames(xkb,XkbAllNamesMask,0,0))!=Success)
return rtrn;
unknown= CREATE_ATOM("unknown");
names = xkb->names;
if (names->keycodes==None) names->keycodes= unknown;
if (names->geometry==None) names->geometry= unknown;
if (names->phys_symbols==None) names->phys_symbols= unknown;
if (names->symbols==None) names->symbols= unknown;
if (names->types==None) names->types= unknown;
if (names->compat==None) names->compat= unknown;
if ((file->xkbinfo.defined&XkmVirtualModsMask)==0) {
if (names->vmods[vmod_NumLock]==None)
names->vmods[vmod_NumLock]= CREATE_ATOM("NumLock");
if (names->vmods[vmod_Alt]==None)
names->vmods[vmod_Alt]= CREATE_ATOM("Alt");
if (names->vmods[vmod_AltGr]==None)
names->vmods[vmod_AltGr]= CREATE_ATOM("ModeSwitch");
}
if (((file->xkbinfo.defined&XkmIndicatorsMask)==0)||
((file->xkbinfo.defined&XkmGeometryMask)==0)) {
initIndicatorNames(NULL,xkb);
if (names->indicators[LED_CAPS-1]==None)
names->indicators[LED_CAPS-1] = CREATE_ATOM("Caps Lock");
if (names->indicators[LED_NUM-1]==None)
names->indicators[LED_NUM-1] = CREATE_ATOM("Num Lock");
if (names->indicators[LED_SCROLL-1]==None)
names->indicators[LED_SCROLL-1] = CREATE_ATOM("Scroll Lock");
#ifdef LED_COMPOSE
if (names->indicators[LED_COMPOSE-1]==None)
names->indicators[LED_COMPOSE-1] = CREATE_ATOM("Compose");
#endif
}
#ifdef DEBUG_RADIO_GROUPS
if (names->num_rg<1) {
names->radio_groups= (Atom *)_XkbCalloc(RG_COUNT, sizeof(Atom));
if (names->radio_groups) {
names->num_rg = RG_COUNT;
names->radio_groups[RG_BOGUS_FUNCTION_GROUP]= CREATE_ATOM("BOGUS");
}
}
#endif
if (xkb->geom!=NULL)
names->geometry= xkb->geom->name;
else names->geometry= unknown;
return Success;
}
static Status
XkbInitIndicatorMap(XkbSrvInfoPtr xkbi,SrvXkmInfo *file)
{
XkbDescPtr xkb;
XkbIndicatorPtr map;
XkbSrvLedInfoPtr sli;
xkb= xkbi->desc;
if (XkbAllocIndicatorMaps(xkb)!=Success)
return BadAlloc;
if ((file->xkbinfo.defined&XkmIndicatorsMask)==0) {
map= xkb->indicators;
map->phys_indicators = PHYS_LEDS;
map->maps[LED_CAPS-1].flags= XkbIM_NoExplicit;
map->maps[LED_CAPS-1].which_mods= XkbIM_UseLocked;
map->maps[LED_CAPS-1].mods.mask= LockMask;
map->maps[LED_CAPS-1].mods.real_mods= LockMask;
map->maps[LED_NUM-1].flags= XkbIM_NoExplicit;
map->maps[LED_NUM-1].which_mods= XkbIM_UseLocked;
map->maps[LED_NUM-1].mods.mask= 0;
map->maps[LED_NUM-1].mods.real_mods= 0;
map->maps[LED_NUM-1].mods.vmods= vmod_NumLockMask;
map->maps[LED_SCROLL-1].flags= XkbIM_NoExplicit;
map->maps[LED_SCROLL-1].which_mods= XkbIM_UseLocked;
map->maps[LED_SCROLL-1].mods.mask= Mod3Mask;
map->maps[LED_SCROLL-1].mods.real_mods= Mod3Mask;
}
sli= XkbFindSrvLedInfo(xkbi->device,XkbDfltXIClass,XkbDfltXIId,0);
if (sli)
XkbCheckIndicatorMaps(xkbi->device,sli,XkbAllIndicatorsMask);
return Success;
}
static Status
XkbInitControls(DeviceIntPtr pXDev,XkbSrvInfoPtr xkbi,SrvXkmInfo *file)
{
XkbDescPtr xkb;
XkbControlsPtr ctrls;
xkb= xkbi->desc;
if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success)
FatalError("Couldn't allocate keyboard controls\n");
ctrls= xkb->ctrls;
if ((file->xkbinfo.defined&XkmSymbolsMask)==0)
ctrls->num_groups = 1;
ctrls->groups_wrap = XkbSetGroupInfo(1,XkbWrapIntoRange,0);
ctrls->internal.mask = 0;
ctrls->internal.real_mods = 0;
ctrls->internal.vmods = 0;
ctrls->ignore_lock.mask = 0;
ctrls->ignore_lock.real_mods = 0;
ctrls->ignore_lock.vmods = 0;
ctrls->enabled_ctrls = XkbAccessXTimeoutMask|XkbRepeatKeysMask|
XkbMouseKeysAccelMask|XkbAudibleBellMask|
XkbIgnoreGroupLockMask;
if (XkbWantAccessX)
ctrls->enabled_ctrls|= XkbAccessXKeysMask;
AccessXInit(pXDev);
return Success;
}
void
XkbInitDevice(DeviceIntPtr pXDev)
{
int i;
XkbSrvInfoPtr xkbi;
XkbChangesRec changes;
SrvXkmInfo file;
unsigned check;
XkbEventCauseRec cause;
file.dev= pXDev;
file.file=NULL;
bzero(&file.xkbinfo,sizeof(XkbFileInfo));
bzero(&changes,sizeof(XkbChangesRec));
pXDev->key->xkbInfo= xkbi= _XkbTypedCalloc(1,XkbSrvInfoRec);
if ( xkbi ) {
XkbDescPtr xkb;
if ((_XkbInitFileInfo!=NULL)&&(_XkbInitFileInfo->xkb!=NULL)) {
file.xkbinfo= *_XkbInitFileInfo;
xkbi->desc= _XkbInitFileInfo->xkb;
_XkbInitFileInfo= NULL;
}
else {
xkbi->desc= XkbAllocKeyboard();
if (!xkbi->desc)
FatalError("Couldn't allocate keyboard description\n");
xkbi->desc->min_key_code = pXDev->key->curKeySyms.minKeyCode;
xkbi->desc->max_key_code = pXDev->key->curKeySyms.maxKeyCode;
}
xkb= xkbi->desc;
if (xkb->min_key_code == 0)
xkb->min_key_code = pXDev->key->curKeySyms.minKeyCode;
if (xkb->max_key_code == 0)
xkb->max_key_code = pXDev->key->curKeySyms.maxKeyCode;
if ((pXDev->key->curKeySyms.minKeyCode!=xkbi->desc->min_key_code)||
(pXDev->key->curKeySyms.maxKeyCode!=xkbi->desc->max_key_code)) {
ErrorF("Internal Error!! XKB and core keymap have different range\n");
}
if (XkbAllocClientMap(xkb,XkbAllClientInfoMask,0)!=Success)
FatalError("Couldn't allocate client map in XkbInitDevice\n");
i= XkbNumKeys(xkb)/3+1;
if (XkbAllocServerMap(xkb,XkbAllServerInfoMask,i)!=Success)
FatalError("Couldn't allocate server map in XkbInitDevice\n");
xkbi->dfltPtrDelta=1;
xkbi->device = pXDev;
file.xkbinfo.xkb= xkb;
XkbInitSemantics(xkb,&file);
XkbInitNames(xkbi,&file);
XkbInitRadioGroups(xkbi,&file);
bzero(&xkbi->state,sizeof(XkbStateRec));
XkbInitControls(pXDev,xkbi,&file);
if (file.xkbinfo.defined&XkmSymbolsMask)
memcpy(pXDev->key->modifierMap,xkb->map->modmap,xkb->max_key_code+1);
else
memcpy(xkb->map->modmap,pXDev->key->modifierMap,xkb->max_key_code+1);
XkbInitIndicatorMap(xkbi,&file);
XkbDDXInitDevice(pXDev);
if (!(file.xkbinfo.defined&XkmSymbolsMask)) {
XkbUpdateKeyTypesFromCore(pXDev,xkb->min_key_code,XkbNumKeys(xkb),
&changes);
}
else {
XkbUpdateCoreDescription(pXDev,True);
}
XkbSetCauseUnknown(&cause);
XkbUpdateActions(pXDev,xkb->min_key_code, XkbNumKeys(xkb),&changes,
&check,&cause);
pXDev->key->curKeySyms.minKeyCode = xkb->min_key_code;
pXDev->key->curKeySyms.maxKeyCode = xkb->max_key_code;
}
if (file.file!=NULL)
fclose(file.file);
return;
}
#if MAP_LENGTH > XkbMaxKeyCount
#undef XkbMaxKeyCount
#define XkbMaxKeyCount MAP_LENGTH
#endif
_X_EXPORT Bool
XkbInitKeyboardDeviceStruct(
DeviceIntPtr dev,
XkbComponentNamesPtr names,
KeySymsPtr pSymsIn,
CARD8 pModsIn[],
void (*bellProc)(
int ,
DeviceIntPtr ,
pointer ,
int),
void (*ctrlProc)(
DeviceIntPtr ,
KeybdCtrl * ))
{
XkbFileInfo finfo;
KeySymsRec tmpSyms,*pSyms;
CARD8 tmpMods[XkbMaxLegalKeyCode+1],*pMods;
char name[PATH_MAX],*rules;
Bool ok=False;
XkbRF_VarDefsRec defs;
if ((dev->key!=NULL)||(dev->kbdfeed!=NULL))
return False;
pSyms= pSymsIn;
pMods= pModsIn;
bzero(&defs,sizeof(XkbRF_VarDefsRec));
rules= XkbGetRulesDflts(&defs);
if (names->keymap) names->keymap = _XkbDupString(names->keymap);
if (names->keycodes) names->keycodes = _XkbDupString(names->keycodes);
if (names->types) names->types = _XkbDupString(names->types);
if (names->compat) names->compat = _XkbDupString(names->compat);
if (names->geometry) names->geometry = _XkbDupString(names->geometry);
if (names->symbols) names->symbols = _XkbDupString(names->symbols);
if (defs.model && defs.layout && rules) {
XkbComponentNamesRec rNames;
bzero(&rNames,sizeof(XkbComponentNamesRec));
if (XkbDDXNamesFromRules(dev,rules,&defs,&rNames)) {
if (rNames.keymap) {
if (!names->keymap)
names->keymap = rNames.keymap;
else _XkbFree(rNames.keymap);
}
if (rNames.keycodes) {
if (!names->keycodes)
names->keycodes = rNames.keycodes;
else
_XkbFree(rNames.keycodes);
}
if (rNames.types) {
if (!names->types)
names->types = rNames.types;
else _XkbFree(rNames.types);
}
if (rNames.compat) {
if (!names->compat)
names->compat = rNames.compat;
else _XkbFree(rNames.compat);
}
if (rNames.symbols) {
if (!names->symbols)
names->symbols = rNames.symbols;
else _XkbFree(rNames.symbols);
}
if (rNames.geometry) {
if (!names->geometry)
names->geometry = rNames.geometry;
else _XkbFree(rNames.geometry);
}
XkbSetRulesUsed(&defs);
}
}
if (names->keymap) {
XkbComponentNamesRec tmpNames;
bzero(&tmpNames,sizeof(XkbComponentNamesRec));
tmpNames.keymap = names->keymap;
ok = (Bool) XkbDDXLoadKeymapByNames(dev,&tmpNames,XkmAllIndicesMask,0,
&finfo,name,PATH_MAX);
}
if (!(ok && (finfo.xkb!=NULL)))
ok = (Bool) XkbDDXLoadKeymapByNames(dev,names,XkmAllIndicesMask,0,
&finfo,name,PATH_MAX);
if (ok && (finfo.xkb!=NULL)) {
XkbDescPtr xkb;
KeyCode minKC,maxKC;
xkb= finfo.xkb;
minKC= xkb->min_key_code;
maxKC= xkb->max_key_code;
if (XkbIsLegalKeycode(minKC)&&XkbIsLegalKeycode(maxKC)&&(minKC<=maxKC)&&
((minKC!=pSyms->minKeyCode)||(maxKC!=pSyms->maxKeyCode))) {
if (xkb->map!=NULL) {
KeySym *inSym,*outSym;
int width= pSymsIn->mapWidth;
tmpSyms.minKeyCode= minKC;
tmpSyms.maxKeyCode= maxKC;
if (minKC<pSymsIn->minKeyCode)
minKC= pSymsIn->minKeyCode;
if (maxKC>pSymsIn->maxKeyCode)
maxKC= pSymsIn->maxKeyCode;
tmpSyms.mapWidth= width;
tmpSyms.map= _XkbTypedCalloc(width*XkbNumKeys(xkb),KeySym);
inSym= &pSymsIn->map[(minKC-pSymsIn->minKeyCode)*width];
outSym= &tmpSyms.map[(minKC-tmpSyms.minKeyCode)*width];
memcpy(outSym,inSym,((maxKC-minKC+1)*width)*sizeof(KeySym));
pSyms= &tmpSyms;
}
if ((xkb->map!=NULL)&&(xkb->map->modmap!=NULL)) {
bzero(tmpMods,XkbMaxKeyCount);
memcpy(tmpMods,xkb->map->modmap,maxKC+1);
pMods= tmpMods;
}
}
_XkbInitFileInfo= &finfo;
}
else {
LogMessage(X_WARNING, "Couldn't load XKB keymap, falling back to pre-XKB keymap\n");
}
ok= InitKeyboardDeviceStruct((DevicePtr)dev,pSyms,pMods,bellProc,ctrlProc);
_XkbInitFileInfo= NULL;
if ((pSyms==&tmpSyms)&&(pSyms->map!=NULL)) {
_XkbFree(pSyms->map);
pSyms->map= NULL;
}
if (names->keymap) _XkbFree(names->keymap);
names->keymap = NULL;
if (names->keycodes) _XkbFree(names->keycodes);
names->keycodes = NULL;
if (names->types) _XkbFree(names->types);
names->types = NULL;
if (names->compat) _XkbFree(names->compat);
names->compat = NULL;
if (names->geometry) _XkbFree(names->geometry);
names->geometry = NULL;
if (names->symbols) _XkbFree(names->symbols);
names->symbols = NULL;
return ok;
}
int
XkbFinishDeviceInit(DeviceIntPtr pXDev)
{
XkbSrvInfoPtr xkbi;
XkbDescPtr xkb;
int softRepeat;
XkbSrvLedInfoPtr sli;
xkbi = NULL;
if (pXDev && pXDev->key && pXDev->key->xkbInfo && pXDev->kbdfeed) {
xkbi= pXDev->key->xkbInfo;
xkb= xkbi->desc;
if (pXDev->kbdfeed) {
xkbi->kbdProc= pXDev->kbdfeed->CtrlProc;
pXDev->kbdfeed->CtrlProc= XkbDDXKeybdCtrlProc;
}
if (pXDev->kbdfeed->ctrl.autoRepeat)
xkb->ctrls->enabled_ctrls|= XkbRepeatKeysMask;
softRepeat= (xkb->ctrls->enabled_ctrls&XkbRepeatKeysMask)!=0;
if (pXDev->kbdfeed) {
memcpy(pXDev->kbdfeed->ctrl.autoRepeats,
xkb->ctrls->per_key_repeat,XkbPerKeyBitArraySize);
softRepeat= softRepeat&&pXDev->kbdfeed->ctrl.autoRepeat;
}
}
else softRepeat= 0;
sli= XkbFindSrvLedInfo(pXDev,XkbDfltXIClass,XkbDfltXIId,0);
if (sli && xkbi)
XkbCheckIndicatorMaps(xkbi->device,sli,XkbAllIndicatorsMask);
#ifdef DEBUG
else ErrorF("No indicator feedback in XkbFinishInit (shouldn't happen)!\n");
#endif
return softRepeat;
}
void
XkbFreeInfo(XkbSrvInfoPtr xkbi)
{
if (xkbi->radioGroups) {
_XkbFree(xkbi->radioGroups);
xkbi->radioGroups= NULL;
}
if (xkbi->mouseKeyTimer) {
TimerFree(xkbi->mouseKeyTimer);
xkbi->mouseKeyTimer= NULL;
}
if (xkbi->slowKeysTimer) {
TimerFree(xkbi->slowKeysTimer);
xkbi->slowKeysTimer= NULL;
}
if (xkbi->bounceKeysTimer) {
TimerFree(xkbi->bounceKeysTimer);
xkbi->bounceKeysTimer= NULL;
}
if (xkbi->repeatKeyTimer) {
TimerFree(xkbi->repeatKeyTimer);
xkbi->repeatKeyTimer= NULL;
}
if (xkbi->krgTimer) {
TimerFree(xkbi->krgTimer);
xkbi->krgTimer= NULL;
}
xkbi->beepType= _BEEP_NONE;
if (xkbi->beepTimer) {
TimerFree(xkbi->beepTimer);
xkbi->beepTimer= NULL;
}
if (xkbi->desc) {
XkbFreeKeyboard(xkbi->desc,XkbAllComponentsMask,True);
xkbi->desc= NULL;
}
_XkbFree(xkbi);
return;
}
extern int XkbDfltRepeatDelay;
extern int XkbDfltRepeatInterval;
extern unsigned short XkbDfltAccessXTimeout;
extern unsigned int XkbDfltAccessXTimeoutMask;
extern unsigned int XkbDfltAccessXFeedback;
extern unsigned char XkbDfltAccessXOptions;
int
XkbProcessArguments(int argc,char *argv[],int i)
{
if (strcmp(argv[i],"-kb")==0) {
noXkbExtension= True;
return 1;
}
else if (strcmp(argv[i],"+kb")==0) {
noXkbExtension= False;
return 1;
}
else if (strncmp(argv[i], "-xkbdir", 7) == 0) {
if(++i < argc) {
#if !defined(WIN32) && !defined(__CYGWIN__)
if (getuid() != geteuid()) {
LogMessage(X_WARNING, "-xkbdir is not available for setuid X servers\n");
return -1;
} else
#endif
{
if (strlen(argv[i]) < PATH_MAX) {
XkbBaseDirectory= argv[i];
return 2;
} else {
LogMessage(X_ERROR, "-xkbdir pathname too long\n");
return -1;
}
}
}
else {
return -1;
}
}
else if ((strncmp(argv[i],"-accessx",8)==0)||
(strncmp(argv[i],"+accessx",8)==0)) {
int j=1;
if (argv[i][0]=='-')
XkbWantAccessX= 0;
else {
XkbWantAccessX= 1;
if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
XkbDfltAccessXTimeout = atoi(argv[++i]);
j++;
if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
XkbDfltAccessXTimeoutMask=(unsigned int)
strtol(argv[++i],NULL,16);
j++;
}
if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
if (argv[++i][0] == '1' )
XkbDfltAccessXFeedback=XkbAccessXFeedbackMask;
else
XkbDfltAccessXFeedback=0;
j++;
}
if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
XkbDfltAccessXOptions=(unsigned char)
strtol(argv[++i],NULL,16);
j++;
}
}
}
return j;
}
if ((strcmp(argv[i], "-ardelay") == 0) ||
(strcmp (argv[i], "-ar1") == 0)) {
if (++i >= argc) UseMsg ();
XkbDfltRepeatDelay = (long)atoi(argv[i]);
return 2;
}
if ((strcmp(argv[i], "-arinterval") == 0) ||
(strcmp (argv[i], "-ar2") == 0)) {
if (++i >= argc) UseMsg ();
XkbDfltRepeatInterval = (long)atoi(argv[i]);
return 2;
}
return 0;
}
void
XkbUseMsg(void)
{
ErrorF("-kb disable the X Keyboard Extension\n");
ErrorF("+kb enable the X Keyboard Extension\n");
ErrorF("[+-]accessx [ timeout [ timeout_mask [ feedback [ options_mask] ] ] ]\n");
ErrorF(" enable/disable accessx key sequences\n");
ErrorF("-ardelay set XKB autorepeat delay\n");
ErrorF("-arinterval set XKB autorepeat interval\n");
}