Imported Upstream version 1.15.1
[deb_xorg-server.git] / xkb / xkbInit.c
CommitLineData
a09e091a
JB
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, pointer 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
209static void
210XkbSetRulesUsed(XkbRMLVOSet * rmlvo)
211{
212 free(XkbRulesUsed);
213 XkbRulesUsed = (rmlvo->rules ? Xstrdup(rmlvo->rules) : NULL);
214 free(XkbModelUsed);
215 XkbModelUsed = (rmlvo->model ? Xstrdup(rmlvo->model) : NULL);
216 free(XkbLayoutUsed);
217 XkbLayoutUsed = (rmlvo->layout ? Xstrdup(rmlvo->layout) : NULL);
218 free(XkbVariantUsed);
219 XkbVariantUsed = (rmlvo->variant ? Xstrdup(rmlvo->variant) : NULL);
220 free(XkbOptionsUsed);
221 XkbOptionsUsed = (rmlvo->options ? Xstrdup(rmlvo->options) : NULL);
222 if (XkbWantRulesProp)
223 QueueWorkProc(XkbWriteRulesProp, NULL, NULL);
224 return;
225}
226
227void
228XkbSetRulesDflts(XkbRMLVOSet * rmlvo)
229{
230 if (rmlvo->rules) {
231 free(XkbRulesDflt);
232 XkbRulesDflt = Xstrdup(rmlvo->rules);
233 }
234 if (rmlvo->model) {
235 free(XkbModelDflt);
236 XkbModelDflt = Xstrdup(rmlvo->model);
237 }
238 if (rmlvo->layout) {
239 free(XkbLayoutDflt);
240 XkbLayoutDflt = Xstrdup(rmlvo->layout);
241 }
242 if (rmlvo->variant) {
243 free(XkbVariantDflt);
244 XkbVariantDflt = Xstrdup(rmlvo->variant);
245 }
246 if (rmlvo->options) {
247 free(XkbOptionsDflt);
248 XkbOptionsDflt = Xstrdup(rmlvo->options);
249 }
250 return;
251}
252
253void
254XkbDeleteRulesUsed(void)
255{
256 free(XkbRulesUsed);
257 XkbRulesUsed = NULL;
258 free(XkbModelUsed);
259 XkbModelUsed = NULL;
260 free(XkbLayoutUsed);
261 XkbLayoutUsed = NULL;
262 free(XkbVariantUsed);
263 XkbVariantUsed = NULL;
264 free(XkbOptionsUsed);
265 XkbOptionsUsed = NULL;
266}
267
268void
269XkbDeleteRulesDflts(void)
270{
271 free(XkbRulesDflt);
272 XkbRulesDflt = NULL;
273 free(XkbModelDflt);
274 XkbModelDflt = NULL;
275 free(XkbLayoutDflt);
276 XkbLayoutDflt = NULL;
277 free(XkbVariantDflt);
278 XkbVariantDflt = NULL;
279 free(XkbOptionsDflt);
280 XkbOptionsDflt = NULL;
281
282 XkbFreeKeyboard(xkb_cached_map, XkbAllComponentsMask, TRUE);
283 xkb_cached_map = NULL;
284}
285
286#define DIFFERS(a, b) (strcmp((a) ? (a) : "", (b) ? (b) : "") != 0)
287
288static Bool
289XkbCompareUsedRMLVO(XkbRMLVOSet * rmlvo)
290{
291 if (DIFFERS(rmlvo->rules, XkbRulesUsed) ||
292 DIFFERS(rmlvo->model, XkbModelUsed) ||
293 DIFFERS(rmlvo->layout, XkbLayoutUsed) ||
294 DIFFERS(rmlvo->variant, XkbVariantUsed) ||
295 DIFFERS(rmlvo->options, XkbOptionsUsed))
296 return FALSE;
297 return TRUE;
298}
299
300#undef DIFFERS
301
302/***====================================================================***/
303
304#include "xkbDflts.h"
305
306static Bool
307XkbInitKeyTypes(XkbDescPtr xkb)
308{
309 if (xkb->defined & XkmTypesMask)
310 return TRUE;
311
312 initTypeNames(NULL);
313 if (XkbAllocClientMap(xkb, XkbKeyTypesMask, num_dflt_types) != Success)
314 return FALSE;
315 if (XkbCopyKeyTypes(dflt_types, xkb->map->types, num_dflt_types) != Success) {
316 return FALSE;
317 }
318 xkb->map->size_types = xkb->map->num_types = num_dflt_types;
319 return TRUE;
320}
321
322static void
323XkbInitRadioGroups(XkbSrvInfoPtr xkbi)
324{
325 xkbi->nRadioGroups = 0;
326 xkbi->radioGroups = NULL;
327 return;
328}
329
330static Status
331XkbInitCompatStructs(XkbDescPtr xkb)
332{
333 register int i;
334 XkbCompatMapPtr compat;
335
336 if (xkb->defined & XkmCompatMapMask)
337 return TRUE;
338
339 if (XkbAllocCompatMap(xkb, XkbAllCompatMask, num_dfltSI) != Success)
340 return BadAlloc;
341 compat = xkb->compat;
342 if (compat->sym_interpret) {
343 compat->num_si = num_dfltSI;
344 memcpy((char *) compat->sym_interpret, (char *) dfltSI, sizeof(dfltSI));
345 }
346 for (i = 0; i < XkbNumKbdGroups; i++) {
347 compat->groups[i] = compatMap.groups[i];
348 if (compat->groups[i].vmods != 0) {
349 unsigned mask;
350
351 mask = XkbMaskForVMask(xkb, compat->groups[i].vmods);
352 compat->groups[i].mask = compat->groups[i].real_mods | mask;
353 }
354 else
355 compat->groups[i].mask = compat->groups[i].real_mods;
356 }
357 return Success;
358}
359
360static void
361XkbInitSemantics(XkbDescPtr xkb)
362{
363 XkbInitKeyTypes(xkb);
364 XkbInitCompatStructs(xkb);
365 return;
366}
367
368/***====================================================================***/
369
370static Status
371XkbInitNames(XkbSrvInfoPtr xkbi)
372{
373 XkbDescPtr xkb;
374 XkbNamesPtr names;
375 Status rtrn;
376 Atom unknown;
377
378 xkb = xkbi->desc;
379 if ((rtrn = XkbAllocNames(xkb, XkbAllNamesMask, 0, 0)) != Success)
380 return rtrn;
381 unknown = CREATE_ATOM("unknown");
382 names = xkb->names;
383 if (names->keycodes == None)
384 names->keycodes = unknown;
385 if (names->geometry == None)
386 names->geometry = unknown;
387 if (names->phys_symbols == None)
388 names->phys_symbols = unknown;
389 if (names->symbols == None)
390 names->symbols = unknown;
391 if (names->types == None)
392 names->types = unknown;
393 if (names->compat == None)
394 names->compat = unknown;
395 if (!(xkb->defined & XkmVirtualModsMask)) {
396 if (names->vmods[vmod_NumLock] == None)
397 names->vmods[vmod_NumLock] = CREATE_ATOM("NumLock");
398 if (names->vmods[vmod_Alt] == None)
399 names->vmods[vmod_Alt] = CREATE_ATOM("Alt");
400 if (names->vmods[vmod_AltGr] == None)
401 names->vmods[vmod_AltGr] = CREATE_ATOM("ModeSwitch");
402 }
403
404 if (!(xkb->defined & XkmIndicatorsMask) ||
405 !(xkb->defined & XkmGeometryMask)) {
406 initIndicatorNames(NULL, xkb);
407 if (names->indicators[LED_CAPS - 1] == None)
408 names->indicators[LED_CAPS - 1] = CREATE_ATOM("Caps Lock");
409 if (names->indicators[LED_NUM - 1] == None)
410 names->indicators[LED_NUM - 1] = CREATE_ATOM("Num Lock");
411 if (names->indicators[LED_SCROLL - 1] == None)
412 names->indicators[LED_SCROLL - 1] = CREATE_ATOM("Scroll Lock");
413#ifdef LED_COMPOSE
414 if (names->indicators[LED_COMPOSE - 1] == None)
415 names->indicators[LED_COMPOSE - 1] = CREATE_ATOM("Compose");
416#endif
417 }
418
419 if (xkb->geom != NULL)
420 names->geometry = xkb->geom->name;
421 else
422 names->geometry = unknown;
423
424 return Success;
425}
426
427static Status
428XkbInitIndicatorMap(XkbSrvInfoPtr xkbi)
429{
430 XkbDescPtr xkb;
431 XkbIndicatorPtr map;
432 XkbSrvLedInfoPtr sli;
433
434 xkb = xkbi->desc;
435 if (XkbAllocIndicatorMaps(xkb) != Success)
436 return BadAlloc;
437
438 if (!(xkb->defined & XkmIndicatorsMask)) {
439 map = xkb->indicators;
440 map->phys_indicators = PHYS_LEDS;
441 map->maps[LED_CAPS - 1].flags = XkbIM_NoExplicit;
442 map->maps[LED_CAPS - 1].which_mods = XkbIM_UseLocked;
443 map->maps[LED_CAPS - 1].mods.mask = LockMask;
444 map->maps[LED_CAPS - 1].mods.real_mods = LockMask;
445
446 map->maps[LED_NUM - 1].flags = XkbIM_NoExplicit;
447 map->maps[LED_NUM - 1].which_mods = XkbIM_UseLocked;
448 map->maps[LED_NUM - 1].mods.mask = 0;
449 map->maps[LED_NUM - 1].mods.real_mods = 0;
450 map->maps[LED_NUM - 1].mods.vmods = vmod_NumLockMask;
451
452 map->maps[LED_SCROLL - 1].flags = XkbIM_NoExplicit;
453 map->maps[LED_SCROLL - 1].which_mods = XkbIM_UseLocked;
454 map->maps[LED_SCROLL - 1].mods.mask = Mod3Mask;
455 map->maps[LED_SCROLL - 1].mods.real_mods = Mod3Mask;
456 }
457
458 sli = XkbFindSrvLedInfo(xkbi->device, XkbDfltXIClass, XkbDfltXIId, 0);
459 if (sli)
460 XkbCheckIndicatorMaps(xkbi->device, sli, XkbAllIndicatorsMask);
461
462 return Success;
463}
464
465static Status
466XkbInitControls(DeviceIntPtr pXDev, XkbSrvInfoPtr xkbi)
467{
468 XkbDescPtr xkb;
469 XkbControlsPtr ctrls;
470
471 xkb = xkbi->desc;
472 /* 12/31/94 (ef) -- XXX! Should check if controls loaded from file */
473 if (XkbAllocControls(xkb, XkbAllControlsMask) != Success)
474 FatalError("Couldn't allocate keyboard controls\n");
475 ctrls = xkb->ctrls;
476 if (!(xkb->defined & XkmSymbolsMask))
477 ctrls->num_groups = 1;
478 ctrls->groups_wrap = XkbSetGroupInfo(1, XkbWrapIntoRange, 0);
479 ctrls->internal.mask = 0;
480 ctrls->internal.real_mods = 0;
481 ctrls->internal.vmods = 0;
482 ctrls->ignore_lock.mask = 0;
483 ctrls->ignore_lock.real_mods = 0;
484 ctrls->ignore_lock.vmods = 0;
485 ctrls->enabled_ctrls = XkbAccessXTimeoutMask | XkbRepeatKeysMask |
486 XkbMouseKeysAccelMask | XkbAudibleBellMask | XkbIgnoreGroupLockMask;
487 if (XkbWantAccessX)
488 ctrls->enabled_ctrls |= XkbAccessXKeysMask;
489 AccessXInit(pXDev);
490 return Success;
491}
492
493_X_EXPORT Bool
494InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
495 BellProcPtr bell_func, KbdCtrlProcPtr ctrl_func)
496{
497 int i;
498 unsigned int check;
499 XkbSrvInfoPtr xkbi;
500 XkbDescPtr xkb;
501 XkbSrvLedInfoPtr sli;
502 XkbChangesRec changes;
503 XkbEventCauseRec cause;
504 XkbRMLVOSet rmlvo_dflts = { NULL };
505
506 BUG_RETURN_VAL(dev == NULL, FALSE);
507 BUG_RETURN_VAL(dev->key != NULL, FALSE);
508 BUG_RETURN_VAL(dev->kbdfeed != NULL, FALSE);
509
510 if (!rmlvo) {
511 rmlvo = &rmlvo_dflts;
512 XkbGetRulesDflts(rmlvo);
513 }
514
515 memset(&changes, 0, sizeof(changes));
516 XkbSetCauseUnknown(&cause);
517
518 dev->key = calloc(1, sizeof(*dev->key));
519 if (!dev->key) {
520 ErrorF("XKB: Failed to allocate key class\n");
521 return FALSE;
522 }
523 dev->key->sourceid = dev->id;
524
525 dev->kbdfeed = calloc(1, sizeof(*dev->kbdfeed));
526 if (!dev->kbdfeed) {
527 ErrorF("XKB: Failed to allocate key feedback class\n");
528 goto unwind_key;
529 }
530
531 xkbi = calloc(1, sizeof(*xkbi));
532 if (!xkbi) {
533 ErrorF("XKB: Failed to allocate XKB info\n");
534 goto unwind_kbdfeed;
535 }
536 dev->key->xkbInfo = xkbi;
537
538 if (xkb_cached_map && !XkbCompareUsedRMLVO(rmlvo)) {
539 XkbFreeKeyboard(xkb_cached_map, XkbAllComponentsMask, TRUE);
540 xkb_cached_map = NULL;
541 }
542
543 if (xkb_cached_map)
544 LogMessageVerb(X_INFO, 4, "XKB: Reusing cached keymap\n");
545 else {
546 xkb_cached_map = XkbCompileKeymap(dev, rmlvo);
547 if (!xkb_cached_map) {
548 ErrorF("XKB: Failed to compile keymap\n");
549 goto unwind_info;
550 }
551 }
552
553 xkb = XkbAllocKeyboard();
554 if (!xkb) {
555 ErrorF("XKB: Failed to allocate keyboard description\n");
556 goto unwind_info;
557 }
558
559 if (!XkbCopyKeymap(xkb, xkb_cached_map)) {
560 ErrorF("XKB: Failed to copy keymap\n");
561 goto unwind_desc;
562 }
563 xkb->defined = xkb_cached_map->defined;
564 xkb->flags = xkb_cached_map->flags;
565 xkb->device_spec = xkb_cached_map->device_spec;
566 xkbi->desc = xkb;
567
568 if (xkb->min_key_code == 0)
569 xkb->min_key_code = 8;
570 if (xkb->max_key_code == 0)
571 xkb->max_key_code = 255;
572
573 i = XkbNumKeys(xkb) / 3 + 1;
574 if (XkbAllocClientMap(xkb, XkbAllClientInfoMask, 0) != Success)
575 goto unwind_desc;
576 if (XkbAllocServerMap(xkb, XkbAllServerInfoMask, i) != Success)
577 goto unwind_desc;
578
579 xkbi->dfltPtrDelta = 1;
580 xkbi->device = dev;
581
582 XkbInitSemantics(xkb);
583 XkbInitNames(xkbi);
584 XkbInitRadioGroups(xkbi);
585
586 XkbInitControls(dev, xkbi);
587
588 XkbInitIndicatorMap(xkbi);
589
590 XkbUpdateActions(dev, xkb->min_key_code, XkbNumKeys(xkb), &changes,
591 &check, &cause);
592
593 if (!dev->focus)
594 InitFocusClassDeviceStruct(dev);
595
596 xkbi->kbdProc = ctrl_func;
597 dev->kbdfeed->BellProc = bell_func;
598 dev->kbdfeed->CtrlProc = XkbDDXKeybdCtrlProc;
599
600 dev->kbdfeed->ctrl = defaultKeyboardControl;
601 if (dev->kbdfeed->ctrl.autoRepeat)
602 xkb->ctrls->enabled_ctrls |= XkbRepeatKeysMask;
603
604 memcpy(dev->kbdfeed->ctrl.autoRepeats, xkb->ctrls->per_key_repeat,
605 XkbPerKeyBitArraySize);
606
607 sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 0);
608 if (sli)
609 XkbCheckIndicatorMaps(dev, sli, XkbAllIndicatorsMask);
610 else
611 DebugF("XKB: No indicator feedback in XkbFinishInit!\n");
612
613 dev->kbdfeed->CtrlProc(dev, &dev->kbdfeed->ctrl);
614
615 XkbSetRulesDflts(rmlvo);
616 XkbSetRulesUsed(rmlvo);
617 XkbFreeRMLVOSet(&rmlvo_dflts, FALSE);
618
619 return TRUE;
620
621 unwind_desc:
622 XkbFreeKeyboard(xkb, 0, TRUE);
623 unwind_info:
624 free(xkbi);
625 dev->key->xkbInfo = NULL;
626 unwind_kbdfeed:
627 free(dev->kbdfeed);
628 dev->kbdfeed = NULL;
629 unwind_key:
630 free(dev->key);
631 dev->key = NULL;
632 return FALSE;
633}
634
635/***====================================================================***/
636
637 /*
638 * Be very careful about what does and doesn't get freed by this
639 * function. To reduce fragmentation, XkbInitDevice allocates a
640 * single huge block per device and divides it up into most of the
641 * fixed-size structures for the device. Don't free anything that
642 * is part of this larger block.
643 */
644void
645XkbFreeInfo(XkbSrvInfoPtr xkbi)
646{
647 free(xkbi->radioGroups);
648 xkbi->radioGroups = NULL;
649 if (xkbi->mouseKeyTimer) {
650 TimerFree(xkbi->mouseKeyTimer);
651 xkbi->mouseKeyTimer = NULL;
652 }
653 if (xkbi->slowKeysTimer) {
654 TimerFree(xkbi->slowKeysTimer);
655 xkbi->slowKeysTimer = NULL;
656 }
657 if (xkbi->bounceKeysTimer) {
658 TimerFree(xkbi->bounceKeysTimer);
659 xkbi->bounceKeysTimer = NULL;
660 }
661 if (xkbi->repeatKeyTimer) {
662 TimerFree(xkbi->repeatKeyTimer);
663 xkbi->repeatKeyTimer = NULL;
664 }
665 if (xkbi->krgTimer) {
666 TimerFree(xkbi->krgTimer);
667 xkbi->krgTimer = NULL;
668 }
669 xkbi->beepType = _BEEP_NONE;
670 if (xkbi->beepTimer) {
671 TimerFree(xkbi->beepTimer);
672 xkbi->beepTimer = NULL;
673 }
674 if (xkbi->desc) {
675 XkbFreeKeyboard(xkbi->desc, XkbAllComponentsMask, TRUE);
676 xkbi->desc = NULL;
677 }
678 free(xkbi);
679 return;
680}
681
682/***====================================================================***/
683
684extern int XkbDfltRepeatDelay;
685extern int XkbDfltRepeatInterval;
686
687extern unsigned short XkbDfltAccessXTimeout;
688extern unsigned int XkbDfltAccessXTimeoutMask;
689extern unsigned int XkbDfltAccessXFeedback;
690extern unsigned char XkbDfltAccessXOptions;
691
692int
693XkbProcessArguments(int argc, char *argv[], int i)
694{
695 if (strncmp(argv[i], "-xkbdir", 7) == 0) {
696 if (++i < argc) {
697#if !defined(WIN32) && !defined(__CYGWIN__)
698 if (getuid() != geteuid()) {
699 LogMessage(X_WARNING,
700 "-xkbdir is not available for setuid X servers\n");
701 return -1;
702 }
703 else
704#endif
705 {
706 if (strlen(argv[i]) < PATH_MAX) {
707 XkbBaseDirectory = argv[i];
708 return 2;
709 }
710 else {
711 LogMessage(X_ERROR, "-xkbdir pathname too long\n");
712 return -1;
713 }
714 }
715 }
716 else {
717 return -1;
718 }
719 }
720 else if ((strncmp(argv[i], "-accessx", 8) == 0) ||
721 (strncmp(argv[i], "+accessx", 8) == 0)) {
722 int j = 1;
723
724 if (argv[i][0] == '-')
725 XkbWantAccessX = 0;
726 else {
727 XkbWantAccessX = 1;
728
729 if (((i + 1) < argc) && (isdigit(argv[i + 1][0]))) {
730 XkbDfltAccessXTimeout = atoi(argv[++i]);
731 j++;
732
733 if (((i + 1) < argc) && (isdigit(argv[i + 1][0]))) {
734 /*
735 * presumption that the reasonably useful range of
736 * values fits in 0..MAXINT since SunOS 4 doesn't
737 * have strtoul.
738 */
739 XkbDfltAccessXTimeoutMask = (unsigned int)
740 strtol(argv[++i], NULL, 16);
741 j++;
742 }
743 if (((i + 1) < argc) && (isdigit(argv[i + 1][0]))) {
744 if (argv[++i][0] == '1')
745 XkbDfltAccessXFeedback = XkbAccessXFeedbackMask;
746 else
747 XkbDfltAccessXFeedback = 0;
748 j++;
749 }
750 if (((i + 1) < argc) && (isdigit(argv[i + 1][0]))) {
751 XkbDfltAccessXOptions = (unsigned char)
752 strtol(argv[++i], NULL, 16);
753 j++;
754 }
755 }
756 }
757 return j;
758 }
759 if ((strcmp(argv[i], "-ardelay") == 0) || (strcmp(argv[i], "-ar1") == 0)) { /* -ardelay int */
760 if (++i >= argc)
761 UseMsg();
762 else
763 XkbDfltRepeatDelay = (long) atoi(argv[i]);
764 return 2;
765 }
766 if ((strcmp(argv[i], "-arinterval") == 0) || (strcmp(argv[i], "-ar2") == 0)) { /* -arinterval int */
767 if (++i >= argc)
768 UseMsg();
769 else
770 XkbDfltRepeatInterval = (long) atoi(argv[i]);
771 return 2;
772 }
773 return 0;
774}
775
776void
777XkbUseMsg(void)
778{
779 ErrorF
780 ("[+-]accessx [ timeout [ timeout_mask [ feedback [ options_mask] ] ] ]\n");
781 ErrorF(" enable/disable accessx key sequences\n");
782 ErrorF("-ardelay set XKB autorepeat delay\n");
783 ErrorF("-arinterval set XKB autorepeat interval\n");
784}