Imported Upstream version 1.15.1
[deb_xorg-server.git] / xkb / xkbUtils.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
28Copyright © 2008 Red Hat Inc.
29
30Permission is hereby granted, free of charge, to any person obtaining a
31copy of this software and associated documentation files (the "Software"),
32to deal in the Software without restriction, including without limitation
33the rights to use, copy, modify, merge, publish, distribute, sublicense,
34and/or sell copies of the Software, and to permit persons to whom the
35Software is furnished to do so, subject to the following conditions:
36
37The above copyright notice and this permission notice (including the next
38paragraph) shall be included in all copies or substantial portions of the
39Software.
40
41THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
44THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
46FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
47DEALINGS IN THE SOFTWARE.
48
49*/
50
51#ifdef HAVE_DIX_CONFIG_H
52#include <dix-config.h>
53#endif
54
55#include "os.h"
56#include <stdio.h>
57#include <ctype.h>
58#include <math.h>
59#include <X11/X.h>
60#include <X11/Xproto.h>
61#define XK_CYRILLIC
62#include <X11/keysym.h>
63#include "misc.h"
64#include "inputstr.h"
65#include "eventstr.h"
66
67#define XKBSRV_NEED_FILE_FUNCS
68#include <xkbsrv.h>
69#include "xkbgeom.h"
70#include "xkb.h"
71
72/***====================================================================***/
73
74int
75_XkbLookupAnyDevice(DeviceIntPtr *pDev, int id, ClientPtr client,
76 Mask access_mode, int *xkb_err)
77{
78 int rc = XkbKeyboardErrorCode;
79
80 if (id == XkbUseCoreKbd)
81 id = PickKeyboard(client)->id;
82 else if (id == XkbUseCorePtr)
83 id = PickPointer(client)->id;
84
85 rc = dixLookupDevice(pDev, id, client, access_mode);
86 if (rc != Success)
87 *xkb_err = XkbErr_BadDevice;
88
89 return rc;
90}
91
92int
93_XkbLookupKeyboard(DeviceIntPtr *pDev, int id, ClientPtr client,
94 Mask access_mode, int *xkb_err)
95{
96 DeviceIntPtr dev;
97 int rc;
98
99 if (id == XkbDfltXIId)
100 id = XkbUseCoreKbd;
101
102 rc = _XkbLookupAnyDevice(pDev, id, client, access_mode, xkb_err);
103 if (rc != Success)
104 return rc;
105
106 dev = *pDev;
107 if (!dev->key || !dev->key->xkbInfo) {
108 *pDev = NULL;
109 *xkb_err = XkbErr_BadClass;
110 return XkbKeyboardErrorCode;
111 }
112 return Success;
113}
114
115int
116_XkbLookupBellDevice(DeviceIntPtr *pDev, int id, ClientPtr client,
117 Mask access_mode, int *xkb_err)
118{
119 DeviceIntPtr dev;
120 int rc;
121
122 rc = _XkbLookupAnyDevice(pDev, id, client, access_mode, xkb_err);
123 if (rc != Success)
124 return rc;
125
126 dev = *pDev;
127 if (!dev->kbdfeed && !dev->bell) {
128 *pDev = NULL;
129 *xkb_err = XkbErr_BadClass;
130 return XkbKeyboardErrorCode;
131 }
132 return Success;
133}
134
135int
136_XkbLookupLedDevice(DeviceIntPtr *pDev, int id, ClientPtr client,
137 Mask access_mode, int *xkb_err)
138{
139 DeviceIntPtr dev;
140 int rc;
141
142 if (id == XkbDfltXIId)
143 id = XkbUseCorePtr;
144
145 rc = _XkbLookupAnyDevice(pDev, id, client, access_mode, xkb_err);
146 if (rc != Success)
147 return rc;
148
149 dev = *pDev;
150 if (!dev->kbdfeed && !dev->leds) {
151 *pDev = NULL;
152 *xkb_err = XkbErr_BadClass;
153 return XkbKeyboardErrorCode;
154 }
155 return Success;
156}
157
158int
159_XkbLookupButtonDevice(DeviceIntPtr *pDev, int id, ClientPtr client,
160 Mask access_mode, int *xkb_err)
161{
162 DeviceIntPtr dev;
163 int rc;
164
165 rc = _XkbLookupAnyDevice(pDev, id, client, access_mode, xkb_err);
166 if (rc != Success)
167 return rc;
168
169 dev = *pDev;
170 if (!dev->button) {
171 *pDev = NULL;
172 *xkb_err = XkbErr_BadClass;
173 return XkbKeyboardErrorCode;
174 }
175 return Success;
176}
177
178void
179XkbSetActionKeyMods(XkbDescPtr xkb, XkbAction *act, unsigned mods)
180{
181 register unsigned tmp;
182
183 switch (act->type) {
184 case XkbSA_SetMods:
185 case XkbSA_LatchMods:
186 case XkbSA_LockMods:
187 if (act->mods.flags & XkbSA_UseModMapMods)
188 act->mods.real_mods = act->mods.mask = mods;
189 if ((tmp = XkbModActionVMods(&act->mods)) != 0)
190 act->mods.mask |= XkbMaskForVMask(xkb, tmp);
191 break;
192 case XkbSA_ISOLock:
193 if (act->iso.flags & XkbSA_UseModMapMods)
194 act->iso.real_mods = act->iso.mask = mods;
195 if ((tmp = XkbModActionVMods(&act->iso)) != 0)
196 act->iso.mask |= XkbMaskForVMask(xkb, tmp);
197 break;
198 }
199 return;
200}
201
202unsigned
203XkbMaskForVMask(XkbDescPtr xkb, unsigned vmask)
204{
205 register int i, bit;
206 register unsigned mask;
207
208 for (mask = i = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
209 if (vmask & bit)
210 mask |= xkb->server->vmods[i];
211 }
212 return mask;
213}
214
215/***====================================================================***/
216
217void
218XkbUpdateKeyTypesFromCore(DeviceIntPtr pXDev,
219 KeySymsPtr pCore,
220 KeyCode first, CARD8 num, XkbChangesPtr changes)
221{
222 XkbDescPtr xkb;
223 unsigned key, nG, explicit;
224 int types[XkbNumKbdGroups];
225 KeySym tsyms[XkbMaxSymsPerKey], *syms;
226 XkbMapChangesPtr mc;
227
228 xkb = pXDev->key->xkbInfo->desc;
229 if (first + num - 1 > xkb->max_key_code) {
230 /* 1/12/95 (ef) -- XXX! should allow XKB structures to grow */
231 num = xkb->max_key_code - first + 1;
232 }
233
234 mc = (changes ? (&changes->map) : NULL);
235
236 syms = &pCore->map[(first - pCore->minKeyCode) * pCore->mapWidth];
237 for (key = first; key < (first + num); key++, syms += pCore->mapWidth) {
238 explicit = xkb->server->explicit[key] & XkbExplicitKeyTypesMask;
239 types[XkbGroup1Index] = XkbKeyKeyTypeIndex(xkb, key, XkbGroup1Index);
240 types[XkbGroup2Index] = XkbKeyKeyTypeIndex(xkb, key, XkbGroup2Index);
241 types[XkbGroup3Index] = XkbKeyKeyTypeIndex(xkb, key, XkbGroup3Index);
242 types[XkbGroup4Index] = XkbKeyKeyTypeIndex(xkb, key, XkbGroup4Index);
243 nG = XkbKeyTypesForCoreSymbols(xkb, pCore->mapWidth, syms, explicit,
244 types, tsyms);
245 XkbChangeTypesOfKey(xkb, key, nG, XkbAllGroupsMask, types, mc);
246 memcpy((char *) XkbKeySymsPtr(xkb, key), (char *) tsyms,
247 XkbKeyNumSyms(xkb, key) * sizeof(KeySym));
248 }
249 if (changes->map.changed & XkbKeySymsMask) {
250 CARD8 oldLast, newLast;
251
252 oldLast = changes->map.first_key_sym + changes->map.num_key_syms - 1;
253 newLast = first + num - 1;
254
255 if (first < changes->map.first_key_sym)
256 changes->map.first_key_sym = first;
257 if (oldLast > newLast)
258 newLast = oldLast;
259 changes->map.num_key_syms = newLast - changes->map.first_key_sym + 1;
260 }
261 else {
262 changes->map.changed |= XkbKeySymsMask;
263 changes->map.first_key_sym = first;
264 changes->map.num_key_syms = num;
265 }
266 return;
267}
268
269void
270XkbUpdateDescActions(XkbDescPtr xkb,
271 KeyCode first, CARD8 num, XkbChangesPtr changes)
272{
273 register unsigned key;
274
275 for (key = first; key < (first + num); key++) {
276 XkbApplyCompatMapToKey(xkb, key, changes);
277 }
278
279 if (changes->map.changed & (XkbVirtualModMapMask | XkbModifierMapMask)) {
280 unsigned char newVMods[XkbNumVirtualMods];
281 register unsigned bit, i;
282 unsigned present;
283
284 memset(newVMods, 0, XkbNumVirtualMods);
285 present = 0;
286 for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
287 if (xkb->server->vmodmap[key] == 0)
288 continue;
289 for (i = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
290 if (bit & xkb->server->vmodmap[key]) {
291 present |= bit;
292 newVMods[i] |= xkb->map->modmap[key];
293 }
294 }
295 }
296 for (i = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
297 if ((bit & present) && (newVMods[i] != xkb->server->vmods[i])) {
298 changes->map.changed |= XkbVirtualModsMask;
299 changes->map.vmods |= bit;
300 xkb->server->vmods[i] = newVMods[i];
301 }
302 }
303 }
304 if (changes->map.changed & XkbVirtualModsMask)
305 XkbApplyVirtualModChanges(xkb, changes->map.vmods, changes);
306
307 if (changes->map.changed & XkbKeyActionsMask) {
308 CARD8 oldLast, newLast;
309
310 oldLast = changes->map.first_key_act + changes->map.num_key_acts - 1;
311 newLast = first + num - 1;
312
313 if (first < changes->map.first_key_act)
314 changes->map.first_key_act = first;
315 if (newLast > oldLast)
316 newLast = oldLast;
317 changes->map.num_key_acts = newLast - changes->map.first_key_act + 1;
318 }
319 else {
320 changes->map.changed |= XkbKeyActionsMask;
321 changes->map.first_key_act = first;
322 changes->map.num_key_acts = num;
323 }
324 return;
325}
326
327void
328XkbUpdateActions(DeviceIntPtr pXDev,
329 KeyCode first,
330 CARD8 num,
331 XkbChangesPtr changes,
332 unsigned *needChecksRtrn, XkbEventCausePtr cause)
333{
334 XkbSrvInfoPtr xkbi;
335 XkbDescPtr xkb;
336 CARD8 *repeat;
337
338 if (needChecksRtrn)
339 *needChecksRtrn = 0;
340 xkbi = pXDev->key->xkbInfo;
341 xkb = xkbi->desc;
342 repeat = xkb->ctrls->per_key_repeat;
343
344 /* before letting XKB do any changes, copy the current core values */
345 if (pXDev->kbdfeed)
346 memcpy(repeat, pXDev->kbdfeed->ctrl.autoRepeats, XkbPerKeyBitArraySize);
347
348 XkbUpdateDescActions(xkb, first, num, changes);
349
350 if ((pXDev->kbdfeed) &&
351 (changes->ctrls.changed_ctrls & XkbPerKeyRepeatMask)) {
352 /* now copy the modified changes back to core */
353 memcpy(pXDev->kbdfeed->ctrl.autoRepeats, repeat, XkbPerKeyBitArraySize);
354 if (pXDev->kbdfeed->CtrlProc)
355 (*pXDev->kbdfeed->CtrlProc) (pXDev, &pXDev->kbdfeed->ctrl);
356 }
357 return;
358}
359
360KeySymsPtr
361XkbGetCoreMap(DeviceIntPtr keybd)
362{
363 register int key, tmp;
364 int maxSymsPerKey, maxGroup1Width;
365 XkbDescPtr xkb;
366 KeySymsPtr syms;
367 int maxNumberOfGroups;
368
369 if (!keybd || !keybd->key || !keybd->key->xkbInfo)
370 return NULL;
371
372 xkb = keybd->key->xkbInfo->desc;
373 maxSymsPerKey = maxGroup1Width = 0;
374 maxNumberOfGroups = 0;
375
376 /* determine sizes */
377 for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
378 if (XkbKeycodeInRange(xkb, key)) {
379 int nGroups;
380 int w;
381
382 nGroups = XkbKeyNumGroups(xkb, key);
383 tmp = 0;
384 if (nGroups > 0) {
385 if ((w = XkbKeyGroupWidth(xkb, key, XkbGroup1Index)) <= 2)
386 tmp += 2;
387 else
388 tmp += w + 2;
389 /* remember highest G1 width */
390 if (w > maxGroup1Width)
391 maxGroup1Width = w;
392 }
393 if (nGroups > 1) {
394 if (tmp <= 2) {
395 if ((w = XkbKeyGroupWidth(xkb, key, XkbGroup2Index)) < 2)
396 tmp += 2;
397 else
398 tmp += w;
399 }
400 else {
401 if ((w = XkbKeyGroupWidth(xkb, key, XkbGroup2Index)) > 2)
402 tmp += w - 2;
403 }
404 }
405 if (nGroups > 2)
406 tmp += XkbKeyGroupWidth(xkb, key, XkbGroup3Index);
407 if (nGroups > 3)
408 tmp += XkbKeyGroupWidth(xkb, key, XkbGroup4Index);
409 if (tmp > maxSymsPerKey)
410 maxSymsPerKey = tmp;
411 if (nGroups > maxNumberOfGroups)
412 maxNumberOfGroups = nGroups;
413 }
414 }
415
416 if (maxSymsPerKey <= 0)
417 return NULL;
418
419 syms = calloc(1, sizeof(*syms));
420 if (!syms)
421 return NULL;
422
423 /* See Section 12.4 of the XKB Protocol spec. Because of the
424 * single-group distribution for multi-group keyboards, we have to
425 * have enough symbols for the largest group 1 to replicate across the
426 * number of groups on the keyboard. e.g. a single-group key with 4
427 * symbols on a keyboard that has 3 groups -> 12 syms per key */
428 if (maxSymsPerKey < maxNumberOfGroups * maxGroup1Width)
429 maxSymsPerKey = maxNumberOfGroups * maxGroup1Width;
430
431 syms->mapWidth = maxSymsPerKey;
432 syms->minKeyCode = xkb->min_key_code;
433 syms->maxKeyCode = xkb->max_key_code;
434
435 tmp = syms->mapWidth * (xkb->max_key_code - xkb->min_key_code + 1);
436 syms->map = calloc(tmp, sizeof(*syms->map));
437 if (!syms->map) {
438 free(syms);
439 return NULL;
440 }
441
442 for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
443 KeySym *pCore, *pXKB;
444 unsigned nGroups, groupWidth, n, nOut;
445
446 nGroups = XkbKeyNumGroups(xkb, key);
447 n = (key - xkb->min_key_code) * syms->mapWidth;
448 pCore = &syms->map[n];
449 pXKB = XkbKeySymsPtr(xkb, key);
450 nOut = 2;
451 if (nGroups > 0) {
452 groupWidth = XkbKeyGroupWidth(xkb, key, XkbGroup1Index);
453 if (groupWidth > 0)
454 pCore[0] = pXKB[0];
455 if (groupWidth > 1)
456 pCore[1] = pXKB[1];
457 for (n = 2; n < groupWidth; n++)
458 pCore[2 + n] = pXKB[n];
459 if (groupWidth > 2)
460 nOut = groupWidth;
461 }
462
463 /* See XKB Protocol Sec, Section 12.4.
464 A 1-group key with ABCDE on a 2 group keyboard must be
465 duplicated across all groups as ABABCDECDE.
466 */
467 if (nGroups == 1) {
468 int idx, j;
469
470 groupWidth = XkbKeyGroupWidth(xkb, key, XkbGroup1Index);
471
472 /* AB..CDE... -> ABABCDE... */
473 if (groupWidth > 0 && syms->mapWidth >= 3)
474 pCore[2] = pCore[0];
475 if (groupWidth > 1 && syms->mapWidth >= 4)
476 pCore[3] = pCore[1];
477
478 /* ABABCDE... -> ABABCDECDE */
479 idx = 2 + groupWidth;
480 while (groupWidth > 2 && idx < syms->mapWidth &&
481 idx < groupWidth * 2) {
482 pCore[idx] = pCore[idx - groupWidth + 2];
483 idx++;
484 }
485 idx = 2 * groupWidth;
486 if (idx < 4)
487 idx = 4;
488 /* 3 or more groups: ABABCDECDEABCDEABCDE */
489 for (j = 3; j <= maxNumberOfGroups; j++)
490 for (n = 0; n < groupWidth && idx < maxSymsPerKey; n++)
491 pCore[idx++] = pXKB[n];
492 }
493
494 pXKB += XkbKeyGroupsWidth(xkb, key);
495 nOut += 2;
496 if (nGroups > 1) {
497 groupWidth = XkbKeyGroupWidth(xkb, key, XkbGroup2Index);
498 if (groupWidth > 0)
499 pCore[2] = pXKB[0];
500 if (groupWidth > 1)
501 pCore[3] = pXKB[1];
502 for (n = 2; n < groupWidth; n++) {
503 pCore[nOut + (n - 2)] = pXKB[n];
504 }
505 if (groupWidth > 2)
506 nOut += (groupWidth - 2);
507 }
508 pXKB += XkbKeyGroupsWidth(xkb, key);
509 for (n = XkbGroup3Index; n < nGroups; n++) {
510 register int s;
511
512 groupWidth = XkbKeyGroupWidth(xkb, key, n);
513 for (s = 0; s < groupWidth; s++) {
514 pCore[nOut++] = pXKB[s];
515 }
516 pXKB += XkbKeyGroupsWidth(xkb, key);
517 }
518 }
519
520 return syms;
521}
522
523void
524XkbSetRepeatKeys(DeviceIntPtr pXDev, int key, int onoff)
525{
526 if (pXDev && pXDev->key && pXDev->key->xkbInfo) {
527 xkbControlsNotify cn;
528 XkbControlsPtr ctrls = pXDev->key->xkbInfo->desc->ctrls;
529 XkbControlsRec old;
530
531 old = *ctrls;
532
533 if (key == -1) { /* global autorepeat setting changed */
534 if (onoff)
535 ctrls->enabled_ctrls |= XkbRepeatKeysMask;
536 else
537 ctrls->enabled_ctrls &= ~XkbRepeatKeysMask;
538 }
539 else if (pXDev->kbdfeed) {
540 ctrls->per_key_repeat[key / 8] =
541 pXDev->kbdfeed->ctrl.autoRepeats[key / 8];
542 }
543
544 if (XkbComputeControlsNotify(pXDev, &old, ctrls, &cn, TRUE))
545 XkbSendControlsNotify(pXDev, &cn);
546 }
547 return;
548}
549
550/* Applies a change to a single device, does not traverse the device tree. */
551void
552XkbApplyMappingChange(DeviceIntPtr kbd, KeySymsPtr map, KeyCode first_key,
553 CARD8 num_keys, CARD8 *modmap, ClientPtr client)
554{
555 XkbDescPtr xkb = kbd->key->xkbInfo->desc;
556 XkbEventCauseRec cause;
557 XkbChangesRec changes;
558 unsigned int check;
559
560 memset(&changes, 0, sizeof(changes));
561 memset(&cause, 0, sizeof(cause));
562
563 if (map && first_key && num_keys) {
564 check = 0;
565 XkbSetCauseCoreReq(&cause, X_ChangeKeyboardMapping, client);
566
567 XkbUpdateKeyTypesFromCore(kbd, map, first_key, num_keys, &changes);
568 XkbUpdateActions(kbd, first_key, num_keys, &changes, &check, &cause);
569
570 if (check)
571 XkbCheckSecondaryEffects(kbd->key->xkbInfo, 1, &changes, &cause);
572 }
573
574 if (modmap) {
575 /* A keymap change can imply a modmap change, se we prefer the
576 * former. */
577 if (!cause.mjr)
578 XkbSetCauseCoreReq(&cause, X_SetModifierMapping, client);
579
580 check = 0;
581 num_keys = xkb->max_key_code - xkb->min_key_code + 1;
582 changes.map.changed |= XkbModifierMapMask;
583 changes.map.first_modmap_key = xkb->min_key_code;
584 changes.map.num_modmap_keys = num_keys;
585 memcpy(kbd->key->xkbInfo->desc->map->modmap, modmap, MAP_LENGTH);
586 XkbUpdateActions(kbd, xkb->min_key_code, num_keys, &changes, &check,
587 &cause);
588
589 if (check)
590 XkbCheckSecondaryEffects(kbd->key->xkbInfo, 1, &changes, &cause);
591 }
592
593 XkbSendNotification(kbd, &changes, &cause);
594}
595
596void
597XkbDisableComputedAutoRepeats(DeviceIntPtr dev, unsigned key)
598{
599 XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
600 xkbMapNotify mn;
601
602 xkbi->desc->server->explicit[key] |= XkbExplicitAutoRepeatMask;
603 memset(&mn, 0, sizeof(mn));
604 mn.changed = XkbExplicitComponentsMask;
605 mn.firstKeyExplicit = key;
606 mn.nKeyExplicit = 1;
607 XkbSendMapNotify(dev, &mn);
608 return;
609}
610
611unsigned
612XkbStateChangedFlags(XkbStatePtr old, XkbStatePtr new)
613{
614 int changed;
615
616 changed = (old->group != new->group ? XkbGroupStateMask : 0);
617 changed |= (old->base_group != new->base_group ? XkbGroupBaseMask : 0);
618 changed |=
619 (old->latched_group != new->latched_group ? XkbGroupLatchMask : 0);
620 changed |= (old->locked_group != new->locked_group ? XkbGroupLockMask : 0);
621 changed |= (old->mods != new->mods ? XkbModifierStateMask : 0);
622 changed |= (old->base_mods != new->base_mods ? XkbModifierBaseMask : 0);
623 changed |=
624 (old->latched_mods != new->latched_mods ? XkbModifierLatchMask : 0);
625 changed |= (old->locked_mods != new->locked_mods ? XkbModifierLockMask : 0);
626 changed |=
627 (old->compat_state != new->compat_state ? XkbCompatStateMask : 0);
628 changed |= (old->grab_mods != new->grab_mods ? XkbGrabModsMask : 0);
629 if (old->compat_grab_mods != new->compat_grab_mods)
630 changed |= XkbCompatGrabModsMask;
631 changed |= (old->lookup_mods != new->lookup_mods ? XkbLookupModsMask : 0);
632 if (old->compat_lookup_mods != new->compat_lookup_mods)
633 changed |= XkbCompatLookupModsMask;
634 changed |=
635 (old->ptr_buttons != new->ptr_buttons ? XkbPointerButtonMask : 0);
636 return changed;
637}
638
639static void
640XkbComputeCompatState(XkbSrvInfoPtr xkbi)
641{
642 CARD16 grp_mask;
643 XkbStatePtr state = &xkbi->state;
644 XkbCompatMapPtr map;
645 XkbControlsPtr ctrls;
646
647 if (!state || !xkbi->desc || !xkbi->desc->ctrls || !xkbi->desc->compat)
648 return;
649
650 map = xkbi->desc->compat;
651 grp_mask = map->groups[state->group].mask;
652 state->compat_state = state->mods | grp_mask;
653 state->compat_lookup_mods = state->lookup_mods | grp_mask;
654 ctrls= xkbi->desc->ctrls;
655
656 if (ctrls->enabled_ctrls & XkbIgnoreGroupLockMask) {
657 unsigned char grp = state->base_group+state->latched_group;
658 if (grp >= ctrls->num_groups)
659 grp = XkbAdjustGroup(XkbCharToInt(grp), ctrls);
660 grp_mask = map->groups[grp].mask;
661 }
662 state->compat_grab_mods = state->grab_mods | grp_mask;
663 return;
664}
665
666unsigned
667XkbAdjustGroup(int group, XkbControlsPtr ctrls)
668{
669 unsigned act;
670
671 act = XkbOutOfRangeGroupAction(ctrls->groups_wrap);
672 if (group < 0) {
673 while (group < 0) {
674 if (act == XkbClampIntoRange) {
675 group = XkbGroup1Index;
676 }
677 else if (act == XkbRedirectIntoRange) {
678 int newGroup;
679
680 newGroup = XkbOutOfRangeGroupNumber(ctrls->groups_wrap);
681 if (newGroup >= ctrls->num_groups)
682 group = XkbGroup1Index;
683 else
684 group = newGroup;
685 }
686 else {
687 group += ctrls->num_groups;
688 }
689 }
690 }
691 else if (group >= ctrls->num_groups) {
692 if (act == XkbClampIntoRange) {
693 group = ctrls->num_groups - 1;
694 }
695 else if (act == XkbRedirectIntoRange) {
696 int newGroup;
697
698 newGroup = XkbOutOfRangeGroupNumber(ctrls->groups_wrap);
699 if (newGroup >= ctrls->num_groups)
700 group = XkbGroup1Index;
701 else
702 group = newGroup;
703 }
704 else {
705 group %= ctrls->num_groups;
706 }
707 }
708 return group;
709}
710
711void
712XkbComputeDerivedState(XkbSrvInfoPtr xkbi)
713{
714 XkbStatePtr state = &xkbi->state;
715 XkbControlsPtr ctrls = xkbi->desc->ctrls;
716 unsigned char grp;
717
718 if (!state || !ctrls)
719 return;
720
721 state->mods = (state->base_mods | state->latched_mods | state->locked_mods);
722 state->lookup_mods = state->mods & (~ctrls->internal.mask);
723 state->grab_mods = state->lookup_mods & (~ctrls->ignore_lock.mask);
724 state->grab_mods |=
725 ((state->base_mods | state->latched_mods) & ctrls->ignore_lock.mask);
726
727 grp = state->locked_group;
728 if (grp >= ctrls->num_groups)
729 state->locked_group = XkbAdjustGroup(XkbCharToInt(grp), ctrls);
730
731 grp = state->locked_group + state->base_group + state->latched_group;
732 if (grp >= ctrls->num_groups)
733 state->group = XkbAdjustGroup(XkbCharToInt(grp), ctrls);
734 else
735 state->group = grp;
736 XkbComputeCompatState(xkbi);
737 return;
738}
739
740/***====================================================================***/
741
742void
743XkbCheckSecondaryEffects(XkbSrvInfoPtr xkbi,
744 unsigned which,
745 XkbChangesPtr changes, XkbEventCausePtr cause)
746{
747 if (which & XkbStateNotifyMask) {
748 XkbStateRec old;
749
750 old = xkbi->state;
751 changes->state_changes |= XkbStateChangedFlags(&old, &xkbi->state);
752 XkbComputeDerivedState(xkbi);
753 }
754 if (which & XkbIndicatorStateNotifyMask)
755 XkbUpdateIndicators(xkbi->device, XkbAllIndicatorsMask, TRUE, changes,
756 cause);
757 return;
758}
759
760/***====================================================================***/
761
762Bool
763XkbEnableDisableControls(XkbSrvInfoPtr xkbi,
764 unsigned long change,
765 unsigned long newValues,
766 XkbChangesPtr changes, XkbEventCausePtr cause)
767{
768 XkbControlsPtr ctrls;
769 unsigned old;
770 XkbSrvLedInfoPtr sli;
771
772 ctrls = xkbi->desc->ctrls;
773 old = ctrls->enabled_ctrls;
774 ctrls->enabled_ctrls &= ~change;
775 ctrls->enabled_ctrls |= (change & newValues);
776 if (old == ctrls->enabled_ctrls)
777 return FALSE;
778 if (cause != NULL) {
779 xkbControlsNotify cn;
780
781 cn.numGroups = ctrls->num_groups;
782 cn.changedControls = XkbControlsEnabledMask;
783 cn.enabledControls = ctrls->enabled_ctrls;
784 cn.enabledControlChanges = (ctrls->enabled_ctrls ^ old);
785 cn.keycode = cause->kc;
786 cn.eventType = cause->event;
787 cn.requestMajor = cause->mjr;
788 cn.requestMinor = cause->mnr;
789 XkbSendControlsNotify(xkbi->device, &cn);
790 }
791 else {
792 /* Yes, this really should be an XOR. If ctrls->enabled_ctrls_changes */
793 /* is non-zero, the controls in question changed already in "this" */
794 /* request and this change merely undoes the previous one. By the */
795 /* same token, we have to figure out whether or not ControlsEnabled */
796 /* should be set or not in the changes structure */
797 changes->ctrls.enabled_ctrls_changes ^= (ctrls->enabled_ctrls ^ old);
798 if (changes->ctrls.enabled_ctrls_changes)
799 changes->ctrls.changed_ctrls |= XkbControlsEnabledMask;
800 else
801 changes->ctrls.changed_ctrls &= ~XkbControlsEnabledMask;
802 }
803 sli = XkbFindSrvLedInfo(xkbi->device, XkbDfltXIClass, XkbDfltXIId, 0);
804 XkbUpdateIndicators(xkbi->device, sli->usesControls, TRUE, changes, cause);
805 return TRUE;
806}
807
808/***====================================================================***/
809
810#define MAX_TOC 16
811
812XkbGeometryPtr
813XkbLookupNamedGeometry(DeviceIntPtr dev, Atom name, Bool *shouldFree)
814{
815 XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
816 XkbDescPtr xkb = xkbi->desc;
817
818 *shouldFree = 0;
819 if (name == None) {
820 if (xkb->geom != NULL)
821 return xkb->geom;
822 name = xkb->names->geometry;
823 }
824 if ((xkb->geom != NULL) && (xkb->geom->name == name))
825 return xkb->geom;
826 *shouldFree = 1;
827 return NULL;
828}
829
830void
831XkbConvertCase(register KeySym sym, KeySym * lower, KeySym * upper)
832{
833 *lower = sym;
834 *upper = sym;
835 switch (sym >> 8) {
836 case 0: /* Latin 1 */
837 if ((sym >= XK_A) && (sym <= XK_Z))
838 *lower += (XK_a - XK_A);
839 else if ((sym >= XK_a) && (sym <= XK_z))
840 *upper -= (XK_a - XK_A);
841 else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
842 *lower += (XK_agrave - XK_Agrave);
843 else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
844 *upper -= (XK_agrave - XK_Agrave);
845 else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
846 *lower += (XK_oslash - XK_Ooblique);
847 else if ((sym >= XK_oslash) && (sym <= XK_thorn))
848 *upper -= (XK_oslash - XK_Ooblique);
849 break;
850 case 1: /* Latin 2 */
851 /* Assume the KeySym is a legal value (ignore discontinuities) */
852 if (sym == XK_Aogonek)
853 *lower = XK_aogonek;
854 else if (sym >= XK_Lstroke && sym <= XK_Sacute)
855 *lower += (XK_lstroke - XK_Lstroke);
856 else if (sym >= XK_Scaron && sym <= XK_Zacute)
857 *lower += (XK_scaron - XK_Scaron);
858 else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
859 *lower += (XK_zcaron - XK_Zcaron);
860 else if (sym == XK_aogonek)
861 *upper = XK_Aogonek;
862 else if (sym >= XK_lstroke && sym <= XK_sacute)
863 *upper -= (XK_lstroke - XK_Lstroke);
864 else if (sym >= XK_scaron && sym <= XK_zacute)
865 *upper -= (XK_scaron - XK_Scaron);
866 else if (sym >= XK_zcaron && sym <= XK_zabovedot)
867 *upper -= (XK_zcaron - XK_Zcaron);
868 else if (sym >= XK_Racute && sym <= XK_Tcedilla)
869 *lower += (XK_racute - XK_Racute);
870 else if (sym >= XK_racute && sym <= XK_tcedilla)
871 *upper -= (XK_racute - XK_Racute);
872 break;
873 case 2: /* Latin 3 */
874 /* Assume the KeySym is a legal value (ignore discontinuities) */
875 if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
876 *lower += (XK_hstroke - XK_Hstroke);
877 else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
878 *lower += (XK_gbreve - XK_Gbreve);
879 else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
880 *upper -= (XK_hstroke - XK_Hstroke);
881 else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
882 *upper -= (XK_gbreve - XK_Gbreve);
883 else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
884 *lower += (XK_cabovedot - XK_Cabovedot);
885 else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
886 *upper -= (XK_cabovedot - XK_Cabovedot);
887 break;
888 case 3: /* Latin 4 */
889 /* Assume the KeySym is a legal value (ignore discontinuities) */
890 if (sym >= XK_Rcedilla && sym <= XK_Tslash)
891 *lower += (XK_rcedilla - XK_Rcedilla);
892 else if (sym >= XK_rcedilla && sym <= XK_tslash)
893 *upper -= (XK_rcedilla - XK_Rcedilla);
894 else if (sym == XK_ENG)
895 *lower = XK_eng;
896 else if (sym == XK_eng)
897 *upper = XK_ENG;
898 else if (sym >= XK_Amacron && sym <= XK_Umacron)
899 *lower += (XK_amacron - XK_Amacron);
900 else if (sym >= XK_amacron && sym <= XK_umacron)
901 *upper -= (XK_amacron - XK_Amacron);
902 break;
903 case 6: /* Cyrillic */
904 /* Assume the KeySym is a legal value (ignore discontinuities) */
905 if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
906 *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
907 else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
908 *upper += (XK_Serbian_DJE - XK_Serbian_dje);
909 else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
910 *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
911 else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
912 *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
913 break;
914 case 7: /* Greek */
915 /* Assume the KeySym is a legal value (ignore discontinuities) */
916 if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
917 *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
918 else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
919 sym != XK_Greek_iotaaccentdieresis &&
920 sym != XK_Greek_upsilonaccentdieresis)
921 *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
922 else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
923 *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
924 else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
925 sym != XK_Greek_finalsmallsigma)
926 *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
927 break;
928 }
929}
930
931static Bool
932_XkbCopyClientMap(XkbDescPtr src, XkbDescPtr dst)
933{
934 void *tmp = NULL;
935 int i;
936 XkbKeyTypePtr stype = NULL, dtype = NULL;
937
938 /* client map */
939 if (src->map) {
940 if (!dst->map) {
941 tmp = calloc(1, sizeof(XkbClientMapRec));
942 if (!tmp)
943 return FALSE;
944 dst->map = tmp;
945 }
946
947 if (src->map->syms) {
948 if (src->map->size_syms != dst->map->size_syms) {
949 tmp = realloc(dst->map->syms,
950 src->map->size_syms * sizeof(KeySym));
951 if (!tmp)
952 return FALSE;
953 dst->map->syms = tmp;
954
955 }
956 memcpy(dst->map->syms, src->map->syms,
957 src->map->size_syms * sizeof(KeySym));
958 }
959 else {
960 free(dst->map->syms);
961 dst->map->syms = NULL;
962 }
963 dst->map->num_syms = src->map->num_syms;
964 dst->map->size_syms = src->map->size_syms;
965
966 if (src->map->key_sym_map) {
967 if (src->max_key_code != dst->max_key_code) {
968 tmp = realloc(dst->map->key_sym_map,
969 (src->max_key_code + 1) * sizeof(XkbSymMapRec));
970 if (!tmp)
971 return FALSE;
972 dst->map->key_sym_map = tmp;
973 }
974 memcpy(dst->map->key_sym_map, src->map->key_sym_map,
975 (src->max_key_code + 1) * sizeof(XkbSymMapRec));
976 }
977 else {
978 free(dst->map->key_sym_map);
979 dst->map->key_sym_map = NULL;
980 }
981
982 if (src->map->types && src->map->num_types) {
983 if (src->map->num_types > dst->map->size_types ||
984 !dst->map->types || !dst->map->size_types) {
985 if (dst->map->types && dst->map->size_types) {
986 tmp = realloc(dst->map->types,
987 src->map->num_types * sizeof(XkbKeyTypeRec));
988 if (!tmp)
989 return FALSE;
990 dst->map->types = tmp;
991 memset(dst->map->types + dst->map->num_types, 0,
992 (src->map->num_types - dst->map->num_types) *
993 sizeof(XkbKeyTypeRec));
994 }
995 else {
996 tmp = calloc(src->map->num_types, sizeof(XkbKeyTypeRec));
997 if (!tmp)
998 return FALSE;
999 dst->map->types = tmp;
1000 }
1001 }
1002 else if (src->map->num_types < dst->map->num_types &&
1003 dst->map->types) {
1004 for (i = src->map->num_types, dtype = (dst->map->types + i);
1005 i < dst->map->num_types; i++, dtype++) {
1006 free(dtype->level_names);
1007 dtype->level_names = NULL;
1008 dtype->num_levels = 0;
1009 if (dtype->map_count) {
1010 free(dtype->map);
1011 free(dtype->preserve);
1012 }
1013 }
1014 }
1015
1016 stype = src->map->types;
1017 dtype = dst->map->types;
1018 for (i = 0; i < src->map->num_types; i++, dtype++, stype++) {
1019 if (stype->num_levels && stype->level_names) {
1020 if (stype->num_levels != dtype->num_levels &&
1021 dtype->num_levels && dtype->level_names &&
1022 i < dst->map->num_types) {
1023 tmp = realloc(dtype->level_names,
1024 stype->num_levels * sizeof(Atom));
1025 if (!tmp)
1026 continue;
1027 dtype->level_names = tmp;
1028 }
1029 else if (!dtype->num_levels || !dtype->level_names ||
1030 i >= dst->map->num_types) {
1031 tmp = malloc(stype->num_levels * sizeof(Atom));
1032 if (!tmp)
1033 continue;
1034 dtype->level_names = tmp;
1035 }
1036 dtype->num_levels = stype->num_levels;
1037 memcpy(dtype->level_names, stype->level_names,
1038 stype->num_levels * sizeof(Atom));
1039 }
1040 else {
1041 if (dtype->num_levels && dtype->level_names &&
1042 i < dst->map->num_types)
1043 free(dtype->level_names);
1044 dtype->num_levels = 0;
1045 dtype->level_names = NULL;
1046 }
1047
1048 dtype->name = stype->name;
1049 memcpy(&dtype->mods, &stype->mods, sizeof(XkbModsRec));
1050
1051 if (stype->map_count) {
1052 if (stype->map) {
1053 if (stype->map_count != dtype->map_count &&
1054 dtype->map_count && dtype->map &&
1055 i < dst->map->num_types) {
1056 tmp = realloc(dtype->map,
1057 stype->map_count *
1058 sizeof(XkbKTMapEntryRec));
1059 if (!tmp)
1060 return FALSE;
1061 dtype->map = tmp;
1062 }
1063 else if (!dtype->map_count || !dtype->map ||
1064 i >= dst->map->num_types) {
1065 tmp = malloc(stype->map_count *
1066 sizeof(XkbKTMapEntryRec));
1067 if (!tmp)
1068 return FALSE;
1069 dtype->map = tmp;
1070 }
1071
1072 memcpy(dtype->map, stype->map,
1073 stype->map_count * sizeof(XkbKTMapEntryRec));
1074 }
1075 else {
1076 if (dtype->map && i < dst->map->num_types)
1077 free(dtype->map);
1078 dtype->map = NULL;
1079 }
1080
1081 if (stype->preserve) {
1082 if (stype->map_count != dtype->map_count &&
1083 dtype->map_count && dtype->preserve &&
1084 i < dst->map->num_types) {
1085 tmp = realloc(dtype->preserve,
1086 stype->map_count *
1087 sizeof(XkbModsRec));
1088 if (!tmp)
1089 return FALSE;
1090 dtype->preserve = tmp;
1091 }
1092 else if (!dtype->preserve || !dtype->map_count ||
1093 i >= dst->map->num_types) {
1094 tmp = malloc(stype->map_count * sizeof(XkbModsRec));
1095 if (!tmp)
1096 return FALSE;
1097 dtype->preserve = tmp;
1098 }
1099
1100 memcpy(dtype->preserve, stype->preserve,
1101 stype->map_count * sizeof(XkbModsRec));
1102 }
1103 else {
1104 if (dtype->preserve && i < dst->map->num_types)
1105 free(dtype->preserve);
1106 dtype->preserve = NULL;
1107 }
1108
1109 dtype->map_count = stype->map_count;
1110 }
1111 else {
1112 if (dtype->map_count && i < dst->map->num_types) {
1113 free(dtype->map);
1114 free(dtype->preserve);
1115 }
1116 dtype->map_count = 0;
1117 dtype->map = NULL;
1118 dtype->preserve = NULL;
1119 }
1120 }
1121
1122 dst->map->size_types = src->map->num_types;
1123 dst->map->num_types = src->map->num_types;
1124 }
1125 else {
1126 if (dst->map->types) {
1127 for (i = 0, dtype = dst->map->types; i < dst->map->num_types;
1128 i++, dtype++) {
1129 free(dtype->level_names);
1130 if (dtype->map && dtype->map_count)
1131 free(dtype->map);
1132 if (dtype->preserve && dtype->map_count)
1133 free(dtype->preserve);
1134 }
1135 }
1136 free(dst->map->types);
1137 dst->map->types = NULL;
1138 dst->map->num_types = 0;
1139 dst->map->size_types = 0;
1140 }
1141
1142 if (src->map->modmap) {
1143 if (src->max_key_code != dst->max_key_code) {
1144 tmp = realloc(dst->map->modmap, src->max_key_code + 1);
1145 if (!tmp)
1146 return FALSE;
1147 dst->map->modmap = tmp;
1148 }
1149 memcpy(dst->map->modmap, src->map->modmap, src->max_key_code + 1);
1150 }
1151 else {
1152 free(dst->map->modmap);
1153 dst->map->modmap = NULL;
1154 }
1155 }
1156 else {
1157 if (dst->map)
1158 XkbFreeClientMap(dst, XkbAllClientInfoMask, TRUE);
1159 }
1160
1161 return TRUE;
1162}
1163
1164static Bool
1165_XkbCopyServerMap(XkbDescPtr src, XkbDescPtr dst)
1166{
1167 void *tmp = NULL;
1168
1169 /* server map */
1170 if (src->server) {
1171 if (!dst->server) {
1172 tmp = calloc(1, sizeof(XkbServerMapRec));
1173 if (!tmp)
1174 return FALSE;
1175 dst->server = tmp;
1176 }
1177
1178 if (src->server->explicit) {
1179 if (src->max_key_code != dst->max_key_code) {
1180 tmp = realloc(dst->server->explicit, src->max_key_code + 1);
1181 if (!tmp)
1182 return FALSE;
1183 dst->server->explicit = tmp;
1184 }
1185 memcpy(dst->server->explicit, src->server->explicit,
1186 src->max_key_code + 1);
1187 }
1188 else {
1189 free(dst->server->explicit);
1190 dst->server->explicit = NULL;
1191 }
1192
1193 if (src->server->acts) {
1194 if (src->server->size_acts != dst->server->size_acts) {
1195 tmp = realloc(dst->server->acts,
1196 src->server->size_acts * sizeof(XkbAction));
1197 if (!tmp)
1198 return FALSE;
1199 dst->server->acts = tmp;
1200 }
1201 memcpy(dst->server->acts, src->server->acts,
1202 src->server->size_acts * sizeof(XkbAction));
1203 }
1204 else {
1205 free(dst->server->acts);
1206 dst->server->acts = NULL;
1207 }
1208 dst->server->size_acts = src->server->size_acts;
1209 dst->server->num_acts = src->server->num_acts;
1210
1211 if (src->server->key_acts) {
1212 if (src->max_key_code != dst->max_key_code) {
1213 tmp = realloc(dst->server->key_acts,
1214 (src->max_key_code + 1) * sizeof(unsigned short));
1215 if (!tmp)
1216 return FALSE;
1217 dst->server->key_acts = tmp;
1218 }
1219 memcpy(dst->server->key_acts, src->server->key_acts,
1220 (src->max_key_code + 1) * sizeof(unsigned short));
1221 }
1222 else {
1223 free(dst->server->key_acts);
1224 dst->server->key_acts = NULL;
1225 }
1226
1227 if (src->server->behaviors) {
1228 if (src->max_key_code != dst->max_key_code) {
1229 tmp = realloc(dst->server->behaviors,
1230 (src->max_key_code + 1) * sizeof(XkbBehavior));
1231 if (!tmp)
1232 return FALSE;
1233 dst->server->behaviors = tmp;
1234 }
1235 memcpy(dst->server->behaviors, src->server->behaviors,
1236 (src->max_key_code + 1) * sizeof(XkbBehavior));
1237 }
1238 else {
1239 free(dst->server->behaviors);
1240 dst->server->behaviors = NULL;
1241 }
1242
1243 memcpy(dst->server->vmods, src->server->vmods, XkbNumVirtualMods);
1244
1245 if (src->server->vmodmap) {
1246 if (src->max_key_code != dst->max_key_code) {
1247 tmp = realloc(dst->server->vmodmap,
1248 (src->max_key_code + 1) * sizeof(unsigned short));
1249 if (!tmp)
1250 return FALSE;
1251 dst->server->vmodmap = tmp;
1252 }
1253 memcpy(dst->server->vmodmap, src->server->vmodmap,
1254 (src->max_key_code + 1) * sizeof(unsigned short));
1255 }
1256 else {
1257 free(dst->server->vmodmap);
1258 dst->server->vmodmap = NULL;
1259 }
1260 }
1261 else {
1262 if (dst->server)
1263 XkbFreeServerMap(dst, XkbAllServerInfoMask, TRUE);
1264 }
1265
1266 return TRUE;
1267}
1268
1269static Bool
1270_XkbCopyNames(XkbDescPtr src, XkbDescPtr dst)
1271{
1272 void *tmp = NULL;
1273
1274 /* names */
1275 if (src->names) {
1276 if (!dst->names) {
1277 dst->names = calloc(1, sizeof(XkbNamesRec));
1278 if (!dst->names)
1279 return FALSE;
1280 }
1281
1282 if (src->names->keys) {
1283 if (src->max_key_code != dst->max_key_code) {
1284 tmp = realloc(dst->names->keys,
1285 (src->max_key_code + 1) * sizeof(XkbKeyNameRec));
1286 if (!tmp)
1287 return FALSE;
1288 dst->names->keys = tmp;
1289 }
1290 memcpy(dst->names->keys, src->names->keys,
1291 (src->max_key_code + 1) * sizeof(XkbKeyNameRec));
1292 }
1293 else {
1294 free(dst->names->keys);
1295 dst->names->keys = NULL;
1296 }
1297
1298 if (src->names->num_key_aliases) {
1299 if (src->names->num_key_aliases != dst->names->num_key_aliases) {
1300 tmp = realloc(dst->names->key_aliases,
1301 src->names->num_key_aliases *
1302 sizeof(XkbKeyAliasRec));
1303 if (!tmp)
1304 return FALSE;
1305 dst->names->key_aliases = tmp;
1306 }
1307 memcpy(dst->names->key_aliases, src->names->key_aliases,
1308 src->names->num_key_aliases * sizeof(XkbKeyAliasRec));
1309 }
1310 else {
1311 free(dst->names->key_aliases);
1312 dst->names->key_aliases = NULL;
1313 }
1314 dst->names->num_key_aliases = src->names->num_key_aliases;
1315
1316 if (src->names->num_rg) {
1317 if (src->names->num_rg != dst->names->num_rg) {
1318 tmp = realloc(dst->names->radio_groups,
1319 src->names->num_rg * sizeof(Atom));
1320 if (!tmp)
1321 return FALSE;
1322 dst->names->radio_groups = tmp;
1323 }
1324 memcpy(dst->names->radio_groups, src->names->radio_groups,
1325 src->names->num_rg * sizeof(Atom));
1326 }
1327 else {
1328 free(dst->names->radio_groups);
1329 }
1330 dst->names->num_rg = src->names->num_rg;
1331
1332 dst->names->keycodes = src->names->keycodes;
1333 dst->names->geometry = src->names->geometry;
1334 dst->names->symbols = src->names->symbols;
1335 dst->names->types = src->names->types;
1336 dst->names->compat = src->names->compat;
1337 dst->names->phys_symbols = src->names->phys_symbols;
1338
1339 memcpy(dst->names->vmods, src->names->vmods,
1340 XkbNumVirtualMods * sizeof(Atom));
1341 memcpy(dst->names->indicators, src->names->indicators,
1342 XkbNumIndicators * sizeof(Atom));
1343 memcpy(dst->names->groups, src->names->groups,
1344 XkbNumKbdGroups * sizeof(Atom));
1345 }
1346 else {
1347 if (dst->names)
1348 XkbFreeNames(dst, XkbAllNamesMask, TRUE);
1349 }
1350
1351 return TRUE;
1352}
1353
1354static Bool
1355_XkbCopyCompat(XkbDescPtr src, XkbDescPtr dst)
1356{
1357 void *tmp = NULL;
1358
1359 /* compat */
1360 if (src->compat) {
1361 if (!dst->compat) {
1362 dst->compat = calloc(1, sizeof(XkbCompatMapRec));
1363 if (!dst->compat)
1364 return FALSE;
1365 }
1366
1367 if (src->compat->sym_interpret && src->compat->num_si) {
1368 if (src->compat->num_si != dst->compat->size_si) {
1369 tmp = realloc(dst->compat->sym_interpret,
1370 src->compat->num_si * sizeof(XkbSymInterpretRec));
1371 if (!tmp)
1372 return FALSE;
1373 dst->compat->sym_interpret = tmp;
1374 }
1375 memcpy(dst->compat->sym_interpret, src->compat->sym_interpret,
1376 src->compat->num_si * sizeof(XkbSymInterpretRec));
1377
1378 dst->compat->num_si = src->compat->num_si;
1379 dst->compat->size_si = src->compat->num_si;
1380 }
1381 else {
1382 if (dst->compat->sym_interpret && dst->compat->size_si)
1383 free(dst->compat->sym_interpret);
1384
1385 dst->compat->sym_interpret = NULL;
1386 dst->compat->num_si = 0;
1387 dst->compat->size_si = 0;
1388 }
1389
1390 memcpy(dst->compat->groups, src->compat->groups,
1391 XkbNumKbdGroups * sizeof(XkbModsRec));
1392 }
1393 else {
1394 if (dst->compat)
1395 XkbFreeCompatMap(dst, XkbAllCompatMask, TRUE);
1396 }
1397
1398 return TRUE;
1399}
1400
1401static Bool
1402_XkbCopyGeom(XkbDescPtr src, XkbDescPtr dst)
1403{
1404 void *tmp = NULL;
1405 int i = 0, j = 0, k = 0;
1406 XkbColorPtr scolor = NULL, dcolor = NULL;
1407 XkbDoodadPtr sdoodad = NULL, ddoodad = NULL;
1408 XkbOutlinePtr soutline = NULL, doutline = NULL;
1409 XkbPropertyPtr sprop = NULL, dprop = NULL;
1410 XkbRowPtr srow = NULL, drow = NULL;
1411 XkbSectionPtr ssection = NULL, dsection = NULL;
1412 XkbShapePtr sshape = NULL, dshape = NULL;
1413
1414 /* geometry */
1415 if (src->geom) {
1416 if (!dst->geom) {
1417 dst->geom = calloc(sizeof(XkbGeometryRec), 1);
1418 if (!dst->geom)
1419 return FALSE;
1420 }
1421
1422 /* properties */
1423 if (src->geom->num_properties) {
1424 /* If we've got more properties in the destination than
1425 * the source, run through and free all the excess ones
1426 * first. */
1427 if (src->geom->num_properties < dst->geom->sz_properties) {
1428 for (i = src->geom->num_properties, dprop =
1429 dst->geom->properties + i; i < dst->geom->num_properties;
1430 i++, dprop++) {
1431 free(dprop->name);
1432 free(dprop->value);
1433 }
1434 }
1435
1436 /* Reallocate and clear all new items if the buffer grows. */
1437 if (!XkbGeomRealloc
1438 ((void **) &dst->geom->properties, dst->geom->sz_properties,
1439 src->geom->num_properties, sizeof(XkbPropertyRec),
1440 XKB_GEOM_CLEAR_EXCESS))
1441 return FALSE;
1442 /* We don't set num_properties as we need it to try and avoid
1443 * too much reallocing. */
1444 dst->geom->sz_properties = src->geom->num_properties;
1445
1446 for (i = 0,
1447 sprop = src->geom->properties,
1448 dprop = dst->geom->properties;
1449 i < src->geom->num_properties; i++, sprop++, dprop++) {
1450 if (i < dst->geom->num_properties) {
1451 if (strlen(sprop->name) != strlen(dprop->name)) {
1452 tmp = realloc(dprop->name, strlen(sprop->name) + 1);
1453 if (!tmp)
1454 return FALSE;
1455 dprop->name = tmp;
1456 }
1457 if (strlen(sprop->value) != strlen(dprop->value)) {
1458 tmp = realloc(dprop->value, strlen(sprop->value) + 1);
1459 if (!tmp)
1460 return FALSE;
1461 dprop->value = tmp;
1462 }
1463 strcpy(dprop->name, sprop->name);
1464 strcpy(dprop->value, sprop->value);
1465 }
1466 else {
1467 dprop->name = xstrdup(sprop->name);
1468 dprop->value = xstrdup(sprop->value);
1469 }
1470 }
1471
1472 /* ... which is already src->geom->num_properties. */
1473 dst->geom->num_properties = dst->geom->sz_properties;
1474 }
1475 else {
1476 if (dst->geom->sz_properties) {
1477 for (i = 0, dprop = dst->geom->properties;
1478 i < dst->geom->num_properties; i++, dprop++) {
1479 free(dprop->name);
1480 free(dprop->value);
1481 }
1482 free(dst->geom->properties);
1483 dst->geom->properties = NULL;
1484 }
1485
1486 dst->geom->num_properties = 0;
1487 dst->geom->sz_properties = 0;
1488 }
1489
1490 /* colors */
1491 if (src->geom->num_colors) {
1492 if (src->geom->num_colors < dst->geom->sz_colors) {
1493 for (i = src->geom->num_colors, dcolor = dst->geom->colors + i;
1494 i < dst->geom->num_colors; i++, dcolor++) {
1495 free(dcolor->spec);
1496 }
1497 }
1498
1499 /* Reallocate and clear all new items if the buffer grows. */
1500 if (!XkbGeomRealloc
1501 ((void **) &dst->geom->colors, dst->geom->sz_colors,
1502 src->geom->num_colors, sizeof(XkbColorRec),
1503 XKB_GEOM_CLEAR_EXCESS))
1504 return FALSE;
1505 dst->geom->sz_colors = src->geom->num_colors;
1506
1507 for (i = 0,
1508 scolor = src->geom->colors,
1509 dcolor = dst->geom->colors;
1510 i < src->geom->num_colors; i++, scolor++, dcolor++) {
1511 if (i < dst->geom->num_colors) {
1512 if (strlen(scolor->spec) != strlen(dcolor->spec)) {
1513 tmp = realloc(dcolor->spec, strlen(scolor->spec) + 1);
1514 if (!tmp)
1515 return FALSE;
1516 dcolor->spec = tmp;
1517 }
1518 strcpy(dcolor->spec, scolor->spec);
1519 }
1520 else {
1521 dcolor->spec = xstrdup(scolor->spec);
1522 }
1523 dcolor->pixel = scolor->pixel;
1524 }
1525
1526 dst->geom->num_colors = dst->geom->sz_colors;
1527 }
1528 else {
1529 if (dst->geom->sz_colors) {
1530 for (i = 0, dcolor = dst->geom->colors;
1531 i < dst->geom->num_colors; i++, dcolor++) {
1532 free(dcolor->spec);
1533 }
1534 free(dst->geom->colors);
1535 dst->geom->colors = NULL;
1536 }
1537
1538 dst->geom->num_colors = 0;
1539 dst->geom->sz_colors = 0;
1540 }
1541
1542 /* shapes */
1543 /* shapes break down into outlines, which break down into points. */
1544 if (dst->geom->num_shapes) {
1545 for (i = 0, dshape = dst->geom->shapes;
1546 i < dst->geom->num_shapes; i++, dshape++) {
1547 for (j = 0, doutline = dshape->outlines;
1548 j < dshape->num_outlines; j++, doutline++) {
1549 if (doutline->sz_points)
1550 free(doutline->points);
1551 }
1552
1553 if (dshape->sz_outlines) {
1554 free(dshape->outlines);
1555 dshape->outlines = NULL;
1556 }
1557
1558 dshape->num_outlines = 0;
1559 dshape->sz_outlines = 0;
1560 }
1561 }
1562
1563 if (src->geom->num_shapes) {
1564 /* Reallocate and clear all items. */
1565 if (!XkbGeomRealloc
1566 ((void **) &dst->geom->shapes, dst->geom->sz_shapes,
1567 src->geom->num_shapes, sizeof(XkbShapeRec),
1568 XKB_GEOM_CLEAR_ALL))
1569 return FALSE;
1570
1571 for (i = 0, sshape = src->geom->shapes, dshape = dst->geom->shapes;
1572 i < src->geom->num_shapes; i++, sshape++, dshape++) {
1573 if (sshape->num_outlines) {
1574 tmp = calloc(sshape->num_outlines, sizeof(XkbOutlineRec));
1575 if (!tmp)
1576 return FALSE;
1577 dshape->outlines = tmp;
1578
1579 for (j = 0,
1580 soutline = sshape->outlines,
1581 doutline = dshape->outlines;
1582 j < sshape->num_outlines;
1583 j++, soutline++, doutline++) {
1584 if (soutline->num_points) {
1585 tmp = malloc(soutline->num_points *
1586 sizeof(XkbPointRec));
1587 if (!tmp)
1588 return FALSE;
1589 doutline->points = tmp;
1590
1591 memcpy(doutline->points, soutline->points,
1592 soutline->num_points * sizeof(XkbPointRec));
1593
1594 doutline->corner_radius = soutline->corner_radius;
1595 }
1596
1597 doutline->num_points = soutline->num_points;
1598 doutline->sz_points = soutline->num_points;
1599 }
1600 }
1601
1602 dshape->num_outlines = sshape->num_outlines;
1603 dshape->sz_outlines = sshape->num_outlines;
1604 dshape->name = sshape->name;
1605 dshape->bounds = sshape->bounds;
1606
1607 dshape->approx = NULL;
1608 if (sshape->approx && sshape->num_outlines > 0) {
1609
1610 const ptrdiff_t approx_idx =
1611 sshape->approx - sshape->outlines;
1612
1613 if (approx_idx < dshape->num_outlines) {
1614 dshape->approx = dshape->outlines + approx_idx;
1615 }
1616 else {
1617 LogMessage(X_WARNING, "XKB: approx outline "
1618 "index is out of range\n");
1619 }
1620 }
1621
1622 dshape->primary = NULL;
1623 if (sshape->primary && sshape->num_outlines > 0) {
1624
1625 const ptrdiff_t primary_idx =
1626 sshape->primary - sshape->outlines;
1627
1628 if (primary_idx < dshape->num_outlines) {
1629 dshape->primary = dshape->outlines + primary_idx;
1630 }
1631 else {
1632 LogMessage(X_WARNING, "XKB: primary outline "
1633 "index is out of range\n");
1634 }
1635 }
1636 }
1637
1638 dst->geom->num_shapes = src->geom->num_shapes;
1639 dst->geom->sz_shapes = src->geom->num_shapes;
1640 }
1641 else {
1642 if (dst->geom->sz_shapes) {
1643 free(dst->geom->shapes);
1644 }
1645 dst->geom->shapes = NULL;
1646 dst->geom->num_shapes = 0;
1647 dst->geom->sz_shapes = 0;
1648 }
1649
1650 /* sections */
1651 /* sections break down into doodads, and also into rows, which break
1652 * down into keys. */
1653 if (dst->geom->num_sections) {
1654 for (i = 0, dsection = dst->geom->sections;
1655 i < dst->geom->num_sections; i++, dsection++) {
1656 for (j = 0, drow = dsection->rows;
1657 j < dsection->num_rows; j++, drow++) {
1658 if (drow->num_keys)
1659 free(drow->keys);
1660 }
1661
1662 if (dsection->num_rows)
1663 free(dsection->rows);
1664
1665 /* cut and waste from geom/doodad below. */
1666 for (j = 0, ddoodad = dsection->doodads;
1667 j < dsection->num_doodads; j++, ddoodad++) {
1668 if (ddoodad->any.type == XkbTextDoodad) {
1669 free(ddoodad->text.text);
1670 ddoodad->text.text = NULL;
1671 free(ddoodad->text.font);
1672 ddoodad->text.font = NULL;
1673 }
1674 else if (ddoodad->any.type == XkbLogoDoodad) {
1675 free(ddoodad->logo.logo_name);
1676 ddoodad->logo.logo_name = NULL;
1677 }
1678 }
1679
1680 free(dsection->doodads);
1681 }
1682
1683 dst->geom->num_sections = 0;
1684 }
1685
1686 if (src->geom->num_sections) {
1687 /* Reallocate and clear all items. */
1688 if (!XkbGeomRealloc
1689 ((void **) &dst->geom->sections, dst->geom->sz_sections,
1690 src->geom->num_sections, sizeof(XkbSectionRec),
1691 XKB_GEOM_CLEAR_ALL))
1692 return FALSE;
1693 dst->geom->num_sections = src->geom->num_sections;
1694 dst->geom->sz_sections = src->geom->num_sections;
1695
1696 for (i = 0,
1697 ssection = src->geom->sections,
1698 dsection = dst->geom->sections;
1699 i < src->geom->num_sections; i++, ssection++, dsection++) {
1700 *dsection = *ssection;
1701 if (ssection->num_rows) {
1702 tmp = calloc(ssection->num_rows, sizeof(XkbRowRec));
1703 if (!tmp)
1704 return FALSE;
1705 dsection->rows = tmp;
1706 }
1707 dsection->num_rows = ssection->num_rows;
1708 dsection->sz_rows = ssection->num_rows;
1709
1710 for (j = 0, srow = ssection->rows, drow = dsection->rows;
1711 j < ssection->num_rows; j++, srow++, drow++) {
1712 if (srow->num_keys) {
1713 tmp = malloc(srow->num_keys * sizeof(XkbKeyRec));
1714 if (!tmp)
1715 return FALSE;
1716 drow->keys = tmp;
1717 memcpy(drow->keys, srow->keys,
1718 srow->num_keys * sizeof(XkbKeyRec));
1719 }
1720 drow->num_keys = srow->num_keys;
1721 drow->sz_keys = srow->num_keys;
1722 drow->top = srow->top;
1723 drow->left = srow->left;
1724 drow->vertical = srow->vertical;
1725 drow->bounds = srow->bounds;
1726 }
1727
1728 if (ssection->num_doodads) {
1729 tmp = calloc(ssection->num_doodads, sizeof(XkbDoodadRec));
1730 if (!tmp)
1731 return FALSE;
1732 dsection->doodads = tmp;
1733 }
1734 else {
1735 dsection->doodads = NULL;
1736 }
1737
1738 dsection->sz_doodads = ssection->num_doodads;
1739 for (k = 0,
1740 sdoodad = ssection->doodads,
1741 ddoodad = dsection->doodads;
1742 k < ssection->num_doodads; k++, sdoodad++, ddoodad++) {
1743 memcpy(ddoodad, sdoodad, sizeof(XkbDoodadRec));
1744 if (sdoodad->any.type == XkbTextDoodad) {
1745 if (sdoodad->text.text)
1746 ddoodad->text.text = strdup(sdoodad->text.text);
1747 if (sdoodad->text.font)
1748 ddoodad->text.font = strdup(sdoodad->text.font);
1749 }
1750 else if (sdoodad->any.type == XkbLogoDoodad) {
1751 if (sdoodad->logo.logo_name)
1752 ddoodad->logo.logo_name =
1753 strdup(sdoodad->logo.logo_name);
1754 }
1755 }
1756 dsection->overlays = NULL;
1757 dsection->sz_overlays = 0;
1758 dsection->num_overlays = 0;
1759 }
1760 }
1761 else {
1762 if (dst->geom->sz_sections) {
1763 free(dst->geom->sections);
1764 }
1765
1766 dst->geom->sections = NULL;
1767 dst->geom->num_sections = 0;
1768 dst->geom->sz_sections = 0;
1769 }
1770
1771 /* doodads */
1772 if (dst->geom->num_doodads) {
1773 for (i = src->geom->num_doodads,
1774 ddoodad = dst->geom->doodads +
1775 src->geom->num_doodads;
1776 i < dst->geom->num_doodads; i++, ddoodad++) {
1777 if (ddoodad->any.type == XkbTextDoodad) {
1778 free(ddoodad->text.text);
1779 ddoodad->text.text = NULL;
1780 free(ddoodad->text.font);
1781 ddoodad->text.font = NULL;
1782 }
1783 else if (ddoodad->any.type == XkbLogoDoodad) {
1784 free(ddoodad->logo.logo_name);
1785 ddoodad->logo.logo_name = NULL;
1786 }
1787 }
1788 dst->geom->num_doodads = 0;
1789 }
1790
1791 if (src->geom->num_doodads) {
1792 /* Reallocate and clear all items. */
1793 if (!XkbGeomRealloc
1794 ((void **) &dst->geom->doodads, dst->geom->sz_doodads,
1795 src->geom->num_doodads, sizeof(XkbDoodadRec),
1796 XKB_GEOM_CLEAR_ALL))
1797 return FALSE;
1798
1799 dst->geom->sz_doodads = src->geom->num_doodads;
1800
1801 for (i = 0,
1802 sdoodad = src->geom->doodads,
1803 ddoodad = dst->geom->doodads;
1804 i < src->geom->num_doodads; i++, sdoodad++, ddoodad++) {
1805 memcpy(ddoodad, sdoodad, sizeof(XkbDoodadRec));
1806 if (sdoodad->any.type == XkbTextDoodad) {
1807 if (sdoodad->text.text)
1808 ddoodad->text.text = strdup(sdoodad->text.text);
1809 if (sdoodad->text.font)
1810 ddoodad->text.font = strdup(sdoodad->text.font);
1811 }
1812 else if (sdoodad->any.type == XkbLogoDoodad) {
1813 if (sdoodad->logo.logo_name)
1814 ddoodad->logo.logo_name =
1815 strdup(sdoodad->logo.logo_name);
1816 }
1817 }
1818
1819 dst->geom->num_doodads = dst->geom->sz_doodads;
1820 }
1821 else {
1822 if (dst->geom->sz_doodads) {
1823 free(dst->geom->doodads);
1824 }
1825
1826 dst->geom->doodads = NULL;
1827 dst->geom->num_doodads = 0;
1828 dst->geom->sz_doodads = 0;
1829 }
1830
1831 /* key aliases */
1832 if (src->geom->num_key_aliases) {
1833 /* Reallocate but don't clear any items. There is no need
1834 * to clear anything because data is immediately copied
1835 * over the whole memory area with memcpy. */
1836 if (!XkbGeomRealloc
1837 ((void **) &dst->geom->key_aliases, dst->geom->sz_key_aliases,
1838 src->geom->num_key_aliases, 2 * XkbKeyNameLength,
1839 XKB_GEOM_CLEAR_NONE))
1840 return FALSE;
1841
1842 dst->geom->sz_key_aliases = src->geom->num_key_aliases;
1843
1844 memcpy(dst->geom->key_aliases, src->geom->key_aliases,
1845 src->geom->num_key_aliases * 2 * XkbKeyNameLength);
1846
1847 dst->geom->num_key_aliases = dst->geom->sz_key_aliases;
1848 }
1849 else {
1850 free(dst->geom->key_aliases);
1851 dst->geom->key_aliases = NULL;
1852 dst->geom->num_key_aliases = 0;
1853 dst->geom->sz_key_aliases = 0;
1854 }
1855
1856 /* font */
1857 if (src->geom->label_font) {
1858 if (!dst->geom->label_font) {
1859 tmp = malloc(strlen(src->geom->label_font) + 1);
1860 if (!tmp)
1861 return FALSE;
1862 dst->geom->label_font = tmp;
1863 }
1864 else if (strlen(src->geom->label_font) !=
1865 strlen(dst->geom->label_font)) {
1866 tmp = realloc(dst->geom->label_font,
1867 strlen(src->geom->label_font) + 1);
1868 if (!tmp)
1869 return FALSE;
1870 dst->geom->label_font = tmp;
1871 }
1872
1873 strcpy(dst->geom->label_font, src->geom->label_font);
1874 i = XkbGeomColorIndex(src->geom, src->geom->label_color);
1875 dst->geom->label_color = &(dst->geom->colors[i]);
1876 i = XkbGeomColorIndex(src->geom, src->geom->base_color);
1877 dst->geom->base_color = &(dst->geom->colors[i]);
1878 }
1879 else {
1880 free(dst->geom->label_font);
1881 dst->geom->label_font = NULL;
1882 dst->geom->label_color = NULL;
1883 dst->geom->base_color = NULL;
1884 }
1885
1886 dst->geom->name = src->geom->name;
1887 dst->geom->width_mm = src->geom->width_mm;
1888 dst->geom->height_mm = src->geom->height_mm;
1889 }
1890 else {
1891 if (dst->geom) {
1892 /* I LOVE THE DIFFERENT CALL SIGNATURE. REALLY, I DO. */
1893 XkbFreeGeometry(dst->geom, XkbGeomAllMask, TRUE);
1894 dst->geom = NULL;
1895 }
1896 }
1897
1898 return TRUE;
1899}
1900
1901static Bool
1902_XkbCopyIndicators(XkbDescPtr src, XkbDescPtr dst)
1903{
1904 /* indicators */
1905 if (src->indicators) {
1906 if (!dst->indicators) {
1907 dst->indicators = malloc(sizeof(XkbIndicatorRec));
1908 if (!dst->indicators)
1909 return FALSE;
1910 }
1911 memcpy(dst->indicators, src->indicators, sizeof(XkbIndicatorRec));
1912 }
1913 else {
1914 free(dst->indicators);
1915 dst->indicators = NULL;
1916 }
1917 return TRUE;
1918}
1919
1920static Bool
1921_XkbCopyControls(XkbDescPtr src, XkbDescPtr dst)
1922{
1923 /* controls */
1924 if (src->ctrls) {
1925 if (!dst->ctrls) {
1926 dst->ctrls = malloc(sizeof(XkbControlsRec));
1927 if (!dst->ctrls)
1928 return FALSE;
1929 }
1930 memcpy(dst->ctrls, src->ctrls, sizeof(XkbControlsRec));
1931 }
1932 else {
1933 free(dst->ctrls);
1934 dst->ctrls = NULL;
1935 }
1936 return TRUE;
1937}
1938
1939/**
1940 * Copy an XKB map from src to dst, reallocating when necessary: if some
1941 * map components are present in one, but not in the other, the destination
1942 * components will be allocated or freed as necessary.
1943 *
1944 * Basic map consistency is assumed on both sides, so maps with random
1945 * uninitialised data (e.g. names->radio_grous == NULL, names->num_rg == 19)
1946 * _will_ cause failures. You've been warned.
1947 *
1948 * Returns TRUE on success, or FALSE on failure. If this function fails,
1949 * dst may be in an inconsistent state: all its pointers are guaranteed
1950 * to remain valid, but part of the map may be from src and part from dst.
1951 *
1952 */
1953
1954Bool
1955XkbCopyKeymap(XkbDescPtr dst, XkbDescPtr src)
1956{
1957
1958 if (!src || !dst) {
1959 DebugF("XkbCopyKeymap: src (%p) or dst (%p) is NULL\n", src, dst);
1960 return FALSE;
1961 }
1962
1963 if (src == dst)
1964 return TRUE;
1965
1966 if (!_XkbCopyClientMap(src, dst)) {
1967 DebugF("XkbCopyKeymap: failed to copy client map\n");
1968 return FALSE;
1969 }
1970 if (!_XkbCopyServerMap(src, dst)) {
1971 DebugF("XkbCopyKeymap: failed to copy server map\n");
1972 return FALSE;
1973 }
1974 if (!_XkbCopyIndicators(src, dst)) {
1975 DebugF("XkbCopyKeymap: failed to copy indicators\n");
1976 return FALSE;
1977 }
1978 if (!_XkbCopyControls(src, dst)) {
1979 DebugF("XkbCopyKeymap: failed to copy controls\n");
1980 return FALSE;
1981 }
1982 if (!_XkbCopyNames(src, dst)) {
1983 DebugF("XkbCopyKeymap: failed to copy names\n");
1984 return FALSE;
1985 }
1986 if (!_XkbCopyCompat(src, dst)) {
1987 DebugF("XkbCopyKeymap: failed to copy compat map\n");
1988 return FALSE;
1989 }
1990 if (!_XkbCopyGeom(src, dst)) {
1991 DebugF("XkbCopyKeymap: failed to copy geometry\n");
1992 return FALSE;
1993 }
1994
1995 dst->min_key_code = src->min_key_code;
1996 dst->max_key_code = src->max_key_code;
1997
1998 return TRUE;
1999}
2000
2001Bool
2002XkbCopyDeviceKeymap(DeviceIntPtr dst, DeviceIntPtr src)
2003{
2004 xkbNewKeyboardNotify nkn;
2005 Bool ret;
2006
2007 if (!dst->key || !src->key)
2008 return FALSE;
2009
2010 memset(&nkn, 0, sizeof(xkbNewKeyboardNotify));
2011 nkn.oldMinKeyCode = dst->key->xkbInfo->desc->min_key_code;
2012 nkn.oldMaxKeyCode = dst->key->xkbInfo->desc->max_key_code;
2013 nkn.deviceID = dst->id;
2014 nkn.oldDeviceID = dst->id; /* maybe src->id? */
2015 nkn.minKeyCode = src->key->xkbInfo->desc->min_key_code;
2016 nkn.maxKeyCode = src->key->xkbInfo->desc->max_key_code;
2017 nkn.requestMajor = XkbReqCode;
2018 nkn.requestMinor = X_kbSetMap; /* Near enough's good enough. */
2019 nkn.changed = XkbNKN_KeycodesMask;
2020 if (src->key->xkbInfo->desc->geom)
2021 nkn.changed |= XkbNKN_GeometryMask;
2022
2023 ret = XkbCopyKeymap(dst->key->xkbInfo->desc, src->key->xkbInfo->desc);
2024 if (ret)
2025 XkbSendNewKeyboardNotify(dst, &nkn);
2026
2027 return ret;
2028}
2029
2030int
2031XkbGetEffectiveGroup(XkbSrvInfoPtr xkbi, XkbStatePtr xkbState, CARD8 keycode)
2032{
2033 XkbDescPtr xkb = xkbi->desc;
2034 int effectiveGroup = xkbState->group;
2035
2036 if (!XkbKeycodeInRange(xkb, keycode))
2037 return -1;
2038
2039 if (effectiveGroup == XkbGroup1Index)
2040 return effectiveGroup;
2041
2042 if (XkbKeyNumGroups(xkb, keycode) > 1U) {
2043 if (effectiveGroup >= XkbKeyNumGroups(xkb, keycode)) {
2044 unsigned int gi = XkbKeyGroupInfo(xkb, keycode);
2045
2046 switch (XkbOutOfRangeGroupAction(gi)) {
2047 default:
2048 case XkbWrapIntoRange:
2049 effectiveGroup %= XkbKeyNumGroups(xkb, keycode);
2050 break;
2051 case XkbClampIntoRange:
2052 effectiveGroup = XkbKeyNumGroups(xkb, keycode) - 1;
2053 break;
2054 case XkbRedirectIntoRange:
2055 effectiveGroup = XkbOutOfRangeGroupInfo(gi);
2056 if (effectiveGroup >= XkbKeyNumGroups(xkb, keycode))
2057 effectiveGroup = 0;
2058 break;
2059 }
2060 }
2061 }
2062 else
2063 effectiveGroup = XkbGroup1Index;
2064
2065 return effectiveGroup;
2066}
2067
2068/* Merge the lockedPtrButtons from all attached SDs for the given master
2069 * device into the MD's state.
2070 */
2071void
2072XkbMergeLockedPtrBtns(DeviceIntPtr master)
2073{
2074 DeviceIntPtr d = inputInfo.devices;
2075 XkbSrvInfoPtr xkbi = NULL;
2076
2077 if (!IsMaster(master))
2078 return;
2079
2080 if (!master->key)
2081 return;
2082
2083 xkbi = master->key->xkbInfo;
2084 xkbi->lockedPtrButtons = 0;
2085
2086 for (; d; d = d->next) {
2087 if (IsMaster(d) || GetMaster(d, MASTER_KEYBOARD) != master || !d->key)
2088 continue;
2089
2090 xkbi->lockedPtrButtons |= d->key->xkbInfo->lockedPtrButtons;
2091 }
2092}