xkbInit.c revision 4642e01f
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>
514642e01fSmrg#include "xkbgeom.h"
5205b261ecSmrg#include <X11/extensions/XKMformat.h>
534642e01fSmrg#include "xkbfile.h"
5405b261ecSmrg#include "xkb.h"
5505b261ecSmrg
5605b261ecSmrg#define	CREATE_ATOM(s)	MakeAtom(s,sizeof(s)-1,1)
5705b261ecSmrg
584642e01fSmrg#if defined(__alpha) || defined(__alpha__)
5905b261ecSmrg#define	LED_COMPOSE	2
6005b261ecSmrg#define LED_CAPS	3
6105b261ecSmrg#define	LED_SCROLL	4
6205b261ecSmrg#define	LED_NUM		5
6305b261ecSmrg#define	PHYS_LEDS	0x1f
6405b261ecSmrg#else
6505b261ecSmrg#ifdef sun
6605b261ecSmrg#define LED_NUM		1
6705b261ecSmrg#define	LED_SCROLL	2
6805b261ecSmrg#define	LED_COMPOSE	3
6905b261ecSmrg#define LED_CAPS	4
7005b261ecSmrg#define	PHYS_LEDS	0x0f
7105b261ecSmrg#else
7205b261ecSmrg#define	LED_CAPS	1
7305b261ecSmrg#define	LED_NUM		2
7405b261ecSmrg#define	LED_SCROLL	3
7505b261ecSmrg#define	PHYS_LEDS	0x07
7605b261ecSmrg#endif
7705b261ecSmrg#endif
7805b261ecSmrg
7905b261ecSmrg#define	MAX_TOC	16
8005b261ecSmrgtypedef struct	_SrvXkmInfo {
8105b261ecSmrg	DeviceIntPtr	dev;
8205b261ecSmrg	FILE *		file;
834642e01fSmrg	XkbDescPtr	xkb;
8405b261ecSmrg} SrvXkmInfo;
8505b261ecSmrg
8605b261ecSmrg
8705b261ecSmrg/***====================================================================***/
8805b261ecSmrg
8905b261ecSmrg#ifndef XKB_BASE_DIRECTORY
9005b261ecSmrg#define	XKB_BASE_DIRECTORY	"/usr/lib/X11/xkb"
9105b261ecSmrg#endif
9205b261ecSmrg#ifndef XKB_BIN_DIRECTORY
9305b261ecSmrg#define	XKB_BIN_DIRECTORY	XKB_BASE_DIRECTORY
9405b261ecSmrg#endif
9505b261ecSmrg#ifndef XKB_DFLT_RULES_FILE
964642e01fSmrg#define	XKB_DFLT_RULES_FILE	"base"
9705b261ecSmrg#endif
9805b261ecSmrg#ifndef XKB_DFLT_KB_LAYOUT
9905b261ecSmrg#define	XKB_DFLT_KB_LAYOUT	"us"
10005b261ecSmrg#endif
10105b261ecSmrg#ifndef XKB_DFLT_KB_MODEL
10205b261ecSmrg#define	XKB_DFLT_KB_MODEL	"dflt"
10305b261ecSmrg#endif
10405b261ecSmrg#ifndef XKB_DFLT_KB_VARIANT
10505b261ecSmrg#define	XKB_DFLT_KB_VARIANT	NULL
10605b261ecSmrg#endif
10705b261ecSmrg#ifndef XKB_DFLT_KB_OPTIONS
10805b261ecSmrg#define	XKB_DFLT_KB_OPTIONS	NULL
10905b261ecSmrg#endif
11005b261ecSmrg#ifndef XKB_DFLT_DISABLED
11105b261ecSmrg#define	XKB_DFLT_DISABLED	True
11205b261ecSmrg#endif
11305b261ecSmrg#ifndef XKB_DFLT_RULES_PROP
11405b261ecSmrg#define	XKB_DFLT_RULES_PROP	True
11505b261ecSmrg#endif
11605b261ecSmrg
11705b261ecSmrgchar	*		XkbBaseDirectory=	XKB_BASE_DIRECTORY;
11805b261ecSmrgchar	*		XkbBinDirectory=	XKB_BIN_DIRECTORY;
11905b261ecSmrgstatic int	 	XkbWantAccessX=		0;
12005b261ecSmrg
12105b261ecSmrgstatic Bool		rulesDefined=		False;
12205b261ecSmrgstatic char *		XkbRulesFile=		NULL;
12305b261ecSmrgstatic char *		XkbModelDflt=		NULL;
12405b261ecSmrgstatic char *		XkbLayoutDflt=		NULL;
12505b261ecSmrgstatic char *		XkbVariantDflt=		NULL;
12605b261ecSmrgstatic char *		XkbOptionsDflt=		NULL;
12705b261ecSmrg
12805b261ecSmrgstatic char *		XkbModelUsed=	NULL;
12905b261ecSmrgstatic char *		XkbLayoutUsed=	NULL;
13005b261ecSmrgstatic char *		XkbVariantUsed=	NULL;
13105b261ecSmrgstatic char *		XkbOptionsUsed=	NULL;
13205b261ecSmrg
1334642e01fSmrgstatic XkbDescPtr       xkb_cached_map = NULL;
1344642e01fSmrg
13505b261ecSmrg_X_EXPORT Bool		noXkbExtension=		XKB_DFLT_DISABLED;
13605b261ecSmrgstatic Bool		XkbWantRulesProp=	XKB_DFLT_RULES_PROP;
13705b261ecSmrg
13805b261ecSmrg/***====================================================================***/
13905b261ecSmrg
14005b261ecSmrgstatic char *
14105b261ecSmrgXkbGetRulesDflts(XkbRF_VarDefsPtr defs)
14205b261ecSmrg{
14305b261ecSmrg    if (XkbModelDflt)	defs->model= XkbModelDflt;
14405b261ecSmrg    else		defs->model= XKB_DFLT_KB_MODEL;
14505b261ecSmrg    if (XkbLayoutDflt)	defs->layout= XkbLayoutDflt;
14605b261ecSmrg    else		defs->layout= XKB_DFLT_KB_LAYOUT;
14705b261ecSmrg    if (XkbVariantDflt)	defs->variant= XkbVariantDflt;
14805b261ecSmrg    else		defs->variant= XKB_DFLT_KB_VARIANT;
14905b261ecSmrg    if (XkbOptionsDflt)	defs->options= XkbOptionsDflt;
15005b261ecSmrg    else		defs->options= XKB_DFLT_KB_OPTIONS;
15105b261ecSmrg    return (rulesDefined?XkbRulesFile:XKB_DFLT_RULES_FILE);
15205b261ecSmrg}
15305b261ecSmrg
15405b261ecSmrgstatic Bool
15505b261ecSmrgXkbWriteRulesProp(ClientPtr client, pointer closure)
15605b261ecSmrg{
15705b261ecSmrgint 			len,out;
15805b261ecSmrgAtom			name;
15905b261ecSmrgchar *			pval;
16005b261ecSmrg
16105b261ecSmrg    if (rulesDefined && (!XkbRulesFile))
16205b261ecSmrg	return False;
16305b261ecSmrg    len= (XkbRulesFile?strlen(XkbRulesFile):strlen(XKB_DFLT_RULES_FILE));
16405b261ecSmrg    len+= (XkbModelUsed?strlen(XkbModelUsed):0);
16505b261ecSmrg    len+= (XkbLayoutUsed?strlen(XkbLayoutUsed):0);
16605b261ecSmrg    len+= (XkbVariantUsed?strlen(XkbVariantUsed):0);
16705b261ecSmrg    len+= (XkbOptionsUsed?strlen(XkbOptionsUsed):0);
16805b261ecSmrg    if (len<1)
16905b261ecSmrg	return True;
17005b261ecSmrg
17105b261ecSmrg    len+= 5; /* trailing NULs */
17205b261ecSmrg
17305b261ecSmrg    name= MakeAtom(_XKB_RF_NAMES_PROP_ATOM,strlen(_XKB_RF_NAMES_PROP_ATOM),1);
17405b261ecSmrg    if (name==None) {
1754642e01fSmrg	ErrorF("[xkb] Atom error: %s not created\n",_XKB_RF_NAMES_PROP_ATOM);
17605b261ecSmrg	return True;
17705b261ecSmrg    }
1784642e01fSmrg    pval= (char*) xalloc(len);
17905b261ecSmrg    if (!pval) {
1804642e01fSmrg	ErrorF("[xkb] Allocation error: %s proprerty not created\n",
18105b261ecSmrg						_XKB_RF_NAMES_PROP_ATOM);
18205b261ecSmrg	return True;
18305b261ecSmrg    }
18405b261ecSmrg    out= 0;
18505b261ecSmrg    if (XkbRulesFile) {
18605b261ecSmrg	strcpy(&pval[out],XkbRulesFile);
18705b261ecSmrg	out+= strlen(XkbRulesFile);
18805b261ecSmrg    } else {
18905b261ecSmrg	strcpy(&pval[out],XKB_DFLT_RULES_FILE);
19005b261ecSmrg	out+= strlen(XKB_DFLT_RULES_FILE);
19105b261ecSmrg    }
19205b261ecSmrg    pval[out++]= '\0';
19305b261ecSmrg    if (XkbModelUsed) {
19405b261ecSmrg	strcpy(&pval[out],XkbModelUsed);
19505b261ecSmrg	out+= strlen(XkbModelUsed);
19605b261ecSmrg    }
19705b261ecSmrg    pval[out++]= '\0';
19805b261ecSmrg    if (XkbLayoutUsed) {
19905b261ecSmrg	strcpy(&pval[out],XkbLayoutUsed);
20005b261ecSmrg	out+= strlen(XkbLayoutUsed);
20105b261ecSmrg    }
20205b261ecSmrg    pval[out++]= '\0';
20305b261ecSmrg    if (XkbVariantUsed) {
20405b261ecSmrg	strcpy(&pval[out],XkbVariantUsed);
20505b261ecSmrg	out+= strlen(XkbVariantUsed);
20605b261ecSmrg    }
20705b261ecSmrg    pval[out++]= '\0';
20805b261ecSmrg    if (XkbOptionsUsed) {
20905b261ecSmrg	strcpy(&pval[out],XkbOptionsUsed);
21005b261ecSmrg	out+= strlen(XkbOptionsUsed);
21105b261ecSmrg    }
21205b261ecSmrg    pval[out++]= '\0';
21305b261ecSmrg    if (out!=len) {
2144642e01fSmrg	ErrorF("[xkb] Internal Error! bad size (%d!=%d) for _XKB_RULES_NAMES\n",
21505b261ecSmrg								out,len);
21605b261ecSmrg    }
2174642e01fSmrg    dixChangeWindowProperty(serverClient, WindowTable[0], name, XA_STRING, 8,
2184642e01fSmrg			    PropModeReplace, len, pval, True);
2194642e01fSmrg    xfree(pval);
22005b261ecSmrg    return True;
22105b261ecSmrg}
22205b261ecSmrg
22305b261ecSmrgstatic void
22405b261ecSmrgXkbSetRulesUsed(XkbRF_VarDefsPtr defs)
22505b261ecSmrg{
22605b261ecSmrg    if (XkbModelUsed)
22705b261ecSmrg	_XkbFree(XkbModelUsed);
22805b261ecSmrg    XkbModelUsed= (defs->model?_XkbDupString(defs->model):NULL);
22905b261ecSmrg    if (XkbLayoutUsed)
23005b261ecSmrg	_XkbFree(XkbLayoutUsed);
23105b261ecSmrg    XkbLayoutUsed= (defs->layout?_XkbDupString(defs->layout):NULL);
23205b261ecSmrg    if (XkbVariantUsed)
23305b261ecSmrg	_XkbFree(XkbVariantUsed);
23405b261ecSmrg    XkbVariantUsed= (defs->variant?_XkbDupString(defs->variant):NULL);
23505b261ecSmrg    if (XkbOptionsUsed)
23605b261ecSmrg	_XkbFree(XkbOptionsUsed);
23705b261ecSmrg    XkbOptionsUsed= (defs->options?_XkbDupString(defs->options):NULL);
23805b261ecSmrg    if (XkbWantRulesProp)
23905b261ecSmrg	QueueWorkProc(XkbWriteRulesProp,NULL,NULL);
24005b261ecSmrg    return;
24105b261ecSmrg}
24205b261ecSmrg
2434642e01fSmrg/**
2444642e01fSmrg * Set the default RMLVO for the next device to be initialised.
2454642e01fSmrg * If a parameter is NULL, the previous setting will be used. Use empty
2464642e01fSmrg * strings if you want to delete a previous setting.
2474642e01fSmrg *
2484642e01fSmrg * If @rulesFile is NULL and no previous @rulesFile has been set, the
2494642e01fSmrg * built-in default is chosen as default.
2504642e01fSmrg */
25105b261ecSmrg_X_EXPORT void
25205b261ecSmrgXkbSetRulesDflts(char *rulesFile,char *model,char *layout,
25305b261ecSmrg					char *variant,char *options)
25405b261ecSmrg{
2554642e01fSmrg    if (!rulesFile && !XkbRulesFile)
2564642e01fSmrg    {
2574642e01fSmrg	LogMessage(X_WARNING, "[xkb] No rule given, and no previous rule "
2584642e01fSmrg		              "defined. Defaulting to '%s'.\n",
2594642e01fSmrg                              XKB_DFLT_RULES_FILE);
2604642e01fSmrg	rulesFile = XKB_DFLT_RULES_FILE;
2614642e01fSmrg    }
2624642e01fSmrg
2634642e01fSmrg    if (rulesFile) {
2644642e01fSmrg	if (XkbRulesFile)
2654642e01fSmrg	    _XkbFree(XkbRulesFile);
2664642e01fSmrg	XkbRulesFile= _XkbDupString(rulesFile);
2674642e01fSmrg	rulesDefined= True;
2684642e01fSmrg    }
2694642e01fSmrg
27005b261ecSmrg    if (model) {
27105b261ecSmrg	if (XkbModelDflt)
27205b261ecSmrg	    _XkbFree(XkbModelDflt);
27305b261ecSmrg	XkbModelDflt= _XkbDupString(model);
27405b261ecSmrg    }
27505b261ecSmrg    if (layout) {
27605b261ecSmrg	if (XkbLayoutDflt)
27705b261ecSmrg	    _XkbFree(XkbLayoutDflt);
27805b261ecSmrg	XkbLayoutDflt= _XkbDupString(layout);
27905b261ecSmrg    }
28005b261ecSmrg    if (variant) {
28105b261ecSmrg	if (XkbVariantDflt)
28205b261ecSmrg	    _XkbFree(XkbVariantDflt);
28305b261ecSmrg	XkbVariantDflt= _XkbDupString(variant);
28405b261ecSmrg    }
28505b261ecSmrg    if (options) {
28605b261ecSmrg	if (XkbOptionsDflt)
28705b261ecSmrg	    _XkbFree(XkbOptionsDflt);
28805b261ecSmrg	XkbOptionsDflt= _XkbDupString(options);
28905b261ecSmrg    }
29005b261ecSmrg    return;
29105b261ecSmrg}
29205b261ecSmrg
2934642e01fSmrgvoid
2944642e01fSmrgXkbDeleteRulesDflts()
2954642e01fSmrg{
2964642e01fSmrg    _XkbFree(XkbRulesFile);
2974642e01fSmrg    XkbRulesFile = NULL;
2984642e01fSmrg    _XkbFree(XkbModelDflt);
2994642e01fSmrg    XkbModelDflt = NULL;
3004642e01fSmrg    _XkbFree(XkbLayoutDflt);
3014642e01fSmrg    XkbLayoutDflt = NULL;
3024642e01fSmrg    _XkbFree(XkbVariantDflt);
3034642e01fSmrg    XkbVariantDflt = NULL;
3044642e01fSmrg    _XkbFree(XkbOptionsDflt);
3054642e01fSmrg    XkbOptionsDflt = NULL;
3064642e01fSmrg
3074642e01fSmrg    XkbFreeKeyboard(xkb_cached_map, XkbAllComponentsMask, True);
3084642e01fSmrg    xkb_cached_map = NULL;
3094642e01fSmrg}
31005b261ecSmrg
3114642e01fSmrg/***====================================================================***/
31205b261ecSmrg
31305b261ecSmrg#include "xkbDflts.h"
31405b261ecSmrg
31505b261ecSmrgstatic Bool
3164642e01fSmrgXkbInitKeyTypes(XkbDescPtr xkb)
31705b261ecSmrg{
3184642e01fSmrg    if (xkb->defined & XkmTypesMask)
3194642e01fSmrg        return True;
3204642e01fSmrg
32105b261ecSmrg    initTypeNames(NULL);
32205b261ecSmrg    if (XkbAllocClientMap(xkb,XkbKeyTypesMask,num_dflt_types)!=Success)
32305b261ecSmrg	return False;
32405b261ecSmrg    if (XkbCopyKeyTypes(dflt_types,xkb->map->types,num_dflt_types)!=
32505b261ecSmrg    								 Success) {
32605b261ecSmrg	return False;
32705b261ecSmrg    }
32805b261ecSmrg    xkb->map->size_types= xkb->map->num_types= num_dflt_types;
32905b261ecSmrg    return True;
33005b261ecSmrg}
33105b261ecSmrg
33205b261ecSmrgstatic void
3334642e01fSmrgXkbInitRadioGroups(XkbSrvInfoPtr xkbi)
33405b261ecSmrg{
33505b261ecSmrg    xkbi->nRadioGroups = 0;
33605b261ecSmrg    xkbi->radioGroups = NULL;
33705b261ecSmrg    return;
33805b261ecSmrg}
33905b261ecSmrg
34005b261ecSmrg
34105b261ecSmrgstatic Status
3424642e01fSmrgXkbInitCompatStructs(XkbDescPtr xkb)
34305b261ecSmrg{
34405b261ecSmrgregister int 	i;
34505b261ecSmrgXkbCompatMapPtr	compat;
34605b261ecSmrg
3474642e01fSmrg    if (xkb->defined & XkmCompatMapMask)
3484642e01fSmrg        return True;
3494642e01fSmrg
35005b261ecSmrg    if (XkbAllocCompatMap(xkb,XkbAllCompatMask,num_dfltSI)!=Success)
35105b261ecSmrg	return BadAlloc;
35205b261ecSmrg    compat = xkb->compat;
35305b261ecSmrg    if (compat->sym_interpret) {
35405b261ecSmrg	compat->num_si = num_dfltSI;
35505b261ecSmrg	memcpy((char *)compat->sym_interpret,(char *)dfltSI,sizeof(dfltSI));
35605b261ecSmrg    }
35705b261ecSmrg    for (i=0;i<XkbNumKbdGroups;i++) {
35805b261ecSmrg	compat->groups[i]= compatMap.groups[i];
35905b261ecSmrg	if (compat->groups[i].vmods!=0) {
36005b261ecSmrg	    unsigned mask;
36105b261ecSmrg	    mask= XkbMaskForVMask(xkb,compat->groups[i].vmods);
36205b261ecSmrg	    compat->groups[i].mask= compat->groups[i].real_mods|mask;
36305b261ecSmrg	}
36405b261ecSmrg	else compat->groups[i].mask= compat->groups[i].real_mods;
36505b261ecSmrg    }
36605b261ecSmrg    return Success;
36705b261ecSmrg}
36805b261ecSmrg
36905b261ecSmrgstatic void
3704642e01fSmrgXkbInitSemantics(XkbDescPtr xkb)
37105b261ecSmrg{
3724642e01fSmrg    XkbInitKeyTypes(xkb);
3734642e01fSmrg    XkbInitCompatStructs(xkb);
37405b261ecSmrg    return;
37505b261ecSmrg}
37605b261ecSmrg
37705b261ecSmrg/***====================================================================***/
37805b261ecSmrg
37905b261ecSmrgstatic Status
3804642e01fSmrgXkbInitNames(XkbSrvInfoPtr xkbi)
38105b261ecSmrg{
38205b261ecSmrgXkbDescPtr	xkb;
38305b261ecSmrgXkbNamesPtr	names;
38405b261ecSmrgStatus		rtrn;
38505b261ecSmrgAtom		unknown;
38605b261ecSmrg
38705b261ecSmrg    xkb= xkbi->desc;
38805b261ecSmrg    if ((rtrn=XkbAllocNames(xkb,XkbAllNamesMask,0,0))!=Success)
38905b261ecSmrg	return rtrn;
39005b261ecSmrg    unknown= CREATE_ATOM("unknown");
39105b261ecSmrg    names = xkb->names;
39205b261ecSmrg    if (names->keycodes==None)		names->keycodes= unknown;
39305b261ecSmrg    if (names->geometry==None)		names->geometry= unknown;
39405b261ecSmrg    if (names->phys_symbols==None)	names->phys_symbols= unknown;
39505b261ecSmrg    if (names->symbols==None)		names->symbols= unknown;
39605b261ecSmrg    if (names->types==None)		names->types= unknown;
39705b261ecSmrg    if (names->compat==None)		names->compat= unknown;
3984642e01fSmrg    if (!(xkb->defined & XkmVirtualModsMask)) {
3994642e01fSmrg        if (names->vmods[vmod_NumLock]==None)
4004642e01fSmrg            names->vmods[vmod_NumLock]= CREATE_ATOM("NumLock");
4014642e01fSmrg        if (names->vmods[vmod_Alt]==None)
4024642e01fSmrg            names->vmods[vmod_Alt]= CREATE_ATOM("Alt");
4034642e01fSmrg        if (names->vmods[vmod_AltGr]==None)
4044642e01fSmrg            names->vmods[vmod_AltGr]= CREATE_ATOM("ModeSwitch");
40505b261ecSmrg    }
40605b261ecSmrg
4074642e01fSmrg    if (!(xkb->defined & XkmIndicatorsMask) ||
4084642e01fSmrg        !(xkb->defined & XkmGeometryMask)) {
4094642e01fSmrg        initIndicatorNames(NULL,xkb);
4104642e01fSmrg        if (names->indicators[LED_CAPS-1]==None)
4114642e01fSmrg            names->indicators[LED_CAPS-1] = CREATE_ATOM("Caps Lock");
4124642e01fSmrg        if (names->indicators[LED_NUM-1]==None)
4134642e01fSmrg            names->indicators[LED_NUM-1] = CREATE_ATOM("Num Lock");
4144642e01fSmrg        if (names->indicators[LED_SCROLL-1]==None)
4154642e01fSmrg            names->indicators[LED_SCROLL-1] = CREATE_ATOM("Scroll Lock");
41605b261ecSmrg#ifdef LED_COMPOSE
4174642e01fSmrg        if (names->indicators[LED_COMPOSE-1]==None)
4184642e01fSmrg            names->indicators[LED_COMPOSE-1] = CREATE_ATOM("Compose");
41905b261ecSmrg#endif
42005b261ecSmrg    }
4214642e01fSmrg
42205b261ecSmrg    if (xkb->geom!=NULL)
42305b261ecSmrg	 names->geometry= xkb->geom->name;
42405b261ecSmrg    else names->geometry= unknown;
4254642e01fSmrg
42605b261ecSmrg    return Success;
42705b261ecSmrg}
42805b261ecSmrg
42905b261ecSmrgstatic Status
4304642e01fSmrgXkbInitIndicatorMap(XkbSrvInfoPtr xkbi)
43105b261ecSmrg{
43205b261ecSmrgXkbDescPtr		xkb;
43305b261ecSmrgXkbIndicatorPtr		map;
43405b261ecSmrgXkbSrvLedInfoPtr	sli;
43505b261ecSmrg
43605b261ecSmrg    xkb= xkbi->desc;
43705b261ecSmrg    if (XkbAllocIndicatorMaps(xkb)!=Success)
43805b261ecSmrg	return BadAlloc;
4394642e01fSmrg
4404642e01fSmrg    if (!(xkb->defined & XkmIndicatorsMask)) {
4414642e01fSmrg        map= xkb->indicators;
4424642e01fSmrg        map->phys_indicators = PHYS_LEDS;
4434642e01fSmrg        map->maps[LED_CAPS-1].flags= XkbIM_NoExplicit;
4444642e01fSmrg        map->maps[LED_CAPS-1].which_mods= XkbIM_UseLocked;
4454642e01fSmrg        map->maps[LED_CAPS-1].mods.mask= LockMask;
4464642e01fSmrg        map->maps[LED_CAPS-1].mods.real_mods= LockMask;
4474642e01fSmrg
4484642e01fSmrg        map->maps[LED_NUM-1].flags= XkbIM_NoExplicit;
4494642e01fSmrg        map->maps[LED_NUM-1].which_mods= XkbIM_UseLocked;
4504642e01fSmrg        map->maps[LED_NUM-1].mods.mask= 0;
4514642e01fSmrg        map->maps[LED_NUM-1].mods.real_mods= 0;
4524642e01fSmrg        map->maps[LED_NUM-1].mods.vmods= vmod_NumLockMask;
4534642e01fSmrg
4544642e01fSmrg        map->maps[LED_SCROLL-1].flags= XkbIM_NoExplicit;
4554642e01fSmrg        map->maps[LED_SCROLL-1].which_mods= XkbIM_UseLocked;
4564642e01fSmrg        map->maps[LED_SCROLL-1].mods.mask= Mod3Mask;
4574642e01fSmrg        map->maps[LED_SCROLL-1].mods.real_mods= Mod3Mask;
45805b261ecSmrg    }
4594642e01fSmrg
46005b261ecSmrg    sli= XkbFindSrvLedInfo(xkbi->device,XkbDfltXIClass,XkbDfltXIId,0);
46105b261ecSmrg    if (sli)
46205b261ecSmrg	XkbCheckIndicatorMaps(xkbi->device,sli,XkbAllIndicatorsMask);
4634642e01fSmrg
46405b261ecSmrg    return Success;
46505b261ecSmrg}
46605b261ecSmrg
46705b261ecSmrgstatic Status
4684642e01fSmrgXkbInitControls(DeviceIntPtr pXDev,XkbSrvInfoPtr xkbi)
46905b261ecSmrg{
47005b261ecSmrgXkbDescPtr	xkb;
47105b261ecSmrgXkbControlsPtr	ctrls;
47205b261ecSmrg
47305b261ecSmrg    xkb= xkbi->desc;
47405b261ecSmrg    /* 12/31/94 (ef) -- XXX! Should check if controls loaded from file */
47505b261ecSmrg    if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success)
47605b261ecSmrg	FatalError("Couldn't allocate keyboard controls\n");
47705b261ecSmrg    ctrls= xkb->ctrls;
4784642e01fSmrg    if (!(xkb->defined & XkmSymbolsMask))
4794642e01fSmrg        ctrls->num_groups = 1;
48005b261ecSmrg    ctrls->groups_wrap = XkbSetGroupInfo(1,XkbWrapIntoRange,0);
48105b261ecSmrg    ctrls->internal.mask = 0;
48205b261ecSmrg    ctrls->internal.real_mods = 0;
48305b261ecSmrg    ctrls->internal.vmods = 0;
48405b261ecSmrg    ctrls->ignore_lock.mask = 0;
48505b261ecSmrg    ctrls->ignore_lock.real_mods = 0;
48605b261ecSmrg    ctrls->ignore_lock.vmods = 0;
48705b261ecSmrg    ctrls->enabled_ctrls = XkbAccessXTimeoutMask|XkbRepeatKeysMask|
48805b261ecSmrg				XkbMouseKeysAccelMask|XkbAudibleBellMask|
48905b261ecSmrg				XkbIgnoreGroupLockMask;
49005b261ecSmrg    if (XkbWantAccessX)
49105b261ecSmrg	ctrls->enabled_ctrls|= XkbAccessXKeysMask;
49205b261ecSmrg    AccessXInit(pXDev);
49305b261ecSmrg    return Success;
49405b261ecSmrg}
49505b261ecSmrg
49605b261ecSmrgvoid
49705b261ecSmrgXkbInitDevice(DeviceIntPtr pXDev)
49805b261ecSmrg{
49905b261ecSmrgint			i;
50005b261ecSmrgXkbSrvInfoPtr		xkbi;
50105b261ecSmrgXkbChangesRec		changes;
50205b261ecSmrgunsigned		check;
50305b261ecSmrgXkbEventCauseRec	cause;
50405b261ecSmrg
50505b261ecSmrg    bzero(&changes,sizeof(XkbChangesRec));
50605b261ecSmrg    pXDev->key->xkbInfo= xkbi= _XkbTypedCalloc(1,XkbSrvInfoRec);
50705b261ecSmrg    if ( xkbi ) {
50805b261ecSmrg	XkbDescPtr	xkb;
5094642e01fSmrg
5104642e01fSmrg        if (xkb_cached_map) {
5114642e01fSmrg            xkbi->desc = xkb_cached_map;
5124642e01fSmrg            xkb_cached_map = NULL;
5134642e01fSmrg        }
5144642e01fSmrg        else {
5154642e01fSmrg            xkbi->desc= XkbAllocKeyboard();
5164642e01fSmrg            if (!xkbi->desc)
5174642e01fSmrg                FatalError("Couldn't allocate keyboard description\n");
5184642e01fSmrg            xkbi->desc->min_key_code = pXDev->key->curKeySyms.minKeyCode;
5194642e01fSmrg            xkbi->desc->max_key_code = pXDev->key->curKeySyms.maxKeyCode;
5204642e01fSmrg        }
52105b261ecSmrg	xkb= xkbi->desc;
52205b261ecSmrg	if (xkb->min_key_code == 0)
52305b261ecSmrg	    xkb->min_key_code = pXDev->key->curKeySyms.minKeyCode;
52405b261ecSmrg	if (xkb->max_key_code == 0)
52505b261ecSmrg	    xkb->max_key_code = pXDev->key->curKeySyms.maxKeyCode;
52605b261ecSmrg	if ((pXDev->key->curKeySyms.minKeyCode!=xkbi->desc->min_key_code)||
52705b261ecSmrg	    (pXDev->key->curKeySyms.maxKeyCode!=xkbi->desc->max_key_code)) {
52805b261ecSmrg	    /* 12/9/95 (ef) -- XXX! Maybe we should try to fix up one or */
52905b261ecSmrg	    /*                 the other here, but for now just complain */
53005b261ecSmrg	    /*                 can't just update the core range without */
53105b261ecSmrg	    /*                 reallocating the KeySymsRec (pain)       */
5324642e01fSmrg	    ErrorF("[xkb] Internal Error!! XKB and core keymap have different range\n");
53305b261ecSmrg	}
53405b261ecSmrg	if (XkbAllocClientMap(xkb,XkbAllClientInfoMask,0)!=Success)
53505b261ecSmrg	    FatalError("Couldn't allocate client map in XkbInitDevice\n");
53605b261ecSmrg	i= XkbNumKeys(xkb)/3+1;
53705b261ecSmrg	if (XkbAllocServerMap(xkb,XkbAllServerInfoMask,i)!=Success)
53805b261ecSmrg	    FatalError("Couldn't allocate server map in XkbInitDevice\n");
53905b261ecSmrg
54005b261ecSmrg	xkbi->dfltPtrDelta=1;
54105b261ecSmrg	xkbi->device = pXDev;
54205b261ecSmrg
5434642e01fSmrg	XkbInitSemantics(xkb);
5444642e01fSmrg	XkbInitNames(xkbi);
5454642e01fSmrg	XkbInitRadioGroups(xkbi);
54605b261ecSmrg
54705b261ecSmrg	/* 12/31/94 (ef) -- XXX! Should check if state loaded from file */
54805b261ecSmrg	bzero(&xkbi->state,sizeof(XkbStateRec));
54905b261ecSmrg
5504642e01fSmrg	XkbInitControls(pXDev,xkbi);
55105b261ecSmrg
5524642e01fSmrg        if (xkb->defined & XkmSymbolsMask)
5534642e01fSmrg            memcpy(pXDev->key->modifierMap, xkb->map->modmap,
5544642e01fSmrg                   xkb->max_key_code + 1);
5554642e01fSmrg        else
5564642e01fSmrg            memcpy(xkb->map->modmap, pXDev->key->modifierMap,
5574642e01fSmrg                   xkb->max_key_code + 1);
55805b261ecSmrg
5594642e01fSmrg	XkbInitIndicatorMap(xkbi);
56005b261ecSmrg
56105b261ecSmrg	XkbDDXInitDevice(pXDev);
56205b261ecSmrg
5634642e01fSmrg        if (xkb->defined & XkmSymbolsMask)
5644642e01fSmrg            XkbUpdateCoreDescription(pXDev, True);
5654642e01fSmrg        else
5664642e01fSmrg            XkbUpdateKeyTypesFromCore(pXDev, xkb->min_key_code,
5674642e01fSmrg                                      XkbNumKeys(xkb), &changes);
5684642e01fSmrg
56905b261ecSmrg	XkbSetCauseUnknown(&cause);
57005b261ecSmrg	XkbUpdateActions(pXDev,xkb->min_key_code, XkbNumKeys(xkb),&changes,
57105b261ecSmrg								&check,&cause);
57205b261ecSmrg        /* For sanity.  The first time the connection
57305b261ecSmrg         * is opened, the client side min and max are set
57405b261ecSmrg         * using QueryMinMaxKeyCodes() which grabs them
57505b261ecSmrg	 * from pXDev.
57605b261ecSmrg	 */
57705b261ecSmrg	pXDev->key->curKeySyms.minKeyCode = xkb->min_key_code;
57805b261ecSmrg	pXDev->key->curKeySyms.maxKeyCode = xkb->max_key_code;
57905b261ecSmrg    }
58005b261ecSmrg    return;
58105b261ecSmrg}
58205b261ecSmrg
58305b261ecSmrg#if MAP_LENGTH > XkbMaxKeyCount
58405b261ecSmrg#undef  XkbMaxKeyCount
58505b261ecSmrg#define XkbMaxKeyCount MAP_LENGTH
58605b261ecSmrg#endif
58705b261ecSmrg
58805b261ecSmrg_X_EXPORT Bool
58905b261ecSmrgXkbInitKeyboardDeviceStruct(
59005b261ecSmrg    DeviceIntPtr		dev,
59105b261ecSmrg    XkbComponentNamesPtr	names,
59205b261ecSmrg    KeySymsPtr                  pSymsIn,
59305b261ecSmrg    CARD8                       pModsIn[],
59405b261ecSmrg    void                        (*bellProc)(
59505b261ecSmrg        int /*percent*/,
59605b261ecSmrg        DeviceIntPtr /*device*/,
59705b261ecSmrg        pointer /*ctrl*/,
59805b261ecSmrg        int),
59905b261ecSmrg    void                        (*ctrlProc)(
60005b261ecSmrg        DeviceIntPtr /*device*/,
60105b261ecSmrg        KeybdCtrl * /*ctrl*/))
60205b261ecSmrg{
60305b261ecSmrgKeySymsRec		tmpSyms,*pSyms;
60405b261ecSmrgCARD8			tmpMods[XkbMaxLegalKeyCode+1],*pMods;
60505b261ecSmrgchar			name[PATH_MAX],*rules;
60605b261ecSmrgBool			ok=False;
60705b261ecSmrgXkbRF_VarDefsRec	defs;
6084642e01fSmrgXkbDescPtr              xkb;
60905b261ecSmrg
61005b261ecSmrg    if ((dev->key!=NULL)||(dev->kbdfeed!=NULL))
61105b261ecSmrg	return False;
61205b261ecSmrg    pSyms= pSymsIn;
61305b261ecSmrg    pMods= pModsIn;
61405b261ecSmrg    bzero(&defs,sizeof(XkbRF_VarDefsRec));
61505b261ecSmrg    rules= XkbGetRulesDflts(&defs);
61605b261ecSmrg
61705b261ecSmrg    /*
61805b261ecSmrg     * The strings are duplicated because it is not guaranteed that
61905b261ecSmrg     * they are allocated, or that they are allocated for every server
62005b261ecSmrg     * generation. Eventually they will be freed at the end of this
62105b261ecSmrg     * function.
62205b261ecSmrg     */
6234642e01fSmrg    names->keymap = NULL;
62405b261ecSmrg    if (names->keycodes) names->keycodes = _XkbDupString(names->keycodes);
62505b261ecSmrg    if (names->types) names->types = _XkbDupString(names->types);
62605b261ecSmrg    if (names->compat) names->compat = _XkbDupString(names->compat);
62705b261ecSmrg    if (names->geometry) names->geometry = _XkbDupString(names->geometry);
62805b261ecSmrg    if (names->symbols) names->symbols = _XkbDupString(names->symbols);
62905b261ecSmrg
63005b261ecSmrg    if (defs.model && defs.layout && rules) {
63105b261ecSmrg	XkbComponentNamesRec	rNames;
63205b261ecSmrg	bzero(&rNames,sizeof(XkbComponentNamesRec));
63305b261ecSmrg	if (XkbDDXNamesFromRules(dev,rules,&defs,&rNames)) {
63405b261ecSmrg	    if (rNames.keycodes) {
63505b261ecSmrg		if (!names->keycodes)
63605b261ecSmrg		    names->keycodes =  rNames.keycodes;
63705b261ecSmrg		else
63805b261ecSmrg		    _XkbFree(rNames.keycodes);
63905b261ecSmrg	    }
64005b261ecSmrg	    if (rNames.types) {
64105b261ecSmrg		if (!names->types)
64205b261ecSmrg		    names->types = rNames.types;
64305b261ecSmrg		else  _XkbFree(rNames.types);
64405b261ecSmrg	    }
64505b261ecSmrg	    if (rNames.compat) {
64605b261ecSmrg		if (!names->compat)
64705b261ecSmrg		    names->compat =  rNames.compat;
64805b261ecSmrg		else  _XkbFree(rNames.compat);
64905b261ecSmrg	    }
65005b261ecSmrg	    if (rNames.symbols) {
65105b261ecSmrg		if (!names->symbols)
65205b261ecSmrg		    names->symbols =  rNames.symbols;
65305b261ecSmrg		else _XkbFree(rNames.symbols);
65405b261ecSmrg	    }
65505b261ecSmrg	    if (rNames.geometry) {
65605b261ecSmrg		if (!names->geometry)
65705b261ecSmrg		    names->geometry = rNames.geometry;
65805b261ecSmrg		else _XkbFree(rNames.geometry);
65905b261ecSmrg	    }
66005b261ecSmrg	    XkbSetRulesUsed(&defs);
66105b261ecSmrg	}
66205b261ecSmrg    }
66305b261ecSmrg
6644642e01fSmrg    ok = (Bool) XkbDDXLoadKeymapByNames(dev,names,XkmAllIndicesMask,0,
6654642e01fSmrg                                        &xkb,name,PATH_MAX);
66605b261ecSmrg
6674642e01fSmrg    if (ok && (xkb!=NULL)) {
66805b261ecSmrg	KeyCode		minKC,maxKC;
66905b261ecSmrg
67005b261ecSmrg	minKC= xkb->min_key_code;
67105b261ecSmrg	maxKC= xkb->max_key_code;
67205b261ecSmrg	if (XkbIsLegalKeycode(minKC)&&XkbIsLegalKeycode(maxKC)&&(minKC<=maxKC)&&
67305b261ecSmrg	    ((minKC!=pSyms->minKeyCode)||(maxKC!=pSyms->maxKeyCode))) {
67405b261ecSmrg	    if (xkb->map!=NULL) {
67505b261ecSmrg		KeySym	*inSym,*outSym;
67605b261ecSmrg		int	width= pSymsIn->mapWidth;
67705b261ecSmrg
67805b261ecSmrg		tmpSyms.minKeyCode= minKC;
67905b261ecSmrg		tmpSyms.maxKeyCode= maxKC;
68005b261ecSmrg
68105b261ecSmrg		if (minKC<pSymsIn->minKeyCode)
68205b261ecSmrg		    minKC= pSymsIn->minKeyCode;
68305b261ecSmrg		if (maxKC>pSymsIn->maxKeyCode)
68405b261ecSmrg		    maxKC= pSymsIn->maxKeyCode;
68505b261ecSmrg
68605b261ecSmrg		tmpSyms.mapWidth= width;
68705b261ecSmrg		tmpSyms.map= _XkbTypedCalloc(width*XkbNumKeys(xkb),KeySym);
68805b261ecSmrg		inSym= &pSymsIn->map[(minKC-pSymsIn->minKeyCode)*width];
68905b261ecSmrg		outSym= &tmpSyms.map[(minKC-tmpSyms.minKeyCode)*width];
69005b261ecSmrg		memcpy(outSym,inSym,((maxKC-minKC+1)*width)*sizeof(KeySym));
69105b261ecSmrg		pSyms= &tmpSyms;
69205b261ecSmrg	    }
69305b261ecSmrg	    if ((xkb->map!=NULL)&&(xkb->map->modmap!=NULL)) {
69405b261ecSmrg		bzero(tmpMods,XkbMaxKeyCount);
69505b261ecSmrg		memcpy(tmpMods,xkb->map->modmap,maxKC+1);
69605b261ecSmrg		pMods= tmpMods;
69705b261ecSmrg	    }
69805b261ecSmrg	}
6994642e01fSmrg        /* Store the map here so we can pick it back up in XkbInitDevice.
7004642e01fSmrg         * Sigh. */
7014642e01fSmrg        xkb_cached_map = xkb;
70205b261ecSmrg    }
70305b261ecSmrg    else {
70405b261ecSmrg	LogMessage(X_WARNING, "Couldn't load XKB keymap, falling back to pre-XKB keymap\n");
70505b261ecSmrg    }
70605b261ecSmrg    ok= InitKeyboardDeviceStruct((DevicePtr)dev,pSyms,pMods,bellProc,ctrlProc);
7074642e01fSmrg    xkb_cached_map = NULL;
70805b261ecSmrg    if ((pSyms==&tmpSyms)&&(pSyms->map!=NULL)) {
70905b261ecSmrg	_XkbFree(pSyms->map);
71005b261ecSmrg	pSyms->map= NULL;
71105b261ecSmrg    }
71205b261ecSmrg
71305b261ecSmrg    if (names->keycodes) _XkbFree(names->keycodes);
71405b261ecSmrg    names->keycodes = NULL;
71505b261ecSmrg    if (names->types) _XkbFree(names->types);
71605b261ecSmrg    names->types = NULL;
71705b261ecSmrg    if (names->compat) _XkbFree(names->compat);
71805b261ecSmrg    names->compat = NULL;
71905b261ecSmrg    if (names->geometry) _XkbFree(names->geometry);
72005b261ecSmrg    names->geometry = NULL;
72105b261ecSmrg    if (names->symbols) _XkbFree(names->symbols);
72205b261ecSmrg    names->symbols = NULL;
72305b261ecSmrg
72405b261ecSmrg    return ok;
72505b261ecSmrg}
72605b261ecSmrg
72705b261ecSmrg/***====================================================================***/
72805b261ecSmrg
72905b261ecSmrg	/*
73005b261ecSmrg	 * InitKeyClassDeviceStruct initializes the key class before it
73105b261ecSmrg	 * initializes the keyboard feedback class for a device.
73205b261ecSmrg	 * UpdateActions can't set up the correct autorepeat for keyboard
73305b261ecSmrg	 * initialization because the keyboard feedback isn't created yet.
73405b261ecSmrg	 * Instead, UpdateActions notes the "correct" autorepeat in the
73505b261ecSmrg	 * SrvInfo structure and InitKbdFeedbackClass calls UpdateAutoRepeat
73605b261ecSmrg	 * to apply the computed autorepeat once the feedback class exists.
73705b261ecSmrg	 *
73805b261ecSmrg	 * DIX will apply the changed autorepeat, so there's no need to
73905b261ecSmrg	 * do so here.   This function returns True if both RepeatKeys and
74005b261ecSmrg	 * the core protocol autorepeat ctrls are set (i.e. should use
74105b261ecSmrg	 * software autorepeat), false otherwise.
74205b261ecSmrg	 *
74305b261ecSmrg	 * This function also computes the autorepeat accelerators for the
74405b261ecSmrg	 * default indicator feedback.
74505b261ecSmrg	 */
74605b261ecSmrgint
74705b261ecSmrgXkbFinishDeviceInit(DeviceIntPtr pXDev)
74805b261ecSmrg{
74905b261ecSmrgXkbSrvInfoPtr		xkbi;
75005b261ecSmrgXkbDescPtr		xkb;
75105b261ecSmrgint			softRepeat;
75205b261ecSmrgXkbSrvLedInfoPtr	sli;
75305b261ecSmrg
75405b261ecSmrg    xkbi = NULL;
75505b261ecSmrg    if (pXDev && pXDev->key && pXDev->key->xkbInfo && pXDev->kbdfeed) {
75605b261ecSmrg	xkbi= pXDev->key->xkbInfo;
75705b261ecSmrg	xkb= xkbi->desc;
7584642e01fSmrg        /* If we come from DeepCopyDeviceClasses, the CtrlProc was already set
7594642e01fSmrg         * to XkbDDXKeybdCtrlProc, overwriting it leads to happy recursion.
7604642e01fSmrg         */
7614642e01fSmrg	if (pXDev->kbdfeed && pXDev->kbdfeed->CtrlProc != XkbDDXKeybdCtrlProc) {
76205b261ecSmrg	    xkbi->kbdProc= pXDev->kbdfeed->CtrlProc;
76305b261ecSmrg	    pXDev->kbdfeed->CtrlProc= XkbDDXKeybdCtrlProc;
76405b261ecSmrg	}
76505b261ecSmrg	if (pXDev->kbdfeed->ctrl.autoRepeat)
76605b261ecSmrg	    xkb->ctrls->enabled_ctrls|= XkbRepeatKeysMask;
76705b261ecSmrg	softRepeat= (xkb->ctrls->enabled_ctrls&XkbRepeatKeysMask)!=0;
76805b261ecSmrg	if (pXDev->kbdfeed) {
76905b261ecSmrg	    memcpy(pXDev->kbdfeed->ctrl.autoRepeats,
77005b261ecSmrg		   xkb->ctrls->per_key_repeat,XkbPerKeyBitArraySize);
77105b261ecSmrg	    softRepeat= softRepeat&&pXDev->kbdfeed->ctrl.autoRepeat;
77205b261ecSmrg	}
77305b261ecSmrg    }
77405b261ecSmrg    else softRepeat= 0;
77505b261ecSmrg    sli= XkbFindSrvLedInfo(pXDev,XkbDfltXIClass,XkbDfltXIId,0);
77605b261ecSmrg    if (sli && xkbi)
77705b261ecSmrg	XkbCheckIndicatorMaps(xkbi->device,sli,XkbAllIndicatorsMask);
7784642e01fSmrg    else DebugF("[xkb] No indicator feedback in XkbFinishInit (shouldn't happen)!\n");
77905b261ecSmrg    return softRepeat;
78005b261ecSmrg}
78105b261ecSmrg
78205b261ecSmrg	/*
78305b261ecSmrg	 * Be very careful about what does and doesn't get freed by this
78405b261ecSmrg	 * function.  To reduce fragmentation, XkbInitDevice allocates a
78505b261ecSmrg	 * single huge block per device and divides it up into most of the
78605b261ecSmrg	 * fixed-size structures for the device.   Don't free anything that
78705b261ecSmrg	 * is part of this larger block.
78805b261ecSmrg	 */
78905b261ecSmrgvoid
79005b261ecSmrgXkbFreeInfo(XkbSrvInfoPtr xkbi)
79105b261ecSmrg{
79205b261ecSmrg    if (xkbi->radioGroups) {
79305b261ecSmrg	_XkbFree(xkbi->radioGroups);
79405b261ecSmrg	xkbi->radioGroups= NULL;
79505b261ecSmrg    }
79605b261ecSmrg    if (xkbi->mouseKeyTimer) {
79705b261ecSmrg	TimerFree(xkbi->mouseKeyTimer);
79805b261ecSmrg	xkbi->mouseKeyTimer= NULL;
79905b261ecSmrg    }
80005b261ecSmrg    if (xkbi->slowKeysTimer) {
80105b261ecSmrg	TimerFree(xkbi->slowKeysTimer);
80205b261ecSmrg	xkbi->slowKeysTimer= NULL;
80305b261ecSmrg    }
80405b261ecSmrg    if (xkbi->bounceKeysTimer) {
80505b261ecSmrg	TimerFree(xkbi->bounceKeysTimer);
80605b261ecSmrg	xkbi->bounceKeysTimer= NULL;
80705b261ecSmrg    }
80805b261ecSmrg    if (xkbi->repeatKeyTimer) {
80905b261ecSmrg	TimerFree(xkbi->repeatKeyTimer);
81005b261ecSmrg	xkbi->repeatKeyTimer= NULL;
81105b261ecSmrg    }
81205b261ecSmrg    if (xkbi->krgTimer) {
81305b261ecSmrg	TimerFree(xkbi->krgTimer);
81405b261ecSmrg	xkbi->krgTimer= NULL;
81505b261ecSmrg    }
81605b261ecSmrg    xkbi->beepType= _BEEP_NONE;
81705b261ecSmrg    if (xkbi->beepTimer) {
81805b261ecSmrg	TimerFree(xkbi->beepTimer);
81905b261ecSmrg	xkbi->beepTimer= NULL;
82005b261ecSmrg    }
82105b261ecSmrg    if (xkbi->desc) {
82205b261ecSmrg	XkbFreeKeyboard(xkbi->desc,XkbAllComponentsMask,True);
82305b261ecSmrg	xkbi->desc= NULL;
82405b261ecSmrg    }
82505b261ecSmrg    _XkbFree(xkbi);
82605b261ecSmrg    return;
82705b261ecSmrg}
82805b261ecSmrg
82905b261ecSmrg/***====================================================================***/
83005b261ecSmrg
83105b261ecSmrgextern int	XkbDfltRepeatDelay;
83205b261ecSmrgextern int	XkbDfltRepeatInterval;
83305b261ecSmrg
83405b261ecSmrgextern unsigned short	XkbDfltAccessXTimeout;
83505b261ecSmrgextern unsigned int	XkbDfltAccessXTimeoutMask;
83605b261ecSmrgextern unsigned int	XkbDfltAccessXFeedback;
83705b261ecSmrgextern unsigned char	XkbDfltAccessXOptions;
83805b261ecSmrg
83905b261ecSmrgint
84005b261ecSmrgXkbProcessArguments(int argc,char *argv[],int i)
84105b261ecSmrg{
84205b261ecSmrg    if (strcmp(argv[i],"-kb")==0) {
84305b261ecSmrg	noXkbExtension= True;
84405b261ecSmrg	return 1;
84505b261ecSmrg    }
84605b261ecSmrg    else if (strcmp(argv[i],"+kb")==0) {
84705b261ecSmrg	noXkbExtension= False;
84805b261ecSmrg	return 1;
84905b261ecSmrg    }
85005b261ecSmrg    else if (strncmp(argv[i], "-xkbdir", 7) == 0) {
85105b261ecSmrg	if(++i < argc) {
85205b261ecSmrg#if !defined(WIN32) && !defined(__CYGWIN__)
85305b261ecSmrg	    if (getuid() != geteuid()) {
85405b261ecSmrg		LogMessage(X_WARNING, "-xkbdir is not available for setuid X servers\n");
85505b261ecSmrg		return -1;
85605b261ecSmrg	    } else
85705b261ecSmrg#endif
85805b261ecSmrg	    {
85905b261ecSmrg		if (strlen(argv[i]) < PATH_MAX) {
86005b261ecSmrg		    XkbBaseDirectory= argv[i];
86105b261ecSmrg		    return 2;
86205b261ecSmrg	        } else {
86305b261ecSmrg		    LogMessage(X_ERROR, "-xkbdir pathname too long\n");
86405b261ecSmrg		    return -1;
86505b261ecSmrg		}
86605b261ecSmrg	    }
86705b261ecSmrg	}
86805b261ecSmrg	else {
86905b261ecSmrg	    return -1;
87005b261ecSmrg	}
87105b261ecSmrg    }
87205b261ecSmrg    else if ((strncmp(argv[i],"-accessx",8)==0)||
87305b261ecSmrg                 (strncmp(argv[i],"+accessx",8)==0)) {
87405b261ecSmrg	int j=1;
87505b261ecSmrg	if (argv[i][0]=='-')
87605b261ecSmrg	    XkbWantAccessX= 0;
87705b261ecSmrg	else {
87805b261ecSmrg	    XkbWantAccessX= 1;
87905b261ecSmrg
88005b261ecSmrg	    if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
88105b261ecSmrg		XkbDfltAccessXTimeout = atoi(argv[++i]);
88205b261ecSmrg		j++;
88305b261ecSmrg
88405b261ecSmrg		if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
88505b261ecSmrg		    /*
88605b261ecSmrg		     * presumption that the reasonably useful range of
88705b261ecSmrg		     * values fits in 0..MAXINT since SunOS 4 doesn't
88805b261ecSmrg		     * have strtoul.
88905b261ecSmrg		     */
89005b261ecSmrg		    XkbDfltAccessXTimeoutMask=(unsigned int)
89105b261ecSmrg					      strtol(argv[++i],NULL,16);
89205b261ecSmrg		    j++;
89305b261ecSmrg		}
89405b261ecSmrg		if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
89505b261ecSmrg		    if (argv[++i][0] == '1' )
89605b261ecSmrg			XkbDfltAccessXFeedback=XkbAccessXFeedbackMask;
89705b261ecSmrg		    else
89805b261ecSmrg			XkbDfltAccessXFeedback=0;
89905b261ecSmrg		    j++;
90005b261ecSmrg		}
90105b261ecSmrg		if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
90205b261ecSmrg		    XkbDfltAccessXOptions=(unsigned char)
90305b261ecSmrg					   strtol(argv[++i],NULL,16);
90405b261ecSmrg		    j++;
90505b261ecSmrg		}
90605b261ecSmrg	    }
90705b261ecSmrg	}
90805b261ecSmrg	return j;
90905b261ecSmrg    }
91005b261ecSmrg    if ((strcmp(argv[i], "-ardelay") == 0) ||
91105b261ecSmrg        (strcmp (argv[i], "-ar1") == 0)) {	/* -ardelay int */
91205b261ecSmrg	if (++i >= argc) UseMsg ();
91305b261ecSmrg	XkbDfltRepeatDelay = (long)atoi(argv[i]);
91405b261ecSmrg	return 2;
91505b261ecSmrg    }
91605b261ecSmrg    if ((strcmp(argv[i], "-arinterval") == 0) ||
91705b261ecSmrg        (strcmp (argv[i], "-ar2") == 0)) {	/* -arinterval int */
91805b261ecSmrg	if (++i >= argc) UseMsg ();
91905b261ecSmrg	XkbDfltRepeatInterval = (long)atoi(argv[i]);
92005b261ecSmrg	return 2;
92105b261ecSmrg    }
92205b261ecSmrg    return 0;
92305b261ecSmrg}
92405b261ecSmrg
92505b261ecSmrgvoid
92605b261ecSmrgXkbUseMsg(void)
92705b261ecSmrg{
92805b261ecSmrg    ErrorF("-kb                    disable the X Keyboard Extension\n");
92905b261ecSmrg    ErrorF("+kb                    enable the X Keyboard Extension\n");
93005b261ecSmrg    ErrorF("[+-]accessx [ timeout [ timeout_mask [ feedback [ options_mask] ] ] ]\n");
93105b261ecSmrg    ErrorF("                       enable/disable accessx key sequences\n");
93205b261ecSmrg    ErrorF("-ardelay               set XKB autorepeat delay\n");
93305b261ecSmrg    ErrorF("-arinterval            set XKB autorepeat interval\n");
93405b261ecSmrg}
935