1706f2543Smrg/************************************************************
2706f2543SmrgCopyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3706f2543Smrg
4706f2543SmrgPermission to use, copy, modify, and distribute this
5706f2543Smrgsoftware and its documentation for any purpose and without
6706f2543Smrgfee is hereby granted, provided that the above copyright
7706f2543Smrgnotice appear in all copies and that both that copyright
8706f2543Smrgnotice and this permission notice appear in supporting
9706f2543Smrgdocumentation, and that the name of Silicon Graphics not be
10706f2543Smrgused in advertising or publicity pertaining to distribution
11706f2543Smrgof the software without specific prior written permission.
12706f2543SmrgSilicon Graphics makes no representation about the suitability
13706f2543Smrgof this software for any purpose. It is provided "as is"
14706f2543Smrgwithout any express or implied warranty.
15706f2543Smrg
16706f2543SmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17706f2543SmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18706f2543SmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19706f2543SmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20706f2543SmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21706f2543SmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22706f2543SmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23706f2543SmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE.
24706f2543Smrg
25706f2543Smrg********************************************************/
26706f2543Smrg
27706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
28706f2543Smrg#include <dix-config.h>
29706f2543Smrg#endif
30706f2543Smrg
31706f2543Smrg#include <xkb-config.h>
32706f2543Smrg
33706f2543Smrg#include <stdio.h>
34706f2543Smrg#include <stdlib.h>
35706f2543Smrg#include <ctype.h>
36706f2543Smrg#include <unistd.h>
37706f2543Smrg#include <math.h>
38706f2543Smrg#include <X11/X.h>
39706f2543Smrg#include <X11/Xproto.h>
40706f2543Smrg#include <X11/keysym.h>
41706f2543Smrg#include <X11/Xatom.h>
42706f2543Smrg#include "misc.h"
43706f2543Smrg#include "inputstr.h"
44706f2543Smrg#include "opaque.h"
45706f2543Smrg#include "property.h"
46706f2543Smrg#include "scrnintstr.h"
47706f2543Smrg#define	XKBSRV_NEED_FILE_FUNCS
48706f2543Smrg#include <xkbsrv.h>
49706f2543Smrg#include "xkbgeom.h"
50706f2543Smrg#include <X11/extensions/XKMformat.h>
51706f2543Smrg#include "xkbfile.h"
52706f2543Smrg#include "xkb.h"
53706f2543Smrg
54706f2543Smrg#define	CREATE_ATOM(s)	MakeAtom(s,sizeof(s)-1,1)
55706f2543Smrg
56706f2543Smrg#if defined(__alpha) || defined(__alpha__)
57706f2543Smrg#define	LED_COMPOSE	2
58706f2543Smrg#define LED_CAPS	3
59706f2543Smrg#define	LED_SCROLL	4
60706f2543Smrg#define	LED_NUM		5
61706f2543Smrg#define	PHYS_LEDS	0x1f
62706f2543Smrg#else
63706f2543Smrg#ifdef sun
64706f2543Smrg#define LED_NUM		1
65706f2543Smrg#define	LED_SCROLL	2
66706f2543Smrg#define	LED_COMPOSE	3
67706f2543Smrg#define LED_CAPS	4
68706f2543Smrg#define	PHYS_LEDS	0x0f
69706f2543Smrg#else
70706f2543Smrg#define	LED_CAPS	1
71706f2543Smrg#define	LED_NUM		2
72706f2543Smrg#define	LED_SCROLL	3
73706f2543Smrg#define	PHYS_LEDS	0x07
74706f2543Smrg#endif
75706f2543Smrg#endif
76706f2543Smrg
77706f2543Smrg#define	MAX_TOC	16
78706f2543Smrgtypedef struct	_SrvXkmInfo {
79706f2543Smrg	DeviceIntPtr	dev;
80706f2543Smrg	FILE *		file;
81706f2543Smrg	XkbDescPtr	xkb;
82706f2543Smrg} SrvXkmInfo;
83706f2543Smrg
84706f2543Smrg
85706f2543Smrg/***====================================================================***/
86706f2543Smrg
87706f2543Smrg#ifndef XKB_DFLT_RULES_PROP
88706f2543Smrg#define	XKB_DFLT_RULES_PROP	TRUE
89706f2543Smrg#endif
90706f2543Smrg
91706f2543Smrgchar	*		XkbBaseDirectory=	XKB_BASE_DIRECTORY;
92706f2543Smrgchar	*		XkbBinDirectory=	XKB_BIN_DIRECTORY;
93706f2543Smrgstatic int	 	XkbWantAccessX=		0;
94706f2543Smrg
95706f2543Smrgstatic char *		XkbRulesDflt=		NULL;
96706f2543Smrgstatic char *		XkbModelDflt=		NULL;
97706f2543Smrgstatic char *		XkbLayoutDflt=		NULL;
98706f2543Smrgstatic char *		XkbVariantDflt=		NULL;
99706f2543Smrgstatic char *		XkbOptionsDflt=		NULL;
100706f2543Smrg
101706f2543Smrgstatic char *           XkbRulesUsed=   NULL;
102706f2543Smrgstatic char *		XkbModelUsed=	NULL;
103706f2543Smrgstatic char *		XkbLayoutUsed=	NULL;
104706f2543Smrgstatic char *		XkbVariantUsed=	NULL;
105706f2543Smrgstatic char *		XkbOptionsUsed=	NULL;
106706f2543Smrg
107706f2543Smrgstatic XkbDescPtr	xkb_cached_map = NULL;
108706f2543Smrg
109706f2543Smrgstatic Bool		XkbWantRulesProp=	XKB_DFLT_RULES_PROP;
110706f2543Smrg
111706f2543Smrg/***====================================================================***/
112706f2543Smrg
113706f2543Smrg/**
114706f2543Smrg * Get the current default XKB rules.
115706f2543Smrg * Caller must free the data in rmlvo.
116706f2543Smrg */
117706f2543Smrgvoid
118706f2543SmrgXkbGetRulesDflts(XkbRMLVOSet *rmlvo)
119706f2543Smrg{
120706f2543Smrg    if (XkbRulesDflt)   rmlvo->rules = XkbRulesDflt;
121706f2543Smrg    else                rmlvo->rules = XKB_DFLT_RULES;
122706f2543Smrg    if (XkbModelDflt)	rmlvo->model= XkbModelDflt;
123706f2543Smrg    else		rmlvo->model= XKB_DFLT_MODEL;
124706f2543Smrg    if (XkbLayoutDflt)	rmlvo->layout= XkbLayoutDflt;
125706f2543Smrg    else		rmlvo->layout= XKB_DFLT_LAYOUT;
126706f2543Smrg    if (XkbVariantDflt)	rmlvo->variant= XkbVariantDflt;
127706f2543Smrg    else		rmlvo->variant= XKB_DFLT_VARIANT;
128706f2543Smrg    if (XkbOptionsDflt)	rmlvo->options= XkbOptionsDflt;
129706f2543Smrg    else		rmlvo->options= XKB_DFLT_OPTIONS;
130706f2543Smrg
131706f2543Smrg    rmlvo->rules = strdup(rmlvo->rules);
132706f2543Smrg    rmlvo->model = strdup(rmlvo->model);
133706f2543Smrg    rmlvo->layout = strdup(rmlvo->layout);
134706f2543Smrg    rmlvo->variant = strdup(rmlvo->variant);
135706f2543Smrg    rmlvo->options = strdup(rmlvo->options);
136706f2543Smrg}
137706f2543Smrg
138706f2543Smrgvoid
139706f2543SmrgXkbFreeRMLVOSet(XkbRMLVOSet *rmlvo, Bool freeRMLVO)
140706f2543Smrg{
141706f2543Smrg    if (!rmlvo)
142706f2543Smrg        return;
143706f2543Smrg
144706f2543Smrg    free(rmlvo->rules);
145706f2543Smrg    free(rmlvo->model);
146706f2543Smrg    free(rmlvo->layout);
147706f2543Smrg    free(rmlvo->variant);
148706f2543Smrg    free(rmlvo->options);
149706f2543Smrg
150706f2543Smrg    if (freeRMLVO)
151706f2543Smrg        free(rmlvo);
152706f2543Smrg    else
153706f2543Smrg        memset(rmlvo, 0, sizeof(XkbRMLVOSet));
154706f2543Smrg}
155706f2543Smrg
156706f2543Smrgstatic Bool
157706f2543SmrgXkbWriteRulesProp(ClientPtr client, pointer closure)
158706f2543Smrg{
159706f2543Smrgint 			len,out;
160706f2543SmrgAtom			name;
161706f2543Smrgchar *			pval;
162706f2543Smrg
163706f2543Smrg    len= (XkbRulesUsed?strlen(XkbRulesUsed):0);
164706f2543Smrg    len+= (XkbModelUsed?strlen(XkbModelUsed):0);
165706f2543Smrg    len+= (XkbLayoutUsed?strlen(XkbLayoutUsed):0);
166706f2543Smrg    len+= (XkbVariantUsed?strlen(XkbVariantUsed):0);
167706f2543Smrg    len+= (XkbOptionsUsed?strlen(XkbOptionsUsed):0);
168706f2543Smrg    if (len<1)
169706f2543Smrg	return TRUE;
170706f2543Smrg
171706f2543Smrg    len+= 5; /* trailing NULs */
172706f2543Smrg
173706f2543Smrg    name= MakeAtom(_XKB_RF_NAMES_PROP_ATOM,strlen(_XKB_RF_NAMES_PROP_ATOM),1);
174706f2543Smrg    if (name==None) {
175706f2543Smrg	ErrorF("[xkb] Atom error: %s not created\n",_XKB_RF_NAMES_PROP_ATOM);
176706f2543Smrg	return TRUE;
177706f2543Smrg    }
178706f2543Smrg    pval= (char*) malloc(len);
179706f2543Smrg    if (!pval) {
180706f2543Smrg	ErrorF("[xkb] Allocation error: %s proprerty not created\n",
181706f2543Smrg						_XKB_RF_NAMES_PROP_ATOM);
182706f2543Smrg	return TRUE;
183706f2543Smrg    }
184706f2543Smrg    out= 0;
185706f2543Smrg    if (XkbRulesUsed) {
186706f2543Smrg	strcpy(&pval[out],XkbRulesUsed);
187706f2543Smrg	out+= strlen(XkbRulesUsed);
188706f2543Smrg    }
189706f2543Smrg    pval[out++]= '\0';
190706f2543Smrg    if (XkbModelUsed) {
191706f2543Smrg	strcpy(&pval[out],XkbModelUsed);
192706f2543Smrg	out+= strlen(XkbModelUsed);
193706f2543Smrg    }
194706f2543Smrg    pval[out++]= '\0';
195706f2543Smrg    if (XkbLayoutUsed) {
196706f2543Smrg	strcpy(&pval[out],XkbLayoutUsed);
197706f2543Smrg	out+= strlen(XkbLayoutUsed);
198706f2543Smrg    }
199706f2543Smrg    pval[out++]= '\0';
200706f2543Smrg    if (XkbVariantUsed) {
201706f2543Smrg	strcpy(&pval[out],XkbVariantUsed);
202706f2543Smrg	out+= strlen(XkbVariantUsed);
203706f2543Smrg    }
204706f2543Smrg    pval[out++]= '\0';
205706f2543Smrg    if (XkbOptionsUsed) {
206706f2543Smrg	strcpy(&pval[out],XkbOptionsUsed);
207706f2543Smrg	out+= strlen(XkbOptionsUsed);
208706f2543Smrg    }
209706f2543Smrg    pval[out++]= '\0';
210706f2543Smrg    if (out!=len) {
211706f2543Smrg	ErrorF("[xkb] Internal Error! bad size (%d!=%d) for _XKB_RULES_NAMES\n",
212706f2543Smrg								out,len);
213706f2543Smrg    }
214706f2543Smrg    dixChangeWindowProperty(serverClient, screenInfo.screens[0]->root, name, XA_STRING, 8,
215706f2543Smrg			    PropModeReplace, len, pval, TRUE);
216706f2543Smrg    free(pval);
217706f2543Smrg    return TRUE;
218706f2543Smrg}
219706f2543Smrg
220706f2543Smrgstatic void
221706f2543SmrgXkbSetRulesUsed(XkbRMLVOSet *rmlvo)
222706f2543Smrg{
223706f2543Smrg    free(XkbRulesUsed);
224706f2543Smrg    XkbRulesUsed= (rmlvo->rules?_XkbDupString(rmlvo->rules):NULL);
225706f2543Smrg    free(XkbModelUsed);
226706f2543Smrg    XkbModelUsed= (rmlvo->model?_XkbDupString(rmlvo->model):NULL);
227706f2543Smrg    free(XkbLayoutUsed);
228706f2543Smrg    XkbLayoutUsed= (rmlvo->layout?_XkbDupString(rmlvo->layout):NULL);
229706f2543Smrg    free(XkbVariantUsed);
230706f2543Smrg    XkbVariantUsed= (rmlvo->variant?_XkbDupString(rmlvo->variant):NULL);
231706f2543Smrg    free(XkbOptionsUsed);
232706f2543Smrg    XkbOptionsUsed= (rmlvo->options?_XkbDupString(rmlvo->options):NULL);
233706f2543Smrg    if (XkbWantRulesProp)
234706f2543Smrg	QueueWorkProc(XkbWriteRulesProp,NULL,NULL);
235706f2543Smrg    return;
236706f2543Smrg}
237706f2543Smrg
238706f2543Smrgvoid
239706f2543SmrgXkbSetRulesDflts(XkbRMLVOSet *rmlvo)
240706f2543Smrg{
241706f2543Smrg    if (rmlvo->rules) {
242706f2543Smrg        free(XkbRulesDflt);
243706f2543Smrg        XkbRulesDflt= _XkbDupString(rmlvo->rules);
244706f2543Smrg    }
245706f2543Smrg    if (rmlvo->model) {
246706f2543Smrg	free(XkbModelDflt);
247706f2543Smrg	XkbModelDflt= _XkbDupString(rmlvo->model);
248706f2543Smrg    }
249706f2543Smrg    if (rmlvo->layout) {
250706f2543Smrg	free(XkbLayoutDflt);
251706f2543Smrg	XkbLayoutDflt= _XkbDupString(rmlvo->layout);
252706f2543Smrg    }
253706f2543Smrg    if (rmlvo->variant) {
254706f2543Smrg	free(XkbVariantDflt);
255706f2543Smrg	XkbVariantDflt= _XkbDupString(rmlvo->variant);
256706f2543Smrg    }
257706f2543Smrg    if (rmlvo->options) {
258706f2543Smrg	free(XkbOptionsDflt);
259706f2543Smrg	XkbOptionsDflt= _XkbDupString(rmlvo->options);
260706f2543Smrg    }
261706f2543Smrg    return;
262706f2543Smrg}
263706f2543Smrg
264706f2543Smrgvoid
265706f2543SmrgXkbDeleteRulesDflts(void)
266706f2543Smrg{
267706f2543Smrg    free(XkbRulesDflt);
268706f2543Smrg    XkbRulesDflt = NULL;
269706f2543Smrg    free(XkbModelDflt);
270706f2543Smrg    XkbModelDflt = NULL;
271706f2543Smrg    free(XkbLayoutDflt);
272706f2543Smrg    XkbLayoutDflt = NULL;
273706f2543Smrg    free(XkbVariantDflt);
274706f2543Smrg    XkbVariantDflt = NULL;
275706f2543Smrg    free(XkbOptionsDflt);
276706f2543Smrg    XkbOptionsDflt = NULL;
277706f2543Smrg
278706f2543Smrg    XkbFreeKeyboard(xkb_cached_map, XkbAllComponentsMask, TRUE);
279706f2543Smrg    xkb_cached_map = NULL;
280706f2543Smrg}
281706f2543Smrg
282706f2543Smrg#define DIFFERS(a, b) (strcmp((a) ? (a) : "", (b) ? (b) : "") != 0)
283706f2543Smrg
284706f2543Smrgstatic Bool
285706f2543SmrgXkbCompareUsedRMLVO(XkbRMLVOSet *rmlvo)
286706f2543Smrg{
287706f2543Smrg    if (DIFFERS(rmlvo->rules, XkbRulesUsed) ||
288706f2543Smrg        DIFFERS(rmlvo->model, XkbModelUsed) ||
289706f2543Smrg        DIFFERS(rmlvo->layout, XkbLayoutUsed) ||
290706f2543Smrg        DIFFERS(rmlvo->variant, XkbVariantUsed) ||
291706f2543Smrg        DIFFERS(rmlvo->options, XkbOptionsUsed))
292706f2543Smrg        return FALSE;
293706f2543Smrg    return TRUE;
294706f2543Smrg}
295706f2543Smrg
296706f2543Smrg#undef DIFFERS
297706f2543Smrg
298706f2543Smrg/***====================================================================***/
299706f2543Smrg
300706f2543Smrg#include "xkbDflts.h"
301706f2543Smrg
302706f2543Smrgstatic Bool
303706f2543SmrgXkbInitKeyTypes(XkbDescPtr xkb)
304706f2543Smrg{
305706f2543Smrg    if (xkb->defined & XkmTypesMask)
306706f2543Smrg        return TRUE;
307706f2543Smrg
308706f2543Smrg    initTypeNames(NULL);
309706f2543Smrg    if (XkbAllocClientMap(xkb,XkbKeyTypesMask,num_dflt_types)!=Success)
310706f2543Smrg	return FALSE;
311706f2543Smrg    if (XkbCopyKeyTypes(dflt_types,xkb->map->types,num_dflt_types)!=
312706f2543Smrg    								 Success) {
313706f2543Smrg	return FALSE;
314706f2543Smrg    }
315706f2543Smrg    xkb->map->size_types= xkb->map->num_types= num_dflt_types;
316706f2543Smrg    return TRUE;
317706f2543Smrg}
318706f2543Smrg
319706f2543Smrgstatic void
320706f2543SmrgXkbInitRadioGroups(XkbSrvInfoPtr xkbi)
321706f2543Smrg{
322706f2543Smrg    xkbi->nRadioGroups = 0;
323706f2543Smrg    xkbi->radioGroups = NULL;
324706f2543Smrg    return;
325706f2543Smrg}
326706f2543Smrg
327706f2543Smrg
328706f2543Smrgstatic Status
329706f2543SmrgXkbInitCompatStructs(XkbDescPtr xkb)
330706f2543Smrg{
331706f2543Smrgregister int 	i;
332706f2543SmrgXkbCompatMapPtr	compat;
333706f2543Smrg
334706f2543Smrg    if (xkb->defined & XkmCompatMapMask)
335706f2543Smrg        return TRUE;
336706f2543Smrg
337706f2543Smrg    if (XkbAllocCompatMap(xkb,XkbAllCompatMask,num_dfltSI)!=Success)
338706f2543Smrg	return BadAlloc;
339706f2543Smrg    compat = xkb->compat;
340706f2543Smrg    if (compat->sym_interpret) {
341706f2543Smrg	compat->num_si = num_dfltSI;
342706f2543Smrg	memcpy((char *)compat->sym_interpret,(char *)dfltSI,sizeof(dfltSI));
343706f2543Smrg    }
344706f2543Smrg    for (i=0;i<XkbNumKbdGroups;i++) {
345706f2543Smrg	compat->groups[i]= compatMap.groups[i];
346706f2543Smrg	if (compat->groups[i].vmods!=0) {
347706f2543Smrg	    unsigned mask;
348706f2543Smrg	    mask= XkbMaskForVMask(xkb,compat->groups[i].vmods);
349706f2543Smrg	    compat->groups[i].mask= compat->groups[i].real_mods|mask;
350706f2543Smrg	}
351706f2543Smrg	else compat->groups[i].mask= compat->groups[i].real_mods;
352706f2543Smrg    }
353706f2543Smrg    return Success;
354706f2543Smrg}
355706f2543Smrg
356706f2543Smrgstatic void
357706f2543SmrgXkbInitSemantics(XkbDescPtr xkb)
358706f2543Smrg{
359706f2543Smrg    XkbInitKeyTypes(xkb);
360706f2543Smrg    XkbInitCompatStructs(xkb);
361706f2543Smrg    return;
362706f2543Smrg}
363706f2543Smrg
364706f2543Smrg/***====================================================================***/
365706f2543Smrg
366706f2543Smrgstatic Status
367706f2543SmrgXkbInitNames(XkbSrvInfoPtr xkbi)
368706f2543Smrg{
369706f2543SmrgXkbDescPtr	xkb;
370706f2543SmrgXkbNamesPtr	names;
371706f2543SmrgStatus		rtrn;
372706f2543SmrgAtom		unknown;
373706f2543Smrg
374706f2543Smrg    xkb= xkbi->desc;
375706f2543Smrg    if ((rtrn=XkbAllocNames(xkb,XkbAllNamesMask,0,0))!=Success)
376706f2543Smrg	return rtrn;
377706f2543Smrg    unknown= CREATE_ATOM("unknown");
378706f2543Smrg    names = xkb->names;
379706f2543Smrg    if (names->keycodes==None)		names->keycodes= unknown;
380706f2543Smrg    if (names->geometry==None)		names->geometry= unknown;
381706f2543Smrg    if (names->phys_symbols==None)	names->phys_symbols= unknown;
382706f2543Smrg    if (names->symbols==None)		names->symbols= unknown;
383706f2543Smrg    if (names->types==None)		names->types= unknown;
384706f2543Smrg    if (names->compat==None)		names->compat= unknown;
385706f2543Smrg    if (!(xkb->defined & XkmVirtualModsMask)) {
386706f2543Smrg        if (names->vmods[vmod_NumLock]==None)
387706f2543Smrg            names->vmods[vmod_NumLock]= CREATE_ATOM("NumLock");
388706f2543Smrg        if (names->vmods[vmod_Alt]==None)
389706f2543Smrg            names->vmods[vmod_Alt]= CREATE_ATOM("Alt");
390706f2543Smrg        if (names->vmods[vmod_AltGr]==None)
391706f2543Smrg            names->vmods[vmod_AltGr]= CREATE_ATOM("ModeSwitch");
392706f2543Smrg    }
393706f2543Smrg
394706f2543Smrg    if (!(xkb->defined & XkmIndicatorsMask) ||
395706f2543Smrg        !(xkb->defined & XkmGeometryMask)) {
396706f2543Smrg        initIndicatorNames(NULL,xkb);
397706f2543Smrg        if (names->indicators[LED_CAPS-1]==None)
398706f2543Smrg            names->indicators[LED_CAPS-1] = CREATE_ATOM("Caps Lock");
399706f2543Smrg        if (names->indicators[LED_NUM-1]==None)
400706f2543Smrg            names->indicators[LED_NUM-1] = CREATE_ATOM("Num Lock");
401706f2543Smrg        if (names->indicators[LED_SCROLL-1]==None)
402706f2543Smrg            names->indicators[LED_SCROLL-1] = CREATE_ATOM("Scroll Lock");
403706f2543Smrg#ifdef LED_COMPOSE
404706f2543Smrg        if (names->indicators[LED_COMPOSE-1]==None)
405706f2543Smrg            names->indicators[LED_COMPOSE-1] = CREATE_ATOM("Compose");
406706f2543Smrg#endif
407706f2543Smrg    }
408706f2543Smrg
409706f2543Smrg    if (xkb->geom!=NULL)
410706f2543Smrg	 names->geometry= xkb->geom->name;
411706f2543Smrg    else names->geometry= unknown;
412706f2543Smrg
413706f2543Smrg    return Success;
414706f2543Smrg}
415706f2543Smrg
416706f2543Smrgstatic Status
417706f2543SmrgXkbInitIndicatorMap(XkbSrvInfoPtr xkbi)
418706f2543Smrg{
419706f2543SmrgXkbDescPtr		xkb;
420706f2543SmrgXkbIndicatorPtr		map;
421706f2543SmrgXkbSrvLedInfoPtr	sli;
422706f2543Smrg
423706f2543Smrg    xkb= xkbi->desc;
424706f2543Smrg    if (XkbAllocIndicatorMaps(xkb)!=Success)
425706f2543Smrg	return BadAlloc;
426706f2543Smrg
427706f2543Smrg    if (!(xkb->defined & XkmIndicatorsMask)) {
428706f2543Smrg        map= xkb->indicators;
429706f2543Smrg        map->phys_indicators = PHYS_LEDS;
430706f2543Smrg        map->maps[LED_CAPS-1].flags= XkbIM_NoExplicit;
431706f2543Smrg        map->maps[LED_CAPS-1].which_mods= XkbIM_UseLocked;
432706f2543Smrg        map->maps[LED_CAPS-1].mods.mask= LockMask;
433706f2543Smrg        map->maps[LED_CAPS-1].mods.real_mods= LockMask;
434706f2543Smrg
435706f2543Smrg        map->maps[LED_NUM-1].flags= XkbIM_NoExplicit;
436706f2543Smrg        map->maps[LED_NUM-1].which_mods= XkbIM_UseLocked;
437706f2543Smrg        map->maps[LED_NUM-1].mods.mask= 0;
438706f2543Smrg        map->maps[LED_NUM-1].mods.real_mods= 0;
439706f2543Smrg        map->maps[LED_NUM-1].mods.vmods= vmod_NumLockMask;
440706f2543Smrg
441706f2543Smrg        map->maps[LED_SCROLL-1].flags= XkbIM_NoExplicit;
442706f2543Smrg        map->maps[LED_SCROLL-1].which_mods= XkbIM_UseLocked;
443706f2543Smrg        map->maps[LED_SCROLL-1].mods.mask= Mod3Mask;
444706f2543Smrg        map->maps[LED_SCROLL-1].mods.real_mods= Mod3Mask;
445706f2543Smrg    }
446706f2543Smrg
447706f2543Smrg    sli= XkbFindSrvLedInfo(xkbi->device,XkbDfltXIClass,XkbDfltXIId,0);
448706f2543Smrg    if (sli)
449706f2543Smrg	XkbCheckIndicatorMaps(xkbi->device,sli,XkbAllIndicatorsMask);
450706f2543Smrg
451706f2543Smrg    return Success;
452706f2543Smrg}
453706f2543Smrg
454706f2543Smrgstatic Status
455706f2543SmrgXkbInitControls(DeviceIntPtr pXDev,XkbSrvInfoPtr xkbi)
456706f2543Smrg{
457706f2543SmrgXkbDescPtr	xkb;
458706f2543SmrgXkbControlsPtr	ctrls;
459706f2543Smrg
460706f2543Smrg    xkb= xkbi->desc;
461706f2543Smrg    /* 12/31/94 (ef) -- XXX! Should check if controls loaded from file */
462706f2543Smrg    if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success)
463706f2543Smrg	FatalError("Couldn't allocate keyboard controls\n");
464706f2543Smrg    ctrls= xkb->ctrls;
465706f2543Smrg    if (!(xkb->defined & XkmSymbolsMask))
466706f2543Smrg        ctrls->num_groups = 1;
467706f2543Smrg    ctrls->groups_wrap = XkbSetGroupInfo(1,XkbWrapIntoRange,0);
468706f2543Smrg    ctrls->internal.mask = 0;
469706f2543Smrg    ctrls->internal.real_mods = 0;
470706f2543Smrg    ctrls->internal.vmods = 0;
471706f2543Smrg    ctrls->ignore_lock.mask = 0;
472706f2543Smrg    ctrls->ignore_lock.real_mods = 0;
473706f2543Smrg    ctrls->ignore_lock.vmods = 0;
474706f2543Smrg    ctrls->enabled_ctrls = XkbAccessXTimeoutMask|XkbRepeatKeysMask|
475706f2543Smrg				XkbMouseKeysAccelMask|XkbAudibleBellMask|
476706f2543Smrg				XkbIgnoreGroupLockMask;
477706f2543Smrg    if (XkbWantAccessX)
478706f2543Smrg	ctrls->enabled_ctrls|= XkbAccessXKeysMask;
479706f2543Smrg    AccessXInit(pXDev);
480706f2543Smrg    return Success;
481706f2543Smrg}
482706f2543Smrg
483706f2543Smrg_X_EXPORT Bool
484706f2543SmrgInitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet *rmlvo,
485706f2543Smrg                         BellProcPtr bell_func, KbdCtrlProcPtr ctrl_func)
486706f2543Smrg{
487706f2543Smrg    int	i;
488706f2543Smrg    unsigned int check;
489706f2543Smrg    XkbSrvInfoPtr xkbi;
490706f2543Smrg    XkbDescPtr xkb;
491706f2543Smrg    XkbSrvLedInfoPtr sli;
492706f2543Smrg    XkbChangesRec changes;
493706f2543Smrg    XkbEventCauseRec cause;
494706f2543Smrg    XkbRMLVOSet rmlvo_dflts = { NULL };
495706f2543Smrg
496706f2543Smrg    if (dev->key || dev->kbdfeed)
497706f2543Smrg	return FALSE;
498706f2543Smrg
499706f2543Smrg    if (!rmlvo)
500706f2543Smrg    {
501706f2543Smrg        rmlvo = &rmlvo_dflts;
502706f2543Smrg        XkbGetRulesDflts(rmlvo);
503706f2543Smrg    }
504706f2543Smrg
505706f2543Smrg
506706f2543Smrg    memset(&changes, 0, sizeof(changes));
507706f2543Smrg    XkbSetCauseUnknown(&cause);
508706f2543Smrg
509706f2543Smrg    dev->key = calloc(1, sizeof(*dev->key));
510706f2543Smrg    if (!dev->key) {
511706f2543Smrg        ErrorF("XKB: Failed to allocate key class\n");
512706f2543Smrg        return FALSE;
513706f2543Smrg    }
514706f2543Smrg    dev->key->sourceid = dev->id;
515706f2543Smrg
516706f2543Smrg    dev->kbdfeed = calloc(1, sizeof(*dev->kbdfeed));
517706f2543Smrg    if (!dev->kbdfeed) {
518706f2543Smrg        ErrorF("XKB: Failed to allocate key feedback class\n");
519706f2543Smrg        goto unwind_key;
520706f2543Smrg    }
521706f2543Smrg
522706f2543Smrg    xkbi = calloc(1, sizeof(*xkbi));
523706f2543Smrg    if (!xkbi) {
524706f2543Smrg        ErrorF("XKB: Failed to allocate XKB info\n");
525706f2543Smrg        goto unwind_kbdfeed;
526706f2543Smrg    }
527706f2543Smrg    dev->key->xkbInfo = xkbi;
528706f2543Smrg
529706f2543Smrg    if (xkb_cached_map && !XkbCompareUsedRMLVO(rmlvo)) {
530706f2543Smrg        XkbFreeKeyboard(xkb_cached_map, XkbAllComponentsMask, TRUE);
531706f2543Smrg        xkb_cached_map = NULL;
532706f2543Smrg    }
533706f2543Smrg
534706f2543Smrg    if (xkb_cached_map)
535706f2543Smrg        LogMessageVerb(X_INFO, 4, "XKB: Reusing cached keymap\n");
536706f2543Smrg    else {
537706f2543Smrg        xkb_cached_map = XkbCompileKeymap(dev, rmlvo);
538706f2543Smrg        if (!xkb_cached_map) {
539706f2543Smrg            ErrorF("XKB: Failed to compile keymap\n");
540706f2543Smrg            goto unwind_info;
541706f2543Smrg        }
542706f2543Smrg    }
543706f2543Smrg
544706f2543Smrg    xkb = XkbAllocKeyboard();
545706f2543Smrg    if (!xkb) {
546706f2543Smrg        ErrorF("XKB: Failed to allocate keyboard description\n");
547706f2543Smrg        goto unwind_info;
548706f2543Smrg    }
549706f2543Smrg
550706f2543Smrg    if (!XkbCopyKeymap(xkb, xkb_cached_map)) {
551706f2543Smrg        ErrorF("XKB: Failed to copy keymap\n");
552706f2543Smrg        goto unwind_desc;
553706f2543Smrg    }
554706f2543Smrg    xkb->defined = xkb_cached_map->defined;
555706f2543Smrg    xkb->flags = xkb_cached_map->flags;
556706f2543Smrg    xkb->device_spec = xkb_cached_map->device_spec;
557706f2543Smrg    xkbi->desc = xkb;
558706f2543Smrg
559706f2543Smrg    if (xkb->min_key_code == 0)
560706f2543Smrg        xkb->min_key_code = 8;
561706f2543Smrg    if (xkb->max_key_code == 0)
562706f2543Smrg        xkb->max_key_code = 255;
563706f2543Smrg
564706f2543Smrg    i = XkbNumKeys(xkb) / 3 + 1;
565706f2543Smrg    if (XkbAllocClientMap(xkb, XkbAllClientInfoMask, 0) != Success)
566706f2543Smrg        goto unwind_desc;
567706f2543Smrg    if (XkbAllocServerMap(xkb, XkbAllServerInfoMask, i) != Success)
568706f2543Smrg        goto unwind_desc;
569706f2543Smrg
570706f2543Smrg    xkbi->dfltPtrDelta = 1;
571706f2543Smrg    xkbi->device = dev;
572706f2543Smrg
573706f2543Smrg    XkbInitSemantics(xkb);
574706f2543Smrg    XkbInitNames(xkbi);
575706f2543Smrg    XkbInitRadioGroups(xkbi);
576706f2543Smrg
577706f2543Smrg    XkbInitControls(dev, xkbi);
578706f2543Smrg
579706f2543Smrg    XkbInitIndicatorMap(xkbi);
580706f2543Smrg
581706f2543Smrg    XkbUpdateActions(dev, xkb->min_key_code, XkbNumKeys(xkb), &changes,
582706f2543Smrg                     &check, &cause);
583706f2543Smrg
584706f2543Smrg    InitFocusClassDeviceStruct(dev);
585706f2543Smrg
586706f2543Smrg    xkbi->kbdProc = ctrl_func;
587706f2543Smrg    dev->kbdfeed->BellProc = bell_func;
588706f2543Smrg    dev->kbdfeed->CtrlProc = XkbDDXKeybdCtrlProc;
589706f2543Smrg
590706f2543Smrg    dev->kbdfeed->ctrl = defaultKeyboardControl;
591706f2543Smrg    if (dev->kbdfeed->ctrl.autoRepeat)
592706f2543Smrg        xkb->ctrls->enabled_ctrls |= XkbRepeatKeysMask;
593706f2543Smrg
594706f2543Smrg    memcpy(dev->kbdfeed->ctrl.autoRepeats, xkb->ctrls->per_key_repeat,
595706f2543Smrg           XkbPerKeyBitArraySize);
596706f2543Smrg
597706f2543Smrg    sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 0);
598706f2543Smrg    if (sli)
599706f2543Smrg	XkbCheckIndicatorMaps(dev, sli, XkbAllIndicatorsMask);
600706f2543Smrg    else
601706f2543Smrg        DebugF("XKB: No indicator feedback in XkbFinishInit!\n");
602706f2543Smrg
603706f2543Smrg    dev->kbdfeed->CtrlProc(dev,&dev->kbdfeed->ctrl);
604706f2543Smrg
605706f2543Smrg    XkbSetRulesDflts(rmlvo);
606706f2543Smrg    XkbSetRulesUsed(rmlvo);
607706f2543Smrg    XkbFreeRMLVOSet(&rmlvo_dflts, FALSE);
608706f2543Smrg
609706f2543Smrg    return TRUE;
610706f2543Smrg
611706f2543Smrgunwind_desc:
612706f2543Smrg    XkbFreeKeyboard(xkb, 0, TRUE);
613706f2543Smrgunwind_info:
614706f2543Smrg    free(xkbi);
615706f2543Smrg    dev->key->xkbInfo = NULL;
616706f2543Smrgunwind_kbdfeed:
617706f2543Smrg    free(dev->kbdfeed);
618706f2543Smrg    dev->kbdfeed = NULL;
619706f2543Smrgunwind_key:
620706f2543Smrg    free(dev->key);
621706f2543Smrg    dev->key = NULL;
622706f2543Smrg    return FALSE;
623706f2543Smrg}
624706f2543Smrg
625706f2543Smrg
626706f2543Smrg/***====================================================================***/
627706f2543Smrg
628706f2543Smrg	/*
629706f2543Smrg	 * Be very careful about what does and doesn't get freed by this
630706f2543Smrg	 * function.  To reduce fragmentation, XkbInitDevice allocates a
631706f2543Smrg	 * single huge block per device and divides it up into most of the
632706f2543Smrg	 * fixed-size structures for the device.   Don't free anything that
633706f2543Smrg	 * is part of this larger block.
634706f2543Smrg	 */
635706f2543Smrgvoid
636706f2543SmrgXkbFreeInfo(XkbSrvInfoPtr xkbi)
637706f2543Smrg{
638706f2543Smrg    free(xkbi->radioGroups);
639706f2543Smrg    xkbi->radioGroups = NULL;
640706f2543Smrg    if (xkbi->mouseKeyTimer) {
641706f2543Smrg	TimerFree(xkbi->mouseKeyTimer);
642706f2543Smrg	xkbi->mouseKeyTimer= NULL;
643706f2543Smrg    }
644706f2543Smrg    if (xkbi->slowKeysTimer) {
645706f2543Smrg	TimerFree(xkbi->slowKeysTimer);
646706f2543Smrg	xkbi->slowKeysTimer= NULL;
647706f2543Smrg    }
648706f2543Smrg    if (xkbi->bounceKeysTimer) {
649706f2543Smrg	TimerFree(xkbi->bounceKeysTimer);
650706f2543Smrg	xkbi->bounceKeysTimer= NULL;
651706f2543Smrg    }
652706f2543Smrg    if (xkbi->repeatKeyTimer) {
653706f2543Smrg	TimerFree(xkbi->repeatKeyTimer);
654706f2543Smrg	xkbi->repeatKeyTimer= NULL;
655706f2543Smrg    }
656706f2543Smrg    if (xkbi->krgTimer) {
657706f2543Smrg	TimerFree(xkbi->krgTimer);
658706f2543Smrg	xkbi->krgTimer= NULL;
659706f2543Smrg    }
660706f2543Smrg    xkbi->beepType= _BEEP_NONE;
661706f2543Smrg    if (xkbi->beepTimer) {
662706f2543Smrg	TimerFree(xkbi->beepTimer);
663706f2543Smrg	xkbi->beepTimer= NULL;
664706f2543Smrg    }
665706f2543Smrg    if (xkbi->desc) {
666706f2543Smrg	XkbFreeKeyboard(xkbi->desc,XkbAllComponentsMask,TRUE);
667706f2543Smrg	xkbi->desc= NULL;
668706f2543Smrg    }
669706f2543Smrg    free(xkbi);
670706f2543Smrg    return;
671706f2543Smrg}
672706f2543Smrg
673706f2543Smrg/***====================================================================***/
674706f2543Smrg
675706f2543Smrgextern int	XkbDfltRepeatDelay;
676706f2543Smrgextern int	XkbDfltRepeatInterval;
677706f2543Smrg
678706f2543Smrgextern unsigned short	XkbDfltAccessXTimeout;
679706f2543Smrgextern unsigned int	XkbDfltAccessXTimeoutMask;
680706f2543Smrgextern unsigned int	XkbDfltAccessXFeedback;
681706f2543Smrgextern unsigned char	XkbDfltAccessXOptions;
682706f2543Smrg
683706f2543Smrgint
684706f2543SmrgXkbProcessArguments(int argc,char *argv[],int i)
685706f2543Smrg{
686706f2543Smrg    if (strncmp(argv[i], "-xkbdir", 7) == 0) {
687706f2543Smrg	if(++i < argc) {
688706f2543Smrg#if !defined(WIN32) && !defined(__CYGWIN__)
689706f2543Smrg	    if (getuid() != geteuid()) {
690706f2543Smrg		LogMessage(X_WARNING, "-xkbdir is not available for setuid X servers\n");
691706f2543Smrg		return -1;
692706f2543Smrg	    } else
693706f2543Smrg#endif
694706f2543Smrg	    {
695706f2543Smrg		if (strlen(argv[i]) < PATH_MAX) {
696706f2543Smrg		    XkbBaseDirectory= argv[i];
697706f2543Smrg		    return 2;
698706f2543Smrg	        } else {
699706f2543Smrg		    LogMessage(X_ERROR, "-xkbdir pathname too long\n");
700706f2543Smrg		    return -1;
701706f2543Smrg		}
702706f2543Smrg	    }
703706f2543Smrg	}
704706f2543Smrg	else {
705706f2543Smrg	    return -1;
706706f2543Smrg	}
707706f2543Smrg    }
708706f2543Smrg    else if ((strncmp(argv[i],"-accessx",8)==0)||
709706f2543Smrg                 (strncmp(argv[i],"+accessx",8)==0)) {
710706f2543Smrg	int j=1;
711706f2543Smrg	if (argv[i][0]=='-')
712706f2543Smrg	    XkbWantAccessX= 0;
713706f2543Smrg	else {
714706f2543Smrg	    XkbWantAccessX= 1;
715706f2543Smrg
716706f2543Smrg	    if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
717706f2543Smrg		XkbDfltAccessXTimeout = atoi(argv[++i]);
718706f2543Smrg		j++;
719706f2543Smrg
720706f2543Smrg		if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
721706f2543Smrg		    /*
722706f2543Smrg		     * presumption that the reasonably useful range of
723706f2543Smrg		     * values fits in 0..MAXINT since SunOS 4 doesn't
724706f2543Smrg		     * have strtoul.
725706f2543Smrg		     */
726706f2543Smrg		    XkbDfltAccessXTimeoutMask=(unsigned int)
727706f2543Smrg					      strtol(argv[++i],NULL,16);
728706f2543Smrg		    j++;
729706f2543Smrg		}
730706f2543Smrg		if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
731706f2543Smrg		    if (argv[++i][0] == '1' )
732706f2543Smrg			XkbDfltAccessXFeedback=XkbAccessXFeedbackMask;
733706f2543Smrg		    else
734706f2543Smrg			XkbDfltAccessXFeedback=0;
735706f2543Smrg		    j++;
736706f2543Smrg		}
737706f2543Smrg		if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
738706f2543Smrg		    XkbDfltAccessXOptions=(unsigned char)
739706f2543Smrg					   strtol(argv[++i],NULL,16);
740706f2543Smrg		    j++;
741706f2543Smrg		}
742706f2543Smrg	    }
743706f2543Smrg	}
744706f2543Smrg	return j;
745706f2543Smrg    }
746706f2543Smrg    if ((strcmp(argv[i], "-ardelay") == 0) ||
747706f2543Smrg        (strcmp (argv[i], "-ar1") == 0)) {	/* -ardelay int */
748706f2543Smrg	if (++i >= argc) UseMsg ();
749706f2543Smrg	XkbDfltRepeatDelay = (long)atoi(argv[i]);
750706f2543Smrg	return 2;
751706f2543Smrg    }
752706f2543Smrg    if ((strcmp(argv[i], "-arinterval") == 0) ||
753706f2543Smrg        (strcmp (argv[i], "-ar2") == 0)) {	/* -arinterval int */
754706f2543Smrg	if (++i >= argc) UseMsg ();
755706f2543Smrg	XkbDfltRepeatInterval = (long)atoi(argv[i]);
756706f2543Smrg	return 2;
757706f2543Smrg    }
758706f2543Smrg    return 0;
759706f2543Smrg}
760706f2543Smrg
761706f2543Smrgvoid
762706f2543SmrgXkbUseMsg(void)
763706f2543Smrg{
764706f2543Smrg    ErrorF("[+-]accessx [ timeout [ timeout_mask [ feedback [ options_mask] ] ] ]\n");
765706f2543Smrg    ErrorF("                       enable/disable accessx key sequences\n");
766706f2543Smrg    ErrorF("-ardelay               set XKB autorepeat delay\n");
767706f2543Smrg    ErrorF("-arinterval            set XKB autorepeat interval\n");
768706f2543Smrg}
769