xkbInit.c revision 4642e01f
1/************************************************************
2Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3
4Permission to use, copy, modify, and distribute this
5software and its documentation for any purpose and without
6fee is hereby granted, provided that the above copyright
7notice appear in all copies and that both that copyright
8notice and this permission notice appear in supporting
9documentation, and that the name of Silicon Graphics not be
10used in advertising or publicity pertaining to distribution
11of the software without specific prior written permission.
12Silicon Graphics makes no representation about the suitability
13of this software for any purpose. It is provided "as is"
14without any express or implied warranty.
15
16SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25********************************************************/
26
27#ifdef HAVE_DIX_CONFIG_H
28#include <dix-config.h>
29#endif
30
31#ifdef HAVE_XKB_CONFIG_H
32#include <xkb-config.h>
33#endif
34
35#include <stdio.h>
36#include <stdlib.h>
37#include <ctype.h>
38#include <unistd.h>
39#include <math.h>
40#define NEED_EVENTS 1
41#include <X11/X.h>
42#include <X11/Xproto.h>
43#include <X11/keysym.h>
44#include <X11/Xatom.h>
45#include "misc.h"
46#include "inputstr.h"
47#include "opaque.h"
48#include "property.h"
49#define	XKBSRV_NEED_FILE_FUNCS
50#include <xkbsrv.h>
51#include "xkbgeom.h"
52#include <X11/extensions/XKMformat.h>
53#include "xkbfile.h"
54#include "xkb.h"
55
56#define	CREATE_ATOM(s)	MakeAtom(s,sizeof(s)-1,1)
57
58#if defined(__alpha) || defined(__alpha__)
59#define	LED_COMPOSE	2
60#define LED_CAPS	3
61#define	LED_SCROLL	4
62#define	LED_NUM		5
63#define	PHYS_LEDS	0x1f
64#else
65#ifdef sun
66#define LED_NUM		1
67#define	LED_SCROLL	2
68#define	LED_COMPOSE	3
69#define LED_CAPS	4
70#define	PHYS_LEDS	0x0f
71#else
72#define	LED_CAPS	1
73#define	LED_NUM		2
74#define	LED_SCROLL	3
75#define	PHYS_LEDS	0x07
76#endif
77#endif
78
79#define	MAX_TOC	16
80typedef struct	_SrvXkmInfo {
81	DeviceIntPtr	dev;
82	FILE *		file;
83	XkbDescPtr	xkb;
84} SrvXkmInfo;
85
86
87/***====================================================================***/
88
89#ifndef XKB_BASE_DIRECTORY
90#define	XKB_BASE_DIRECTORY	"/usr/lib/X11/xkb"
91#endif
92#ifndef XKB_BIN_DIRECTORY
93#define	XKB_BIN_DIRECTORY	XKB_BASE_DIRECTORY
94#endif
95#ifndef XKB_DFLT_RULES_FILE
96#define	XKB_DFLT_RULES_FILE	"base"
97#endif
98#ifndef XKB_DFLT_KB_LAYOUT
99#define	XKB_DFLT_KB_LAYOUT	"us"
100#endif
101#ifndef XKB_DFLT_KB_MODEL
102#define	XKB_DFLT_KB_MODEL	"dflt"
103#endif
104#ifndef XKB_DFLT_KB_VARIANT
105#define	XKB_DFLT_KB_VARIANT	NULL
106#endif
107#ifndef XKB_DFLT_KB_OPTIONS
108#define	XKB_DFLT_KB_OPTIONS	NULL
109#endif
110#ifndef XKB_DFLT_DISABLED
111#define	XKB_DFLT_DISABLED	True
112#endif
113#ifndef XKB_DFLT_RULES_PROP
114#define	XKB_DFLT_RULES_PROP	True
115#endif
116
117char	*		XkbBaseDirectory=	XKB_BASE_DIRECTORY;
118char	*		XkbBinDirectory=	XKB_BIN_DIRECTORY;
119static int	 	XkbWantAccessX=		0;
120
121static Bool		rulesDefined=		False;
122static char *		XkbRulesFile=		NULL;
123static char *		XkbModelDflt=		NULL;
124static char *		XkbLayoutDflt=		NULL;
125static char *		XkbVariantDflt=		NULL;
126static char *		XkbOptionsDflt=		NULL;
127
128static char *		XkbModelUsed=	NULL;
129static char *		XkbLayoutUsed=	NULL;
130static char *		XkbVariantUsed=	NULL;
131static char *		XkbOptionsUsed=	NULL;
132
133static XkbDescPtr       xkb_cached_map = NULL;
134
135_X_EXPORT Bool		noXkbExtension=		XKB_DFLT_DISABLED;
136static Bool		XkbWantRulesProp=	XKB_DFLT_RULES_PROP;
137
138/***====================================================================***/
139
140static char *
141XkbGetRulesDflts(XkbRF_VarDefsPtr defs)
142{
143    if (XkbModelDflt)	defs->model= XkbModelDflt;
144    else		defs->model= XKB_DFLT_KB_MODEL;
145    if (XkbLayoutDflt)	defs->layout= XkbLayoutDflt;
146    else		defs->layout= XKB_DFLT_KB_LAYOUT;
147    if (XkbVariantDflt)	defs->variant= XkbVariantDflt;
148    else		defs->variant= XKB_DFLT_KB_VARIANT;
149    if (XkbOptionsDflt)	defs->options= XkbOptionsDflt;
150    else		defs->options= XKB_DFLT_KB_OPTIONS;
151    return (rulesDefined?XkbRulesFile:XKB_DFLT_RULES_FILE);
152}
153
154static Bool
155XkbWriteRulesProp(ClientPtr client, pointer closure)
156{
157int 			len,out;
158Atom			name;
159char *			pval;
160
161    if (rulesDefined && (!XkbRulesFile))
162	return False;
163    len= (XkbRulesFile?strlen(XkbRulesFile):strlen(XKB_DFLT_RULES_FILE));
164    len+= (XkbModelUsed?strlen(XkbModelUsed):0);
165    len+= (XkbLayoutUsed?strlen(XkbLayoutUsed):0);
166    len+= (XkbVariantUsed?strlen(XkbVariantUsed):0);
167    len+= (XkbOptionsUsed?strlen(XkbOptionsUsed):0);
168    if (len<1)
169	return True;
170
171    len+= 5; /* trailing NULs */
172
173    name= MakeAtom(_XKB_RF_NAMES_PROP_ATOM,strlen(_XKB_RF_NAMES_PROP_ATOM),1);
174    if (name==None) {
175	ErrorF("[xkb] Atom error: %s not created\n",_XKB_RF_NAMES_PROP_ATOM);
176	return True;
177    }
178    pval= (char*) xalloc(len);
179    if (!pval) {
180	ErrorF("[xkb] Allocation error: %s proprerty not created\n",
181						_XKB_RF_NAMES_PROP_ATOM);
182	return True;
183    }
184    out= 0;
185    if (XkbRulesFile) {
186	strcpy(&pval[out],XkbRulesFile);
187	out+= strlen(XkbRulesFile);
188    } else {
189	strcpy(&pval[out],XKB_DFLT_RULES_FILE);
190	out+= strlen(XKB_DFLT_RULES_FILE);
191    }
192    pval[out++]= '\0';
193    if (XkbModelUsed) {
194	strcpy(&pval[out],XkbModelUsed);
195	out+= strlen(XkbModelUsed);
196    }
197    pval[out++]= '\0';
198    if (XkbLayoutUsed) {
199	strcpy(&pval[out],XkbLayoutUsed);
200	out+= strlen(XkbLayoutUsed);
201    }
202    pval[out++]= '\0';
203    if (XkbVariantUsed) {
204	strcpy(&pval[out],XkbVariantUsed);
205	out+= strlen(XkbVariantUsed);
206    }
207    pval[out++]= '\0';
208    if (XkbOptionsUsed) {
209	strcpy(&pval[out],XkbOptionsUsed);
210	out+= strlen(XkbOptionsUsed);
211    }
212    pval[out++]= '\0';
213    if (out!=len) {
214	ErrorF("[xkb] Internal Error! bad size (%d!=%d) for _XKB_RULES_NAMES\n",
215								out,len);
216    }
217    dixChangeWindowProperty(serverClient, WindowTable[0], name, XA_STRING, 8,
218			    PropModeReplace, len, pval, True);
219    xfree(pval);
220    return True;
221}
222
223static void
224XkbSetRulesUsed(XkbRF_VarDefsPtr defs)
225{
226    if (XkbModelUsed)
227	_XkbFree(XkbModelUsed);
228    XkbModelUsed= (defs->model?_XkbDupString(defs->model):NULL);
229    if (XkbLayoutUsed)
230	_XkbFree(XkbLayoutUsed);
231    XkbLayoutUsed= (defs->layout?_XkbDupString(defs->layout):NULL);
232    if (XkbVariantUsed)
233	_XkbFree(XkbVariantUsed);
234    XkbVariantUsed= (defs->variant?_XkbDupString(defs->variant):NULL);
235    if (XkbOptionsUsed)
236	_XkbFree(XkbOptionsUsed);
237    XkbOptionsUsed= (defs->options?_XkbDupString(defs->options):NULL);
238    if (XkbWantRulesProp)
239	QueueWorkProc(XkbWriteRulesProp,NULL,NULL);
240    return;
241}
242
243/**
244 * Set the default RMLVO for the next device to be initialised.
245 * If a parameter is NULL, the previous setting will be used. Use empty
246 * strings if you want to delete a previous setting.
247 *
248 * If @rulesFile is NULL and no previous @rulesFile has been set, the
249 * built-in default is chosen as default.
250 */
251_X_EXPORT void
252XkbSetRulesDflts(char *rulesFile,char *model,char *layout,
253					char *variant,char *options)
254{
255    if (!rulesFile && !XkbRulesFile)
256    {
257	LogMessage(X_WARNING, "[xkb] No rule given, and no previous rule "
258		              "defined. Defaulting to '%s'.\n",
259                              XKB_DFLT_RULES_FILE);
260	rulesFile = XKB_DFLT_RULES_FILE;
261    }
262
263    if (rulesFile) {
264	if (XkbRulesFile)
265	    _XkbFree(XkbRulesFile);
266	XkbRulesFile= _XkbDupString(rulesFile);
267	rulesDefined= True;
268    }
269
270    if (model) {
271	if (XkbModelDflt)
272	    _XkbFree(XkbModelDflt);
273	XkbModelDflt= _XkbDupString(model);
274    }
275    if (layout) {
276	if (XkbLayoutDflt)
277	    _XkbFree(XkbLayoutDflt);
278	XkbLayoutDflt= _XkbDupString(layout);
279    }
280    if (variant) {
281	if (XkbVariantDflt)
282	    _XkbFree(XkbVariantDflt);
283	XkbVariantDflt= _XkbDupString(variant);
284    }
285    if (options) {
286	if (XkbOptionsDflt)
287	    _XkbFree(XkbOptionsDflt);
288	XkbOptionsDflt= _XkbDupString(options);
289    }
290    return;
291}
292
293void
294XkbDeleteRulesDflts()
295{
296    _XkbFree(XkbRulesFile);
297    XkbRulesFile = NULL;
298    _XkbFree(XkbModelDflt);
299    XkbModelDflt = NULL;
300    _XkbFree(XkbLayoutDflt);
301    XkbLayoutDflt = NULL;
302    _XkbFree(XkbVariantDflt);
303    XkbVariantDflt = NULL;
304    _XkbFree(XkbOptionsDflt);
305    XkbOptionsDflt = NULL;
306
307    XkbFreeKeyboard(xkb_cached_map, XkbAllComponentsMask, True);
308    xkb_cached_map = NULL;
309}
310
311/***====================================================================***/
312
313#include "xkbDflts.h"
314
315static Bool
316XkbInitKeyTypes(XkbDescPtr xkb)
317{
318    if (xkb->defined & XkmTypesMask)
319        return True;
320
321    initTypeNames(NULL);
322    if (XkbAllocClientMap(xkb,XkbKeyTypesMask,num_dflt_types)!=Success)
323	return False;
324    if (XkbCopyKeyTypes(dflt_types,xkb->map->types,num_dflt_types)!=
325    								 Success) {
326	return False;
327    }
328    xkb->map->size_types= xkb->map->num_types= num_dflt_types;
329    return True;
330}
331
332static void
333XkbInitRadioGroups(XkbSrvInfoPtr xkbi)
334{
335    xkbi->nRadioGroups = 0;
336    xkbi->radioGroups = NULL;
337    return;
338}
339
340
341static Status
342XkbInitCompatStructs(XkbDescPtr xkb)
343{
344register int 	i;
345XkbCompatMapPtr	compat;
346
347    if (xkb->defined & XkmCompatMapMask)
348        return True;
349
350    if (XkbAllocCompatMap(xkb,XkbAllCompatMask,num_dfltSI)!=Success)
351	return BadAlloc;
352    compat = xkb->compat;
353    if (compat->sym_interpret) {
354	compat->num_si = num_dfltSI;
355	memcpy((char *)compat->sym_interpret,(char *)dfltSI,sizeof(dfltSI));
356    }
357    for (i=0;i<XkbNumKbdGroups;i++) {
358	compat->groups[i]= compatMap.groups[i];
359	if (compat->groups[i].vmods!=0) {
360	    unsigned mask;
361	    mask= XkbMaskForVMask(xkb,compat->groups[i].vmods);
362	    compat->groups[i].mask= compat->groups[i].real_mods|mask;
363	}
364	else compat->groups[i].mask= compat->groups[i].real_mods;
365    }
366    return Success;
367}
368
369static void
370XkbInitSemantics(XkbDescPtr xkb)
371{
372    XkbInitKeyTypes(xkb);
373    XkbInitCompatStructs(xkb);
374    return;
375}
376
377/***====================================================================***/
378
379static Status
380XkbInitNames(XkbSrvInfoPtr xkbi)
381{
382XkbDescPtr	xkb;
383XkbNamesPtr	names;
384Status		rtrn;
385Atom		unknown;
386
387    xkb= xkbi->desc;
388    if ((rtrn=XkbAllocNames(xkb,XkbAllNamesMask,0,0))!=Success)
389	return rtrn;
390    unknown= CREATE_ATOM("unknown");
391    names = xkb->names;
392    if (names->keycodes==None)		names->keycodes= unknown;
393    if (names->geometry==None)		names->geometry= unknown;
394    if (names->phys_symbols==None)	names->phys_symbols= unknown;
395    if (names->symbols==None)		names->symbols= unknown;
396    if (names->types==None)		names->types= unknown;
397    if (names->compat==None)		names->compat= unknown;
398    if (!(xkb->defined & XkmVirtualModsMask)) {
399        if (names->vmods[vmod_NumLock]==None)
400            names->vmods[vmod_NumLock]= CREATE_ATOM("NumLock");
401        if (names->vmods[vmod_Alt]==None)
402            names->vmods[vmod_Alt]= CREATE_ATOM("Alt");
403        if (names->vmods[vmod_AltGr]==None)
404            names->vmods[vmod_AltGr]= CREATE_ATOM("ModeSwitch");
405    }
406
407    if (!(xkb->defined & XkmIndicatorsMask) ||
408        !(xkb->defined & XkmGeometryMask)) {
409        initIndicatorNames(NULL,xkb);
410        if (names->indicators[LED_CAPS-1]==None)
411            names->indicators[LED_CAPS-1] = CREATE_ATOM("Caps Lock");
412        if (names->indicators[LED_NUM-1]==None)
413            names->indicators[LED_NUM-1] = CREATE_ATOM("Num Lock");
414        if (names->indicators[LED_SCROLL-1]==None)
415            names->indicators[LED_SCROLL-1] = CREATE_ATOM("Scroll Lock");
416#ifdef LED_COMPOSE
417        if (names->indicators[LED_COMPOSE-1]==None)
418            names->indicators[LED_COMPOSE-1] = CREATE_ATOM("Compose");
419#endif
420    }
421
422    if (xkb->geom!=NULL)
423	 names->geometry= xkb->geom->name;
424    else names->geometry= unknown;
425
426    return Success;
427}
428
429static Status
430XkbInitIndicatorMap(XkbSrvInfoPtr xkbi)
431{
432XkbDescPtr		xkb;
433XkbIndicatorPtr		map;
434XkbSrvLedInfoPtr	sli;
435
436    xkb= xkbi->desc;
437    if (XkbAllocIndicatorMaps(xkb)!=Success)
438	return BadAlloc;
439
440    if (!(xkb->defined & XkmIndicatorsMask)) {
441        map= xkb->indicators;
442        map->phys_indicators = PHYS_LEDS;
443        map->maps[LED_CAPS-1].flags= XkbIM_NoExplicit;
444        map->maps[LED_CAPS-1].which_mods= XkbIM_UseLocked;
445        map->maps[LED_CAPS-1].mods.mask= LockMask;
446        map->maps[LED_CAPS-1].mods.real_mods= LockMask;
447
448        map->maps[LED_NUM-1].flags= XkbIM_NoExplicit;
449        map->maps[LED_NUM-1].which_mods= XkbIM_UseLocked;
450        map->maps[LED_NUM-1].mods.mask= 0;
451        map->maps[LED_NUM-1].mods.real_mods= 0;
452        map->maps[LED_NUM-1].mods.vmods= vmod_NumLockMask;
453
454        map->maps[LED_SCROLL-1].flags= XkbIM_NoExplicit;
455        map->maps[LED_SCROLL-1].which_mods= XkbIM_UseLocked;
456        map->maps[LED_SCROLL-1].mods.mask= Mod3Mask;
457        map->maps[LED_SCROLL-1].mods.real_mods= Mod3Mask;
458    }
459
460    sli= XkbFindSrvLedInfo(xkbi->device,XkbDfltXIClass,XkbDfltXIId,0);
461    if (sli)
462	XkbCheckIndicatorMaps(xkbi->device,sli,XkbAllIndicatorsMask);
463
464    return Success;
465}
466
467static Status
468XkbInitControls(DeviceIntPtr pXDev,XkbSrvInfoPtr xkbi)
469{
470XkbDescPtr	xkb;
471XkbControlsPtr	ctrls;
472
473    xkb= xkbi->desc;
474    /* 12/31/94 (ef) -- XXX! Should check if controls loaded from file */
475    if (XkbAllocControls(xkb,XkbAllControlsMask)!=Success)
476	FatalError("Couldn't allocate keyboard controls\n");
477    ctrls= xkb->ctrls;
478    if (!(xkb->defined & XkmSymbolsMask))
479        ctrls->num_groups = 1;
480    ctrls->groups_wrap = XkbSetGroupInfo(1,XkbWrapIntoRange,0);
481    ctrls->internal.mask = 0;
482    ctrls->internal.real_mods = 0;
483    ctrls->internal.vmods = 0;
484    ctrls->ignore_lock.mask = 0;
485    ctrls->ignore_lock.real_mods = 0;
486    ctrls->ignore_lock.vmods = 0;
487    ctrls->enabled_ctrls = XkbAccessXTimeoutMask|XkbRepeatKeysMask|
488				XkbMouseKeysAccelMask|XkbAudibleBellMask|
489				XkbIgnoreGroupLockMask;
490    if (XkbWantAccessX)
491	ctrls->enabled_ctrls|= XkbAccessXKeysMask;
492    AccessXInit(pXDev);
493    return Success;
494}
495
496void
497XkbInitDevice(DeviceIntPtr pXDev)
498{
499int			i;
500XkbSrvInfoPtr		xkbi;
501XkbChangesRec		changes;
502unsigned		check;
503XkbEventCauseRec	cause;
504
505    bzero(&changes,sizeof(XkbChangesRec));
506    pXDev->key->xkbInfo= xkbi= _XkbTypedCalloc(1,XkbSrvInfoRec);
507    if ( xkbi ) {
508	XkbDescPtr	xkb;
509
510        if (xkb_cached_map) {
511            xkbi->desc = xkb_cached_map;
512            xkb_cached_map = NULL;
513        }
514        else {
515            xkbi->desc= XkbAllocKeyboard();
516            if (!xkbi->desc)
517                FatalError("Couldn't allocate keyboard description\n");
518            xkbi->desc->min_key_code = pXDev->key->curKeySyms.minKeyCode;
519            xkbi->desc->max_key_code = pXDev->key->curKeySyms.maxKeyCode;
520        }
521	xkb= xkbi->desc;
522	if (xkb->min_key_code == 0)
523	    xkb->min_key_code = pXDev->key->curKeySyms.minKeyCode;
524	if (xkb->max_key_code == 0)
525	    xkb->max_key_code = pXDev->key->curKeySyms.maxKeyCode;
526	if ((pXDev->key->curKeySyms.minKeyCode!=xkbi->desc->min_key_code)||
527	    (pXDev->key->curKeySyms.maxKeyCode!=xkbi->desc->max_key_code)) {
528	    /* 12/9/95 (ef) -- XXX! Maybe we should try to fix up one or */
529	    /*                 the other here, but for now just complain */
530	    /*                 can't just update the core range without */
531	    /*                 reallocating the KeySymsRec (pain)       */
532	    ErrorF("[xkb] Internal Error!! XKB and core keymap have different range\n");
533	}
534	if (XkbAllocClientMap(xkb,XkbAllClientInfoMask,0)!=Success)
535	    FatalError("Couldn't allocate client map in XkbInitDevice\n");
536	i= XkbNumKeys(xkb)/3+1;
537	if (XkbAllocServerMap(xkb,XkbAllServerInfoMask,i)!=Success)
538	    FatalError("Couldn't allocate server map in XkbInitDevice\n");
539
540	xkbi->dfltPtrDelta=1;
541	xkbi->device = pXDev;
542
543	XkbInitSemantics(xkb);
544	XkbInitNames(xkbi);
545	XkbInitRadioGroups(xkbi);
546
547	/* 12/31/94 (ef) -- XXX! Should check if state loaded from file */
548	bzero(&xkbi->state,sizeof(XkbStateRec));
549
550	XkbInitControls(pXDev,xkbi);
551
552        if (xkb->defined & XkmSymbolsMask)
553            memcpy(pXDev->key->modifierMap, xkb->map->modmap,
554                   xkb->max_key_code + 1);
555        else
556            memcpy(xkb->map->modmap, pXDev->key->modifierMap,
557                   xkb->max_key_code + 1);
558
559	XkbInitIndicatorMap(xkbi);
560
561	XkbDDXInitDevice(pXDev);
562
563        if (xkb->defined & XkmSymbolsMask)
564            XkbUpdateCoreDescription(pXDev, True);
565        else
566            XkbUpdateKeyTypesFromCore(pXDev, xkb->min_key_code,
567                                      XkbNumKeys(xkb), &changes);
568
569	XkbSetCauseUnknown(&cause);
570	XkbUpdateActions(pXDev,xkb->min_key_code, XkbNumKeys(xkb),&changes,
571								&check,&cause);
572        /* For sanity.  The first time the connection
573         * is opened, the client side min and max are set
574         * using QueryMinMaxKeyCodes() which grabs them
575	 * from pXDev.
576	 */
577	pXDev->key->curKeySyms.minKeyCode = xkb->min_key_code;
578	pXDev->key->curKeySyms.maxKeyCode = xkb->max_key_code;
579    }
580    return;
581}
582
583#if MAP_LENGTH > XkbMaxKeyCount
584#undef  XkbMaxKeyCount
585#define XkbMaxKeyCount MAP_LENGTH
586#endif
587
588_X_EXPORT Bool
589XkbInitKeyboardDeviceStruct(
590    DeviceIntPtr		dev,
591    XkbComponentNamesPtr	names,
592    KeySymsPtr                  pSymsIn,
593    CARD8                       pModsIn[],
594    void                        (*bellProc)(
595        int /*percent*/,
596        DeviceIntPtr /*device*/,
597        pointer /*ctrl*/,
598        int),
599    void                        (*ctrlProc)(
600        DeviceIntPtr /*device*/,
601        KeybdCtrl * /*ctrl*/))
602{
603KeySymsRec		tmpSyms,*pSyms;
604CARD8			tmpMods[XkbMaxLegalKeyCode+1],*pMods;
605char			name[PATH_MAX],*rules;
606Bool			ok=False;
607XkbRF_VarDefsRec	defs;
608XkbDescPtr              xkb;
609
610    if ((dev->key!=NULL)||(dev->kbdfeed!=NULL))
611	return False;
612    pSyms= pSymsIn;
613    pMods= pModsIn;
614    bzero(&defs,sizeof(XkbRF_VarDefsRec));
615    rules= XkbGetRulesDflts(&defs);
616
617    /*
618     * The strings are duplicated because it is not guaranteed that
619     * they are allocated, or that they are allocated for every server
620     * generation. Eventually they will be freed at the end of this
621     * function.
622     */
623    names->keymap = NULL;
624    if (names->keycodes) names->keycodes = _XkbDupString(names->keycodes);
625    if (names->types) names->types = _XkbDupString(names->types);
626    if (names->compat) names->compat = _XkbDupString(names->compat);
627    if (names->geometry) names->geometry = _XkbDupString(names->geometry);
628    if (names->symbols) names->symbols = _XkbDupString(names->symbols);
629
630    if (defs.model && defs.layout && rules) {
631	XkbComponentNamesRec	rNames;
632	bzero(&rNames,sizeof(XkbComponentNamesRec));
633	if (XkbDDXNamesFromRules(dev,rules,&defs,&rNames)) {
634	    if (rNames.keycodes) {
635		if (!names->keycodes)
636		    names->keycodes =  rNames.keycodes;
637		else
638		    _XkbFree(rNames.keycodes);
639	    }
640	    if (rNames.types) {
641		if (!names->types)
642		    names->types = rNames.types;
643		else  _XkbFree(rNames.types);
644	    }
645	    if (rNames.compat) {
646		if (!names->compat)
647		    names->compat =  rNames.compat;
648		else  _XkbFree(rNames.compat);
649	    }
650	    if (rNames.symbols) {
651		if (!names->symbols)
652		    names->symbols =  rNames.symbols;
653		else _XkbFree(rNames.symbols);
654	    }
655	    if (rNames.geometry) {
656		if (!names->geometry)
657		    names->geometry = rNames.geometry;
658		else _XkbFree(rNames.geometry);
659	    }
660	    XkbSetRulesUsed(&defs);
661	}
662    }
663
664    ok = (Bool) XkbDDXLoadKeymapByNames(dev,names,XkmAllIndicesMask,0,
665                                        &xkb,name,PATH_MAX);
666
667    if (ok && (xkb!=NULL)) {
668	KeyCode		minKC,maxKC;
669
670	minKC= xkb->min_key_code;
671	maxKC= xkb->max_key_code;
672	if (XkbIsLegalKeycode(minKC)&&XkbIsLegalKeycode(maxKC)&&(minKC<=maxKC)&&
673	    ((minKC!=pSyms->minKeyCode)||(maxKC!=pSyms->maxKeyCode))) {
674	    if (xkb->map!=NULL) {
675		KeySym	*inSym,*outSym;
676		int	width= pSymsIn->mapWidth;
677
678		tmpSyms.minKeyCode= minKC;
679		tmpSyms.maxKeyCode= maxKC;
680
681		if (minKC<pSymsIn->minKeyCode)
682		    minKC= pSymsIn->minKeyCode;
683		if (maxKC>pSymsIn->maxKeyCode)
684		    maxKC= pSymsIn->maxKeyCode;
685
686		tmpSyms.mapWidth= width;
687		tmpSyms.map= _XkbTypedCalloc(width*XkbNumKeys(xkb),KeySym);
688		inSym= &pSymsIn->map[(minKC-pSymsIn->minKeyCode)*width];
689		outSym= &tmpSyms.map[(minKC-tmpSyms.minKeyCode)*width];
690		memcpy(outSym,inSym,((maxKC-minKC+1)*width)*sizeof(KeySym));
691		pSyms= &tmpSyms;
692	    }
693	    if ((xkb->map!=NULL)&&(xkb->map->modmap!=NULL)) {
694		bzero(tmpMods,XkbMaxKeyCount);
695		memcpy(tmpMods,xkb->map->modmap,maxKC+1);
696		pMods= tmpMods;
697	    }
698	}
699        /* Store the map here so we can pick it back up in XkbInitDevice.
700         * Sigh. */
701        xkb_cached_map = xkb;
702    }
703    else {
704	LogMessage(X_WARNING, "Couldn't load XKB keymap, falling back to pre-XKB keymap\n");
705    }
706    ok= InitKeyboardDeviceStruct((DevicePtr)dev,pSyms,pMods,bellProc,ctrlProc);
707    xkb_cached_map = NULL;
708    if ((pSyms==&tmpSyms)&&(pSyms->map!=NULL)) {
709	_XkbFree(pSyms->map);
710	pSyms->map= NULL;
711    }
712
713    if (names->keycodes) _XkbFree(names->keycodes);
714    names->keycodes = NULL;
715    if (names->types) _XkbFree(names->types);
716    names->types = NULL;
717    if (names->compat) _XkbFree(names->compat);
718    names->compat = NULL;
719    if (names->geometry) _XkbFree(names->geometry);
720    names->geometry = NULL;
721    if (names->symbols) _XkbFree(names->symbols);
722    names->symbols = NULL;
723
724    return ok;
725}
726
727/***====================================================================***/
728
729	/*
730	 * InitKeyClassDeviceStruct initializes the key class before it
731	 * initializes the keyboard feedback class for a device.
732	 * UpdateActions can't set up the correct autorepeat for keyboard
733	 * initialization because the keyboard feedback isn't created yet.
734	 * Instead, UpdateActions notes the "correct" autorepeat in the
735	 * SrvInfo structure and InitKbdFeedbackClass calls UpdateAutoRepeat
736	 * to apply the computed autorepeat once the feedback class exists.
737	 *
738	 * DIX will apply the changed autorepeat, so there's no need to
739	 * do so here.   This function returns True if both RepeatKeys and
740	 * the core protocol autorepeat ctrls are set (i.e. should use
741	 * software autorepeat), false otherwise.
742	 *
743	 * This function also computes the autorepeat accelerators for the
744	 * default indicator feedback.
745	 */
746int
747XkbFinishDeviceInit(DeviceIntPtr pXDev)
748{
749XkbSrvInfoPtr		xkbi;
750XkbDescPtr		xkb;
751int			softRepeat;
752XkbSrvLedInfoPtr	sli;
753
754    xkbi = NULL;
755    if (pXDev && pXDev->key && pXDev->key->xkbInfo && pXDev->kbdfeed) {
756	xkbi= pXDev->key->xkbInfo;
757	xkb= xkbi->desc;
758        /* If we come from DeepCopyDeviceClasses, the CtrlProc was already set
759         * to XkbDDXKeybdCtrlProc, overwriting it leads to happy recursion.
760         */
761	if (pXDev->kbdfeed && pXDev->kbdfeed->CtrlProc != XkbDDXKeybdCtrlProc) {
762	    xkbi->kbdProc= pXDev->kbdfeed->CtrlProc;
763	    pXDev->kbdfeed->CtrlProc= XkbDDXKeybdCtrlProc;
764	}
765	if (pXDev->kbdfeed->ctrl.autoRepeat)
766	    xkb->ctrls->enabled_ctrls|= XkbRepeatKeysMask;
767	softRepeat= (xkb->ctrls->enabled_ctrls&XkbRepeatKeysMask)!=0;
768	if (pXDev->kbdfeed) {
769	    memcpy(pXDev->kbdfeed->ctrl.autoRepeats,
770		   xkb->ctrls->per_key_repeat,XkbPerKeyBitArraySize);
771	    softRepeat= softRepeat&&pXDev->kbdfeed->ctrl.autoRepeat;
772	}
773    }
774    else softRepeat= 0;
775    sli= XkbFindSrvLedInfo(pXDev,XkbDfltXIClass,XkbDfltXIId,0);
776    if (sli && xkbi)
777	XkbCheckIndicatorMaps(xkbi->device,sli,XkbAllIndicatorsMask);
778    else DebugF("[xkb] No indicator feedback in XkbFinishInit (shouldn't happen)!\n");
779    return softRepeat;
780}
781
782	/*
783	 * Be very careful about what does and doesn't get freed by this
784	 * function.  To reduce fragmentation, XkbInitDevice allocates a
785	 * single huge block per device and divides it up into most of the
786	 * fixed-size structures for the device.   Don't free anything that
787	 * is part of this larger block.
788	 */
789void
790XkbFreeInfo(XkbSrvInfoPtr xkbi)
791{
792    if (xkbi->radioGroups) {
793	_XkbFree(xkbi->radioGroups);
794	xkbi->radioGroups= NULL;
795    }
796    if (xkbi->mouseKeyTimer) {
797	TimerFree(xkbi->mouseKeyTimer);
798	xkbi->mouseKeyTimer= NULL;
799    }
800    if (xkbi->slowKeysTimer) {
801	TimerFree(xkbi->slowKeysTimer);
802	xkbi->slowKeysTimer= NULL;
803    }
804    if (xkbi->bounceKeysTimer) {
805	TimerFree(xkbi->bounceKeysTimer);
806	xkbi->bounceKeysTimer= NULL;
807    }
808    if (xkbi->repeatKeyTimer) {
809	TimerFree(xkbi->repeatKeyTimer);
810	xkbi->repeatKeyTimer= NULL;
811    }
812    if (xkbi->krgTimer) {
813	TimerFree(xkbi->krgTimer);
814	xkbi->krgTimer= NULL;
815    }
816    xkbi->beepType= _BEEP_NONE;
817    if (xkbi->beepTimer) {
818	TimerFree(xkbi->beepTimer);
819	xkbi->beepTimer= NULL;
820    }
821    if (xkbi->desc) {
822	XkbFreeKeyboard(xkbi->desc,XkbAllComponentsMask,True);
823	xkbi->desc= NULL;
824    }
825    _XkbFree(xkbi);
826    return;
827}
828
829/***====================================================================***/
830
831extern int	XkbDfltRepeatDelay;
832extern int	XkbDfltRepeatInterval;
833
834extern unsigned short	XkbDfltAccessXTimeout;
835extern unsigned int	XkbDfltAccessXTimeoutMask;
836extern unsigned int	XkbDfltAccessXFeedback;
837extern unsigned char	XkbDfltAccessXOptions;
838
839int
840XkbProcessArguments(int argc,char *argv[],int i)
841{
842    if (strcmp(argv[i],"-kb")==0) {
843	noXkbExtension= True;
844	return 1;
845    }
846    else if (strcmp(argv[i],"+kb")==0) {
847	noXkbExtension= False;
848	return 1;
849    }
850    else if (strncmp(argv[i], "-xkbdir", 7) == 0) {
851	if(++i < argc) {
852#if !defined(WIN32) && !defined(__CYGWIN__)
853	    if (getuid() != geteuid()) {
854		LogMessage(X_WARNING, "-xkbdir is not available for setuid X servers\n");
855		return -1;
856	    } else
857#endif
858	    {
859		if (strlen(argv[i]) < PATH_MAX) {
860		    XkbBaseDirectory= argv[i];
861		    return 2;
862	        } else {
863		    LogMessage(X_ERROR, "-xkbdir pathname too long\n");
864		    return -1;
865		}
866	    }
867	}
868	else {
869	    return -1;
870	}
871    }
872    else if ((strncmp(argv[i],"-accessx",8)==0)||
873                 (strncmp(argv[i],"+accessx",8)==0)) {
874	int j=1;
875	if (argv[i][0]=='-')
876	    XkbWantAccessX= 0;
877	else {
878	    XkbWantAccessX= 1;
879
880	    if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
881		XkbDfltAccessXTimeout = atoi(argv[++i]);
882		j++;
883
884		if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
885		    /*
886		     * presumption that the reasonably useful range of
887		     * values fits in 0..MAXINT since SunOS 4 doesn't
888		     * have strtoul.
889		     */
890		    XkbDfltAccessXTimeoutMask=(unsigned int)
891					      strtol(argv[++i],NULL,16);
892		    j++;
893		}
894		if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
895		    if (argv[++i][0] == '1' )
896			XkbDfltAccessXFeedback=XkbAccessXFeedbackMask;
897		    else
898			XkbDfltAccessXFeedback=0;
899		    j++;
900		}
901		if ( ((i+1)<argc) && (isdigit(argv[i+1][0])) ) {
902		    XkbDfltAccessXOptions=(unsigned char)
903					   strtol(argv[++i],NULL,16);
904		    j++;
905		}
906	    }
907	}
908	return j;
909    }
910    if ((strcmp(argv[i], "-ardelay") == 0) ||
911        (strcmp (argv[i], "-ar1") == 0)) {	/* -ardelay int */
912	if (++i >= argc) UseMsg ();
913	XkbDfltRepeatDelay = (long)atoi(argv[i]);
914	return 2;
915    }
916    if ((strcmp(argv[i], "-arinterval") == 0) ||
917        (strcmp (argv[i], "-ar2") == 0)) {	/* -arinterval int */
918	if (++i >= argc) UseMsg ();
919	XkbDfltRepeatInterval = (long)atoi(argv[i]);
920	return 2;
921    }
922    return 0;
923}
924
925void
926XkbUseMsg(void)
927{
928    ErrorF("-kb                    disable the X Keyboard Extension\n");
929    ErrorF("+kb                    enable the X Keyboard Extension\n");
930    ErrorF("[+-]accessx [ timeout [ timeout_mask [ feedback [ options_mask] ] ] ]\n");
931    ErrorF("                       enable/disable accessx key sequences\n");
932    ErrorF("-ardelay               set XKB autorepeat delay\n");
933    ErrorF("-arinterval            set XKB autorepeat interval\n");
934}
935