xkbInit.c revision 1b5d61b8
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#include <xkb-config.h>
32
33#include <stdio.h>
34#include <stdlib.h>
35#include <ctype.h>
36#include <unistd.h>
37#include <math.h>
38#include <X11/X.h>
39#include <X11/Xproto.h>
40#include <X11/keysym.h>
41#include <X11/Xatom.h>
42#include "misc.h"
43#include "inputstr.h"
44#include "opaque.h"
45#include "property.h"
46#include "scrnintstr.h"
47#define	XKBSRV_NEED_FILE_FUNCS
48#include <xkbsrv.h>
49#include "xkbgeom.h"
50#include <X11/extensions/XKMformat.h>
51#include "xkbfile.h"
52#include "xkb.h"
53
54#define	CREATE_ATOM(s)	MakeAtom(s,sizeof(s)-1,1)
55
56#if defined(__alpha) || defined(__alpha__)
57#define	LED_COMPOSE	2
58#define LED_CAPS	3
59#define	LED_SCROLL	4
60#define	LED_NUM		5
61#define	PHYS_LEDS	0x1f
62#else
63#ifdef __sun
64#define LED_NUM		1
65#define	LED_SCROLL	2
66#define	LED_COMPOSE	3
67#define LED_CAPS	4
68#define	PHYS_LEDS	0x0f
69#else
70#define	LED_CAPS	1
71#define	LED_NUM		2
72#define	LED_SCROLL	3
73#define	PHYS_LEDS	0x07
74#endif
75#endif
76
77#define	MAX_TOC	16
78typedef struct _SrvXkmInfo {
79    DeviceIntPtr dev;
80    FILE *file;
81    XkbDescPtr xkb;
82} SrvXkmInfo;
83
84/***====================================================================***/
85
86#ifndef XKB_DFLT_RULES_PROP
87#define	XKB_DFLT_RULES_PROP	TRUE
88#endif
89
90const char *XkbBaseDirectory = XKB_BASE_DIRECTORY;
91const char *XkbBinDirectory = XKB_BIN_DIRECTORY;
92static int XkbWantAccessX = 0;
93
94static char *XkbRulesDflt = NULL;
95static char *XkbModelDflt = NULL;
96static char *XkbLayoutDflt = NULL;
97static char *XkbVariantDflt = NULL;
98static char *XkbOptionsDflt = NULL;
99
100static char *XkbRulesUsed = NULL;
101static char *XkbModelUsed = NULL;
102static char *XkbLayoutUsed = NULL;
103static char *XkbVariantUsed = NULL;
104static char *XkbOptionsUsed = NULL;
105
106static XkbDescPtr xkb_cached_map = NULL;
107
108static Bool XkbWantRulesProp = XKB_DFLT_RULES_PROP;
109
110/***====================================================================***/
111
112/**
113 * Get the current default XKB rules.
114 * Caller must free the data in rmlvo.
115 */
116void
117XkbGetRulesDflts(XkbRMLVOSet * rmlvo)
118{
119    rmlvo->rules = strdup(XkbRulesDflt ? XkbRulesDflt : XKB_DFLT_RULES);
120    rmlvo->model = strdup(XkbModelDflt ? XkbModelDflt : XKB_DFLT_MODEL);
121    rmlvo->layout = strdup(XkbLayoutDflt ? XkbLayoutDflt : XKB_DFLT_LAYOUT);
122    rmlvo->variant = strdup(XkbVariantDflt ? XkbVariantDflt : XKB_DFLT_VARIANT);
123    rmlvo->options = strdup(XkbOptionsDflt ? XkbOptionsDflt : XKB_DFLT_OPTIONS);
124}
125
126void
127XkbFreeRMLVOSet(XkbRMLVOSet * rmlvo, Bool freeRMLVO)
128{
129    if (!rmlvo)
130        return;
131
132    free(rmlvo->rules);
133    free(rmlvo->model);
134    free(rmlvo->layout);
135    free(rmlvo->variant);
136    free(rmlvo->options);
137
138    if (freeRMLVO)
139        free(rmlvo);
140    else
141        memset(rmlvo, 0, sizeof(XkbRMLVOSet));
142}
143
144static Bool
145XkbWriteRulesProp(ClientPtr client, void *closure)
146{
147    int len, out;
148    Atom name;
149    char *pval;
150
151    len = (XkbRulesUsed ? strlen(XkbRulesUsed) : 0);
152    len += (XkbModelUsed ? strlen(XkbModelUsed) : 0);
153    len += (XkbLayoutUsed ? strlen(XkbLayoutUsed) : 0);
154    len += (XkbVariantUsed ? strlen(XkbVariantUsed) : 0);
155    len += (XkbOptionsUsed ? strlen(XkbOptionsUsed) : 0);
156    if (len < 1)
157        return TRUE;
158
159    len += 5;                   /* trailing NULs */
160
161    name =
162        MakeAtom(_XKB_RF_NAMES_PROP_ATOM, strlen(_XKB_RF_NAMES_PROP_ATOM), 1);
163    if (name == None) {
164        ErrorF("[xkb] Atom error: %s not created\n", _XKB_RF_NAMES_PROP_ATOM);
165        return TRUE;
166    }
167    pval = (char *) malloc(len);
168    if (!pval) {
169        ErrorF("[xkb] Allocation error: %s proprerty not created\n",
170               _XKB_RF_NAMES_PROP_ATOM);
171        return TRUE;
172    }
173    out = 0;
174    if (XkbRulesUsed) {
175        strcpy(&pval[out], XkbRulesUsed);
176        out += strlen(XkbRulesUsed);
177    }
178    pval[out++] = '\0';
179    if (XkbModelUsed) {
180        strcpy(&pval[out], XkbModelUsed);
181        out += strlen(XkbModelUsed);
182    }
183    pval[out++] = '\0';
184    if (XkbLayoutUsed) {
185        strcpy(&pval[out], XkbLayoutUsed);
186        out += strlen(XkbLayoutUsed);
187    }
188    pval[out++] = '\0';
189    if (XkbVariantUsed) {
190        strcpy(&pval[out], XkbVariantUsed);
191        out += strlen(XkbVariantUsed);
192    }
193    pval[out++] = '\0';
194    if (XkbOptionsUsed) {
195        strcpy(&pval[out], XkbOptionsUsed);
196        out += strlen(XkbOptionsUsed);
197    }
198    pval[out++] = '\0';
199    if (out != len) {
200        ErrorF("[xkb] Internal Error! bad size (%d!=%d) for _XKB_RULES_NAMES\n",
201               out, len);
202    }
203    dixChangeWindowProperty(serverClient, screenInfo.screens[0]->root, name,
204                            XA_STRING, 8, PropModeReplace, len, pval, TRUE);
205    free(pval);
206    return TRUE;
207}
208
209void
210XkbInitRules(XkbRMLVOSet *rmlvo,
211             const char *rules,
212             const char *model,
213             const char *layout,
214             const char *variant,
215             const char *options)
216{
217    rmlvo->rules = rules ? xnfstrdup(rules) : NULL;
218    rmlvo->model = model ? xnfstrdup(model) : NULL;
219    rmlvo->layout = layout ? xnfstrdup(layout) : NULL;
220    rmlvo->variant = variant ? xnfstrdup(variant) : NULL;
221    rmlvo->options = options ? xnfstrdup(options) : NULL;
222}
223
224static void
225XkbSetRulesUsed(XkbRMLVOSet * rmlvo)
226{
227    free(XkbRulesUsed);
228    XkbRulesUsed = (rmlvo->rules ? Xstrdup(rmlvo->rules) : NULL);
229    free(XkbModelUsed);
230    XkbModelUsed = (rmlvo->model ? Xstrdup(rmlvo->model) : NULL);
231    free(XkbLayoutUsed);
232    XkbLayoutUsed = (rmlvo->layout ? Xstrdup(rmlvo->layout) : NULL);
233    free(XkbVariantUsed);
234    XkbVariantUsed = (rmlvo->variant ? Xstrdup(rmlvo->variant) : NULL);
235    free(XkbOptionsUsed);
236    XkbOptionsUsed = (rmlvo->options ? Xstrdup(rmlvo->options) : NULL);
237    if (XkbWantRulesProp)
238        QueueWorkProc(XkbWriteRulesProp, NULL, NULL);
239    return;
240}
241
242void
243XkbSetRulesDflts(XkbRMLVOSet * rmlvo)
244{
245    if (rmlvo->rules) {
246        free(XkbRulesDflt);
247        XkbRulesDflt = Xstrdup(rmlvo->rules);
248    }
249    if (rmlvo->model) {
250        free(XkbModelDflt);
251        XkbModelDflt = Xstrdup(rmlvo->model);
252    }
253    if (rmlvo->layout) {
254        free(XkbLayoutDflt);
255        XkbLayoutDflt = Xstrdup(rmlvo->layout);
256    }
257    if (rmlvo->variant) {
258        free(XkbVariantDflt);
259        XkbVariantDflt = Xstrdup(rmlvo->variant);
260    }
261    if (rmlvo->options) {
262        free(XkbOptionsDflt);
263        XkbOptionsDflt = Xstrdup(rmlvo->options);
264    }
265    return;
266}
267
268void
269XkbDeleteRulesUsed(void)
270{
271    free(XkbRulesUsed);
272    XkbRulesUsed = NULL;
273    free(XkbModelUsed);
274    XkbModelUsed = NULL;
275    free(XkbLayoutUsed);
276    XkbLayoutUsed = NULL;
277    free(XkbVariantUsed);
278    XkbVariantUsed = NULL;
279    free(XkbOptionsUsed);
280    XkbOptionsUsed = NULL;
281}
282
283void
284XkbDeleteRulesDflts(void)
285{
286    free(XkbRulesDflt);
287    XkbRulesDflt = NULL;
288    free(XkbModelDflt);
289    XkbModelDflt = NULL;
290    free(XkbLayoutDflt);
291    XkbLayoutDflt = NULL;
292    free(XkbVariantDflt);
293    XkbVariantDflt = NULL;
294    free(XkbOptionsDflt);
295    XkbOptionsDflt = NULL;
296
297    XkbFreeKeyboard(xkb_cached_map, XkbAllComponentsMask, TRUE);
298    xkb_cached_map = NULL;
299}
300
301#define DIFFERS(a, b) (strcmp((a) ? (a) : "", (b) ? (b) : "") != 0)
302
303static Bool
304XkbCompareUsedRMLVO(XkbRMLVOSet * rmlvo)
305{
306    if (DIFFERS(rmlvo->rules, XkbRulesUsed) ||
307        DIFFERS(rmlvo->model, XkbModelUsed) ||
308        DIFFERS(rmlvo->layout, XkbLayoutUsed) ||
309        DIFFERS(rmlvo->variant, XkbVariantUsed) ||
310        DIFFERS(rmlvo->options, XkbOptionsUsed))
311        return FALSE;
312    return TRUE;
313}
314
315#undef DIFFERS
316
317/***====================================================================***/
318
319#include "xkbDflts.h"
320
321static Bool
322XkbInitKeyTypes(XkbDescPtr xkb)
323{
324    if (xkb->defined & XkmTypesMask)
325        return TRUE;
326
327    initTypeNames(NULL);
328    if (XkbAllocClientMap(xkb, XkbKeyTypesMask, num_dflt_types) != Success)
329        return FALSE;
330    if (XkbCopyKeyTypes(dflt_types, xkb->map->types, num_dflt_types) != Success) {
331        return FALSE;
332    }
333    xkb->map->size_types = xkb->map->num_types = num_dflt_types;
334    return TRUE;
335}
336
337static void
338XkbInitRadioGroups(XkbSrvInfoPtr xkbi)
339{
340    xkbi->nRadioGroups = 0;
341    xkbi->radioGroups = NULL;
342    return;
343}
344
345static Status
346XkbInitCompatStructs(XkbDescPtr xkb)
347{
348    register int i;
349    XkbCompatMapPtr compat;
350
351    if (xkb->defined & XkmCompatMapMask)
352        return TRUE;
353
354    if (XkbAllocCompatMap(xkb, XkbAllCompatMask, num_dfltSI) != Success)
355        return BadAlloc;
356    compat = xkb->compat;
357    if (compat->sym_interpret) {
358        compat->num_si = num_dfltSI;
359        memcpy((char *) compat->sym_interpret, (char *) dfltSI, sizeof(dfltSI));
360    }
361    for (i = 0; i < XkbNumKbdGroups; i++) {
362        compat->groups[i] = compatMap.groups[i];
363        if (compat->groups[i].vmods != 0) {
364            unsigned mask;
365
366            mask = XkbMaskForVMask(xkb, compat->groups[i].vmods);
367            compat->groups[i].mask = compat->groups[i].real_mods | mask;
368        }
369        else
370            compat->groups[i].mask = compat->groups[i].real_mods;
371    }
372    return Success;
373}
374
375static void
376XkbInitSemantics(XkbDescPtr xkb)
377{
378    XkbInitKeyTypes(xkb);
379    XkbInitCompatStructs(xkb);
380    return;
381}
382
383/***====================================================================***/
384
385static Status
386XkbInitNames(XkbSrvInfoPtr xkbi)
387{
388    XkbDescPtr xkb;
389    XkbNamesPtr names;
390    Status rtrn;
391    Atom unknown;
392
393    xkb = xkbi->desc;
394    if ((rtrn = XkbAllocNames(xkb, XkbAllNamesMask, 0, 0)) != Success)
395        return rtrn;
396    unknown = CREATE_ATOM("unknown");
397    names = xkb->names;
398    if (names->keycodes == None)
399        names->keycodes = unknown;
400    if (names->geometry == None)
401        names->geometry = unknown;
402    if (names->phys_symbols == None)
403        names->phys_symbols = unknown;
404    if (names->symbols == None)
405        names->symbols = unknown;
406    if (names->types == None)
407        names->types = unknown;
408    if (names->compat == None)
409        names->compat = unknown;
410    if (!(xkb->defined & XkmVirtualModsMask)) {
411        if (names->vmods[vmod_NumLock] == None)
412            names->vmods[vmod_NumLock] = CREATE_ATOM("NumLock");
413        if (names->vmods[vmod_Alt] == None)
414            names->vmods[vmod_Alt] = CREATE_ATOM("Alt");
415        if (names->vmods[vmod_AltGr] == None)
416            names->vmods[vmod_AltGr] = CREATE_ATOM("ModeSwitch");
417    }
418
419    if (!(xkb->defined & XkmIndicatorsMask) ||
420        !(xkb->defined & XkmGeometryMask)) {
421        initIndicatorNames(NULL, xkb);
422        if (names->indicators[LED_CAPS - 1] == None)
423            names->indicators[LED_CAPS - 1] = CREATE_ATOM("Caps Lock");
424        if (names->indicators[LED_NUM - 1] == None)
425            names->indicators[LED_NUM - 1] = CREATE_ATOM("Num Lock");
426        if (names->indicators[LED_SCROLL - 1] == None)
427            names->indicators[LED_SCROLL - 1] = CREATE_ATOM("Scroll Lock");
428#ifdef LED_COMPOSE
429        if (names->indicators[LED_COMPOSE - 1] == None)
430            names->indicators[LED_COMPOSE - 1] = CREATE_ATOM("Compose");
431#endif
432    }
433
434    if (xkb->geom != NULL)
435        names->geometry = xkb->geom->name;
436    else
437        names->geometry = unknown;
438
439    return Success;
440}
441
442static Status
443XkbInitIndicatorMap(XkbSrvInfoPtr xkbi)
444{
445    XkbDescPtr xkb;
446    XkbIndicatorPtr map;
447    XkbSrvLedInfoPtr sli;
448
449    xkb = xkbi->desc;
450    if (XkbAllocIndicatorMaps(xkb) != Success)
451        return BadAlloc;
452
453    if (!(xkb->defined & XkmIndicatorsMask)) {
454        map = xkb->indicators;
455        map->phys_indicators = PHYS_LEDS;
456        map->maps[LED_CAPS - 1].flags = XkbIM_NoExplicit;
457        map->maps[LED_CAPS - 1].which_mods = XkbIM_UseLocked;
458        map->maps[LED_CAPS - 1].mods.mask = LockMask;
459        map->maps[LED_CAPS - 1].mods.real_mods = LockMask;
460
461        map->maps[LED_NUM - 1].flags = XkbIM_NoExplicit;
462        map->maps[LED_NUM - 1].which_mods = XkbIM_UseLocked;
463        map->maps[LED_NUM - 1].mods.mask = 0;
464        map->maps[LED_NUM - 1].mods.real_mods = 0;
465        map->maps[LED_NUM - 1].mods.vmods = vmod_NumLockMask;
466
467        map->maps[LED_SCROLL - 1].flags = XkbIM_NoExplicit;
468        map->maps[LED_SCROLL - 1].which_mods = XkbIM_UseLocked;
469        map->maps[LED_SCROLL - 1].mods.mask = Mod3Mask;
470        map->maps[LED_SCROLL - 1].mods.real_mods = Mod3Mask;
471    }
472
473    sli = XkbFindSrvLedInfo(xkbi->device, XkbDfltXIClass, XkbDfltXIId, 0);
474    if (sli)
475        XkbCheckIndicatorMaps(xkbi->device, sli, XkbAllIndicatorsMask);
476
477    return Success;
478}
479
480static Status
481XkbInitControls(DeviceIntPtr pXDev, XkbSrvInfoPtr xkbi)
482{
483    XkbDescPtr xkb;
484    XkbControlsPtr ctrls;
485
486    xkb = xkbi->desc;
487    /* 12/31/94 (ef) -- XXX! Should check if controls loaded from file */
488    if (XkbAllocControls(xkb, XkbAllControlsMask) != Success)
489        FatalError("Couldn't allocate keyboard controls\n");
490    ctrls = xkb->ctrls;
491    if (!(xkb->defined & XkmSymbolsMask))
492        ctrls->num_groups = 1;
493    ctrls->groups_wrap = XkbSetGroupInfo(1, XkbWrapIntoRange, 0);
494    ctrls->internal.mask = 0;
495    ctrls->internal.real_mods = 0;
496    ctrls->internal.vmods = 0;
497    ctrls->ignore_lock.mask = 0;
498    ctrls->ignore_lock.real_mods = 0;
499    ctrls->ignore_lock.vmods = 0;
500    ctrls->enabled_ctrls = XkbAccessXTimeoutMask | XkbRepeatKeysMask |
501        XkbMouseKeysAccelMask | XkbAudibleBellMask | XkbIgnoreGroupLockMask;
502    if (XkbWantAccessX)
503        ctrls->enabled_ctrls |= XkbAccessXKeysMask;
504    AccessXInit(pXDev);
505    return Success;
506}
507
508static Status
509XkbInitOverlayState(XkbSrvInfoPtr xkbi)
510{
511    memset(xkbi->overlay_perkey_state, 0, sizeof(xkbi->overlay_perkey_state));
512    return Success;
513}
514
515static Bool
516InitKeyboardDeviceStructInternal(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
517                                 const char *keymap, int keymap_length,
518                                 BellProcPtr bell_func, KbdCtrlProcPtr ctrl_func)
519{
520    int i;
521    unsigned int check;
522    XkbSrvInfoPtr xkbi;
523    XkbDescPtr xkb;
524    XkbSrvLedInfoPtr sli;
525    XkbChangesRec changes;
526    XkbEventCauseRec cause;
527    XkbRMLVOSet rmlvo_dflts = { NULL };
528
529    BUG_RETURN_VAL(dev == NULL, FALSE);
530    BUG_RETURN_VAL(dev->key != NULL, FALSE);
531    BUG_RETURN_VAL(dev->kbdfeed != NULL, FALSE);
532    BUG_RETURN_VAL(rmlvo && keymap, FALSE);
533
534    if (!rmlvo && !keymap) {
535        rmlvo = &rmlvo_dflts;
536        XkbGetRulesDflts(rmlvo);
537    }
538
539    memset(&changes, 0, sizeof(changes));
540    XkbSetCauseUnknown(&cause);
541
542    dev->key = calloc(1, sizeof(*dev->key));
543    if (!dev->key) {
544        ErrorF("XKB: Failed to allocate key class\n");
545        return FALSE;
546    }
547    dev->key->sourceid = dev->id;
548
549    dev->kbdfeed = calloc(1, sizeof(*dev->kbdfeed));
550    if (!dev->kbdfeed) {
551        ErrorF("XKB: Failed to allocate key feedback class\n");
552        goto unwind_key;
553    }
554
555    xkbi = calloc(1, sizeof(*xkbi));
556    if (!xkbi) {
557        ErrorF("XKB: Failed to allocate XKB info\n");
558        goto unwind_kbdfeed;
559    }
560    dev->key->xkbInfo = xkbi;
561
562    if (xkb_cached_map && (keymap || (rmlvo && !XkbCompareUsedRMLVO(rmlvo)))) {
563        XkbFreeKeyboard(xkb_cached_map, XkbAllComponentsMask, TRUE);
564        xkb_cached_map = NULL;
565    }
566
567    if (xkb_cached_map)
568        LogMessageVerb(X_INFO, 4, "XKB: Reusing cached keymap\n");
569    else {
570        if (rmlvo)
571            xkb_cached_map = XkbCompileKeymap(dev, rmlvo);
572        else
573            xkb_cached_map = XkbCompileKeymapFromString(dev, keymap, keymap_length);
574
575        if (!xkb_cached_map) {
576            ErrorF("XKB: Failed to compile keymap\n");
577            goto unwind_info;
578        }
579    }
580
581    xkb = XkbAllocKeyboard();
582    if (!xkb) {
583        ErrorF("XKB: Failed to allocate keyboard description\n");
584        goto unwind_info;
585    }
586
587    if (!XkbCopyKeymap(xkb, xkb_cached_map)) {
588        ErrorF("XKB: Failed to copy keymap\n");
589        goto unwind_desc;
590    }
591    xkb->defined = xkb_cached_map->defined;
592    xkb->flags = xkb_cached_map->flags;
593    xkb->device_spec = xkb_cached_map->device_spec;
594    xkbi->desc = xkb;
595
596    if (xkb->min_key_code == 0)
597        xkb->min_key_code = 8;
598    if (xkb->max_key_code == 0)
599        xkb->max_key_code = 255;
600
601    i = XkbNumKeys(xkb) / 3 + 1;
602    if (XkbAllocClientMap(xkb, XkbAllClientInfoMask, 0) != Success)
603        goto unwind_desc;
604    if (XkbAllocServerMap(xkb, XkbAllServerInfoMask, i) != Success)
605        goto unwind_desc;
606
607    xkbi->dfltPtrDelta = 1;
608    xkbi->device = dev;
609
610    XkbInitSemantics(xkb);
611    XkbInitNames(xkbi);
612    XkbInitRadioGroups(xkbi);
613
614    XkbInitControls(dev, xkbi);
615
616    XkbInitIndicatorMap(xkbi);
617
618    XkbInitOverlayState(xkbi);
619
620    XkbUpdateActions(dev, xkb->min_key_code, XkbNumKeys(xkb), &changes,
621                     &check, &cause);
622
623    if (!dev->focus)
624        InitFocusClassDeviceStruct(dev);
625
626    xkbi->kbdProc = ctrl_func;
627    dev->kbdfeed->BellProc = bell_func;
628    dev->kbdfeed->CtrlProc = XkbDDXKeybdCtrlProc;
629
630    dev->kbdfeed->ctrl = defaultKeyboardControl;
631    if (dev->kbdfeed->ctrl.autoRepeat)
632        xkb->ctrls->enabled_ctrls |= XkbRepeatKeysMask;
633
634    memcpy(dev->kbdfeed->ctrl.autoRepeats, xkb->ctrls->per_key_repeat,
635           XkbPerKeyBitArraySize);
636
637    sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 0);
638    if (sli)
639        XkbCheckIndicatorMaps(dev, sli, XkbAllIndicatorsMask);
640    else
641        DebugF("XKB: No indicator feedback in XkbFinishInit!\n");
642
643    dev->kbdfeed->CtrlProc(dev, &dev->kbdfeed->ctrl);
644
645    if (rmlvo) {
646        XkbSetRulesDflts(rmlvo);
647        XkbSetRulesUsed(rmlvo);
648    }
649    XkbFreeRMLVOSet(&rmlvo_dflts, FALSE);
650
651    return TRUE;
652
653 unwind_desc:
654    XkbFreeKeyboard(xkb, 0, TRUE);
655 unwind_info:
656    free(xkbi);
657    dev->key->xkbInfo = NULL;
658 unwind_kbdfeed:
659    free(dev->kbdfeed);
660    dev->kbdfeed = NULL;
661 unwind_key:
662    free(dev->key);
663    dev->key = NULL;
664    return FALSE;
665}
666
667_X_EXPORT Bool
668InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
669                         BellProcPtr bell_func, KbdCtrlProcPtr ctrl_func)
670{
671    return InitKeyboardDeviceStructInternal(dev, rmlvo,
672                                            NULL, 0, bell_func, ctrl_func);
673}
674
675_X_EXPORT Bool
676InitKeyboardDeviceStructFromString(DeviceIntPtr dev,
677                                   const char *keymap, int keymap_length,
678                                   BellProcPtr bell_func, KbdCtrlProcPtr ctrl_func)
679{
680    return InitKeyboardDeviceStructInternal(dev, NULL,
681                                            keymap, keymap_length,
682                                            bell_func, ctrl_func);
683}
684
685/***====================================================================***/
686
687        /*
688         * Be very careful about what does and doesn't get freed by this
689         * function.  To reduce fragmentation, XkbInitDevice allocates a
690         * single huge block per device and divides it up into most of the
691         * fixed-size structures for the device.   Don't free anything that
692         * is part of this larger block.
693         */
694void
695XkbFreeInfo(XkbSrvInfoPtr xkbi)
696{
697    free(xkbi->radioGroups);
698    xkbi->radioGroups = NULL;
699    if (xkbi->mouseKeyTimer) {
700        TimerFree(xkbi->mouseKeyTimer);
701        xkbi->mouseKeyTimer = NULL;
702    }
703    if (xkbi->slowKeysTimer) {
704        TimerFree(xkbi->slowKeysTimer);
705        xkbi->slowKeysTimer = NULL;
706    }
707    if (xkbi->bounceKeysTimer) {
708        TimerFree(xkbi->bounceKeysTimer);
709        xkbi->bounceKeysTimer = NULL;
710    }
711    if (xkbi->repeatKeyTimer) {
712        TimerFree(xkbi->repeatKeyTimer);
713        xkbi->repeatKeyTimer = NULL;
714    }
715    if (xkbi->krgTimer) {
716        TimerFree(xkbi->krgTimer);
717        xkbi->krgTimer = NULL;
718    }
719    xkbi->beepType = _BEEP_NONE;
720    if (xkbi->beepTimer) {
721        TimerFree(xkbi->beepTimer);
722        xkbi->beepTimer = NULL;
723    }
724    if (xkbi->desc) {
725        XkbFreeKeyboard(xkbi->desc, XkbAllComponentsMask, TRUE);
726        xkbi->desc = NULL;
727    }
728    free(xkbi);
729    return;
730}
731
732/***====================================================================***/
733
734extern int XkbDfltRepeatDelay;
735extern int XkbDfltRepeatInterval;
736
737extern unsigned short XkbDfltAccessXTimeout;
738extern unsigned int XkbDfltAccessXTimeoutMask;
739extern unsigned int XkbDfltAccessXFeedback;
740extern unsigned short XkbDfltAccessXOptions;
741
742int
743XkbProcessArguments(int argc, char *argv[], int i)
744{
745    if (strncmp(argv[i], "-xkbdir", 7) == 0) {
746        if (++i < argc) {
747#if !defined(WIN32) && !defined(__CYGWIN__)
748            if (getuid() != geteuid()) {
749                LogMessage(X_WARNING,
750                           "-xkbdir is not available for setuid X servers\n");
751                return -1;
752            }
753            else
754#endif
755            {
756                if (strlen(argv[i]) < PATH_MAX) {
757                    XkbBaseDirectory = argv[i];
758                    return 2;
759                }
760                else {
761                    LogMessage(X_ERROR, "-xkbdir pathname too long\n");
762                    return -1;
763                }
764            }
765        }
766        else {
767            return -1;
768        }
769    }
770    else if ((strncmp(argv[i], "-accessx", 8) == 0) ||
771             (strncmp(argv[i], "+accessx", 8) == 0)) {
772        int j = 1;
773
774        if (argv[i][0] == '-')
775            XkbWantAccessX = 0;
776        else {
777            XkbWantAccessX = 1;
778
779            if (((i + 1) < argc) && (isdigit(argv[i + 1][0]))) {
780                XkbDfltAccessXTimeout = atoi(argv[++i]);
781                j++;
782
783                if (((i + 1) < argc) && (isdigit(argv[i + 1][0]))) {
784                    /*
785                     * presumption that the reasonably useful range of
786                     * values fits in 0..MAXINT since SunOS 4 doesn't
787                     * have strtoul.
788                     */
789                    XkbDfltAccessXTimeoutMask = (unsigned int)
790                        strtol(argv[++i], NULL, 16);
791                    j++;
792                }
793                if (((i + 1) < argc) && (isdigit(argv[i + 1][0]))) {
794                    if (argv[++i][0] == '1')
795                        XkbDfltAccessXFeedback = XkbAccessXFeedbackMask;
796                    else
797                        XkbDfltAccessXFeedback = 0;
798                    j++;
799                }
800                if (((i + 1) < argc) && (isdigit(argv[i + 1][0]))) {
801                    XkbDfltAccessXOptions = (unsigned short)
802                        strtol(argv[++i], NULL, 16);
803                    j++;
804                }
805            }
806        }
807        return j;
808    }
809    if ((strcmp(argv[i], "-ardelay") == 0) || (strcmp(argv[i], "-ar1") == 0)) { /* -ardelay int */
810        if (++i >= argc)
811            UseMsg();
812        else
813            XkbDfltRepeatDelay = (long) atoi(argv[i]);
814        return 2;
815    }
816    if ((strcmp(argv[i], "-arinterval") == 0) || (strcmp(argv[i], "-ar2") == 0)) {      /* -arinterval int */
817        if (++i >= argc)
818            UseMsg();
819        else
820            XkbDfltRepeatInterval = (long) atoi(argv[i]);
821        return 2;
822    }
823    return 0;
824}
825
826void
827XkbUseMsg(void)
828{
829    ErrorF
830        ("[+-]accessx [ timeout [ timeout_mask [ feedback [ options_mask] ] ] ]\n");
831    ErrorF("                       enable/disable accessx key sequences\n");
832    ErrorF("-ardelay               set XKB autorepeat delay\n");
833    ErrorF("-arinterval            set XKB autorepeat interval\n");
834}
835