1 /************************************************************
2 Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3 
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be
10 used in advertising or publicity pertaining to distribution
11 of the software without specific prior written permission.
12 Silicon Graphics makes no representation about the suitability
13 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
15 
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23 THE 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
78 typedef 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 
90 const char *XkbBaseDirectory = XKB_BASE_DIRECTORY;
91 const char *XkbBinDirectory = XKB_BIN_DIRECTORY;
92 static int XkbWantAccessX = 0;
93 
94 static char *XkbRulesDflt = NULL;
95 static char *XkbModelDflt = NULL;
96 static char *XkbLayoutDflt = NULL;
97 static char *XkbVariantDflt = NULL;
98 static char *XkbOptionsDflt = NULL;
99 
100 static char *XkbRulesUsed = NULL;
101 static char *XkbModelUsed = NULL;
102 static char *XkbLayoutUsed = NULL;
103 static char *XkbVariantUsed = NULL;
104 static char *XkbOptionsUsed = NULL;
105 
106 static XkbDescPtr xkb_cached_map = NULL;
107 
108 static 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  */
116 void
XkbGetRulesDflts(XkbRMLVOSet * rmlvo)117 XkbGetRulesDflts(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 
126 void
XkbFreeRMLVOSet(XkbRMLVOSet * rmlvo,Bool freeRMLVO)127 XkbFreeRMLVOSet(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 
144 static Bool
XkbWriteRulesProp(ClientPtr client,void * closure)145 XkbWriteRulesProp(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 
209 void
XkbInitRules(XkbRMLVOSet * rmlvo,const char * rules,const char * model,const char * layout,const char * variant,const char * options)210 XkbInitRules(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 
224 static void
XkbSetRulesUsed(XkbRMLVOSet * rmlvo)225 XkbSetRulesUsed(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 
242 void
XkbSetRulesDflts(XkbRMLVOSet * rmlvo)243 XkbSetRulesDflts(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 
268 void
XkbDeleteRulesUsed(void)269 XkbDeleteRulesUsed(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 
283 void
XkbDeleteRulesDflts(void)284 XkbDeleteRulesDflts(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 
303 static Bool
XkbCompareUsedRMLVO(XkbRMLVOSet * rmlvo)304 XkbCompareUsedRMLVO(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 
321 static Bool
XkbInitKeyTypes(XkbDescPtr xkb)322 XkbInitKeyTypes(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 
337 static void
XkbInitRadioGroups(XkbSrvInfoPtr xkbi)338 XkbInitRadioGroups(XkbSrvInfoPtr xkbi)
339 {
340     xkbi->nRadioGroups = 0;
341     xkbi->radioGroups = NULL;
342     return;
343 }
344 
345 static Status
XkbInitCompatStructs(XkbDescPtr xkb)346 XkbInitCompatStructs(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 
375 static void
XkbInitSemantics(XkbDescPtr xkb)376 XkbInitSemantics(XkbDescPtr xkb)
377 {
378     XkbInitKeyTypes(xkb);
379     XkbInitCompatStructs(xkb);
380     return;
381 }
382 
383 /***====================================================================***/
384 
385 static Status
XkbInitNames(XkbSrvInfoPtr xkbi)386 XkbInitNames(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 
442 static Status
XkbInitIndicatorMap(XkbSrvInfoPtr xkbi)443 XkbInitIndicatorMap(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 
480 static Status
XkbInitControls(DeviceIntPtr pXDev,XkbSrvInfoPtr xkbi)481 XkbInitControls(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 
508 static Status
XkbInitOverlayState(XkbSrvInfoPtr xkbi)509 XkbInitOverlayState(XkbSrvInfoPtr xkbi)
510 {
511     memset(xkbi->overlay_perkey_state, 0, sizeof(xkbi->overlay_perkey_state));
512     return Success;
513 }
514 
515 static Bool
InitKeyboardDeviceStructInternal(DeviceIntPtr dev,XkbRMLVOSet * rmlvo,const char * keymap,int keymap_length,BellProcPtr bell_func,KbdCtrlProcPtr ctrl_func)516 InitKeyboardDeviceStructInternal(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
InitKeyboardDeviceStruct(DeviceIntPtr dev,XkbRMLVOSet * rmlvo,BellProcPtr bell_func,KbdCtrlProcPtr ctrl_func)668 InitKeyboardDeviceStruct(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
InitKeyboardDeviceStructFromString(DeviceIntPtr dev,const char * keymap,int keymap_length,BellProcPtr bell_func,KbdCtrlProcPtr ctrl_func)676 InitKeyboardDeviceStructFromString(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          */
694 void
XkbFreeInfo(XkbSrvInfoPtr xkbi)695 XkbFreeInfo(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 
734 extern int XkbDfltRepeatDelay;
735 extern int XkbDfltRepeatInterval;
736 
737 extern unsigned short XkbDfltAccessXTimeout;
738 extern unsigned int XkbDfltAccessXTimeoutMask;
739 extern unsigned int XkbDfltAccessXFeedback;
740 extern unsigned short XkbDfltAccessXOptions;
741 
742 int
XkbProcessArguments(int argc,char * argv[],int i)743 XkbProcessArguments(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 
826 void
XkbUseMsg(void)827 XkbUseMsg(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