Edit

IABSD.fr/xenocara/xserver/xkb/xkbInit.c

Branch :

  • Show log

    Commit

  • Author : matthieu
    Date : 2010-07-27 19:02:24
    Hash : 95d684a0
    Message : Update to xserver 1.8. Tested by many. Ok oga@, todd@.

  • xserver/xkb/xkbInit.c
  • /************************************************************
    Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
    
    Permission to use, copy, modify, and distribute this
    software and its documentation for any purpose and without
    fee is hereby granted, provided that the above copyright
    notice appear in all copies and that both that copyright
    notice and this permission notice appear in supporting
    documentation, and that the name of Silicon Graphics not be 
    used in advertising or publicity pertaining to distribution 
    of the software without specific prior written permission.
    Silicon Graphics makes no representation about the suitability 
    of this software for any purpose. It is provided "as is"
    without any express or implied warranty.
    
    SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 
    SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 
    AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
    GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 
    DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 
    DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 
    OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
    THE USE OR PERFORMANCE OF THIS SOFTWARE.
    
    ********************************************************/
    
    #ifdef HAVE_DIX_CONFIG_H
    #include <dix-config.h>
    #endif
    
    #include <xkb-config.h>
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <unistd.h>
    #include <math.h>
    #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 "xkbgeom.h"
    #include <X11/extensions/XKMformat.h>
    #include "xkbfile.h"
    #include "xkb.h"
    
    #define	CREATE_ATOM(s)	MakeAtom(s,sizeof(s)-1,1)
    
    #if 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
    
    #define	MAX_TOC	16
    typedef struct	_SrvXkmInfo {
    	DeviceIntPtr	dev;
    	FILE *		file;
    	XkbDescPtr	xkb;
    } SrvXkmInfo;
    
    
    /***====================================================================***/
    
    #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 char *		XkbRulesDflt=		NULL;
    static char *		XkbModelDflt=		NULL;
    static char *		XkbLayoutDflt=		NULL;
    static char *		XkbVariantDflt=		NULL;
    static char *		XkbOptionsDflt=		NULL;
    
    static char *           XkbRulesUsed=   NULL;
    static char *		XkbModelUsed=	NULL;
    static char *		XkbLayoutUsed=	NULL;
    static char *		XkbVariantUsed=	NULL;
    static char *		XkbOptionsUsed=	NULL;
    
    static XkbDescPtr	xkb_cached_map = NULL;
    
    static Bool		XkbWantRulesProp=	XKB_DFLT_RULES_PROP;
    
    /***====================================================================***/
    
    /**
     * Get the current default XKB rules.
     * Caller must free the data in rmlvo.
     */
    void
    XkbGetRulesDflts(XkbRMLVOSet *rmlvo)
    {
        if (XkbRulesDflt)   rmlvo->rules = XkbRulesDflt;
        else                rmlvo->rules = XKB_DFLT_RULES;
        if (XkbModelDflt)	rmlvo->model= XkbModelDflt;
        else		rmlvo->model= XKB_DFLT_MODEL;
        if (XkbLayoutDflt)	rmlvo->layout= XkbLayoutDflt;
        else		rmlvo->layout= XKB_DFLT_LAYOUT;
        if (XkbVariantDflt)	rmlvo->variant= XkbVariantDflt;
        else		rmlvo->variant= XKB_DFLT_VARIANT;
        if (XkbOptionsDflt)	rmlvo->options= XkbOptionsDflt;
        else		rmlvo->options= XKB_DFLT_OPTIONS;
    
        rmlvo->rules = strdup(rmlvo->rules);
        rmlvo->model = strdup(rmlvo->model);
        rmlvo->layout = strdup(rmlvo->layout);
        rmlvo->variant = strdup(rmlvo->variant);
        rmlvo->options = strdup(rmlvo->options);
    }
    
    void
    XkbFreeRMLVOSet(XkbRMLVOSet *rmlvo, Bool freeRMLVO)
    {
        if (!rmlvo)
            return;
    
        xfree(rmlvo->rules);
        xfree(rmlvo->model);
        xfree(rmlvo->layout);
        xfree(rmlvo->variant);
        xfree(rmlvo->options);
    
        if (freeRMLVO)
            xfree(rmlvo);
        else
            memset(rmlvo, 0, sizeof(XkbRMLVOSet));
    }
    
    static Bool
    XkbWriteRulesProp(ClientPtr client, pointer closure)
    {
    int 			len,out;
    Atom			name;
    char *			pval;
    
        len= (XkbRulesUsed?strlen(XkbRulesUsed):0);
        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; /* trailing NULs */
    
        name= MakeAtom(_XKB_RF_NAMES_PROP_ATOM,strlen(_XKB_RF_NAMES_PROP_ATOM),1);
        if (name==None) {
    	ErrorF("[xkb] Atom error: %s not created\n",_XKB_RF_NAMES_PROP_ATOM);
    	return TRUE;
        }
        pval= (char*) xalloc(len);
        if (!pval) {
    	ErrorF("[xkb] Allocation error: %s proprerty not created\n",
    						_XKB_RF_NAMES_PROP_ATOM);
    	return TRUE;
        }
        out= 0;
        if (XkbRulesUsed) {
    	strcpy(&pval[out],XkbRulesUsed);
    	out+= strlen(XkbRulesUsed);
        }
        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("[xkb] Internal Error! bad size (%d!=%d) for _XKB_RULES_NAMES\n",
    								out,len);
        }
        dixChangeWindowProperty(serverClient, WindowTable[0], name, XA_STRING, 8,
    			    PropModeReplace, len, pval, TRUE);
        xfree(pval);
        return TRUE;
    }
    
    static void
    XkbSetRulesUsed(XkbRMLVOSet *rmlvo)
    {
        if (XkbRulesUsed)
            xfree(XkbRulesUsed);
        XkbRulesUsed= (rmlvo->rules?_XkbDupString(rmlvo->rules):NULL);
        if (XkbModelUsed)
    	xfree(XkbModelUsed);
        XkbModelUsed= (rmlvo->model?_XkbDupString(rmlvo->model):NULL);
        if (XkbLayoutUsed)
    	xfree(XkbLayoutUsed);
        XkbLayoutUsed= (rmlvo->layout?_XkbDupString(rmlvo->layout):NULL);
        if (XkbVariantUsed)
    	xfree(XkbVariantUsed);
        XkbVariantUsed= (rmlvo->variant?_XkbDupString(rmlvo->variant):NULL);
        if (XkbOptionsUsed)
    	xfree(XkbOptionsUsed);
        XkbOptionsUsed= (rmlvo->options?_XkbDupString(rmlvo->options):NULL);
        if (XkbWantRulesProp)
    	QueueWorkProc(XkbWriteRulesProp,NULL,NULL);
        return;
    }
    
    void
    XkbSetRulesDflts(XkbRMLVOSet *rmlvo)
    {
        if (rmlvo->rules) {
            if (XkbRulesDflt)
    	    xfree(XkbRulesDflt);
            XkbRulesDflt= _XkbDupString(rmlvo->rules);
        }
        if (rmlvo->model) {
    	if (XkbModelDflt)
    	    xfree(XkbModelDflt);
    	XkbModelDflt= _XkbDupString(rmlvo->model);
        }
        if (rmlvo->layout) {
    	if (XkbLayoutDflt)
    	    xfree(XkbLayoutDflt);
    	XkbLayoutDflt= _XkbDupString(rmlvo->layout);
        }
        if (rmlvo->variant) {
    	if (XkbVariantDflt)
    	    xfree(XkbVariantDflt);
    	XkbVariantDflt= _XkbDupString(rmlvo->variant);
        }
        if (rmlvo->options) {
    	if (XkbOptionsDflt)
    	    xfree(XkbOptionsDflt);
    	XkbOptionsDflt= _XkbDupString(rmlvo->options);
        }
        return;
    }
    
    void
    XkbDeleteRulesDflts(void)
    {
        xfree(XkbRulesDflt);
        XkbRulesDflt = NULL;
        xfree(XkbModelDflt);
        XkbModelDflt = NULL;
        xfree(XkbLayoutDflt);
        XkbLayoutDflt = NULL;
        xfree(XkbVariantDflt);
        XkbVariantDflt = NULL;
        xfree(XkbOptionsDflt);
        XkbOptionsDflt = NULL;
    
        XkbFreeKeyboard(xkb_cached_map, XkbAllComponentsMask, TRUE);
        xkb_cached_map = NULL;
    }
    
    #define DIFFERS(a, b) (strcmp((a) ? (a) : "", (b) ? (b) : "") != 0)
    
    static Bool
    XkbCompareUsedRMLVO(XkbRMLVOSet *rmlvo)
    {
        if (DIFFERS(rmlvo->rules, XkbRulesUsed) ||
            DIFFERS(rmlvo->model, XkbModelUsed) ||
            DIFFERS(rmlvo->layout, XkbLayoutUsed) ||
            DIFFERS(rmlvo->variant, XkbVariantUsed) ||
            DIFFERS(rmlvo->options, XkbOptionsUsed))
            return FALSE;
        return TRUE;
    }
    
    #undef DIFFERS
    
    /***====================================================================***/
    
    #include "xkbDflts.h"
    
    static Bool
    XkbInitKeyTypes(XkbDescPtr xkb)
    {
        if (xkb->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)
    {
        xkbi->nRadioGroups = 0;
        xkbi->radioGroups = NULL;
        return;
    }
    
    
    static Status
    XkbInitCompatStructs(XkbDescPtr xkb)
    {
    register int 	i;
    XkbCompatMapPtr	compat;
    
        if (xkb->defined & XkmCompatMapMask)
            return TRUE;
    
        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)
    {
        XkbInitKeyTypes(xkb);
        XkbInitCompatStructs(xkb);
        return;
    }
    
    /***====================================================================***/
    
    static Status
    XkbInitNames(XkbSrvInfoPtr xkbi)
    {
    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 (!(xkb->defined & XkmVirtualModsMask)) {
            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 (!(xkb->defined & XkmIndicatorsMask) ||
            !(xkb->defined & XkmGeometryMask)) {
            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
        }
    
        if (xkb->geom!=NULL)
    	 names->geometry= xkb->geom->name;
        else names->geometry= unknown;
    
        return Success;
    }
    
    static Status
    XkbInitIndicatorMap(XkbSrvInfoPtr xkbi)
    {
    XkbDescPtr		xkb;
    XkbIndicatorPtr		map;
    XkbSrvLedInfoPtr	sli;
    
        xkb= xkbi->desc;
        if (XkbAllocIndicatorMaps(xkb)!=Success)
    	return BadAlloc;
    
        if (!(xkb->defined & XkmIndicatorsMask)) {
            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)
    {
    XkbDescPtr	xkb;
    XkbControlsPtr	ctrls;
    
        xkb= xkbi->desc;
        /* 12/31/94 (ef) -- XXX! Should check if controls loaded from file */
        if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success)
    	FatalError("Couldn't allocate keyboard controls\n");
        ctrls= xkb->ctrls;
        if (!(xkb->defined & XkmSymbolsMask))
            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;
    }
    
    _X_EXPORT Bool
    InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet *rmlvo,
                             BellProcPtr bell_func, KbdCtrlProcPtr ctrl_func)
    {
        int	i;
        unsigned int check;
        XkbSrvInfoPtr xkbi;
        XkbDescPtr xkb;
        XkbSrvLedInfoPtr sli;
        XkbChangesRec changes;
        XkbEventCauseRec cause;
        XkbRMLVOSet rmlvo_dflts = { NULL };
    
        if (dev->key || dev->kbdfeed)
    	return FALSE;
    
        if (!rmlvo)
        {
            rmlvo = &rmlvo_dflts;
            XkbGetRulesDflts(rmlvo);
        }
    
    
        memset(&changes, 0, sizeof(changes));
        XkbSetCauseUnknown(&cause);
    
        dev->key = xcalloc(1, sizeof(*dev->key));
        if (!dev->key) {
            ErrorF("XKB: Failed to allocate key class\n");
            return FALSE;
        }
        dev->key->sourceid = dev->id;
    
        dev->kbdfeed = xcalloc(1, sizeof(*dev->kbdfeed));
        if (!dev->kbdfeed) {
            ErrorF("XKB: Failed to allocate key feedback class\n");
            goto unwind_key;
        }
    
        xkbi = xcalloc(1, sizeof(*xkbi));
        if (!xkbi) {
            ErrorF("XKB: Failed to allocate XKB info\n");
            goto unwind_kbdfeed;
        }
        dev->key->xkbInfo = xkbi;
    
        if (xkb_cached_map && !XkbCompareUsedRMLVO(rmlvo)) {
            XkbFreeKeyboard(xkb_cached_map, XkbAllComponentsMask, TRUE);
            xkb_cached_map = NULL;
        }
    
        if (xkb_cached_map)
            LogMessageVerb(X_INFO, 4, "XKB: Reusing cached keymap\n");
        else {
            xkb_cached_map = XkbCompileKeymap(dev, rmlvo);
            if (!xkb_cached_map) {
                ErrorF("XKB: Failed to compile keymap\n");
                goto unwind_info;
            }
        }
    
        xkb = XkbAllocKeyboard();
        if (!xkb) {
            ErrorF("XKB: Failed to allocate keyboard description\n");
            goto unwind_info;
        }
    
        if (!XkbCopyKeymap(xkb, xkb_cached_map)) {
            ErrorF("XKB: Failed to copy keymap\n");
            goto unwind_desc;
        }
        xkb->defined = xkb_cached_map->defined;
        xkb->flags = xkb_cached_map->flags;
        xkb->device_spec = xkb_cached_map->device_spec;
        xkbi->desc = xkb;
    
        if (xkb->min_key_code == 0)
            xkb->min_key_code = 8;
        if (xkb->max_key_code == 0)
            xkb->max_key_code = 255;
    
        i = XkbNumKeys(xkb) / 3 + 1;
        if (XkbAllocClientMap(xkb, XkbAllClientInfoMask, 0) != Success)
            goto unwind_desc;
        if (XkbAllocServerMap(xkb, XkbAllServerInfoMask, i) != Success)
            goto unwind_desc;
    
        xkbi->dfltPtrDelta = 1;
        xkbi->device = dev;
    
        XkbInitSemantics(xkb);
        XkbInitNames(xkbi);
        XkbInitRadioGroups(xkbi);
    
        XkbInitControls(dev, xkbi);
    
        XkbInitIndicatorMap(xkbi);
    
        XkbUpdateActions(dev, xkb->min_key_code, XkbNumKeys(xkb), &changes,
                         &check, &cause);
    
        InitFocusClassDeviceStruct(dev);
    
        xkbi->kbdProc = ctrl_func;
        dev->kbdfeed->BellProc = bell_func;
        dev->kbdfeed->CtrlProc = XkbDDXKeybdCtrlProc;
    
        dev->kbdfeed->ctrl = defaultKeyboardControl;
        if (dev->kbdfeed->ctrl.autoRepeat)
            xkb->ctrls->enabled_ctrls |= XkbRepeatKeysMask;
    
        memcpy(dev->kbdfeed->ctrl.autoRepeats, xkb->ctrls->per_key_repeat,
               XkbPerKeyBitArraySize);
    
        sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 0);
        if (sli)
    	XkbCheckIndicatorMaps(dev, sli, XkbAllIndicatorsMask);
        else
            DebugF("XKB: No indicator feedback in XkbFinishInit!\n");
    
        dev->kbdfeed->CtrlProc(dev,&dev->kbdfeed->ctrl);
    
        XkbSetRulesDflts(rmlvo);
        XkbSetRulesUsed(rmlvo);
        XkbFreeRMLVOSet(&rmlvo_dflts, FALSE);
    
        return TRUE;
    
    unwind_desc:
        XkbFreeKeyboard(xkb, 0, TRUE);
    unwind_info:
        xfree(xkbi);
        dev->key->xkbInfo = NULL;
    unwind_kbdfeed:
        xfree(dev->kbdfeed);
        dev->kbdfeed = NULL;
    unwind_key:
        xfree(dev->key);
        dev->key = NULL;
        return FALSE;
    }
    
    
    /***====================================================================***/
    
    	/*
    	 * Be very careful about what does and doesn't get freed by this 
    	 * function.  To reduce fragmentation, XkbInitDevice allocates a 
    	 * single huge block per device and divides it up into most of the 
    	 * fixed-size structures for the device.   Don't free anything that
    	 * is part of this larger block.
    	 */
    void
    XkbFreeInfo(XkbSrvInfoPtr xkbi)
    {
        if (xkbi->radioGroups) {
    	xfree(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;
        }
        xfree(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 (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])) ) {
    		    /*
    		     * presumption that the reasonably useful range of
    		     * values fits in 0..MAXINT since SunOS 4 doesn't
    		     * have strtoul.
    		     */
    		    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)) {	/* -ardelay int */
    	if (++i >= argc) UseMsg ();
    	XkbDfltRepeatDelay = (long)atoi(argv[i]);
    	return 2;
        }
        if ((strcmp(argv[i], "-arinterval") == 0) ||
            (strcmp (argv[i], "-ar2") == 0)) {	/* -arinterval int */
    	if (++i >= argc) UseMsg ();
    	XkbDfltRepeatInterval = (long)atoi(argv[i]);
    	return 2;
        }
        return 0;
    }
    
    void
    XkbUseMsg(void)
    {
        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");
    }