xkbInit.c revision 05b261ec
105b261ecSmrg/************************************************************
205b261ecSmrgCopyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
305b261ecSmrg
405b261ecSmrgPermission to use, copy, modify, and distribute this
505b261ecSmrgsoftware and its documentation for any purpose and without
605b261ecSmrgfee is hereby granted, provided that the above copyright
705b261ecSmrgnotice appear in all copies and that both that copyright
805b261ecSmrgnotice and this permission notice appear in supporting
905b261ecSmrgdocumentation, and that the name of Silicon Graphics not be
1005b261ecSmrgused in advertising or publicity pertaining to distribution
1105b261ecSmrgof the software without specific prior written permission.
1205b261ecSmrgSilicon Graphics makes no representation about the suitability
1305b261ecSmrgof this software for any purpose. It is provided "as is"
1405b261ecSmrgwithout any express or implied warranty.
1505b261ecSmrg
1605b261ecSmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
1705b261ecSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1805b261ecSmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
1905b261ecSmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
2005b261ecSmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
2105b261ecSmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
2205b261ecSmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
2305b261ecSmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE.
2405b261ecSmrg
2505b261ecSmrg********************************************************/
2605b261ecSmrg
2705b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
2805b261ecSmrg#include <dix-config.h>
2905b261ecSmrg#endif
3005b261ecSmrg
3105b261ecSmrg#ifdef HAVE_XKB_CONFIG_H
3205b261ecSmrg#include <xkb-config.h>
3305b261ecSmrg#endif
3405b261ecSmrg
3505b261ecSmrg#include <stdio.h>
3605b261ecSmrg#include <stdlib.h>
3705b261ecSmrg#include <ctype.h>
3805b261ecSmrg#include <unistd.h>
3905b261ecSmrg#include <math.h>
4005b261ecSmrg#define NEED_EVENTS 1
4105b261ecSmrg#include <X11/X.h>
4205b261ecSmrg#include <X11/Xproto.h>
4305b261ecSmrg#include <X11/keysym.h>
4405b261ecSmrg#include <X11/Xatom.h>
4505b261ecSmrg#include "misc.h"
4605b261ecSmrg#include "inputstr.h"
4705b261ecSmrg#include "opaque.h"
4805b261ecSmrg#include "property.h"
4905b261ecSmrg#define	XKBSRV_NEED_FILE_FUNCS
5005b261ecSmrg#include <xkbsrv.h>
5105b261ecSmrg#include <X11/extensions/XKBgeom.h>
5205b261ecSmrg#include <X11/extensions/XKMformat.h>
5305b261ecSmrg#include <X11/extensions/XKBfile.h>
5405b261ecSmrg#include "xkb.h"
5505b261ecSmrg
5605b261ecSmrg#define	CREATE_ATOM(s)	MakeAtom(s,sizeof(s)-1,1)
5705b261ecSmrg
5805b261ecSmrg#ifdef sgi
5905b261ecSmrg#define LED_CAPS	5
6005b261ecSmrg#define	LED_NUM		6
6105b261ecSmrg#define	LED_SCROLL	7
6205b261ecSmrg#define	PHYS_LEDS	0x7f
6305b261ecSmrg#define	LED_COMPOSE	8
6405b261ecSmrg#else
6505b261ecSmrg#if defined(ultrix) || defined(__osf__) || defined(__alpha) || defined(__alpha__)
6605b261ecSmrg#define	LED_COMPOSE	2
6705b261ecSmrg#define LED_CAPS	3
6805b261ecSmrg#define	LED_SCROLL	4
6905b261ecSmrg#define	LED_NUM		5
7005b261ecSmrg#define	PHYS_LEDS	0x1f
7105b261ecSmrg#else
7205b261ecSmrg#ifdef sun
7305b261ecSmrg#define LED_NUM		1
7405b261ecSmrg#define	LED_SCROLL	2
7505b261ecSmrg#define	LED_COMPOSE	3
7605b261ecSmrg#define LED_CAPS	4
7705b261ecSmrg#define	PHYS_LEDS	0x0f
7805b261ecSmrg#else
7905b261ecSmrg#define	LED_CAPS	1
8005b261ecSmrg#define	LED_NUM		2
8105b261ecSmrg#define	LED_SCROLL	3
8205b261ecSmrg#define	PHYS_LEDS	0x07
8305b261ecSmrg#endif
8405b261ecSmrg#endif
8505b261ecSmrg#endif
8605b261ecSmrg
8705b261ecSmrg#define	MAX_TOC	16
8805b261ecSmrgtypedef struct	_SrvXkmInfo {
8905b261ecSmrg	DeviceIntPtr	dev;
9005b261ecSmrg	FILE *		file;
9105b261ecSmrg	XkbFileInfo	xkbinfo;
9205b261ecSmrg} SrvXkmInfo;
9305b261ecSmrg
9405b261ecSmrg
9505b261ecSmrg/***====================================================================***/
9605b261ecSmrg
9705b261ecSmrg#ifndef XKB_BASE_DIRECTORY
9805b261ecSmrg#define	XKB_BASE_DIRECTORY	"/usr/lib/X11/xkb"
9905b261ecSmrg#endif
10005b261ecSmrg#ifndef XKB_BIN_DIRECTORY
10105b261ecSmrg#define	XKB_BIN_DIRECTORY	XKB_BASE_DIRECTORY
10205b261ecSmrg#endif
10305b261ecSmrg#ifndef XKB_DFLT_RULES_FILE
10405b261ecSmrg#define	XKB_DFLT_RULES_FILE	"rules"
10505b261ecSmrg#endif
10605b261ecSmrg#ifndef XKB_DFLT_KB_LAYOUT
10705b261ecSmrg#define	XKB_DFLT_KB_LAYOUT	"us"
10805b261ecSmrg#endif
10905b261ecSmrg#ifndef XKB_DFLT_KB_MODEL
11005b261ecSmrg#define	XKB_DFLT_KB_MODEL	"dflt"
11105b261ecSmrg#endif
11205b261ecSmrg#ifndef XKB_DFLT_KB_VARIANT
11305b261ecSmrg#define	XKB_DFLT_KB_VARIANT	NULL
11405b261ecSmrg#endif
11505b261ecSmrg#ifndef XKB_DFLT_KB_OPTIONS
11605b261ecSmrg#define	XKB_DFLT_KB_OPTIONS	NULL
11705b261ecSmrg#endif
11805b261ecSmrg#ifndef XKB_DFLT_DISABLED
11905b261ecSmrg#define	XKB_DFLT_DISABLED	True
12005b261ecSmrg#endif
12105b261ecSmrg#ifndef XKB_DFLT_RULES_PROP
12205b261ecSmrg#define	XKB_DFLT_RULES_PROP	True
12305b261ecSmrg#endif
12405b261ecSmrg
12505b261ecSmrgchar	*		XkbBaseDirectory=	XKB_BASE_DIRECTORY;
12605b261ecSmrgchar	*		XkbBinDirectory=	XKB_BIN_DIRECTORY;
12705b261ecSmrgstatic int	 	XkbWantAccessX=		0;
12805b261ecSmrgstatic XkbFileInfo *	_XkbInitFileInfo=	NULL;
12905b261ecSmrg
13005b261ecSmrgstatic Bool		rulesDefined=		False;
13105b261ecSmrgstatic char *		XkbRulesFile=		NULL;
13205b261ecSmrgstatic char *		XkbModelDflt=		NULL;
13305b261ecSmrgstatic char *		XkbLayoutDflt=		NULL;
13405b261ecSmrgstatic char *		XkbVariantDflt=		NULL;
13505b261ecSmrgstatic char *		XkbOptionsDflt=		NULL;
13605b261ecSmrg
13705b261ecSmrgstatic char *		XkbModelUsed=	NULL;
13805b261ecSmrgstatic char *		XkbLayoutUsed=	NULL;
13905b261ecSmrgstatic char *		XkbVariantUsed=	NULL;
14005b261ecSmrgstatic char *		XkbOptionsUsed=	NULL;
14105b261ecSmrg
14205b261ecSmrg_X_EXPORT Bool		noXkbExtension=		XKB_DFLT_DISABLED;
14305b261ecSmrgstatic Bool		XkbWantRulesProp=	XKB_DFLT_RULES_PROP;
14405b261ecSmrg
14505b261ecSmrg/***====================================================================***/
14605b261ecSmrg
14705b261ecSmrgstatic char *
14805b261ecSmrgXkbGetRulesDflts(XkbRF_VarDefsPtr defs)
14905b261ecSmrg{
15005b261ecSmrg    if (XkbModelDflt)	defs->model= XkbModelDflt;
15105b261ecSmrg    else		defs->model= XKB_DFLT_KB_MODEL;
15205b261ecSmrg    if (XkbLayoutDflt)	defs->layout= XkbLayoutDflt;
15305b261ecSmrg    else		defs->layout= XKB_DFLT_KB_LAYOUT;
15405b261ecSmrg    if (XkbVariantDflt)	defs->variant= XkbVariantDflt;
15505b261ecSmrg    else		defs->variant= XKB_DFLT_KB_VARIANT;
15605b261ecSmrg    if (XkbOptionsDflt)	defs->options= XkbOptionsDflt;
15705b261ecSmrg    else		defs->options= XKB_DFLT_KB_OPTIONS;
15805b261ecSmrg    return (rulesDefined?XkbRulesFile:XKB_DFLT_RULES_FILE);
15905b261ecSmrg}
16005b261ecSmrg
16105b261ecSmrgstatic Bool
16205b261ecSmrgXkbWriteRulesProp(ClientPtr client, pointer closure)
16305b261ecSmrg{
16405b261ecSmrgint 			len,out;
16505b261ecSmrgAtom			name;
16605b261ecSmrgchar *			pval;
16705b261ecSmrg
16805b261ecSmrg    if (rulesDefined && (!XkbRulesFile))
16905b261ecSmrg	return False;
17005b261ecSmrg    len= (XkbRulesFile?strlen(XkbRulesFile):strlen(XKB_DFLT_RULES_FILE));
17105b261ecSmrg    len+= (XkbModelUsed?strlen(XkbModelUsed):0);
17205b261ecSmrg    len+= (XkbLayoutUsed?strlen(XkbLayoutUsed):0);
17305b261ecSmrg    len+= (XkbVariantUsed?strlen(XkbVariantUsed):0);
17405b261ecSmrg    len+= (XkbOptionsUsed?strlen(XkbOptionsUsed):0);
17505b261ecSmrg    if (len<1)
17605b261ecSmrg	return True;
17705b261ecSmrg
17805b261ecSmrg    len+= 5; /* trailing NULs */
17905b261ecSmrg
18005b261ecSmrg    name= MakeAtom(_XKB_RF_NAMES_PROP_ATOM,strlen(_XKB_RF_NAMES_PROP_ATOM),1);
18105b261ecSmrg    if (name==None) {
18205b261ecSmrg	ErrorF("Atom error: %s not created\n",_XKB_RF_NAMES_PROP_ATOM);
18305b261ecSmrg	return True;
18405b261ecSmrg    }
18505b261ecSmrg    pval= (char*) ALLOCATE_LOCAL(len);
18605b261ecSmrg    if (!pval) {
18705b261ecSmrg	ErrorF("Allocation error: %s proprerty not created\n",
18805b261ecSmrg						_XKB_RF_NAMES_PROP_ATOM);
18905b261ecSmrg	return True;
19005b261ecSmrg    }
19105b261ecSmrg    out= 0;
19205b261ecSmrg    if (XkbRulesFile) {
19305b261ecSmrg	strcpy(&pval[out],XkbRulesFile);
19405b261ecSmrg	out+= strlen(XkbRulesFile);
19505b261ecSmrg    } else {
19605b261ecSmrg	strcpy(&pval[out],XKB_DFLT_RULES_FILE);
19705b261ecSmrg	out+= strlen(XKB_DFLT_RULES_FILE);
19805b261ecSmrg    }
19905b261ecSmrg    pval[out++]= '\0';
20005b261ecSmrg    if (XkbModelUsed) {
20105b261ecSmrg	strcpy(&pval[out],XkbModelUsed);
20205b261ecSmrg	out+= strlen(XkbModelUsed);
20305b261ecSmrg    }
20405b261ecSmrg    pval[out++]= '\0';
20505b261ecSmrg    if (XkbLayoutUsed) {
20605b261ecSmrg	strcpy(&pval[out],XkbLayoutUsed);
20705b261ecSmrg	out+= strlen(XkbLayoutUsed);
20805b261ecSmrg    }
20905b261ecSmrg    pval[out++]= '\0';
21005b261ecSmrg    if (XkbVariantUsed) {
21105b261ecSmrg	strcpy(&pval[out],XkbVariantUsed);
21205b261ecSmrg	out+= strlen(XkbVariantUsed);
21305b261ecSmrg    }
21405b261ecSmrg    pval[out++]= '\0';
21505b261ecSmrg    if (XkbOptionsUsed) {
21605b261ecSmrg	strcpy(&pval[out],XkbOptionsUsed);
21705b261ecSmrg	out+= strlen(XkbOptionsUsed);
21805b261ecSmrg    }
21905b261ecSmrg    pval[out++]= '\0';
22005b261ecSmrg    if (out!=len) {
22105b261ecSmrg	ErrorF("Internal Error! bad size (%d!=%d) for _XKB_RULES_NAMES\n",
22205b261ecSmrg								out,len);
22305b261ecSmrg    }
22405b261ecSmrg    ChangeWindowProperty(WindowTable[0],name,XA_STRING,8,PropModeReplace,
22505b261ecSmrg							len,pval,True);
22605b261ecSmrg    DEALLOCATE_LOCAL(pval);
22705b261ecSmrg    return True;
22805b261ecSmrg}
22905b261ecSmrg
23005b261ecSmrgstatic void
23105b261ecSmrgXkbSetRulesUsed(XkbRF_VarDefsPtr defs)
23205b261ecSmrg{
23305b261ecSmrg    if (XkbModelUsed)
23405b261ecSmrg	_XkbFree(XkbModelUsed);
23505b261ecSmrg    XkbModelUsed= (defs->model?_XkbDupString(defs->model):NULL);
23605b261ecSmrg    if (XkbLayoutUsed)
23705b261ecSmrg	_XkbFree(XkbLayoutUsed);
23805b261ecSmrg    XkbLayoutUsed= (defs->layout?_XkbDupString(defs->layout):NULL);
23905b261ecSmrg    if (XkbVariantUsed)
24005b261ecSmrg	_XkbFree(XkbVariantUsed);
24105b261ecSmrg    XkbVariantUsed= (defs->variant?_XkbDupString(defs->variant):NULL);
24205b261ecSmrg    if (XkbOptionsUsed)
24305b261ecSmrg	_XkbFree(XkbOptionsUsed);
24405b261ecSmrg    XkbOptionsUsed= (defs->options?_XkbDupString(defs->options):NULL);
24505b261ecSmrg    if (XkbWantRulesProp)
24605b261ecSmrg	QueueWorkProc(XkbWriteRulesProp,NULL,NULL);
24705b261ecSmrg    return;
24805b261ecSmrg}
24905b261ecSmrg
25005b261ecSmrg_X_EXPORT void
25105b261ecSmrgXkbSetRulesDflts(char *rulesFile,char *model,char *layout,
25205b261ecSmrg					char *variant,char *options)
25305b261ecSmrg{
25405b261ecSmrg    if (XkbRulesFile)
25505b261ecSmrg	_XkbFree(XkbRulesFile);
25605b261ecSmrg    XkbRulesFile= _XkbDupString(rulesFile);
25705b261ecSmrg    rulesDefined= True;
25805b261ecSmrg    if (model) {
25905b261ecSmrg	if (XkbModelDflt)
26005b261ecSmrg	    _XkbFree(XkbModelDflt);
26105b261ecSmrg	XkbModelDflt= _XkbDupString(model);
26205b261ecSmrg    }
26305b261ecSmrg    if (layout) {
26405b261ecSmrg	if (XkbLayoutDflt)
26505b261ecSmrg	    _XkbFree(XkbLayoutDflt);
26605b261ecSmrg	XkbLayoutDflt= _XkbDupString(layout);
26705b261ecSmrg    }
26805b261ecSmrg    if (variant) {
26905b261ecSmrg	if (XkbVariantDflt)
27005b261ecSmrg	    _XkbFree(XkbVariantDflt);
27105b261ecSmrg	XkbVariantDflt= _XkbDupString(variant);
27205b261ecSmrg    }
27305b261ecSmrg    if (options) {
27405b261ecSmrg	if (XkbOptionsDflt)
27505b261ecSmrg	    _XkbFree(XkbOptionsDflt);
27605b261ecSmrg	XkbOptionsDflt= _XkbDupString(options);
27705b261ecSmrg    }
27805b261ecSmrg    return;
27905b261ecSmrg}
28005b261ecSmrg
28105b261ecSmrg/***====================================================================***/
28205b261ecSmrg
28305b261ecSmrg#if defined(luna)
28405b261ecSmrg#define	XKB_DDX_PERMANENT_LOCK	1
28505b261ecSmrg#endif
28605b261ecSmrg
28705b261ecSmrg#include "xkbDflts.h"
28805b261ecSmrg
28905b261ecSmrgstatic Bool
29005b261ecSmrgXkbInitKeyTypes(XkbDescPtr xkb,SrvXkmInfo *file)
29105b261ecSmrg{
29205b261ecSmrg    if (file->xkbinfo.defined&XkmTypesMask)
29305b261ecSmrg	return True;
29405b261ecSmrg    initTypeNames(NULL);
29505b261ecSmrg    if (XkbAllocClientMap(xkb,XkbKeyTypesMask,num_dflt_types)!=Success)
29605b261ecSmrg	return False;
29705b261ecSmrg    if (XkbCopyKeyTypes(dflt_types,xkb->map->types,num_dflt_types)!=
29805b261ecSmrg    								 Success) {
29905b261ecSmrg	return False;
30005b261ecSmrg    }
30105b261ecSmrg    xkb->map->size_types= xkb->map->num_types= num_dflt_types;
30205b261ecSmrg    return True;
30305b261ecSmrg}
30405b261ecSmrg
30505b261ecSmrgstatic void
30605b261ecSmrgXkbInitRadioGroups(XkbSrvInfoPtr xkbi,SrvXkmInfo *file)
30705b261ecSmrg{
30805b261ecSmrg    xkbi->nRadioGroups = 0;
30905b261ecSmrg    xkbi->radioGroups = NULL;
31005b261ecSmrg    return;
31105b261ecSmrg}
31205b261ecSmrg
31305b261ecSmrg
31405b261ecSmrgstatic Status
31505b261ecSmrgXkbInitCompatStructs(XkbDescPtr xkb,SrvXkmInfo *file)
31605b261ecSmrg{
31705b261ecSmrgregister int 	i;
31805b261ecSmrgXkbCompatMapPtr	compat;
31905b261ecSmrg
32005b261ecSmrg    if (file->xkbinfo.defined&XkmCompatMapMask)
32105b261ecSmrg	return Success;
32205b261ecSmrg    if (XkbAllocCompatMap(xkb,XkbAllCompatMask,num_dfltSI)!=Success)
32305b261ecSmrg	return BadAlloc;
32405b261ecSmrg    compat = xkb->compat;
32505b261ecSmrg    if (compat->sym_interpret) {
32605b261ecSmrg	compat->num_si = num_dfltSI;
32705b261ecSmrg	memcpy((char *)compat->sym_interpret,(char *)dfltSI,sizeof(dfltSI));
32805b261ecSmrg    }
32905b261ecSmrg    for (i=0;i<XkbNumKbdGroups;i++) {
33005b261ecSmrg	compat->groups[i]= compatMap.groups[i];
33105b261ecSmrg	if (compat->groups[i].vmods!=0) {
33205b261ecSmrg	    unsigned mask;
33305b261ecSmrg	    mask= XkbMaskForVMask(xkb,compat->groups[i].vmods);
33405b261ecSmrg	    compat->groups[i].mask= compat->groups[i].real_mods|mask;
33505b261ecSmrg	}
33605b261ecSmrg	else compat->groups[i].mask= compat->groups[i].real_mods;
33705b261ecSmrg    }
33805b261ecSmrg    return Success;
33905b261ecSmrg}
34005b261ecSmrg
34105b261ecSmrgstatic void
34205b261ecSmrgXkbInitSemantics(XkbDescPtr xkb,SrvXkmInfo *file)
34305b261ecSmrg{
34405b261ecSmrg    XkbInitKeyTypes(xkb,file);
34505b261ecSmrg    XkbInitCompatStructs(xkb,file);
34605b261ecSmrg    return;
34705b261ecSmrg}
34805b261ecSmrg
34905b261ecSmrg/***====================================================================***/
35005b261ecSmrg
35105b261ecSmrgstatic Status
35205b261ecSmrgXkbInitNames(XkbSrvInfoPtr xkbi,SrvXkmInfo *file)
35305b261ecSmrg{
35405b261ecSmrgXkbDescPtr	xkb;
35505b261ecSmrgXkbNamesPtr	names;
35605b261ecSmrgStatus		rtrn;
35705b261ecSmrgAtom		unknown;
35805b261ecSmrg
35905b261ecSmrg    xkb= xkbi->desc;
36005b261ecSmrg    if ((rtrn=XkbAllocNames(xkb,XkbAllNamesMask,0,0))!=Success)
36105b261ecSmrg	return rtrn;
36205b261ecSmrg    unknown= CREATE_ATOM("unknown");
36305b261ecSmrg    names = xkb->names;
36405b261ecSmrg    if (names->keycodes==None)		names->keycodes= unknown;
36505b261ecSmrg    if (names->geometry==None)		names->geometry= unknown;
36605b261ecSmrg    if (names->phys_symbols==None)	names->phys_symbols= unknown;
36705b261ecSmrg    if (names->symbols==None)		names->symbols= unknown;
36805b261ecSmrg    if (names->types==None)		names->types= unknown;
36905b261ecSmrg    if (names->compat==None)		names->compat= unknown;
37005b261ecSmrg    if ((file->xkbinfo.defined&XkmVirtualModsMask)==0) {
37105b261ecSmrg	if (names->vmods[vmod_NumLock]==None)
37205b261ecSmrg	    names->vmods[vmod_NumLock]= CREATE_ATOM("NumLock");
37305b261ecSmrg	if (names->vmods[vmod_Alt]==None)
37405b261ecSmrg	    names->vmods[vmod_Alt]= CREATE_ATOM("Alt");
37505b261ecSmrg	if (names->vmods[vmod_AltGr]==None)
37605b261ecSmrg	    names->vmods[vmod_AltGr]= CREATE_ATOM("ModeSwitch");
37705b261ecSmrg    }
37805b261ecSmrg
37905b261ecSmrg    if (((file->xkbinfo.defined&XkmIndicatorsMask)==0)||
38005b261ecSmrg	((file->xkbinfo.defined&XkmGeometryMask)==0)) {
38105b261ecSmrg	initIndicatorNames(NULL,xkb);
38205b261ecSmrg	if (names->indicators[LED_CAPS-1]==None)
38305b261ecSmrg	    names->indicators[LED_CAPS-1] = CREATE_ATOM("Caps Lock");
38405b261ecSmrg	if (names->indicators[LED_NUM-1]==None)
38505b261ecSmrg	    names->indicators[LED_NUM-1] = CREATE_ATOM("Num Lock");
38605b261ecSmrg	if (names->indicators[LED_SCROLL-1]==None)
38705b261ecSmrg	    names->indicators[LED_SCROLL-1] = CREATE_ATOM("Scroll Lock");
38805b261ecSmrg#ifdef LED_COMPOSE
38905b261ecSmrg	if (names->indicators[LED_COMPOSE-1]==None)
39005b261ecSmrg	    names->indicators[LED_COMPOSE-1] = CREATE_ATOM("Compose");
39105b261ecSmrg#endif
39205b261ecSmrg    }
39305b261ecSmrg#ifdef DEBUG_RADIO_GROUPS
39405b261ecSmrg    if (names->num_rg<1) {
39505b261ecSmrg	names->radio_groups= (Atom *)_XkbCalloc(RG_COUNT, sizeof(Atom));
39605b261ecSmrg	if (names->radio_groups) {
39705b261ecSmrg	    names->num_rg = RG_COUNT;
39805b261ecSmrg	    names->radio_groups[RG_BOGUS_FUNCTION_GROUP]= CREATE_ATOM("BOGUS");
39905b261ecSmrg	}
40005b261ecSmrg    }
40105b261ecSmrg#endif
40205b261ecSmrg    if (xkb->geom!=NULL)
40305b261ecSmrg	 names->geometry= xkb->geom->name;
40405b261ecSmrg    else names->geometry= unknown;
40505b261ecSmrg    return Success;
40605b261ecSmrg}
40705b261ecSmrg
40805b261ecSmrgstatic Status
40905b261ecSmrgXkbInitIndicatorMap(XkbSrvInfoPtr xkbi,SrvXkmInfo *file)
41005b261ecSmrg{
41105b261ecSmrgXkbDescPtr		xkb;
41205b261ecSmrgXkbIndicatorPtr		map;
41305b261ecSmrgXkbSrvLedInfoPtr	sli;
41405b261ecSmrg
41505b261ecSmrg    xkb= xkbi->desc;
41605b261ecSmrg    if (XkbAllocIndicatorMaps(xkb)!=Success)
41705b261ecSmrg	return BadAlloc;
41805b261ecSmrg    if ((file->xkbinfo.defined&XkmIndicatorsMask)==0) {
41905b261ecSmrg	map= xkb->indicators;
42005b261ecSmrg	map->phys_indicators = PHYS_LEDS;
42105b261ecSmrg	map->maps[LED_CAPS-1].flags= XkbIM_NoExplicit;
42205b261ecSmrg	map->maps[LED_CAPS-1].which_mods= XkbIM_UseLocked;
42305b261ecSmrg	map->maps[LED_CAPS-1].mods.mask= LockMask;
42405b261ecSmrg	map->maps[LED_CAPS-1].mods.real_mods= LockMask;
42505b261ecSmrg
42605b261ecSmrg	map->maps[LED_NUM-1].flags= XkbIM_NoExplicit;
42705b261ecSmrg	map->maps[LED_NUM-1].which_mods= XkbIM_UseLocked;
42805b261ecSmrg	map->maps[LED_NUM-1].mods.mask= 0;
42905b261ecSmrg	map->maps[LED_NUM-1].mods.real_mods= 0;
43005b261ecSmrg	map->maps[LED_NUM-1].mods.vmods= vmod_NumLockMask;
43105b261ecSmrg
43205b261ecSmrg/* Metro Link */
43305b261ecSmrg	map->maps[LED_SCROLL-1].flags= XkbIM_NoExplicit;
43405b261ecSmrg	map->maps[LED_SCROLL-1].which_mods= XkbIM_UseLocked;
43505b261ecSmrg	map->maps[LED_SCROLL-1].mods.mask= Mod3Mask;
43605b261ecSmrg	map->maps[LED_SCROLL-1].mods.real_mods= Mod3Mask;
43705b261ecSmrg/* Metro Link */
43805b261ecSmrg    }
43905b261ecSmrg    sli= XkbFindSrvLedInfo(xkbi->device,XkbDfltXIClass,XkbDfltXIId,0);
44005b261ecSmrg    if (sli)
44105b261ecSmrg	XkbCheckIndicatorMaps(xkbi->device,sli,XkbAllIndicatorsMask);
44205b261ecSmrg    return Success;
44305b261ecSmrg}
44405b261ecSmrg
44505b261ecSmrgstatic Status
44605b261ecSmrgXkbInitControls(DeviceIntPtr pXDev,XkbSrvInfoPtr xkbi,SrvXkmInfo *file)
44705b261ecSmrg{
44805b261ecSmrgXkbDescPtr	xkb;
44905b261ecSmrgXkbControlsPtr	ctrls;
45005b261ecSmrg
45105b261ecSmrg    xkb= xkbi->desc;
45205b261ecSmrg    /* 12/31/94 (ef) -- XXX! Should check if controls loaded from file */
45305b261ecSmrg    if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success)
45405b261ecSmrg	FatalError("Couldn't allocate keyboard controls\n");
45505b261ecSmrg    ctrls= xkb->ctrls;
45605b261ecSmrg    if ((file->xkbinfo.defined&XkmSymbolsMask)==0)
45705b261ecSmrg	ctrls->num_groups = 1;
45805b261ecSmrg    ctrls->groups_wrap = XkbSetGroupInfo(1,XkbWrapIntoRange,0);
45905b261ecSmrg    ctrls->internal.mask = 0;
46005b261ecSmrg    ctrls->internal.real_mods = 0;
46105b261ecSmrg    ctrls->internal.vmods = 0;
46205b261ecSmrg    ctrls->ignore_lock.mask = 0;
46305b261ecSmrg    ctrls->ignore_lock.real_mods = 0;
46405b261ecSmrg    ctrls->ignore_lock.vmods = 0;
46505b261ecSmrg    ctrls->enabled_ctrls = XkbAccessXTimeoutMask|XkbRepeatKeysMask|
46605b261ecSmrg				XkbMouseKeysAccelMask|XkbAudibleBellMask|
46705b261ecSmrg				XkbIgnoreGroupLockMask;
46805b261ecSmrg    if (XkbWantAccessX)
46905b261ecSmrg	ctrls->enabled_ctrls|= XkbAccessXKeysMask;
47005b261ecSmrg    AccessXInit(pXDev);
47105b261ecSmrg    return Success;
47205b261ecSmrg}
47305b261ecSmrg
47405b261ecSmrgvoid
47505b261ecSmrgXkbInitDevice(DeviceIntPtr pXDev)
47605b261ecSmrg{
47705b261ecSmrgint			i;
47805b261ecSmrgXkbSrvInfoPtr		xkbi;
47905b261ecSmrgXkbChangesRec		changes;
48005b261ecSmrgSrvXkmInfo		file;
48105b261ecSmrgunsigned		check;
48205b261ecSmrgXkbEventCauseRec	cause;
48305b261ecSmrg
48405b261ecSmrg    file.dev= pXDev;
48505b261ecSmrg    file.file=NULL;
48605b261ecSmrg    bzero(&file.xkbinfo,sizeof(XkbFileInfo));
48705b261ecSmrg    bzero(&changes,sizeof(XkbChangesRec));
48805b261ecSmrg    pXDev->key->xkbInfo= xkbi= _XkbTypedCalloc(1,XkbSrvInfoRec);
48905b261ecSmrg    if ( xkbi ) {
49005b261ecSmrg	XkbDescPtr	xkb;
49105b261ecSmrg	if ((_XkbInitFileInfo!=NULL)&&(_XkbInitFileInfo->xkb!=NULL)) {
49205b261ecSmrg	    file.xkbinfo= *_XkbInitFileInfo;
49305b261ecSmrg	    xkbi->desc= _XkbInitFileInfo->xkb;
49405b261ecSmrg	    _XkbInitFileInfo= NULL;
49505b261ecSmrg	}
49605b261ecSmrg	else {
49705b261ecSmrg	    xkbi->desc= XkbAllocKeyboard();
49805b261ecSmrg	    if (!xkbi->desc)
49905b261ecSmrg		FatalError("Couldn't allocate keyboard description\n");
50005b261ecSmrg	    xkbi->desc->min_key_code = pXDev->key->curKeySyms.minKeyCode;
50105b261ecSmrg	    xkbi->desc->max_key_code = pXDev->key->curKeySyms.maxKeyCode;
50205b261ecSmrg	}
50305b261ecSmrg	xkb= xkbi->desc;
50405b261ecSmrg	if (xkb->min_key_code == 0)
50505b261ecSmrg	    xkb->min_key_code = pXDev->key->curKeySyms.minKeyCode;
50605b261ecSmrg	if (xkb->max_key_code == 0)
50705b261ecSmrg	    xkb->max_key_code = pXDev->key->curKeySyms.maxKeyCode;
50805b261ecSmrg	if ((pXDev->key->curKeySyms.minKeyCode!=xkbi->desc->min_key_code)||
50905b261ecSmrg	    (pXDev->key->curKeySyms.maxKeyCode!=xkbi->desc->max_key_code)) {
51005b261ecSmrg	    /* 12/9/95 (ef) -- XXX! Maybe we should try to fix up one or */
51105b261ecSmrg	    /*                 the other here, but for now just complain */
51205b261ecSmrg	    /*                 can't just update the core range without */
51305b261ecSmrg	    /*                 reallocating the KeySymsRec (pain)       */
51405b261ecSmrg	    ErrorF("Internal Error!! XKB and core keymap have different range\n");
51505b261ecSmrg	}
51605b261ecSmrg	if (XkbAllocClientMap(xkb,XkbAllClientInfoMask,0)!=Success)
51705b261ecSmrg	    FatalError("Couldn't allocate client map in XkbInitDevice\n");
51805b261ecSmrg	i= XkbNumKeys(xkb)/3+1;
51905b261ecSmrg	if (XkbAllocServerMap(xkb,XkbAllServerInfoMask,i)!=Success)
52005b261ecSmrg	    FatalError("Couldn't allocate server map in XkbInitDevice\n");
52105b261ecSmrg
52205b261ecSmrg	xkbi->dfltPtrDelta=1;
52305b261ecSmrg	xkbi->device = pXDev;
52405b261ecSmrg
52505b261ecSmrg	file.xkbinfo.xkb= xkb;
52605b261ecSmrg	XkbInitSemantics(xkb,&file);
52705b261ecSmrg	XkbInitNames(xkbi,&file);
52805b261ecSmrg	XkbInitRadioGroups(xkbi,&file);
52905b261ecSmrg
53005b261ecSmrg	/* 12/31/94 (ef) -- XXX! Should check if state loaded from file */
53105b261ecSmrg	bzero(&xkbi->state,sizeof(XkbStateRec));
53205b261ecSmrg
53305b261ecSmrg	XkbInitControls(pXDev,xkbi,&file);
53405b261ecSmrg
53505b261ecSmrg	if (file.xkbinfo.defined&XkmSymbolsMask)
53605b261ecSmrg	   memcpy(pXDev->key->modifierMap,xkb->map->modmap,xkb->max_key_code+1);
53705b261ecSmrg	else
53805b261ecSmrg	   memcpy(xkb->map->modmap,pXDev->key->modifierMap,xkb->max_key_code+1);
53905b261ecSmrg
54005b261ecSmrg	XkbInitIndicatorMap(xkbi,&file);
54105b261ecSmrg
54205b261ecSmrg	XkbDDXInitDevice(pXDev);
54305b261ecSmrg
54405b261ecSmrg	if (!(file.xkbinfo.defined&XkmSymbolsMask)) {
54505b261ecSmrg	    XkbUpdateKeyTypesFromCore(pXDev,xkb->min_key_code,XkbNumKeys(xkb),
54605b261ecSmrg								&changes);
54705b261ecSmrg	}
54805b261ecSmrg	else {
54905b261ecSmrg	    XkbUpdateCoreDescription(pXDev,True);
55005b261ecSmrg	}
55105b261ecSmrg	XkbSetCauseUnknown(&cause);
55205b261ecSmrg	XkbUpdateActions(pXDev,xkb->min_key_code, XkbNumKeys(xkb),&changes,
55305b261ecSmrg								&check,&cause);
55405b261ecSmrg        /* For sanity.  The first time the connection
55505b261ecSmrg         * is opened, the client side min and max are set
55605b261ecSmrg         * using QueryMinMaxKeyCodes() which grabs them
55705b261ecSmrg	 * from pXDev.
55805b261ecSmrg	 */
55905b261ecSmrg	pXDev->key->curKeySyms.minKeyCode = xkb->min_key_code;
56005b261ecSmrg	pXDev->key->curKeySyms.maxKeyCode = xkb->max_key_code;
56105b261ecSmrg    }
56205b261ecSmrg    if (file.file!=NULL)
56305b261ecSmrg	fclose(file.file);
56405b261ecSmrg    return;
56505b261ecSmrg}
56605b261ecSmrg
56705b261ecSmrg#if MAP_LENGTH > XkbMaxKeyCount
56805b261ecSmrg#undef  XkbMaxKeyCount
56905b261ecSmrg#define XkbMaxKeyCount MAP_LENGTH
57005b261ecSmrg#endif
57105b261ecSmrg
57205b261ecSmrg_X_EXPORT Bool
57305b261ecSmrgXkbInitKeyboardDeviceStruct(
57405b261ecSmrg    DeviceIntPtr		dev,
57505b261ecSmrg    XkbComponentNamesPtr	names,
57605b261ecSmrg    KeySymsPtr                  pSymsIn,
57705b261ecSmrg    CARD8                       pModsIn[],
57805b261ecSmrg    void                        (*bellProc)(
57905b261ecSmrg        int /*percent*/,
58005b261ecSmrg        DeviceIntPtr /*device*/,
58105b261ecSmrg        pointer /*ctrl*/,
58205b261ecSmrg        int),
58305b261ecSmrg    void                        (*ctrlProc)(
58405b261ecSmrg        DeviceIntPtr /*device*/,
58505b261ecSmrg        KeybdCtrl * /*ctrl*/))
58605b261ecSmrg{
58705b261ecSmrgXkbFileInfo		finfo;
58805b261ecSmrgKeySymsRec		tmpSyms,*pSyms;
58905b261ecSmrgCARD8			tmpMods[XkbMaxLegalKeyCode+1],*pMods;
59005b261ecSmrgchar			name[PATH_MAX],*rules;
59105b261ecSmrgBool			ok=False;
59205b261ecSmrgXkbRF_VarDefsRec	defs;
59305b261ecSmrg
59405b261ecSmrg    if ((dev->key!=NULL)||(dev->kbdfeed!=NULL))
59505b261ecSmrg	return False;
59605b261ecSmrg    pSyms= pSymsIn;
59705b261ecSmrg    pMods= pModsIn;
59805b261ecSmrg    bzero(&defs,sizeof(XkbRF_VarDefsRec));
59905b261ecSmrg    rules= XkbGetRulesDflts(&defs);
60005b261ecSmrg
60105b261ecSmrg    /*
60205b261ecSmrg     * The strings are duplicated because it is not guaranteed that
60305b261ecSmrg     * they are allocated, or that they are allocated for every server
60405b261ecSmrg     * generation. Eventually they will be freed at the end of this
60505b261ecSmrg     * function.
60605b261ecSmrg     */
60705b261ecSmrg    if (names->keymap) names->keymap = _XkbDupString(names->keymap);
60805b261ecSmrg    if (names->keycodes) names->keycodes = _XkbDupString(names->keycodes);
60905b261ecSmrg    if (names->types) names->types = _XkbDupString(names->types);
61005b261ecSmrg    if (names->compat) names->compat = _XkbDupString(names->compat);
61105b261ecSmrg    if (names->geometry) names->geometry = _XkbDupString(names->geometry);
61205b261ecSmrg    if (names->symbols) names->symbols = _XkbDupString(names->symbols);
61305b261ecSmrg
61405b261ecSmrg    if (defs.model && defs.layout && rules) {
61505b261ecSmrg	XkbComponentNamesRec	rNames;
61605b261ecSmrg	bzero(&rNames,sizeof(XkbComponentNamesRec));
61705b261ecSmrg	if (XkbDDXNamesFromRules(dev,rules,&defs,&rNames)) {
61805b261ecSmrg	    if (rNames.keymap) {
61905b261ecSmrg		if (!names->keymap)
62005b261ecSmrg		    names->keymap = rNames.keymap;
62105b261ecSmrg		else _XkbFree(rNames.keymap);
62205b261ecSmrg	    }
62305b261ecSmrg	    if (rNames.keycodes) {
62405b261ecSmrg		if (!names->keycodes)
62505b261ecSmrg		    names->keycodes =  rNames.keycodes;
62605b261ecSmrg		else
62705b261ecSmrg		    _XkbFree(rNames.keycodes);
62805b261ecSmrg	    }
62905b261ecSmrg	    if (rNames.types) {
63005b261ecSmrg		if (!names->types)
63105b261ecSmrg		    names->types = rNames.types;
63205b261ecSmrg		else  _XkbFree(rNames.types);
63305b261ecSmrg	    }
63405b261ecSmrg	    if (rNames.compat) {
63505b261ecSmrg		if (!names->compat)
63605b261ecSmrg		    names->compat =  rNames.compat;
63705b261ecSmrg		else  _XkbFree(rNames.compat);
63805b261ecSmrg	    }
63905b261ecSmrg	    if (rNames.symbols) {
64005b261ecSmrg		if (!names->symbols)
64105b261ecSmrg		    names->symbols =  rNames.symbols;
64205b261ecSmrg		else _XkbFree(rNames.symbols);
64305b261ecSmrg	    }
64405b261ecSmrg	    if (rNames.geometry) {
64505b261ecSmrg		if (!names->geometry)
64605b261ecSmrg		    names->geometry = rNames.geometry;
64705b261ecSmrg		else _XkbFree(rNames.geometry);
64805b261ecSmrg	    }
64905b261ecSmrg	    XkbSetRulesUsed(&defs);
65005b261ecSmrg	}
65105b261ecSmrg    }
65205b261ecSmrg
65305b261ecSmrg    if (names->keymap) {
65405b261ecSmrg        XkbComponentNamesRec	tmpNames;
65505b261ecSmrg	bzero(&tmpNames,sizeof(XkbComponentNamesRec));
65605b261ecSmrg	tmpNames.keymap = names->keymap;
65705b261ecSmrg        ok = (Bool) XkbDDXLoadKeymapByNames(dev,&tmpNames,XkmAllIndicesMask,0,
65805b261ecSmrg					    &finfo,name,PATH_MAX);
65905b261ecSmrg    }
66005b261ecSmrg    if (!(ok && (finfo.xkb!=NULL)))
66105b261ecSmrg        ok = (Bool) XkbDDXLoadKeymapByNames(dev,names,XkmAllIndicesMask,0,
66205b261ecSmrg					    &finfo,name,PATH_MAX);
66305b261ecSmrg
66405b261ecSmrg    if (ok && (finfo.xkb!=NULL)) {
66505b261ecSmrg	XkbDescPtr	xkb;
66605b261ecSmrg	KeyCode		minKC,maxKC;
66705b261ecSmrg
66805b261ecSmrg	xkb= finfo.xkb;
66905b261ecSmrg	minKC= xkb->min_key_code;
67005b261ecSmrg	maxKC= xkb->max_key_code;
67105b261ecSmrg	if (XkbIsLegalKeycode(minKC)&&XkbIsLegalKeycode(maxKC)&&(minKC<=maxKC)&&
67205b261ecSmrg	    ((minKC!=pSyms->minKeyCode)||(maxKC!=pSyms->maxKeyCode))) {
67305b261ecSmrg	    if (xkb->map!=NULL) {
67405b261ecSmrg		KeySym	*inSym,*outSym;
67505b261ecSmrg		int	width= pSymsIn->mapWidth;
67605b261ecSmrg
67705b261ecSmrg		tmpSyms.minKeyCode= minKC;
67805b261ecSmrg		tmpSyms.maxKeyCode= maxKC;
67905b261ecSmrg
68005b261ecSmrg		if (minKC<pSymsIn->minKeyCode)
68105b261ecSmrg		    minKC= pSymsIn->minKeyCode;
68205b261ecSmrg		if (maxKC>pSymsIn->maxKeyCode)
68305b261ecSmrg		    maxKC= pSymsIn->maxKeyCode;
68405b261ecSmrg
68505b261ecSmrg		tmpSyms.mapWidth= width;
68605b261ecSmrg		tmpSyms.map= _XkbTypedCalloc(width*XkbNumKeys(xkb),KeySym);
68705b261ecSmrg		inSym= &pSymsIn->map[(minKC-pSymsIn->minKeyCode)*width];
68805b261ecSmrg		outSym= &tmpSyms.map[(minKC-tmpSyms.minKeyCode)*width];
68905b261ecSmrg		memcpy(outSym,inSym,((maxKC-minKC+1)*width)*sizeof(KeySym));
69005b261ecSmrg		pSyms= &tmpSyms;
69105b261ecSmrg	    }
69205b261ecSmrg	    if ((xkb->map!=NULL)&&(xkb->map->modmap!=NULL)) {
69305b261ecSmrg		bzero(tmpMods,XkbMaxKeyCount);
69405b261ecSmrg		memcpy(tmpMods,xkb->map->modmap,maxKC+1);
69505b261ecSmrg		pMods= tmpMods;
69605b261ecSmrg	    }
69705b261ecSmrg	}
69805b261ecSmrg	_XkbInitFileInfo= &finfo;
69905b261ecSmrg    }
70005b261ecSmrg    else {
70105b261ecSmrg	LogMessage(X_WARNING, "Couldn't load XKB keymap, falling back to pre-XKB keymap\n");
70205b261ecSmrg    }
70305b261ecSmrg    ok= InitKeyboardDeviceStruct((DevicePtr)dev,pSyms,pMods,bellProc,ctrlProc);
70405b261ecSmrg    _XkbInitFileInfo= NULL;
70505b261ecSmrg    if ((pSyms==&tmpSyms)&&(pSyms->map!=NULL)) {
70605b261ecSmrg	_XkbFree(pSyms->map);
70705b261ecSmrg	pSyms->map= NULL;
70805b261ecSmrg    }
70905b261ecSmrg
71005b261ecSmrg    if (names->keymap) _XkbFree(names->keymap);
71105b261ecSmrg    names->keymap = NULL;
71205b261ecSmrg    if (names->keycodes) _XkbFree(names->keycodes);
71305b261ecSmrg    names->keycodes = NULL;
71405b261ecSmrg    if (names->types) _XkbFree(names->types);
71505b261ecSmrg    names->types = NULL;
71605b261ecSmrg    if (names->compat) _XkbFree(names->compat);
71705b261ecSmrg    names->compat = NULL;
71805b261ecSmrg    if (names->geometry) _XkbFree(names->geometry);
71905b261ecSmrg    names->geometry = NULL;
72005b261ecSmrg    if (names->symbols) _XkbFree(names->symbols);
72105b261ecSmrg    names->symbols = NULL;
72205b261ecSmrg
72305b261ecSmrg    return ok;
72405b261ecSmrg}
72505b261ecSmrg
72605b261ecSmrg/***====================================================================***/
72705b261ecSmrg
72805b261ecSmrg	/*
72905b261ecSmrg	 * InitKeyClassDeviceStruct initializes the key class before it
73005b261ecSmrg	 * initializes the keyboard feedback class for a device.
73105b261ecSmrg	 * UpdateActions can't set up the correct autorepeat for keyboard
73205b261ecSmrg	 * initialization because the keyboard feedback isn't created yet.
73305b261ecSmrg	 * Instead, UpdateActions notes the "correct" autorepeat in the
73405b261ecSmrg	 * SrvInfo structure and InitKbdFeedbackClass calls UpdateAutoRepeat
73505b261ecSmrg	 * to apply the computed autorepeat once the feedback class exists.
73605b261ecSmrg	 *
73705b261ecSmrg	 * DIX will apply the changed autorepeat, so there's no need to
73805b261ecSmrg	 * do so here.   This function returns True if both RepeatKeys and
73905b261ecSmrg	 * the core protocol autorepeat ctrls are set (i.e. should use
74005b261ecSmrg	 * software autorepeat), false otherwise.
74105b261ecSmrg	 *
74205b261ecSmrg	 * This function also computes the autorepeat accelerators for the
74305b261ecSmrg	 * default indicator feedback.
74405b261ecSmrg	 */
74505b261ecSmrgint
74605b261ecSmrgXkbFinishDeviceInit(DeviceIntPtr pXDev)
74705b261ecSmrg{
74805b261ecSmrgXkbSrvInfoPtr		xkbi;
74905b261ecSmrgXkbDescPtr		xkb;
75005b261ecSmrgint			softRepeat;
75105b261ecSmrgXkbSrvLedInfoPtr	sli;
75205b261ecSmrg
75305b261ecSmrg    xkbi = NULL;
75405b261ecSmrg    if (pXDev && pXDev->key && pXDev->key->xkbInfo && pXDev->kbdfeed) {
75505b261ecSmrg	xkbi= pXDev->key->xkbInfo;
75605b261ecSmrg	xkb= xkbi->desc;
75705b261ecSmrg	if (pXDev->kbdfeed) {
75805b261ecSmrg	    xkbi->kbdProc= pXDev->kbdfeed->CtrlProc;
75905b261ecSmrg	    pXDev->kbdfeed->CtrlProc= XkbDDXKeybdCtrlProc;
76005b261ecSmrg	}
76105b261ecSmrg	if (pXDev->kbdfeed->ctrl.autoRepeat)
76205b261ecSmrg	    xkb->ctrls->enabled_ctrls|= XkbRepeatKeysMask;
76305b261ecSmrg	softRepeat= (xkb->ctrls->enabled_ctrls&XkbRepeatKeysMask)!=0;
76405b261ecSmrg	if (pXDev->kbdfeed) {
76505b261ecSmrg	    memcpy(pXDev->kbdfeed->ctrl.autoRepeats,
76605b261ecSmrg		   xkb->ctrls->per_key_repeat,XkbPerKeyBitArraySize);
76705b261ecSmrg	    softRepeat= softRepeat&&pXDev->kbdfeed->ctrl.autoRepeat;
76805b261ecSmrg	}
76905b261ecSmrg    }
77005b261ecSmrg    else softRepeat= 0;
77105b261ecSmrg    sli= XkbFindSrvLedInfo(pXDev,XkbDfltXIClass,XkbDfltXIId,0);
77205b261ecSmrg    if (sli && xkbi)
77305b261ecSmrg	XkbCheckIndicatorMaps(xkbi->device,sli,XkbAllIndicatorsMask);
77405b261ecSmrg#ifdef DEBUG
77505b261ecSmrg    else ErrorF("No indicator feedback in XkbFinishInit (shouldn't happen)!\n");
77605b261ecSmrg#endif
77705b261ecSmrg    return softRepeat;
77805b261ecSmrg}
77905b261ecSmrg
78005b261ecSmrg	/*
78105b261ecSmrg	 * Be very careful about what does and doesn't get freed by this
78205b261ecSmrg	 * function.  To reduce fragmentation, XkbInitDevice allocates a
78305b261ecSmrg	 * single huge block per device and divides it up into most of the
78405b261ecSmrg	 * fixed-size structures for the device.   Don't free anything that
78505b261ecSmrg	 * is part of this larger block.
78605b261ecSmrg	 */
78705b261ecSmrgvoid
78805b261ecSmrgXkbFreeInfo(XkbSrvInfoPtr xkbi)
78905b261ecSmrg{
79005b261ecSmrg    if (xkbi->radioGroups) {
79105b261ecSmrg	_XkbFree(xkbi->radioGroups);
79205b261ecSmrg	xkbi->radioGroups= NULL;
79305b261ecSmrg    }
79405b261ecSmrg    if (xkbi->mouseKeyTimer) {
79505b261ecSmrg	TimerFree(xkbi->mouseKeyTimer);
79605b261ecSmrg	xkbi->mouseKeyTimer= NULL;
79705b261ecSmrg    }
79805b261ecSmrg    if (xkbi->slowKeysTimer) {
79905b261ecSmrg	TimerFree(xkbi->slowKeysTimer);
80005b261ecSmrg	xkbi->slowKeysTimer= NULL;
80105b261ecSmrg    }
80205b261ecSmrg    if (xkbi->bounceKeysTimer) {
80305b261ecSmrg	TimerFree(xkbi->bounceKeysTimer);
80405b261ecSmrg	xkbi->bounceKeysTimer= NULL;
80505b261ecSmrg    }
80605b261ecSmrg    if (xkbi->repeatKeyTimer) {
80705b261ecSmrg	TimerFree(xkbi->repeatKeyTimer);
80805b261ecSmrg	xkbi->repeatKeyTimer= NULL;
80905b261ecSmrg    }
81005b261ecSmrg    if (xkbi->krgTimer) {
81105b261ecSmrg	TimerFree(xkbi->krgTimer);
81205b261ecSmrg	xkbi->krgTimer= NULL;
81305b261ecSmrg    }
81405b261ecSmrg    xkbi->beepType= _BEEP_NONE;
81505b261ecSmrg    if (xkbi->beepTimer) {
81605b261ecSmrg	TimerFree(xkbi->beepTimer);
81705b261ecSmrg	xkbi->beepTimer= NULL;
81805b261ecSmrg    }
81905b261ecSmrg    if (xkbi->desc) {
82005b261ecSmrg	XkbFreeKeyboard(xkbi->desc,XkbAllComponentsMask,True);
82105b261ecSmrg	xkbi->desc= NULL;
82205b261ecSmrg    }
82305b261ecSmrg    _XkbFree(xkbi);
82405b261ecSmrg    return;
82505b261ecSmrg}
82605b261ecSmrg
82705b261ecSmrg/***====================================================================***/
82805b261ecSmrg
82905b261ecSmrgextern int	XkbDfltRepeatDelay;
83005b261ecSmrgextern int	XkbDfltRepeatInterval;
83105b261ecSmrg
83205b261ecSmrgextern unsigned short	XkbDfltAccessXTimeout;
83305b261ecSmrgextern unsigned int	XkbDfltAccessXTimeoutMask;
83405b261ecSmrgextern unsigned int	XkbDfltAccessXFeedback;
83505b261ecSmrgextern unsigned char	XkbDfltAccessXOptions;
83605b261ecSmrg
83705b261ecSmrgint
83805b261ecSmrgXkbProcessArguments(int argc,char *argv[],int i)
83905b261ecSmrg{
84005b261ecSmrg    if (strcmp(argv[i],"-kb")==0) {
84105b261ecSmrg	noXkbExtension= True;
84205b261ecSmrg	return 1;
84305b261ecSmrg    }
84405b261ecSmrg    else if (strcmp(argv[i],"+kb")==0) {
84505b261ecSmrg	noXkbExtension= False;
84605b261ecSmrg	return 1;
84705b261ecSmrg    }
84805b261ecSmrg    else if (strncmp(argv[i], "-xkbdir", 7) == 0) {
84905b261ecSmrg	if(++i < argc) {
85005b261ecSmrg#if !defined(WIN32) && !defined(__CYGWIN__)
85105b261ecSmrg	    if (getuid() != geteuid()) {
85205b261ecSmrg		LogMessage(X_WARNING, "-xkbdir is not available for setuid X servers\n");
85305b261ecSmrg		return -1;
85405b261ecSmrg	    } else
85505b261ecSmrg#endif
85605b261ecSmrg	    {
85705b261ecSmrg		if (strlen(argv[i]) < PATH_MAX) {
85805b261ecSmrg		    XkbBaseDirectory= argv[i];
85905b261ecSmrg		    return 2;
86005b261ecSmrg	        } else {
86105b261ecSmrg		    LogMessage(X_ERROR, "-xkbdir pathname too long\n");
86205b261ecSmrg		    return -1;
86305b261ecSmrg		}
86405b261ecSmrg	    }
86505b261ecSmrg	}
86605b261ecSmrg	else {
86705b261ecSmrg	    return -1;
86805b261ecSmrg	}
86905b261ecSmrg    }
87005b261ecSmrg    else if ((strncmp(argv[i],"-accessx",8)==0)||
87105b261ecSmrg                 (strncmp(argv[i],"+accessx",8)==0)) {
87205b261ecSmrg	int j=1;
87305b261ecSmrg	if (argv[i][0]=='-')
87405b261ecSmrg	    XkbWantAccessX= 0;
87505b261ecSmrg	else {
87605b261ecSmrg	    XkbWantAccessX= 1;
87705b261ecSmrg
87805b261ecSmrg	    if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
87905b261ecSmrg		XkbDfltAccessXTimeout = atoi(argv[++i]);
88005b261ecSmrg		j++;
88105b261ecSmrg
88205b261ecSmrg		if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
88305b261ecSmrg		    /*
88405b261ecSmrg		     * presumption that the reasonably useful range of
88505b261ecSmrg		     * values fits in 0..MAXINT since SunOS 4 doesn't
88605b261ecSmrg		     * have strtoul.
88705b261ecSmrg		     */
88805b261ecSmrg		    XkbDfltAccessXTimeoutMask=(unsigned int)
88905b261ecSmrg					      strtol(argv[++i],NULL,16);
89005b261ecSmrg		    j++;
89105b261ecSmrg		}
89205b261ecSmrg		if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
89305b261ecSmrg		    if (argv[++i][0] == '1' )
89405b261ecSmrg			XkbDfltAccessXFeedback=XkbAccessXFeedbackMask;
89505b261ecSmrg		    else
89605b261ecSmrg			XkbDfltAccessXFeedback=0;
89705b261ecSmrg		    j++;
89805b261ecSmrg		}
89905b261ecSmrg		if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
90005b261ecSmrg		    XkbDfltAccessXOptions=(unsigned char)
90105b261ecSmrg					   strtol(argv[++i],NULL,16);
90205b261ecSmrg		    j++;
90305b261ecSmrg		}
90405b261ecSmrg	    }
90505b261ecSmrg	}
90605b261ecSmrg	return j;
90705b261ecSmrg    }
90805b261ecSmrg    if ((strcmp(argv[i], "-ardelay") == 0) ||
90905b261ecSmrg        (strcmp (argv[i], "-ar1") == 0)) {	/* -ardelay int */
91005b261ecSmrg	if (++i >= argc) UseMsg ();
91105b261ecSmrg	XkbDfltRepeatDelay = (long)atoi(argv[i]);
91205b261ecSmrg	return 2;
91305b261ecSmrg    }
91405b261ecSmrg    if ((strcmp(argv[i], "-arinterval") == 0) ||
91505b261ecSmrg        (strcmp (argv[i], "-ar2") == 0)) {	/* -arinterval int */
91605b261ecSmrg	if (++i >= argc) UseMsg ();
91705b261ecSmrg	XkbDfltRepeatInterval = (long)atoi(argv[i]);
91805b261ecSmrg	return 2;
91905b261ecSmrg    }
92005b261ecSmrg    return 0;
92105b261ecSmrg}
92205b261ecSmrg
92305b261ecSmrgvoid
92405b261ecSmrgXkbUseMsg(void)
92505b261ecSmrg{
92605b261ecSmrg    ErrorF("-kb                    disable the X Keyboard Extension\n");
92705b261ecSmrg    ErrorF("+kb                    enable the X Keyboard Extension\n");
92805b261ecSmrg    ErrorF("[+-]accessx [ timeout [ timeout_mask [ feedback [ options_mask] ] ] ]\n");
92905b261ecSmrg    ErrorF("                       enable/disable accessx key sequences\n");
93005b261ecSmrg    ErrorF("-ardelay               set XKB autorepeat delay\n");
93105b261ecSmrg    ErrorF("-arinterval            set XKB autorepeat interval\n");
93205b261ecSmrg}
933