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
28 Copyright © 2008 Red Hat Inc.
29
30 Permission is hereby granted, free of charge, to any person obtaining a
31 copy of this software and associated documentation files (the "Software"),
32 to deal in the Software without restriction, including without limitation
33 the rights to use, copy, modify, merge, publish, distribute, sublicense,
34 and/or sell copies of the Software, and to permit persons to whom the
35 Software is furnished to do so, subject to the following conditions:
36
37 The above copyright notice and this permission notice (including the next
38 paragraph) shall be included in all copies or substantial portions of the
39 Software.
40
41 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
44 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
46 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
47 DEALINGS 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
74 int
_XkbLookupAnyDevice(DeviceIntPtr * pDev,int id,ClientPtr client,Mask access_mode,int * xkb_err)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
92 int
_XkbLookupKeyboard(DeviceIntPtr * pDev,int id,ClientPtr client,Mask access_mode,int * xkb_err)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
115 int
_XkbLookupBellDevice(DeviceIntPtr * pDev,int id,ClientPtr client,Mask access_mode,int * xkb_err)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
135 int
_XkbLookupLedDevice(DeviceIntPtr * pDev,int id,ClientPtr client,Mask access_mode,int * xkb_err)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
158 int
_XkbLookupButtonDevice(DeviceIntPtr * pDev,int id,ClientPtr client,Mask access_mode,int * xkb_err)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
178 void
XkbSetActionKeyMods(XkbDescPtr xkb,XkbAction * act,unsigned mods)179 XkbSetActionKeyMods(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
202 unsigned
XkbMaskForVMask(XkbDescPtr xkb,unsigned vmask)203 XkbMaskForVMask(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
217 void
XkbUpdateKeyTypesFromCore(DeviceIntPtr pXDev,KeySymsPtr pCore,KeyCode first,CARD8 num,XkbChangesPtr changes)218 XkbUpdateKeyTypesFromCore(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] = {NoSymbol}, *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
269 void
XkbUpdateDescActions(XkbDescPtr xkb,KeyCode first,CARD8 num,XkbChangesPtr changes)270 XkbUpdateDescActions(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
327 void
XkbUpdateActions(DeviceIntPtr pXDev,KeyCode first,CARD8 num,XkbChangesPtr changes,unsigned * needChecksRtrn,XkbEventCausePtr cause)328 XkbUpdateActions(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
360 KeySymsPtr
XkbGetCoreMap(DeviceIntPtr keybd)361 XkbGetCoreMap(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
523 void
XkbSetRepeatKeys(DeviceIntPtr pXDev,int key,int onoff)524 XkbSetRepeatKeys(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. */
551 void
XkbApplyMappingChange(DeviceIntPtr kbd,KeySymsPtr map,KeyCode first_key,CARD8 num_keys,CARD8 * modmap,ClientPtr client)552 XkbApplyMappingChange(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
596 void
XkbDisableComputedAutoRepeats(DeviceIntPtr dev,unsigned key)597 XkbDisableComputedAutoRepeats(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
611 unsigned
XkbStateChangedFlags(XkbStatePtr old,XkbStatePtr new)612 XkbStateChangedFlags(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
639 static void
XkbComputeCompatState(XkbSrvInfoPtr xkbi)640 XkbComputeCompatState(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
666 unsigned
XkbAdjustGroup(int group,XkbControlsPtr ctrls)667 XkbAdjustGroup(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
711 void
XkbComputeDerivedState(XkbSrvInfoPtr xkbi)712 XkbComputeDerivedState(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
742 void
XkbCheckSecondaryEffects(XkbSrvInfoPtr xkbi,unsigned which,XkbChangesPtr changes,XkbEventCausePtr cause)743 XkbCheckSecondaryEffects(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
762 Bool
XkbEnableDisableControls(XkbSrvInfoPtr xkbi,unsigned long change,unsigned long newValues,XkbChangesPtr changes,XkbEventCausePtr cause)763 XkbEnableDisableControls(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
812 XkbGeometryPtr
XkbLookupNamedGeometry(DeviceIntPtr dev,Atom name,Bool * shouldFree)813 XkbLookupNamedGeometry(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
830 void
XkbConvertCase(register KeySym sym,KeySym * lower,KeySym * upper)831 XkbConvertCase(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
931 static Bool
_XkbCopyClientMap(XkbDescPtr src,XkbDescPtr dst)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 = reallocarray(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 = reallocarray(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 = reallocarray(dst->map->types, src->map->num_types,
987 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 = reallocarray(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 = reallocarray(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 = xallocarray(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 = reallocarray(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 = xallocarray(stype->map_count,
1095 sizeof(XkbModsRec));
1096 if (!tmp)
1097 return FALSE;
1098 dtype->preserve = tmp;
1099 }
1100
1101 memcpy(dtype->preserve, stype->preserve,
1102 stype->map_count * sizeof(XkbModsRec));
1103 }
1104 else {
1105 if (dtype->preserve && i < dst->map->num_types)
1106 free(dtype->preserve);
1107 dtype->preserve = NULL;
1108 }
1109
1110 dtype->map_count = stype->map_count;
1111 }
1112 else {
1113 if (dtype->map_count && i < dst->map->num_types) {
1114 free(dtype->map);
1115 free(dtype->preserve);
1116 }
1117 dtype->map_count = 0;
1118 dtype->map = NULL;
1119 dtype->preserve = NULL;
1120 }
1121 }
1122
1123 dst->map->size_types = src->map->num_types;
1124 dst->map->num_types = src->map->num_types;
1125 }
1126 else {
1127 if (dst->map->types) {
1128 for (i = 0, dtype = dst->map->types; i < dst->map->num_types;
1129 i++, dtype++) {
1130 free(dtype->level_names);
1131 if (dtype->map && dtype->map_count)
1132 free(dtype->map);
1133 if (dtype->preserve && dtype->map_count)
1134 free(dtype->preserve);
1135 }
1136 }
1137 free(dst->map->types);
1138 dst->map->types = NULL;
1139 dst->map->num_types = 0;
1140 dst->map->size_types = 0;
1141 }
1142
1143 if (src->map->modmap) {
1144 if (src->max_key_code != dst->max_key_code) {
1145 tmp = realloc(dst->map->modmap, src->max_key_code + 1);
1146 if (!tmp)
1147 return FALSE;
1148 dst->map->modmap = tmp;
1149 }
1150 memcpy(dst->map->modmap, src->map->modmap, src->max_key_code + 1);
1151 }
1152 else {
1153 free(dst->map->modmap);
1154 dst->map->modmap = NULL;
1155 }
1156 }
1157 else {
1158 if (dst->map)
1159 XkbFreeClientMap(dst, XkbAllClientInfoMask, TRUE);
1160 }
1161
1162 return TRUE;
1163 }
1164
1165 static Bool
_XkbCopyServerMap(XkbDescPtr src,XkbDescPtr dst)1166 _XkbCopyServerMap(XkbDescPtr src, XkbDescPtr dst)
1167 {
1168 void *tmp = NULL;
1169
1170 /* server map */
1171 if (src->server) {
1172 if (!dst->server) {
1173 tmp = calloc(1, sizeof(XkbServerMapRec));
1174 if (!tmp)
1175 return FALSE;
1176 dst->server = tmp;
1177 }
1178
1179 if (src->server->explicit) {
1180 if (src->max_key_code != dst->max_key_code) {
1181 tmp = realloc(dst->server->explicit, src->max_key_code + 1);
1182 if (!tmp)
1183 return FALSE;
1184 dst->server->explicit = tmp;
1185 }
1186 memcpy(dst->server->explicit, src->server->explicit,
1187 src->max_key_code + 1);
1188 }
1189 else {
1190 free(dst->server->explicit);
1191 dst->server->explicit = NULL;
1192 }
1193
1194 if (src->server->acts) {
1195 if (src->server->size_acts != dst->server->size_acts) {
1196 tmp = reallocarray(dst->server->acts,
1197 src->server->size_acts, sizeof(XkbAction));
1198 if (!tmp)
1199 return FALSE;
1200 dst->server->acts = tmp;
1201 }
1202 memcpy(dst->server->acts, src->server->acts,
1203 src->server->size_acts * sizeof(XkbAction));
1204 }
1205 else {
1206 free(dst->server->acts);
1207 dst->server->acts = NULL;
1208 }
1209 dst->server->size_acts = src->server->size_acts;
1210 dst->server->num_acts = src->server->num_acts;
1211
1212 if (src->server->key_acts) {
1213 if (src->max_key_code != dst->max_key_code) {
1214 tmp = reallocarray(dst->server->key_acts,
1215 src->max_key_code + 1, sizeof(unsigned short));
1216 if (!tmp)
1217 return FALSE;
1218 dst->server->key_acts = tmp;
1219 }
1220 memcpy(dst->server->key_acts, src->server->key_acts,
1221 (src->max_key_code + 1) * sizeof(unsigned short));
1222 }
1223 else {
1224 free(dst->server->key_acts);
1225 dst->server->key_acts = NULL;
1226 }
1227
1228 if (src->server->behaviors) {
1229 if (src->max_key_code != dst->max_key_code) {
1230 tmp = reallocarray(dst->server->behaviors,
1231 src->max_key_code + 1, sizeof(XkbBehavior));
1232 if (!tmp)
1233 return FALSE;
1234 dst->server->behaviors = tmp;
1235 }
1236 memcpy(dst->server->behaviors, src->server->behaviors,
1237 (src->max_key_code + 1) * sizeof(XkbBehavior));
1238 }
1239 else {
1240 free(dst->server->behaviors);
1241 dst->server->behaviors = NULL;
1242 }
1243
1244 memcpy(dst->server->vmods, src->server->vmods, XkbNumVirtualMods);
1245
1246 if (src->server->vmodmap) {
1247 if (src->max_key_code != dst->max_key_code) {
1248 tmp = reallocarray(dst->server->vmodmap,
1249 src->max_key_code + 1, sizeof(unsigned short));
1250 if (!tmp)
1251 return FALSE;
1252 dst->server->vmodmap = tmp;
1253 }
1254 memcpy(dst->server->vmodmap, src->server->vmodmap,
1255 (src->max_key_code + 1) * sizeof(unsigned short));
1256 }
1257 else {
1258 free(dst->server->vmodmap);
1259 dst->server->vmodmap = NULL;
1260 }
1261 }
1262 else {
1263 if (dst->server)
1264 XkbFreeServerMap(dst, XkbAllServerInfoMask, TRUE);
1265 }
1266
1267 return TRUE;
1268 }
1269
1270 static Bool
_XkbCopyNames(XkbDescPtr src,XkbDescPtr dst)1271 _XkbCopyNames(XkbDescPtr src, XkbDescPtr dst)
1272 {
1273 void *tmp = NULL;
1274
1275 /* names */
1276 if (src->names) {
1277 if (!dst->names) {
1278 dst->names = calloc(1, sizeof(XkbNamesRec));
1279 if (!dst->names)
1280 return FALSE;
1281 }
1282
1283 if (src->names->keys) {
1284 if (src->max_key_code != dst->max_key_code) {
1285 tmp = reallocarray(dst->names->keys, src->max_key_code + 1,
1286 sizeof(XkbKeyNameRec));
1287 if (!tmp)
1288 return FALSE;
1289 dst->names->keys = tmp;
1290 }
1291 memcpy(dst->names->keys, src->names->keys,
1292 (src->max_key_code + 1) * sizeof(XkbKeyNameRec));
1293 }
1294 else {
1295 free(dst->names->keys);
1296 dst->names->keys = NULL;
1297 }
1298
1299 if (src->names->num_key_aliases) {
1300 if (src->names->num_key_aliases != dst->names->num_key_aliases) {
1301 tmp = reallocarray(dst->names->key_aliases,
1302 src->names->num_key_aliases,
1303 sizeof(XkbKeyAliasRec));
1304 if (!tmp)
1305 return FALSE;
1306 dst->names->key_aliases = tmp;
1307 }
1308 memcpy(dst->names->key_aliases, src->names->key_aliases,
1309 src->names->num_key_aliases * sizeof(XkbKeyAliasRec));
1310 }
1311 else {
1312 free(dst->names->key_aliases);
1313 dst->names->key_aliases = NULL;
1314 }
1315 dst->names->num_key_aliases = src->names->num_key_aliases;
1316
1317 if (src->names->num_rg) {
1318 if (src->names->num_rg != dst->names->num_rg) {
1319 tmp = reallocarray(dst->names->radio_groups,
1320 src->names->num_rg, sizeof(Atom));
1321 if (!tmp)
1322 return FALSE;
1323 dst->names->radio_groups = tmp;
1324 }
1325 memcpy(dst->names->radio_groups, src->names->radio_groups,
1326 src->names->num_rg * sizeof(Atom));
1327 }
1328 else {
1329 free(dst->names->radio_groups);
1330 }
1331 dst->names->num_rg = src->names->num_rg;
1332
1333 dst->names->keycodes = src->names->keycodes;
1334 dst->names->geometry = src->names->geometry;
1335 dst->names->symbols = src->names->symbols;
1336 dst->names->types = src->names->types;
1337 dst->names->compat = src->names->compat;
1338 dst->names->phys_symbols = src->names->phys_symbols;
1339
1340 memcpy(dst->names->vmods, src->names->vmods,
1341 XkbNumVirtualMods * sizeof(Atom));
1342 memcpy(dst->names->indicators, src->names->indicators,
1343 XkbNumIndicators * sizeof(Atom));
1344 memcpy(dst->names->groups, src->names->groups,
1345 XkbNumKbdGroups * sizeof(Atom));
1346 }
1347 else {
1348 if (dst->names)
1349 XkbFreeNames(dst, XkbAllNamesMask, TRUE);
1350 }
1351
1352 return TRUE;
1353 }
1354
1355 static Bool
_XkbCopyCompat(XkbDescPtr src,XkbDescPtr dst)1356 _XkbCopyCompat(XkbDescPtr src, XkbDescPtr dst)
1357 {
1358 void *tmp = NULL;
1359
1360 /* compat */
1361 if (src->compat) {
1362 if (!dst->compat) {
1363 dst->compat = calloc(1, sizeof(XkbCompatMapRec));
1364 if (!dst->compat)
1365 return FALSE;
1366 }
1367
1368 if (src->compat->sym_interpret && src->compat->num_si) {
1369 if (src->compat->num_si != dst->compat->size_si) {
1370 tmp = reallocarray(dst->compat->sym_interpret,
1371 src->compat->num_si,
1372 sizeof(XkbSymInterpretRec));
1373 if (!tmp)
1374 return FALSE;
1375 dst->compat->sym_interpret = tmp;
1376 }
1377 memcpy(dst->compat->sym_interpret, src->compat->sym_interpret,
1378 src->compat->num_si * sizeof(XkbSymInterpretRec));
1379
1380 dst->compat->num_si = src->compat->num_si;
1381 dst->compat->size_si = src->compat->num_si;
1382 }
1383 else {
1384 if (dst->compat->sym_interpret && dst->compat->size_si)
1385 free(dst->compat->sym_interpret);
1386
1387 dst->compat->sym_interpret = NULL;
1388 dst->compat->num_si = 0;
1389 dst->compat->size_si = 0;
1390 }
1391
1392 memcpy(dst->compat->groups, src->compat->groups,
1393 XkbNumKbdGroups * sizeof(XkbModsRec));
1394 }
1395 else {
1396 if (dst->compat)
1397 XkbFreeCompatMap(dst, XkbAllCompatMask, TRUE);
1398 }
1399
1400 return TRUE;
1401 }
1402
1403 static Bool
_XkbCopyGeom(XkbDescPtr src,XkbDescPtr dst)1404 _XkbCopyGeom(XkbDescPtr src, XkbDescPtr dst)
1405 {
1406 void *tmp = NULL;
1407 int i = 0, j = 0, k = 0;
1408 XkbColorPtr scolor = NULL, dcolor = NULL;
1409 XkbDoodadPtr sdoodad = NULL, ddoodad = NULL;
1410 XkbOutlinePtr soutline = NULL, doutline = NULL;
1411 XkbPropertyPtr sprop = NULL, dprop = NULL;
1412 XkbRowPtr srow = NULL, drow = NULL;
1413 XkbSectionPtr ssection = NULL, dsection = NULL;
1414 XkbShapePtr sshape = NULL, dshape = NULL;
1415
1416 /* geometry */
1417 if (src->geom) {
1418 if (!dst->geom) {
1419 dst->geom = calloc(sizeof(XkbGeometryRec), 1);
1420 if (!dst->geom)
1421 return FALSE;
1422 }
1423
1424 /* properties */
1425 if (src->geom->num_properties) {
1426 /* If we've got more properties in the destination than
1427 * the source, run through and free all the excess ones
1428 * first. */
1429 if (src->geom->num_properties < dst->geom->sz_properties) {
1430 for (i = src->geom->num_properties, dprop =
1431 dst->geom->properties + i; i < dst->geom->num_properties;
1432 i++, dprop++) {
1433 free(dprop->name);
1434 free(dprop->value);
1435 }
1436 }
1437
1438 /* Reallocate and clear all new items if the buffer grows. */
1439 if (!XkbGeomRealloc
1440 ((void **) &dst->geom->properties, dst->geom->sz_properties,
1441 src->geom->num_properties, sizeof(XkbPropertyRec),
1442 XKB_GEOM_CLEAR_EXCESS))
1443 return FALSE;
1444 /* We don't set num_properties as we need it to try and avoid
1445 * too much reallocing. */
1446 dst->geom->sz_properties = src->geom->num_properties;
1447
1448 for (i = 0,
1449 sprop = src->geom->properties,
1450 dprop = dst->geom->properties;
1451 i < src->geom->num_properties; i++, sprop++, dprop++) {
1452 if (i < dst->geom->num_properties) {
1453 if (strlen(sprop->name) != strlen(dprop->name)) {
1454 tmp = realloc(dprop->name, strlen(sprop->name) + 1);
1455 if (!tmp)
1456 return FALSE;
1457 dprop->name = tmp;
1458 }
1459 if (strlen(sprop->value) != strlen(dprop->value)) {
1460 tmp = realloc(dprop->value, strlen(sprop->value) + 1);
1461 if (!tmp)
1462 return FALSE;
1463 dprop->value = tmp;
1464 }
1465 strcpy(dprop->name, sprop->name);
1466 strcpy(dprop->value, sprop->value);
1467 }
1468 else {
1469 dprop->name = xstrdup(sprop->name);
1470 dprop->value = xstrdup(sprop->value);
1471 }
1472 }
1473
1474 /* ... which is already src->geom->num_properties. */
1475 dst->geom->num_properties = dst->geom->sz_properties;
1476 }
1477 else {
1478 if (dst->geom->sz_properties) {
1479 for (i = 0, dprop = dst->geom->properties;
1480 i < dst->geom->num_properties; i++, dprop++) {
1481 free(dprop->name);
1482 free(dprop->value);
1483 }
1484 free(dst->geom->properties);
1485 dst->geom->properties = NULL;
1486 }
1487
1488 dst->geom->num_properties = 0;
1489 dst->geom->sz_properties = 0;
1490 }
1491
1492 /* colors */
1493 if (src->geom->num_colors) {
1494 if (src->geom->num_colors < dst->geom->sz_colors) {
1495 for (i = src->geom->num_colors, dcolor = dst->geom->colors + i;
1496 i < dst->geom->num_colors; i++, dcolor++) {
1497 free(dcolor->spec);
1498 }
1499 }
1500
1501 /* Reallocate and clear all new items if the buffer grows. */
1502 if (!XkbGeomRealloc
1503 ((void **) &dst->geom->colors, dst->geom->sz_colors,
1504 src->geom->num_colors, sizeof(XkbColorRec),
1505 XKB_GEOM_CLEAR_EXCESS))
1506 return FALSE;
1507 dst->geom->sz_colors = src->geom->num_colors;
1508
1509 for (i = 0,
1510 scolor = src->geom->colors,
1511 dcolor = dst->geom->colors;
1512 i < src->geom->num_colors; i++, scolor++, dcolor++) {
1513 if (i < dst->geom->num_colors) {
1514 if (strlen(scolor->spec) != strlen(dcolor->spec)) {
1515 tmp = realloc(dcolor->spec, strlen(scolor->spec) + 1);
1516 if (!tmp)
1517 return FALSE;
1518 dcolor->spec = tmp;
1519 }
1520 strcpy(dcolor->spec, scolor->spec);
1521 }
1522 else {
1523 dcolor->spec = xstrdup(scolor->spec);
1524 }
1525 dcolor->pixel = scolor->pixel;
1526 }
1527
1528 dst->geom->num_colors = dst->geom->sz_colors;
1529 }
1530 else {
1531 if (dst->geom->sz_colors) {
1532 for (i = 0, dcolor = dst->geom->colors;
1533 i < dst->geom->num_colors; i++, dcolor++) {
1534 free(dcolor->spec);
1535 }
1536 free(dst->geom->colors);
1537 dst->geom->colors = NULL;
1538 }
1539
1540 dst->geom->num_colors = 0;
1541 dst->geom->sz_colors = 0;
1542 }
1543
1544 /* shapes */
1545 /* shapes break down into outlines, which break down into points. */
1546 if (dst->geom->num_shapes) {
1547 for (i = 0, dshape = dst->geom->shapes;
1548 i < dst->geom->num_shapes; i++, dshape++) {
1549 for (j = 0, doutline = dshape->outlines;
1550 j < dshape->num_outlines; j++, doutline++) {
1551 if (doutline->sz_points)
1552 free(doutline->points);
1553 }
1554
1555 if (dshape->sz_outlines) {
1556 free(dshape->outlines);
1557 dshape->outlines = NULL;
1558 }
1559
1560 dshape->num_outlines = 0;
1561 dshape->sz_outlines = 0;
1562 }
1563 }
1564
1565 if (src->geom->num_shapes) {
1566 /* Reallocate and clear all items. */
1567 if (!XkbGeomRealloc
1568 ((void **) &dst->geom->shapes, dst->geom->sz_shapes,
1569 src->geom->num_shapes, sizeof(XkbShapeRec),
1570 XKB_GEOM_CLEAR_ALL))
1571 return FALSE;
1572
1573 for (i = 0, sshape = src->geom->shapes, dshape = dst->geom->shapes;
1574 i < src->geom->num_shapes; i++, sshape++, dshape++) {
1575 if (sshape->num_outlines) {
1576 tmp = calloc(sshape->num_outlines, sizeof(XkbOutlineRec));
1577 if (!tmp)
1578 return FALSE;
1579 dshape->outlines = tmp;
1580
1581 for (j = 0,
1582 soutline = sshape->outlines,
1583 doutline = dshape->outlines;
1584 j < sshape->num_outlines;
1585 j++, soutline++, doutline++) {
1586 if (soutline->num_points) {
1587 tmp = xallocarray(soutline->num_points,
1588 sizeof(XkbPointRec));
1589 if (!tmp)
1590 return FALSE;
1591 doutline->points = tmp;
1592
1593 memcpy(doutline->points, soutline->points,
1594 soutline->num_points * sizeof(XkbPointRec));
1595
1596 doutline->corner_radius = soutline->corner_radius;
1597 }
1598
1599 doutline->num_points = soutline->num_points;
1600 doutline->sz_points = soutline->num_points;
1601 }
1602 }
1603
1604 dshape->num_outlines = sshape->num_outlines;
1605 dshape->sz_outlines = sshape->num_outlines;
1606 dshape->name = sshape->name;
1607 dshape->bounds = sshape->bounds;
1608
1609 dshape->approx = NULL;
1610 if (sshape->approx && sshape->num_outlines > 0) {
1611
1612 const ptrdiff_t approx_idx =
1613 sshape->approx - sshape->outlines;
1614
1615 if (approx_idx < dshape->num_outlines) {
1616 dshape->approx = dshape->outlines + approx_idx;
1617 }
1618 else {
1619 LogMessage(X_WARNING, "XKB: approx outline "
1620 "index is out of range\n");
1621 }
1622 }
1623
1624 dshape->primary = NULL;
1625 if (sshape->primary && sshape->num_outlines > 0) {
1626
1627 const ptrdiff_t primary_idx =
1628 sshape->primary - sshape->outlines;
1629
1630 if (primary_idx < dshape->num_outlines) {
1631 dshape->primary = dshape->outlines + primary_idx;
1632 }
1633 else {
1634 LogMessage(X_WARNING, "XKB: primary outline "
1635 "index is out of range\n");
1636 }
1637 }
1638 }
1639
1640 dst->geom->num_shapes = src->geom->num_shapes;
1641 dst->geom->sz_shapes = src->geom->num_shapes;
1642 }
1643 else {
1644 if (dst->geom->sz_shapes) {
1645 free(dst->geom->shapes);
1646 }
1647 dst->geom->shapes = NULL;
1648 dst->geom->num_shapes = 0;
1649 dst->geom->sz_shapes = 0;
1650 }
1651
1652 /* sections */
1653 /* sections break down into doodads, and also into rows, which break
1654 * down into keys. */
1655 if (dst->geom->num_sections) {
1656 for (i = 0, dsection = dst->geom->sections;
1657 i < dst->geom->num_sections; i++, dsection++) {
1658 for (j = 0, drow = dsection->rows;
1659 j < dsection->num_rows; j++, drow++) {
1660 if (drow->num_keys)
1661 free(drow->keys);
1662 }
1663
1664 if (dsection->num_rows)
1665 free(dsection->rows);
1666
1667 /* cut and waste from geom/doodad below. */
1668 for (j = 0, ddoodad = dsection->doodads;
1669 j < dsection->num_doodads; j++, ddoodad++) {
1670 if (ddoodad->any.type == XkbTextDoodad) {
1671 free(ddoodad->text.text);
1672 ddoodad->text.text = NULL;
1673 free(ddoodad->text.font);
1674 ddoodad->text.font = NULL;
1675 }
1676 else if (ddoodad->any.type == XkbLogoDoodad) {
1677 free(ddoodad->logo.logo_name);
1678 ddoodad->logo.logo_name = NULL;
1679 }
1680 }
1681
1682 free(dsection->doodads);
1683 }
1684
1685 dst->geom->num_sections = 0;
1686 }
1687
1688 if (src->geom->num_sections) {
1689 /* Reallocate and clear all items. */
1690 if (!XkbGeomRealloc
1691 ((void **) &dst->geom->sections, dst->geom->sz_sections,
1692 src->geom->num_sections, sizeof(XkbSectionRec),
1693 XKB_GEOM_CLEAR_ALL))
1694 return FALSE;
1695 dst->geom->num_sections = src->geom->num_sections;
1696 dst->geom->sz_sections = src->geom->num_sections;
1697
1698 for (i = 0,
1699 ssection = src->geom->sections,
1700 dsection = dst->geom->sections;
1701 i < src->geom->num_sections; i++, ssection++, dsection++) {
1702 *dsection = *ssection;
1703 if (ssection->num_rows) {
1704 tmp = calloc(ssection->num_rows, sizeof(XkbRowRec));
1705 if (!tmp)
1706 return FALSE;
1707 dsection->rows = tmp;
1708 }
1709 dsection->num_rows = ssection->num_rows;
1710 dsection->sz_rows = ssection->num_rows;
1711
1712 for (j = 0, srow = ssection->rows, drow = dsection->rows;
1713 j < ssection->num_rows; j++, srow++, drow++) {
1714 if (srow->num_keys) {
1715 tmp = xallocarray(srow->num_keys, sizeof(XkbKeyRec));
1716 if (!tmp)
1717 return FALSE;
1718 drow->keys = tmp;
1719 memcpy(drow->keys, srow->keys,
1720 srow->num_keys * sizeof(XkbKeyRec));
1721 }
1722 drow->num_keys = srow->num_keys;
1723 drow->sz_keys = srow->num_keys;
1724 drow->top = srow->top;
1725 drow->left = srow->left;
1726 drow->vertical = srow->vertical;
1727 drow->bounds = srow->bounds;
1728 }
1729
1730 if (ssection->num_doodads) {
1731 tmp = calloc(ssection->num_doodads, sizeof(XkbDoodadRec));
1732 if (!tmp)
1733 return FALSE;
1734 dsection->doodads = tmp;
1735 }
1736 else {
1737 dsection->doodads = NULL;
1738 }
1739
1740 dsection->sz_doodads = ssection->num_doodads;
1741 for (k = 0,
1742 sdoodad = ssection->doodads,
1743 ddoodad = dsection->doodads;
1744 k < ssection->num_doodads; k++, sdoodad++, ddoodad++) {
1745 memcpy(ddoodad, sdoodad, sizeof(XkbDoodadRec));
1746 if (sdoodad->any.type == XkbTextDoodad) {
1747 if (sdoodad->text.text)
1748 ddoodad->text.text = strdup(sdoodad->text.text);
1749 if (sdoodad->text.font)
1750 ddoodad->text.font = strdup(sdoodad->text.font);
1751 }
1752 else if (sdoodad->any.type == XkbLogoDoodad) {
1753 if (sdoodad->logo.logo_name)
1754 ddoodad->logo.logo_name =
1755 strdup(sdoodad->logo.logo_name);
1756 }
1757 }
1758 dsection->overlays = NULL;
1759 dsection->sz_overlays = 0;
1760 dsection->num_overlays = 0;
1761 }
1762 }
1763 else {
1764 if (dst->geom->sz_sections) {
1765 free(dst->geom->sections);
1766 }
1767
1768 dst->geom->sections = NULL;
1769 dst->geom->num_sections = 0;
1770 dst->geom->sz_sections = 0;
1771 }
1772
1773 /* doodads */
1774 if (dst->geom->num_doodads) {
1775 for (i = src->geom->num_doodads,
1776 ddoodad = dst->geom->doodads +
1777 src->geom->num_doodads;
1778 i < dst->geom->num_doodads; i++, ddoodad++) {
1779 if (ddoodad->any.type == XkbTextDoodad) {
1780 free(ddoodad->text.text);
1781 ddoodad->text.text = NULL;
1782 free(ddoodad->text.font);
1783 ddoodad->text.font = NULL;
1784 }
1785 else if (ddoodad->any.type == XkbLogoDoodad) {
1786 free(ddoodad->logo.logo_name);
1787 ddoodad->logo.logo_name = NULL;
1788 }
1789 }
1790 dst->geom->num_doodads = 0;
1791 }
1792
1793 if (src->geom->num_doodads) {
1794 /* Reallocate and clear all items. */
1795 if (!XkbGeomRealloc
1796 ((void **) &dst->geom->doodads, dst->geom->sz_doodads,
1797 src->geom->num_doodads, sizeof(XkbDoodadRec),
1798 XKB_GEOM_CLEAR_ALL))
1799 return FALSE;
1800
1801 dst->geom->sz_doodads = src->geom->num_doodads;
1802
1803 for (i = 0,
1804 sdoodad = src->geom->doodads,
1805 ddoodad = dst->geom->doodads;
1806 i < src->geom->num_doodads; i++, sdoodad++, ddoodad++) {
1807 memcpy(ddoodad, sdoodad, sizeof(XkbDoodadRec));
1808 if (sdoodad->any.type == XkbTextDoodad) {
1809 if (sdoodad->text.text)
1810 ddoodad->text.text = strdup(sdoodad->text.text);
1811 if (sdoodad->text.font)
1812 ddoodad->text.font = strdup(sdoodad->text.font);
1813 }
1814 else if (sdoodad->any.type == XkbLogoDoodad) {
1815 if (sdoodad->logo.logo_name)
1816 ddoodad->logo.logo_name =
1817 strdup(sdoodad->logo.logo_name);
1818 }
1819 }
1820
1821 dst->geom->num_doodads = dst->geom->sz_doodads;
1822 }
1823 else {
1824 if (dst->geom->sz_doodads) {
1825 free(dst->geom->doodads);
1826 }
1827
1828 dst->geom->doodads = NULL;
1829 dst->geom->num_doodads = 0;
1830 dst->geom->sz_doodads = 0;
1831 }
1832
1833 /* key aliases */
1834 if (src->geom->num_key_aliases) {
1835 /* Reallocate but don't clear any items. There is no need
1836 * to clear anything because data is immediately copied
1837 * over the whole memory area with memcpy. */
1838 if (!XkbGeomRealloc
1839 ((void **) &dst->geom->key_aliases, dst->geom->sz_key_aliases,
1840 src->geom->num_key_aliases, 2 * XkbKeyNameLength,
1841 XKB_GEOM_CLEAR_NONE))
1842 return FALSE;
1843
1844 dst->geom->sz_key_aliases = src->geom->num_key_aliases;
1845
1846 memcpy(dst->geom->key_aliases, src->geom->key_aliases,
1847 src->geom->num_key_aliases * 2 * XkbKeyNameLength);
1848
1849 dst->geom->num_key_aliases = dst->geom->sz_key_aliases;
1850 }
1851 else {
1852 free(dst->geom->key_aliases);
1853 dst->geom->key_aliases = NULL;
1854 dst->geom->num_key_aliases = 0;
1855 dst->geom->sz_key_aliases = 0;
1856 }
1857
1858 /* font */
1859 if (src->geom->label_font) {
1860 if (!dst->geom->label_font) {
1861 tmp = malloc(strlen(src->geom->label_font) + 1);
1862 if (!tmp)
1863 return FALSE;
1864 dst->geom->label_font = tmp;
1865 }
1866 else if (strlen(src->geom->label_font) !=
1867 strlen(dst->geom->label_font)) {
1868 tmp = realloc(dst->geom->label_font,
1869 strlen(src->geom->label_font) + 1);
1870 if (!tmp)
1871 return FALSE;
1872 dst->geom->label_font = tmp;
1873 }
1874
1875 strcpy(dst->geom->label_font, src->geom->label_font);
1876 i = XkbGeomColorIndex(src->geom, src->geom->label_color);
1877 dst->geom->label_color = &(dst->geom->colors[i]);
1878 i = XkbGeomColorIndex(src->geom, src->geom->base_color);
1879 dst->geom->base_color = &(dst->geom->colors[i]);
1880 }
1881 else {
1882 free(dst->geom->label_font);
1883 dst->geom->label_font = NULL;
1884 dst->geom->label_color = NULL;
1885 dst->geom->base_color = NULL;
1886 }
1887
1888 dst->geom->name = src->geom->name;
1889 dst->geom->width_mm = src->geom->width_mm;
1890 dst->geom->height_mm = src->geom->height_mm;
1891 }
1892 else {
1893 if (dst->geom) {
1894 /* I LOVE THE DIFFERENT CALL SIGNATURE. REALLY, I DO. */
1895 XkbFreeGeometry(dst->geom, XkbGeomAllMask, TRUE);
1896 dst->geom = NULL;
1897 }
1898 }
1899
1900 return TRUE;
1901 }
1902
1903 static Bool
_XkbCopyIndicators(XkbDescPtr src,XkbDescPtr dst)1904 _XkbCopyIndicators(XkbDescPtr src, XkbDescPtr dst)
1905 {
1906 /* indicators */
1907 if (src->indicators) {
1908 if (!dst->indicators) {
1909 dst->indicators = malloc(sizeof(XkbIndicatorRec));
1910 if (!dst->indicators)
1911 return FALSE;
1912 }
1913 memcpy(dst->indicators, src->indicators, sizeof(XkbIndicatorRec));
1914 }
1915 else {
1916 free(dst->indicators);
1917 dst->indicators = NULL;
1918 }
1919 return TRUE;
1920 }
1921
1922 static Bool
_XkbCopyControls(XkbDescPtr src,XkbDescPtr dst)1923 _XkbCopyControls(XkbDescPtr src, XkbDescPtr dst)
1924 {
1925 /* controls */
1926 if (src->ctrls) {
1927 if (!dst->ctrls) {
1928 dst->ctrls = malloc(sizeof(XkbControlsRec));
1929 if (!dst->ctrls)
1930 return FALSE;
1931 }
1932 memcpy(dst->ctrls, src->ctrls, sizeof(XkbControlsRec));
1933 }
1934 else {
1935 free(dst->ctrls);
1936 dst->ctrls = NULL;
1937 }
1938 return TRUE;
1939 }
1940
1941 /**
1942 * Copy an XKB map from src to dst, reallocating when necessary: if some
1943 * map components are present in one, but not in the other, the destination
1944 * components will be allocated or freed as necessary.
1945 *
1946 * Basic map consistency is assumed on both sides, so maps with random
1947 * uninitialised data (e.g. names->radio_grous == NULL, names->num_rg == 19)
1948 * _will_ cause failures. You've been warned.
1949 *
1950 * Returns TRUE on success, or FALSE on failure. If this function fails,
1951 * dst may be in an inconsistent state: all its pointers are guaranteed
1952 * to remain valid, but part of the map may be from src and part from dst.
1953 *
1954 */
1955
1956 Bool
XkbCopyKeymap(XkbDescPtr dst,XkbDescPtr src)1957 XkbCopyKeymap(XkbDescPtr dst, XkbDescPtr src)
1958 {
1959
1960 if (!src || !dst) {
1961 DebugF("XkbCopyKeymap: src (%p) or dst (%p) is NULL\n", src, dst);
1962 return FALSE;
1963 }
1964
1965 if (src == dst)
1966 return TRUE;
1967
1968 if (!_XkbCopyClientMap(src, dst)) {
1969 DebugF("XkbCopyKeymap: failed to copy client map\n");
1970 return FALSE;
1971 }
1972 if (!_XkbCopyServerMap(src, dst)) {
1973 DebugF("XkbCopyKeymap: failed to copy server map\n");
1974 return FALSE;
1975 }
1976 if (!_XkbCopyIndicators(src, dst)) {
1977 DebugF("XkbCopyKeymap: failed to copy indicators\n");
1978 return FALSE;
1979 }
1980 if (!_XkbCopyControls(src, dst)) {
1981 DebugF("XkbCopyKeymap: failed to copy controls\n");
1982 return FALSE;
1983 }
1984 if (!_XkbCopyNames(src, dst)) {
1985 DebugF("XkbCopyKeymap: failed to copy names\n");
1986 return FALSE;
1987 }
1988 if (!_XkbCopyCompat(src, dst)) {
1989 DebugF("XkbCopyKeymap: failed to copy compat map\n");
1990 return FALSE;
1991 }
1992 if (!_XkbCopyGeom(src, dst)) {
1993 DebugF("XkbCopyKeymap: failed to copy geometry\n");
1994 return FALSE;
1995 }
1996
1997 dst->min_key_code = src->min_key_code;
1998 dst->max_key_code = src->max_key_code;
1999
2000 return TRUE;
2001 }
2002
2003 Bool
XkbDeviceApplyKeymap(DeviceIntPtr dst,XkbDescPtr desc)2004 XkbDeviceApplyKeymap(DeviceIntPtr dst, XkbDescPtr desc)
2005 {
2006 xkbNewKeyboardNotify nkn;
2007 Bool ret;
2008
2009 if (!dst->key || !desc)
2010 return FALSE;
2011
2012 memset(&nkn, 0, sizeof(xkbNewKeyboardNotify));
2013 nkn.oldMinKeyCode = dst->key->xkbInfo->desc->min_key_code;
2014 nkn.oldMaxKeyCode = dst->key->xkbInfo->desc->max_key_code;
2015 nkn.deviceID = dst->id;
2016 nkn.oldDeviceID = dst->id;
2017 nkn.minKeyCode = desc->min_key_code;
2018 nkn.maxKeyCode = desc->max_key_code;
2019 nkn.requestMajor = XkbReqCode;
2020 nkn.requestMinor = X_kbSetMap; /* Near enough's good enough. */
2021 nkn.changed = XkbNKN_KeycodesMask;
2022 if (desc->geom)
2023 nkn.changed |= XkbNKN_GeometryMask;
2024
2025 ret = XkbCopyKeymap(dst->key->xkbInfo->desc, desc);
2026 if (ret)
2027 XkbSendNewKeyboardNotify(dst, &nkn);
2028
2029 return ret;
2030 }
2031
2032 Bool
XkbCopyDeviceKeymap(DeviceIntPtr dst,DeviceIntPtr src)2033 XkbCopyDeviceKeymap(DeviceIntPtr dst, DeviceIntPtr src)
2034 {
2035 return XkbDeviceApplyKeymap(dst, src->key->xkbInfo->desc);
2036 }
2037
2038 int
XkbGetEffectiveGroup(XkbSrvInfoPtr xkbi,XkbStatePtr xkbState,CARD8 keycode)2039 XkbGetEffectiveGroup(XkbSrvInfoPtr xkbi, XkbStatePtr xkbState, CARD8 keycode)
2040 {
2041 XkbDescPtr xkb = xkbi->desc;
2042 int effectiveGroup = xkbState->group;
2043
2044 if (!XkbKeycodeInRange(xkb, keycode))
2045 return -1;
2046
2047 if (effectiveGroup == XkbGroup1Index)
2048 return effectiveGroup;
2049
2050 if (XkbKeyNumGroups(xkb, keycode) > 1U) {
2051 if (effectiveGroup >= XkbKeyNumGroups(xkb, keycode)) {
2052 unsigned int gi = XkbKeyGroupInfo(xkb, keycode);
2053
2054 switch (XkbOutOfRangeGroupAction(gi)) {
2055 default:
2056 case XkbWrapIntoRange:
2057 effectiveGroup %= XkbKeyNumGroups(xkb, keycode);
2058 break;
2059 case XkbClampIntoRange:
2060 effectiveGroup = XkbKeyNumGroups(xkb, keycode) - 1;
2061 break;
2062 case XkbRedirectIntoRange:
2063 effectiveGroup = XkbOutOfRangeGroupInfo(gi);
2064 if (effectiveGroup >= XkbKeyNumGroups(xkb, keycode))
2065 effectiveGroup = 0;
2066 break;
2067 }
2068 }
2069 }
2070 else
2071 effectiveGroup = XkbGroup1Index;
2072
2073 return effectiveGroup;
2074 }
2075
2076 /* Merge the lockedPtrButtons from all attached SDs for the given master
2077 * device into the MD's state.
2078 */
2079 void
XkbMergeLockedPtrBtns(DeviceIntPtr master)2080 XkbMergeLockedPtrBtns(DeviceIntPtr master)
2081 {
2082 DeviceIntPtr d = inputInfo.devices;
2083 XkbSrvInfoPtr xkbi = NULL;
2084
2085 if (!IsMaster(master))
2086 return;
2087
2088 if (!master->key)
2089 return;
2090
2091 xkbi = master->key->xkbInfo;
2092 xkbi->lockedPtrButtons = 0;
2093
2094 for (; d; d = d->next) {
2095 if (IsMaster(d) || GetMaster(d, MASTER_KEYBOARD) != master || !d->key)
2096 continue;
2097
2098 xkbi->lockedPtrButtons |= d->key->xkbInfo->lockedPtrButtons;
2099 }
2100 }
2101
2102 void
XkbCopyControls(XkbDescPtr dst,XkbDescPtr src)2103 XkbCopyControls(XkbDescPtr dst, XkbDescPtr src)
2104 {
2105 int i, nG, nTG;
2106
2107 if (!dst || !src)
2108 return;
2109
2110 *dst->ctrls = *src->ctrls;
2111
2112 for (nG = nTG = 0, i = dst->min_key_code; i <= dst->max_key_code; i++) {
2113 nG = XkbKeyNumGroups(dst, i);
2114 if (nG >= XkbNumKbdGroups) {
2115 nTG = XkbNumKbdGroups;
2116 break;
2117 }
2118 if (nG > nTG) {
2119 nTG = nG;
2120 }
2121 }
2122 dst->ctrls->num_groups = nTG;
2123 }
2124