xkb.c revision 4e185dc0
1/************************************************************
2Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3
4Permission to use, copy, modify, and distribute this
5software and its documentation for any purpose and without
6fee is hereby granted, provided that the above copyright
7notice appear in all copies and that both that copyright
8notice and this permission notice appear in supporting
9documentation, and that the name of Silicon Graphics not be
10used in advertising or publicity pertaining to distribution
11of the software without specific prior written permission.
12Silicon Graphics makes no representation about the suitability
13of this software for any purpose. It is provided "as is"
14without any express or implied warranty.
15
16SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25********************************************************/
26
27#ifdef HAVE_DIX_CONFIG_H
28#include <dix-config.h>
29#endif
30
31#include <stdio.h>
32#include <X11/X.h>
33#include <X11/Xproto.h>
34#include "misc.h"
35#include "inputstr.h"
36#define	XKBSRV_NEED_FILE_FUNCS
37#include <xkbsrv.h>
38#include "extnsionst.h"
39#include "extinit.h"
40#include "xace.h"
41#include "xkb.h"
42#include "protocol-versions.h"
43
44#include <X11/extensions/XI.h>
45#include <X11/extensions/XKMformat.h>
46
47int XkbEventBase;
48static int XkbErrorBase;
49int XkbReqCode;
50int XkbKeyboardErrorCode;
51CARD32 xkbDebugFlags = 0;
52static CARD32 xkbDebugCtrls = 0;
53
54static RESTYPE RT_XKBCLIENT;
55
56/***====================================================================***/
57
58#define	CHK_DEVICE(dev, id, client, access_mode, lf) {\
59    int why;\
60    int tmprc = lf(&(dev), id, client, access_mode, &why);\
61    if (tmprc != Success) {\
62	client->errorValue = _XkbErrCode2(why, id);\
63	return tmprc;\
64    }\
65}
66
67#define	CHK_KBD_DEVICE(dev, id, client, mode) \
68    CHK_DEVICE(dev, id, client, mode, _XkbLookupKeyboard)
69#define	CHK_LED_DEVICE(dev, id, client, mode) \
70    CHK_DEVICE(dev, id, client, mode, _XkbLookupLedDevice)
71#define	CHK_BELL_DEVICE(dev, id, client, mode) \
72    CHK_DEVICE(dev, id, client, mode, _XkbLookupBellDevice)
73#define	CHK_ANY_DEVICE(dev, id, client, mode) \
74    CHK_DEVICE(dev, id, client, mode, _XkbLookupAnyDevice)
75
76#define	CHK_ATOM_ONLY2(a,ev,er) {\
77	if (((a)==None)||(!ValidAtom((a)))) {\
78	    (ev)= (XID)(a);\
79	    return er;\
80	}\
81}
82#define	CHK_ATOM_ONLY(a) \
83	CHK_ATOM_ONLY2(a,client->errorValue,BadAtom)
84
85#define	CHK_ATOM_OR_NONE3(a,ev,er,ret) {\
86	if (((a)!=None)&&(!ValidAtom((a)))) {\
87	    (ev)= (XID)(a);\
88	    (er)= BadAtom;\
89	    return ret;\
90	}\
91}
92#define	CHK_ATOM_OR_NONE2(a,ev,er) {\
93	if (((a)!=None)&&(!ValidAtom((a)))) {\
94	    (ev)= (XID)(a);\
95	    return er;\
96	}\
97}
98#define	CHK_ATOM_OR_NONE(a) \
99	CHK_ATOM_OR_NONE2(a,client->errorValue,BadAtom)
100
101#define	CHK_MASK_LEGAL3(err,mask,legal,ev,er,ret)	{\
102	if ((mask)&(~(legal))) { \
103	    (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\
104	    (er)= BadValue;\
105	    return ret;\
106	}\
107}
108#define	CHK_MASK_LEGAL2(err,mask,legal,ev,er)	{\
109	if ((mask)&(~(legal))) { \
110	    (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\
111	    return er;\
112	}\
113}
114#define	CHK_MASK_LEGAL(err,mask,legal) \
115	CHK_MASK_LEGAL2(err,mask,legal,client->errorValue,BadValue)
116
117#define	CHK_MASK_MATCH(err,affect,value) {\
118	if ((value)&(~(affect))) { \
119	    client->errorValue= _XkbErrCode2((err),((value)&(~(affect))));\
120	    return BadMatch;\
121	}\
122}
123#define	CHK_MASK_OVERLAP(err,m1,m2) {\
124	if ((m1)&(m2)) { \
125	    client->errorValue= _XkbErrCode2((err),((m1)&(m2)));\
126	    return BadMatch;\
127	}\
128}
129#define	CHK_KEY_RANGE2(err,first,num,x,ev,er) {\
130	if (((unsigned)(first)+(num)-1)>(x)->max_key_code) {\
131	    (ev)=_XkbErrCode4(err,(first),(num),(x)->max_key_code);\
132	    return er;\
133	}\
134	else if ( (first)<(x)->min_key_code ) {\
135	    (ev)=_XkbErrCode3(err+1,(first),xkb->min_key_code);\
136	    return er;\
137	}\
138}
139#define	CHK_KEY_RANGE(err,first,num,x)  \
140	CHK_KEY_RANGE2(err,first,num,x,client->errorValue,BadValue)
141
142#define	CHK_REQ_KEY_RANGE2(err,first,num,r,ev,er) {\
143	if (((unsigned)(first)+(num)-1)>(r)->maxKeyCode) {\
144	    (ev)=_XkbErrCode4(err,(first),(num),(r)->maxKeyCode);\
145	    return er;\
146	}\
147	else if ( (first)<(r)->minKeyCode ) {\
148	    (ev)=_XkbErrCode3(err+1,(first),(r)->minKeyCode);\
149	    return er;\
150	}\
151}
152#define	CHK_REQ_KEY_RANGE(err,first,num,r)  \
153	CHK_REQ_KEY_RANGE2(err,first,num,r,client->errorValue,BadValue)
154
155/***====================================================================***/
156
157int
158ProcXkbUseExtension(ClientPtr client)
159{
160    REQUEST(xkbUseExtensionReq);
161    xkbUseExtensionReply rep;
162    int supported;
163
164    REQUEST_SIZE_MATCH(xkbUseExtensionReq);
165    if (stuff->wantedMajor != SERVER_XKB_MAJOR_VERSION) {
166        /* pre-release version 0.65 is compatible with 1.00 */
167        supported = ((SERVER_XKB_MAJOR_VERSION == 1) &&
168                     (stuff->wantedMajor == 0) && (stuff->wantedMinor == 65));
169    }
170    else
171        supported = 1;
172
173    if ((supported) && (!(client->xkbClientFlags & _XkbClientInitialized))) {
174        client->xkbClientFlags = _XkbClientInitialized;
175        if (stuff->wantedMajor == 0)
176            client->xkbClientFlags |= _XkbClientIsAncient;
177    }
178    else if (xkbDebugFlags & 0x1) {
179        ErrorF
180            ("[xkb] Rejecting client %d (0x%lx) (wants %d.%02d, have %d.%02d)\n",
181             client->index, (long) client->clientAsMask, stuff->wantedMajor,
182             stuff->wantedMinor, SERVER_XKB_MAJOR_VERSION,
183             SERVER_XKB_MINOR_VERSION);
184    }
185    rep = (xkbUseExtensionReply) {
186        .type = X_Reply,
187        .supported = supported,
188        .sequenceNumber = client->sequence,
189        .length = 0,
190        .serverMajor = SERVER_XKB_MAJOR_VERSION,
191        .serverMinor = SERVER_XKB_MINOR_VERSION
192    };
193    if (client->swapped) {
194        swaps(&rep.sequenceNumber);
195        swaps(&rep.serverMajor);
196        swaps(&rep.serverMinor);
197    }
198    WriteToClient(client, SIZEOF(xkbUseExtensionReply), &rep);
199    return Success;
200}
201
202/***====================================================================***/
203
204int
205ProcXkbSelectEvents(ClientPtr client)
206{
207    unsigned legal;
208    DeviceIntPtr dev;
209    XkbInterestPtr masks;
210
211    REQUEST(xkbSelectEventsReq);
212
213    REQUEST_AT_LEAST_SIZE(xkbSelectEventsReq);
214
215    if (!(client->xkbClientFlags & _XkbClientInitialized))
216        return BadAccess;
217
218    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixUseAccess);
219
220    if (((stuff->affectWhich & XkbMapNotifyMask) != 0) && (stuff->affectMap)) {
221        client->mapNotifyMask &= ~stuff->affectMap;
222        client->mapNotifyMask |= (stuff->affectMap & stuff->map);
223    }
224    if ((stuff->affectWhich & (~XkbMapNotifyMask)) == 0)
225        return Success;
226
227    masks = XkbFindClientResource((DevicePtr) dev, client);
228    if (!masks) {
229        XID id = FakeClientID(client->index);
230
231        if (!AddResource(id, RT_XKBCLIENT, dev))
232            return BadAlloc;
233        masks = XkbAddClientResource((DevicePtr) dev, client, id);
234    }
235    if (masks) {
236        union {
237            CARD8 *c8;
238            CARD16 *c16;
239            CARD32 *c32;
240        } from, to;
241        register unsigned bit, ndx, maskLeft, dataLeft, size;
242
243        from.c8 = (CARD8 *) &stuff[1];
244        dataLeft = (stuff->length * 4) - SIZEOF(xkbSelectEventsReq);
245        maskLeft = (stuff->affectWhich & (~XkbMapNotifyMask));
246        for (ndx = 0, bit = 1; (maskLeft != 0); ndx++, bit <<= 1) {
247            if ((bit & maskLeft) == 0)
248                continue;
249            maskLeft &= ~bit;
250            switch (ndx) {
251            case XkbNewKeyboardNotify:
252                to.c16 = &client->newKeyboardNotifyMask;
253                legal = XkbAllNewKeyboardEventsMask;
254                size = 2;
255                break;
256            case XkbStateNotify:
257                to.c16 = &masks->stateNotifyMask;
258                legal = XkbAllStateEventsMask;
259                size = 2;
260                break;
261            case XkbControlsNotify:
262                to.c32 = &masks->ctrlsNotifyMask;
263                legal = XkbAllControlEventsMask;
264                size = 4;
265                break;
266            case XkbIndicatorStateNotify:
267                to.c32 = &masks->iStateNotifyMask;
268                legal = XkbAllIndicatorEventsMask;
269                size = 4;
270                break;
271            case XkbIndicatorMapNotify:
272                to.c32 = &masks->iMapNotifyMask;
273                legal = XkbAllIndicatorEventsMask;
274                size = 4;
275                break;
276            case XkbNamesNotify:
277                to.c16 = &masks->namesNotifyMask;
278                legal = XkbAllNameEventsMask;
279                size = 2;
280                break;
281            case XkbCompatMapNotify:
282                to.c8 = &masks->compatNotifyMask;
283                legal = XkbAllCompatMapEventsMask;
284                size = 1;
285                break;
286            case XkbBellNotify:
287                to.c8 = &masks->bellNotifyMask;
288                legal = XkbAllBellEventsMask;
289                size = 1;
290                break;
291            case XkbActionMessage:
292                to.c8 = &masks->actionMessageMask;
293                legal = XkbAllActionMessagesMask;
294                size = 1;
295                break;
296            case XkbAccessXNotify:
297                to.c16 = &masks->accessXNotifyMask;
298                legal = XkbAllAccessXEventsMask;
299                size = 2;
300                break;
301            case XkbExtensionDeviceNotify:
302                to.c16 = &masks->extDevNotifyMask;
303                legal = XkbAllExtensionDeviceEventsMask;
304                size = 2;
305                break;
306            default:
307                client->errorValue = _XkbErrCode2(33, bit);
308                return BadValue;
309            }
310
311            if (stuff->clear & bit) {
312                if (size == 2)
313                    to.c16[0] = 0;
314                else if (size == 4)
315                    to.c32[0] = 0;
316                else
317                    to.c8[0] = 0;
318            }
319            else if (stuff->selectAll & bit) {
320                if (size == 2)
321                    to.c16[0] = ~0;
322                else if (size == 4)
323                    to.c32[0] = ~0;
324                else
325                    to.c8[0] = ~0;
326            }
327            else {
328                if (dataLeft < (size * 2))
329                    return BadLength;
330                if (size == 2) {
331                    CHK_MASK_MATCH(ndx, from.c16[0], from.c16[1]);
332                    CHK_MASK_LEGAL(ndx, from.c16[0], legal);
333                    to.c16[0] &= ~from.c16[0];
334                    to.c16[0] |= (from.c16[0] & from.c16[1]);
335                }
336                else if (size == 4) {
337                    CHK_MASK_MATCH(ndx, from.c32[0], from.c32[1]);
338                    CHK_MASK_LEGAL(ndx, from.c32[0], legal);
339                    to.c32[0] &= ~from.c32[0];
340                    to.c32[0] |= (from.c32[0] & from.c32[1]);
341                }
342                else {
343                    CHK_MASK_MATCH(ndx, from.c8[0], from.c8[1]);
344                    CHK_MASK_LEGAL(ndx, from.c8[0], legal);
345                    to.c8[0] &= ~from.c8[0];
346                    to.c8[0] |= (from.c8[0] & from.c8[1]);
347                    size = 2;
348                }
349                from.c8 += (size * 2);
350                dataLeft -= (size * 2);
351            }
352        }
353        if (dataLeft > 2) {
354            ErrorF("[xkb] Extra data (%d bytes) after SelectEvents\n",
355                   dataLeft);
356            return BadLength;
357        }
358        return Success;
359    }
360    return BadAlloc;
361}
362
363/***====================================================================***/
364/**
365 * Ring a bell on the given device for the given client.
366 */
367static int
368_XkbBell(ClientPtr client, DeviceIntPtr dev, WindowPtr pWin,
369         int bellClass, int bellID, int pitch, int duration,
370         int percent, int forceSound, int eventOnly, Atom name)
371{
372    int base;
373    void *ctrl;
374    int oldPitch, oldDuration;
375    int newPercent;
376
377    if (bellClass == KbdFeedbackClass) {
378        KbdFeedbackPtr k;
379
380        if (bellID == XkbDfltXIId)
381            k = dev->kbdfeed;
382        else {
383            for (k = dev->kbdfeed; k; k = k->next) {
384                if (k->ctrl.id == bellID)
385                    break;
386            }
387        }
388        if (!k) {
389            client->errorValue = _XkbErrCode2(0x5, bellID);
390            return BadValue;
391        }
392        base = k->ctrl.bell;
393        ctrl = (void *) &(k->ctrl);
394        oldPitch = k->ctrl.bell_pitch;
395        oldDuration = k->ctrl.bell_duration;
396        if (pitch != 0) {
397            if (pitch == -1)
398                k->ctrl.bell_pitch = defaultKeyboardControl.bell_pitch;
399            else
400                k->ctrl.bell_pitch = pitch;
401        }
402        if (duration != 0) {
403            if (duration == -1)
404                k->ctrl.bell_duration = defaultKeyboardControl.bell_duration;
405            else
406                k->ctrl.bell_duration = duration;
407        }
408    }
409    else if (bellClass == BellFeedbackClass) {
410        BellFeedbackPtr b;
411
412        if (bellID == XkbDfltXIId)
413            b = dev->bell;
414        else {
415            for (b = dev->bell; b; b = b->next) {
416                if (b->ctrl.id == bellID)
417                    break;
418            }
419        }
420        if (!b) {
421            client->errorValue = _XkbErrCode2(0x6, bellID);
422            return BadValue;
423        }
424        base = b->ctrl.percent;
425        ctrl = (void *) &(b->ctrl);
426        oldPitch = b->ctrl.pitch;
427        oldDuration = b->ctrl.duration;
428        if (pitch != 0) {
429            if (pitch == -1)
430                b->ctrl.pitch = defaultKeyboardControl.bell_pitch;
431            else
432                b->ctrl.pitch = pitch;
433        }
434        if (duration != 0) {
435            if (duration == -1)
436                b->ctrl.duration = defaultKeyboardControl.bell_duration;
437            else
438                b->ctrl.duration = duration;
439        }
440    }
441    else {
442        client->errorValue = _XkbErrCode2(0x7, bellClass);
443        return BadValue;
444    }
445
446    newPercent = (base * percent) / 100;
447    if (percent < 0)
448        newPercent = base + newPercent;
449    else
450        newPercent = base - newPercent + percent;
451
452    XkbHandleBell(forceSound, eventOnly,
453                  dev, newPercent, ctrl, bellClass, name, pWin, client);
454    if ((pitch != 0) || (duration != 0)) {
455        if (bellClass == KbdFeedbackClass) {
456            KbdFeedbackPtr k;
457
458            k = (KbdFeedbackPtr) ctrl;
459            if (pitch != 0)
460                k->ctrl.bell_pitch = oldPitch;
461            if (duration != 0)
462                k->ctrl.bell_duration = oldDuration;
463        }
464        else {
465            BellFeedbackPtr b;
466
467            b = (BellFeedbackPtr) ctrl;
468            if (pitch != 0)
469                b->ctrl.pitch = oldPitch;
470            if (duration != 0)
471                b->ctrl.duration = oldDuration;
472        }
473    }
474
475    return Success;
476}
477
478int
479ProcXkbBell(ClientPtr client)
480{
481    REQUEST(xkbBellReq);
482    DeviceIntPtr dev;
483    WindowPtr pWin;
484    int rc;
485
486    REQUEST_SIZE_MATCH(xkbBellReq);
487
488    if (!(client->xkbClientFlags & _XkbClientInitialized))
489        return BadAccess;
490
491    CHK_BELL_DEVICE(dev, stuff->deviceSpec, client, DixBellAccess);
492    CHK_ATOM_OR_NONE(stuff->name);
493
494    /* device-independent checks request for sane values */
495    if ((stuff->forceSound) && (stuff->eventOnly)) {
496        client->errorValue =
497            _XkbErrCode3(0x1, stuff->forceSound, stuff->eventOnly);
498        return BadMatch;
499    }
500    if (stuff->percent < -100 || stuff->percent > 100) {
501        client->errorValue = _XkbErrCode2(0x2, stuff->percent);
502        return BadValue;
503    }
504    if (stuff->duration < -1) {
505        client->errorValue = _XkbErrCode2(0x3, stuff->duration);
506        return BadValue;
507    }
508    if (stuff->pitch < -1) {
509        client->errorValue = _XkbErrCode2(0x4, stuff->pitch);
510        return BadValue;
511    }
512
513    if (stuff->bellClass == XkbDfltXIClass) {
514        if (dev->kbdfeed != NULL)
515            stuff->bellClass = KbdFeedbackClass;
516        else
517            stuff->bellClass = BellFeedbackClass;
518    }
519
520    if (stuff->window != None) {
521        rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
522        if (rc != Success) {
523            client->errorValue = stuff->window;
524            return rc;
525        }
526    }
527    else
528        pWin = NULL;
529
530    /* Client wants to ring a bell on the core keyboard?
531       Ring the bell on the core keyboard (which does nothing, but if that
532       fails the client is screwed anyway), and then on all extension devices.
533       Fail if the core keyboard fails but not the extension devices.  this
534       may cause some keyboards to ding and others to stay silent. Fix
535       your client to use explicit keyboards to avoid this.
536
537       dev is the device the client requested.
538     */
539    rc = _XkbBell(client, dev, pWin, stuff->bellClass, stuff->bellID,
540                  stuff->pitch, stuff->duration, stuff->percent,
541                  stuff->forceSound, stuff->eventOnly, stuff->name);
542
543    if ((rc == Success) && ((stuff->deviceSpec == XkbUseCoreKbd) ||
544                            (stuff->deviceSpec == XkbUseCorePtr))) {
545        DeviceIntPtr other;
546
547        for (other = inputInfo.devices; other; other = other->next) {
548            if ((other != dev) && other->key && !IsMaster(other) &&
549                GetMaster(other, MASTER_KEYBOARD) == dev) {
550                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixBellAccess);
551                if (rc == Success)
552                    _XkbBell(client, other, pWin, stuff->bellClass,
553                             stuff->bellID, stuff->pitch, stuff->duration,
554                             stuff->percent, stuff->forceSound,
555                             stuff->eventOnly, stuff->name);
556            }
557        }
558        rc = Success;           /* reset to success, that's what we got for the VCK */
559    }
560
561    return rc;
562}
563
564/***====================================================================***/
565
566int
567ProcXkbGetState(ClientPtr client)
568{
569    REQUEST(xkbGetStateReq);
570    DeviceIntPtr dev;
571    xkbGetStateReply rep;
572    XkbStateRec *xkb;
573
574    REQUEST_SIZE_MATCH(xkbGetStateReq);
575
576    if (!(client->xkbClientFlags & _XkbClientInitialized))
577        return BadAccess;
578
579    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
580
581    xkb = &dev->key->xkbInfo->state;
582    rep = (xkbGetStateReply) {
583        .type = X_Reply,
584        .deviceID = dev->id,
585        .sequenceNumber = client->sequence,
586        .length = 0,
587        .mods = XkbStateFieldFromRec(xkb) & 0xff,
588        .baseMods = xkb->base_mods,
589        .latchedMods = xkb->latched_mods,
590        .lockedMods = xkb->locked_mods,
591        .group = xkb->group,
592        .lockedGroup = xkb->locked_group,
593        .baseGroup = xkb->base_group,
594        .latchedGroup = xkb->latched_group,
595        .compatState = xkb->compat_state,
596        .ptrBtnState = xkb->ptr_buttons
597    };
598    if (client->swapped) {
599        swaps(&rep.sequenceNumber);
600        swaps(&rep.ptrBtnState);
601    }
602    WriteToClient(client, SIZEOF(xkbGetStateReply), &rep);
603    return Success;
604}
605
606/***====================================================================***/
607
608int
609ProcXkbLatchLockState(ClientPtr client)
610{
611    int status;
612    DeviceIntPtr dev, tmpd;
613    XkbStateRec oldState, *newState;
614    CARD16 changed;
615    xkbStateNotify sn;
616    XkbEventCauseRec cause;
617
618    REQUEST(xkbLatchLockStateReq);
619    REQUEST_SIZE_MATCH(xkbLatchLockStateReq);
620
621    if (!(client->xkbClientFlags & _XkbClientInitialized))
622        return BadAccess;
623
624    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
625    CHK_MASK_MATCH(0x01, stuff->affectModLocks, stuff->modLocks);
626    CHK_MASK_MATCH(0x01, stuff->affectModLatches, stuff->modLatches);
627
628    status = Success;
629
630    for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
631        if ((tmpd == dev) ||
632            (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) {
633            if (!tmpd->key || !tmpd->key->xkbInfo)
634                continue;
635
636            oldState = tmpd->key->xkbInfo->state;
637            newState = &tmpd->key->xkbInfo->state;
638            if (stuff->affectModLocks) {
639                newState->locked_mods &= ~stuff->affectModLocks;
640                newState->locked_mods |=
641                    (stuff->affectModLocks & stuff->modLocks);
642            }
643            if (status == Success && stuff->lockGroup)
644                newState->locked_group = stuff->groupLock;
645            if (status == Success && stuff->affectModLatches)
646                status = XkbLatchModifiers(tmpd, stuff->affectModLatches,
647                                           stuff->modLatches);
648            if (status == Success && stuff->latchGroup)
649                status = XkbLatchGroup(tmpd, stuff->groupLatch);
650
651            if (status != Success)
652                return status;
653
654            XkbComputeDerivedState(tmpd->key->xkbInfo);
655
656            changed = XkbStateChangedFlags(&oldState, newState);
657            if (changed) {
658                sn.keycode = 0;
659                sn.eventType = 0;
660                sn.requestMajor = XkbReqCode;
661                sn.requestMinor = X_kbLatchLockState;
662                sn.changed = changed;
663                XkbSendStateNotify(tmpd, &sn);
664                changed = XkbIndicatorsToUpdate(tmpd, changed, FALSE);
665                if (changed) {
666                    XkbSetCauseXkbReq(&cause, X_kbLatchLockState, client);
667                    XkbUpdateIndicators(tmpd, changed, TRUE, NULL, &cause);
668                }
669            }
670        }
671    }
672
673    return Success;
674}
675
676/***====================================================================***/
677
678int
679ProcXkbGetControls(ClientPtr client)
680{
681    xkbGetControlsReply rep;
682    XkbControlsPtr xkb;
683    DeviceIntPtr dev;
684
685    REQUEST(xkbGetControlsReq);
686    REQUEST_SIZE_MATCH(xkbGetControlsReq);
687
688    if (!(client->xkbClientFlags & _XkbClientInitialized))
689        return BadAccess;
690
691    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
692
693    xkb = dev->key->xkbInfo->desc->ctrls;
694    rep = (xkbGetControlsReply) {
695        .type = X_Reply,
696        .deviceID = ((DeviceIntPtr) dev)->id,
697        .sequenceNumber = client->sequence,
698        .length = bytes_to_int32(SIZEOF(xkbGetControlsReply) -
699                                 SIZEOF(xGenericReply)),
700        .mkDfltBtn = xkb->mk_dflt_btn,
701        .numGroups = xkb->num_groups,
702        .groupsWrap = xkb->groups_wrap,
703        .internalMods = xkb->internal.mask,
704        .ignoreLockMods = xkb->ignore_lock.mask,
705        .internalRealMods = xkb->internal.real_mods,
706        .ignoreLockRealMods = xkb->ignore_lock.real_mods,
707        .internalVMods = xkb->internal.vmods,
708        .ignoreLockVMods = xkb->ignore_lock.vmods,
709        .repeatDelay = xkb->repeat_delay,
710        .repeatInterval = xkb->repeat_interval,
711        .slowKeysDelay = xkb->slow_keys_delay,
712        .debounceDelay = xkb->debounce_delay,
713        .mkDelay = xkb->mk_delay,
714        .mkInterval = xkb->mk_interval,
715        .mkTimeToMax = xkb->mk_time_to_max,
716        .mkMaxSpeed = xkb->mk_max_speed,
717        .mkCurve = xkb->mk_curve,
718        .axOptions = xkb->ax_options,
719        .axTimeout = xkb->ax_timeout,
720        .axtOptsMask = xkb->axt_opts_mask,
721        .axtOptsValues = xkb->axt_opts_values,
722        .axtCtrlsMask = xkb->axt_ctrls_mask,
723        .axtCtrlsValues = xkb->axt_ctrls_values,
724        .enabledCtrls = xkb->enabled_ctrls,
725    };
726    memcpy(rep.perKeyRepeat, xkb->per_key_repeat, XkbPerKeyBitArraySize);
727    if (client->swapped) {
728        swaps(&rep.sequenceNumber);
729        swapl(&rep.length);
730        swaps(&rep.internalVMods);
731        swaps(&rep.ignoreLockVMods);
732        swapl(&rep.enabledCtrls);
733        swaps(&rep.repeatDelay);
734        swaps(&rep.repeatInterval);
735        swaps(&rep.slowKeysDelay);
736        swaps(&rep.debounceDelay);
737        swaps(&rep.mkDelay);
738        swaps(&rep.mkInterval);
739        swaps(&rep.mkTimeToMax);
740        swaps(&rep.mkMaxSpeed);
741        swaps(&rep.mkCurve);
742        swaps(&rep.axTimeout);
743        swapl(&rep.axtCtrlsMask);
744        swapl(&rep.axtCtrlsValues);
745        swaps(&rep.axtOptsMask);
746        swaps(&rep.axtOptsValues);
747        swaps(&rep.axOptions);
748    }
749    WriteToClient(client, SIZEOF(xkbGetControlsReply), &rep);
750    return Success;
751}
752
753int
754ProcXkbSetControls(ClientPtr client)
755{
756    DeviceIntPtr dev, tmpd;
757    XkbSrvInfoPtr xkbi;
758    XkbControlsPtr ctrl;
759    XkbControlsRec new, old;
760    xkbControlsNotify cn;
761    XkbEventCauseRec cause;
762    XkbSrvLedInfoPtr sli;
763
764    REQUEST(xkbSetControlsReq);
765    REQUEST_SIZE_MATCH(xkbSetControlsReq);
766
767    if (!(client->xkbClientFlags & _XkbClientInitialized))
768        return BadAccess;
769
770    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
771    CHK_MASK_LEGAL(0x01, stuff->changeCtrls, XkbAllControlsMask);
772
773    for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
774        if (!tmpd->key || !tmpd->key->xkbInfo)
775            continue;
776        if ((tmpd == dev) ||
777            (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) {
778            xkbi = tmpd->key->xkbInfo;
779            ctrl = xkbi->desc->ctrls;
780            new = *ctrl;
781            XkbSetCauseXkbReq(&cause, X_kbSetControls, client);
782
783            if (stuff->changeCtrls & XkbInternalModsMask) {
784                CHK_MASK_MATCH(0x02, stuff->affectInternalMods,
785                               stuff->internalMods);
786                CHK_MASK_MATCH(0x03, stuff->affectInternalVMods,
787                               stuff->internalVMods);
788
789                new.internal.real_mods &= ~(stuff->affectInternalMods);
790                new.internal.real_mods |= (stuff->affectInternalMods &
791                                           stuff->internalMods);
792                new.internal.vmods &= ~(stuff->affectInternalVMods);
793                new.internal.vmods |= (stuff->affectInternalVMods &
794                                       stuff->internalVMods);
795                new.internal.mask = new.internal.real_mods |
796                    XkbMaskForVMask(xkbi->desc, new.internal.vmods);
797            }
798
799            if (stuff->changeCtrls & XkbIgnoreLockModsMask) {
800                CHK_MASK_MATCH(0x4, stuff->affectIgnoreLockMods,
801                               stuff->ignoreLockMods);
802                CHK_MASK_MATCH(0x5, stuff->affectIgnoreLockVMods,
803                               stuff->ignoreLockVMods);
804
805                new.ignore_lock.real_mods &= ~(stuff->affectIgnoreLockMods);
806                new.ignore_lock.real_mods |= (stuff->affectIgnoreLockMods &
807                                              stuff->ignoreLockMods);
808                new.ignore_lock.vmods &= ~(stuff->affectIgnoreLockVMods);
809                new.ignore_lock.vmods |= (stuff->affectIgnoreLockVMods &
810                                          stuff->ignoreLockVMods);
811                new.ignore_lock.mask = new.ignore_lock.real_mods |
812                    XkbMaskForVMask(xkbi->desc, new.ignore_lock.vmods);
813            }
814
815            CHK_MASK_MATCH(0x06, stuff->affectEnabledCtrls,
816                           stuff->enabledCtrls);
817            if (stuff->affectEnabledCtrls) {
818                CHK_MASK_LEGAL(0x07, stuff->affectEnabledCtrls,
819                               XkbAllBooleanCtrlsMask);
820
821                new.enabled_ctrls &= ~(stuff->affectEnabledCtrls);
822                new.enabled_ctrls |= (stuff->affectEnabledCtrls &
823                                      stuff->enabledCtrls);
824            }
825
826            if (stuff->changeCtrls & XkbRepeatKeysMask) {
827                if (stuff->repeatDelay < 1 || stuff->repeatInterval < 1) {
828                    client->errorValue = _XkbErrCode3(0x08, stuff->repeatDelay,
829                                                      stuff->repeatInterval);
830                    return BadValue;
831                }
832
833                new.repeat_delay = stuff->repeatDelay;
834                new.repeat_interval = stuff->repeatInterval;
835            }
836
837            if (stuff->changeCtrls & XkbSlowKeysMask) {
838                if (stuff->slowKeysDelay < 1) {
839                    client->errorValue = _XkbErrCode2(0x09,
840                                                      stuff->slowKeysDelay);
841                    return BadValue;
842                }
843
844                new.slow_keys_delay = stuff->slowKeysDelay;
845            }
846
847            if (stuff->changeCtrls & XkbBounceKeysMask) {
848                if (stuff->debounceDelay < 1) {
849                    client->errorValue = _XkbErrCode2(0x0A,
850                                                      stuff->debounceDelay);
851                    return BadValue;
852                }
853
854                new.debounce_delay = stuff->debounceDelay;
855            }
856
857            if (stuff->changeCtrls & XkbMouseKeysMask) {
858                if (stuff->mkDfltBtn > XkbMaxMouseKeysBtn) {
859                    client->errorValue = _XkbErrCode2(0x0B, stuff->mkDfltBtn);
860                    return BadValue;
861                }
862
863                new.mk_dflt_btn = stuff->mkDfltBtn;
864            }
865
866            if (stuff->changeCtrls & XkbMouseKeysAccelMask) {
867                if (stuff->mkDelay < 1 || stuff->mkInterval < 1 ||
868                    stuff->mkTimeToMax < 1 || stuff->mkMaxSpeed < 1 ||
869                    stuff->mkCurve < -1000) {
870                    client->errorValue = _XkbErrCode2(0x0C, 0);
871                    return BadValue;
872                }
873
874                new.mk_delay = stuff->mkDelay;
875                new.mk_interval = stuff->mkInterval;
876                new.mk_time_to_max = stuff->mkTimeToMax;
877                new.mk_max_speed = stuff->mkMaxSpeed;
878                new.mk_curve = stuff->mkCurve;
879                AccessXComputeCurveFactor(xkbi, &new);
880            }
881
882            if (stuff->changeCtrls & XkbGroupsWrapMask) {
883                unsigned act, num;
884
885                act = XkbOutOfRangeGroupAction(stuff->groupsWrap);
886                switch (act) {
887                case XkbRedirectIntoRange:
888                    num = XkbOutOfRangeGroupNumber(stuff->groupsWrap);
889                    if (num >= new.num_groups) {
890                        client->errorValue = _XkbErrCode3(0x0D, new.num_groups,
891                                                          num);
892                        return BadValue;
893                    }
894                case XkbWrapIntoRange:
895                case XkbClampIntoRange:
896                    break;
897                default:
898                    client->errorValue = _XkbErrCode2(0x0E, act);
899                    return BadValue;
900                }
901
902                new.groups_wrap = stuff->groupsWrap;
903            }
904
905            CHK_MASK_LEGAL(0x0F, stuff->axOptions, XkbAX_AllOptionsMask);
906            if (stuff->changeCtrls & XkbAccessXKeysMask) {
907                new.ax_options = stuff->axOptions & XkbAX_AllOptionsMask;
908            }
909            else {
910                if (stuff->changeCtrls & XkbStickyKeysMask) {
911                    new.ax_options &= ~(XkbAX_SKOptionsMask);
912                    new.ax_options |= (stuff->axOptions & XkbAX_SKOptionsMask);
913                }
914
915                if (stuff->changeCtrls & XkbAccessXFeedbackMask) {
916                    new.ax_options &= ~(XkbAX_FBOptionsMask);
917                    new.ax_options |= (stuff->axOptions & XkbAX_FBOptionsMask);
918                }
919            }
920
921            if (stuff->changeCtrls & XkbAccessXTimeoutMask) {
922                if (stuff->axTimeout < 1) {
923                    client->errorValue = _XkbErrCode2(0x10, stuff->axTimeout);
924                    return BadValue;
925                }
926                CHK_MASK_MATCH(0x11, stuff->axtCtrlsMask,
927                               stuff->axtCtrlsValues);
928                CHK_MASK_LEGAL(0x12, stuff->axtCtrlsMask,
929                               XkbAllBooleanCtrlsMask);
930                CHK_MASK_MATCH(0x13, stuff->axtOptsMask, stuff->axtOptsValues);
931                CHK_MASK_LEGAL(0x14, stuff->axtOptsMask, XkbAX_AllOptionsMask);
932                new.ax_timeout = stuff->axTimeout;
933                new.axt_ctrls_mask = stuff->axtCtrlsMask;
934                new.axt_ctrls_values = (stuff->axtCtrlsValues &
935                                        stuff->axtCtrlsMask);
936                new.axt_opts_mask = stuff->axtOptsMask;
937                new.axt_opts_values = (stuff->axtOptsValues &
938                                       stuff->axtOptsMask);
939            }
940
941            if (stuff->changeCtrls & XkbPerKeyRepeatMask) {
942                memcpy(new.per_key_repeat, stuff->perKeyRepeat,
943                       XkbPerKeyBitArraySize);
944                if (xkbi->repeatKey &&
945                    !BitIsOn(new.per_key_repeat, xkbi->repeatKey)) {
946                    AccessXCancelRepeatKey(xkbi, xkbi->repeatKey);
947                }
948            }
949
950            old = *ctrl;
951            *ctrl = new;
952            XkbDDXChangeControls(tmpd, &old, ctrl);
953
954            if (XkbComputeControlsNotify(tmpd, &old, ctrl, &cn, FALSE)) {
955                cn.keycode = 0;
956                cn.eventType = 0;
957                cn.requestMajor = XkbReqCode;
958                cn.requestMinor = X_kbSetControls;
959                XkbSendControlsNotify(tmpd, &cn);
960            }
961
962            sli = XkbFindSrvLedInfo(tmpd, XkbDfltXIClass, XkbDfltXIId, 0);
963            if (sli)
964                XkbUpdateIndicators(tmpd, sli->usesControls, TRUE, NULL,
965                                    &cause);
966
967            /* If sticky keys were disabled, clear all locks and latches */
968            if ((old.enabled_ctrls & XkbStickyKeysMask) &&
969                !(ctrl->enabled_ctrls & XkbStickyKeysMask))
970                XkbClearAllLatchesAndLocks(tmpd, xkbi, TRUE, &cause);
971        }
972    }
973
974    return Success;
975}
976
977/***====================================================================***/
978
979static int
980XkbSizeKeyTypes(XkbDescPtr xkb, xkbGetMapReply * rep)
981{
982    XkbKeyTypeRec *type;
983    unsigned i, len;
984
985    len = 0;
986    if (((rep->present & XkbKeyTypesMask) == 0) || (rep->nTypes < 1) ||
987        (!xkb) || (!xkb->map) || (!xkb->map->types)) {
988        rep->present &= ~XkbKeyTypesMask;
989        rep->firstType = rep->nTypes = 0;
990        return 0;
991    }
992    type = &xkb->map->types[rep->firstType];
993    for (i = 0; i < rep->nTypes; i++, type++) {
994        len += SIZEOF(xkbKeyTypeWireDesc);
995        if (type->map_count > 0) {
996            len += (type->map_count * SIZEOF(xkbKTMapEntryWireDesc));
997            if (type->preserve)
998                len += (type->map_count * SIZEOF(xkbModsWireDesc));
999        }
1000    }
1001    return len;
1002}
1003
1004static char *
1005XkbWriteKeyTypes(XkbDescPtr xkb,
1006                 xkbGetMapReply * rep, char *buf, ClientPtr client)
1007{
1008    XkbKeyTypePtr type;
1009    unsigned i;
1010    xkbKeyTypeWireDesc *wire;
1011
1012    type = &xkb->map->types[rep->firstType];
1013    for (i = 0; i < rep->nTypes; i++, type++) {
1014        register unsigned n;
1015
1016        wire = (xkbKeyTypeWireDesc *) buf;
1017        wire->mask = type->mods.mask;
1018        wire->realMods = type->mods.real_mods;
1019        wire->virtualMods = type->mods.vmods;
1020        wire->numLevels = type->num_levels;
1021        wire->nMapEntries = type->map_count;
1022        wire->preserve = (type->preserve != NULL);
1023        if (client->swapped) {
1024            swaps(&wire->virtualMods);
1025        }
1026
1027        buf = (char *) &wire[1];
1028        if (wire->nMapEntries > 0) {
1029            xkbKTMapEntryWireDesc *ewire;
1030            XkbKTMapEntryPtr entry;
1031
1032            ewire = (xkbKTMapEntryWireDesc *) buf;
1033            entry = type->map;
1034            for (n = 0; n < type->map_count; n++, ewire++, entry++) {
1035                ewire->active = entry->active;
1036                ewire->mask = entry->mods.mask;
1037                ewire->level = entry->level;
1038                ewire->realMods = entry->mods.real_mods;
1039                ewire->virtualMods = entry->mods.vmods;
1040                if (client->swapped) {
1041                    swaps(&ewire->virtualMods);
1042                }
1043            }
1044            buf = (char *) ewire;
1045            if (type->preserve != NULL) {
1046                xkbModsWireDesc *pwire;
1047                XkbModsPtr preserve;
1048
1049                pwire = (xkbModsWireDesc *) buf;
1050                preserve = type->preserve;
1051                for (n = 0; n < type->map_count; n++, pwire++, preserve++) {
1052                    pwire->mask = preserve->mask;
1053                    pwire->realMods = preserve->real_mods;
1054                    pwire->virtualMods = preserve->vmods;
1055                    if (client->swapped) {
1056                        swaps(&pwire->virtualMods);
1057                    }
1058                }
1059                buf = (char *) pwire;
1060            }
1061        }
1062    }
1063    return buf;
1064}
1065
1066static int
1067XkbSizeKeySyms(XkbDescPtr xkb, xkbGetMapReply * rep)
1068{
1069    XkbSymMapPtr symMap;
1070    unsigned i, len;
1071    unsigned nSyms, nSymsThisKey;
1072
1073    if (((rep->present & XkbKeySymsMask) == 0) || (rep->nKeySyms < 1) ||
1074        (!xkb) || (!xkb->map) || (!xkb->map->key_sym_map)) {
1075        rep->present &= ~XkbKeySymsMask;
1076        rep->firstKeySym = rep->nKeySyms = 0;
1077        rep->totalSyms = 0;
1078        return 0;
1079    }
1080    len = rep->nKeySyms * SIZEOF(xkbSymMapWireDesc);
1081    symMap = &xkb->map->key_sym_map[rep->firstKeySym];
1082    for (i = nSyms = 0; i < rep->nKeySyms; i++, symMap++) {
1083        if (symMap->offset != 0) {
1084            nSymsThisKey = XkbNumGroups(symMap->group_info) * symMap->width;
1085            nSyms += nSymsThisKey;
1086        }
1087    }
1088    len += nSyms * 4;
1089    rep->totalSyms = nSyms;
1090    return len;
1091}
1092
1093static int
1094XkbSizeVirtualMods(XkbDescPtr xkb, xkbGetMapReply * rep)
1095{
1096    register unsigned i, nMods, bit;
1097
1098    if (((rep->present & XkbVirtualModsMask) == 0) || (rep->virtualMods == 0) ||
1099        (!xkb) || (!xkb->server)) {
1100        rep->present &= ~XkbVirtualModsMask;
1101        rep->virtualMods = 0;
1102        return 0;
1103    }
1104    for (i = nMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
1105        if (rep->virtualMods & bit)
1106            nMods++;
1107    }
1108    return XkbPaddedSize(nMods);
1109}
1110
1111static char *
1112XkbWriteKeySyms(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1113                ClientPtr client)
1114{
1115    register KeySym *pSym;
1116    XkbSymMapPtr symMap;
1117    xkbSymMapWireDesc *outMap;
1118    register unsigned i;
1119
1120    symMap = &xkb->map->key_sym_map[rep->firstKeySym];
1121    for (i = 0; i < rep->nKeySyms; i++, symMap++) {
1122        outMap = (xkbSymMapWireDesc *) buf;
1123        outMap->ktIndex[0] = symMap->kt_index[0];
1124        outMap->ktIndex[1] = symMap->kt_index[1];
1125        outMap->ktIndex[2] = symMap->kt_index[2];
1126        outMap->ktIndex[3] = symMap->kt_index[3];
1127        outMap->groupInfo = symMap->group_info;
1128        outMap->width = symMap->width;
1129        outMap->nSyms = symMap->width * XkbNumGroups(symMap->group_info);
1130        buf = (char *) &outMap[1];
1131        if (outMap->nSyms == 0)
1132            continue;
1133
1134        pSym = &xkb->map->syms[symMap->offset];
1135        memcpy((char *) buf, (char *) pSym, outMap->nSyms * 4);
1136        if (client->swapped) {
1137            register int nSyms = outMap->nSyms;
1138
1139            swaps(&outMap->nSyms);
1140            while (nSyms-- > 0) {
1141                swapl((int *) buf);
1142                buf += 4;
1143            }
1144        }
1145        else
1146            buf += outMap->nSyms * 4;
1147    }
1148    return buf;
1149}
1150
1151static int
1152XkbSizeKeyActions(XkbDescPtr xkb, xkbGetMapReply * rep)
1153{
1154    unsigned i, len, nActs;
1155    register KeyCode firstKey;
1156
1157    if (((rep->present & XkbKeyActionsMask) == 0) || (rep->nKeyActs < 1) ||
1158        (!xkb) || (!xkb->server) || (!xkb->server->key_acts)) {
1159        rep->present &= ~XkbKeyActionsMask;
1160        rep->firstKeyAct = rep->nKeyActs = 0;
1161        rep->totalActs = 0;
1162        return 0;
1163    }
1164    firstKey = rep->firstKeyAct;
1165    for (nActs = i = 0; i < rep->nKeyActs; i++) {
1166        if (xkb->server->key_acts[i + firstKey] != 0)
1167            nActs += XkbKeyNumActions(xkb, i + firstKey);
1168    }
1169    len = XkbPaddedSize(rep->nKeyActs) + (nActs * SIZEOF(xkbActionWireDesc));
1170    rep->totalActs = nActs;
1171    return len;
1172}
1173
1174static char *
1175XkbWriteKeyActions(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1176                   ClientPtr client)
1177{
1178    unsigned i;
1179    CARD8 *numDesc;
1180    XkbAnyAction *actDesc;
1181
1182    numDesc = (CARD8 *) buf;
1183    for (i = 0; i < rep->nKeyActs; i++) {
1184        if (xkb->server->key_acts[i + rep->firstKeyAct] == 0)
1185            numDesc[i] = 0;
1186        else
1187            numDesc[i] = XkbKeyNumActions(xkb, (i + rep->firstKeyAct));
1188    }
1189    buf += XkbPaddedSize(rep->nKeyActs);
1190
1191    actDesc = (XkbAnyAction *) buf;
1192    for (i = 0; i < rep->nKeyActs; i++) {
1193        if (xkb->server->key_acts[i + rep->firstKeyAct] != 0) {
1194            unsigned int num;
1195
1196            num = XkbKeyNumActions(xkb, (i + rep->firstKeyAct));
1197            memcpy((char *) actDesc,
1198                   (char *) XkbKeyActionsPtr(xkb, (i + rep->firstKeyAct)),
1199                   num * SIZEOF(xkbActionWireDesc));
1200            actDesc += num;
1201        }
1202    }
1203    buf = (char *) actDesc;
1204    return buf;
1205}
1206
1207static int
1208XkbSizeKeyBehaviors(XkbDescPtr xkb, xkbGetMapReply * rep)
1209{
1210    unsigned i, len, nBhvr;
1211    XkbBehavior *bhv;
1212
1213    if (((rep->present & XkbKeyBehaviorsMask) == 0) || (rep->nKeyBehaviors < 1)
1214        || (!xkb) || (!xkb->server) || (!xkb->server->behaviors)) {
1215        rep->present &= ~XkbKeyBehaviorsMask;
1216        rep->firstKeyBehavior = rep->nKeyBehaviors = 0;
1217        rep->totalKeyBehaviors = 0;
1218        return 0;
1219    }
1220    bhv = &xkb->server->behaviors[rep->firstKeyBehavior];
1221    for (nBhvr = i = 0; i < rep->nKeyBehaviors; i++, bhv++) {
1222        if (bhv->type != XkbKB_Default)
1223            nBhvr++;
1224    }
1225    len = nBhvr * SIZEOF(xkbBehaviorWireDesc);
1226    rep->totalKeyBehaviors = nBhvr;
1227    return len;
1228}
1229
1230static char *
1231XkbWriteKeyBehaviors(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1232                     ClientPtr client)
1233{
1234    unsigned i;
1235    xkbBehaviorWireDesc *wire;
1236    XkbBehavior *pBhvr;
1237
1238    wire = (xkbBehaviorWireDesc *) buf;
1239    pBhvr = &xkb->server->behaviors[rep->firstKeyBehavior];
1240    for (i = 0; i < rep->nKeyBehaviors; i++, pBhvr++) {
1241        if (pBhvr->type != XkbKB_Default) {
1242            wire->key = i + rep->firstKeyBehavior;
1243            wire->type = pBhvr->type;
1244            wire->data = pBhvr->data;
1245            wire++;
1246        }
1247    }
1248    buf = (char *) wire;
1249    return buf;
1250}
1251
1252static int
1253XkbSizeExplicit(XkbDescPtr xkb, xkbGetMapReply * rep)
1254{
1255    unsigned i, len, nRtrn;
1256
1257    if (((rep->present & XkbExplicitComponentsMask) == 0) ||
1258        (rep->nKeyExplicit < 1) || (!xkb) || (!xkb->server) ||
1259        (!xkb->server->explicit)) {
1260        rep->present &= ~XkbExplicitComponentsMask;
1261        rep->firstKeyExplicit = rep->nKeyExplicit = 0;
1262        rep->totalKeyExplicit = 0;
1263        return 0;
1264    }
1265    for (nRtrn = i = 0; i < rep->nKeyExplicit; i++) {
1266        if (xkb->server->explicit[i + rep->firstKeyExplicit] != 0)
1267            nRtrn++;
1268    }
1269    rep->totalKeyExplicit = nRtrn;
1270    len = XkbPaddedSize(nRtrn * 2);     /* two bytes per non-zero explicit component */
1271    return len;
1272}
1273
1274static char *
1275XkbWriteExplicit(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1276                 ClientPtr client)
1277{
1278    unsigned i;
1279    char *start;
1280    unsigned char *pExp;
1281
1282    start = buf;
1283    pExp = &xkb->server->explicit[rep->firstKeyExplicit];
1284    for (i = 0; i < rep->nKeyExplicit; i++, pExp++) {
1285        if (*pExp != 0) {
1286            *buf++ = i + rep->firstKeyExplicit;
1287            *buf++ = *pExp;
1288        }
1289    }
1290    i = XkbPaddedSize(buf - start) - (buf - start);     /* pad to word boundary */
1291    return buf + i;
1292}
1293
1294static int
1295XkbSizeModifierMap(XkbDescPtr xkb, xkbGetMapReply * rep)
1296{
1297    unsigned i, len, nRtrn;
1298
1299    if (((rep->present & XkbModifierMapMask) == 0) || (rep->nModMapKeys < 1) ||
1300        (!xkb) || (!xkb->map) || (!xkb->map->modmap)) {
1301        rep->present &= ~XkbModifierMapMask;
1302        rep->firstModMapKey = rep->nModMapKeys = 0;
1303        rep->totalModMapKeys = 0;
1304        return 0;
1305    }
1306    for (nRtrn = i = 0; i < rep->nModMapKeys; i++) {
1307        if (xkb->map->modmap[i + rep->firstModMapKey] != 0)
1308            nRtrn++;
1309    }
1310    rep->totalModMapKeys = nRtrn;
1311    len = XkbPaddedSize(nRtrn * 2);     /* two bytes per non-zero modmap component */
1312    return len;
1313}
1314
1315static char *
1316XkbWriteModifierMap(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1317                    ClientPtr client)
1318{
1319    unsigned i;
1320    char *start;
1321    unsigned char *pMap;
1322
1323    start = buf;
1324    pMap = &xkb->map->modmap[rep->firstModMapKey];
1325    for (i = 0; i < rep->nModMapKeys; i++, pMap++) {
1326        if (*pMap != 0) {
1327            *buf++ = i + rep->firstModMapKey;
1328            *buf++ = *pMap;
1329        }
1330    }
1331    i = XkbPaddedSize(buf - start) - (buf - start);     /* pad to word boundary */
1332    return buf + i;
1333}
1334
1335static int
1336XkbSizeVirtualModMap(XkbDescPtr xkb, xkbGetMapReply * rep)
1337{
1338    unsigned i, len, nRtrn;
1339
1340    if (((rep->present & XkbVirtualModMapMask) == 0) || (rep->nVModMapKeys < 1)
1341        || (!xkb) || (!xkb->server) || (!xkb->server->vmodmap)) {
1342        rep->present &= ~XkbVirtualModMapMask;
1343        rep->firstVModMapKey = rep->nVModMapKeys = 0;
1344        rep->totalVModMapKeys = 0;
1345        return 0;
1346    }
1347    for (nRtrn = i = 0; i < rep->nVModMapKeys; i++) {
1348        if (xkb->server->vmodmap[i + rep->firstVModMapKey] != 0)
1349            nRtrn++;
1350    }
1351    rep->totalVModMapKeys = nRtrn;
1352    len = nRtrn * SIZEOF(xkbVModMapWireDesc);
1353    return len;
1354}
1355
1356static char *
1357XkbWriteVirtualModMap(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1358                      ClientPtr client)
1359{
1360    unsigned i;
1361    xkbVModMapWireDesc *wire;
1362    unsigned short *pMap;
1363
1364    wire = (xkbVModMapWireDesc *) buf;
1365    pMap = &xkb->server->vmodmap[rep->firstVModMapKey];
1366    for (i = 0; i < rep->nVModMapKeys; i++, pMap++) {
1367        if (*pMap != 0) {
1368            wire->key = i + rep->firstVModMapKey;
1369            wire->vmods = *pMap;
1370            wire++;
1371        }
1372    }
1373    return (char *) wire;
1374}
1375
1376static Status
1377XkbComputeGetMapReplySize(XkbDescPtr xkb, xkbGetMapReply * rep)
1378{
1379    int len;
1380
1381    rep->minKeyCode = xkb->min_key_code;
1382    rep->maxKeyCode = xkb->max_key_code;
1383    len = XkbSizeKeyTypes(xkb, rep);
1384    len += XkbSizeKeySyms(xkb, rep);
1385    len += XkbSizeKeyActions(xkb, rep);
1386    len += XkbSizeKeyBehaviors(xkb, rep);
1387    len += XkbSizeVirtualMods(xkb, rep);
1388    len += XkbSizeExplicit(xkb, rep);
1389    len += XkbSizeModifierMap(xkb, rep);
1390    len += XkbSizeVirtualModMap(xkb, rep);
1391    rep->length += (len / 4);
1392    return Success;
1393}
1394
1395static int
1396XkbSendMap(ClientPtr client, XkbDescPtr xkb, xkbGetMapReply * rep)
1397{
1398    unsigned i, len;
1399    char *desc, *start;
1400
1401    len = (rep->length * 4) - (SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply));
1402    start = desc = calloc(1, len);
1403    if (!start)
1404        return BadAlloc;
1405    if (rep->nTypes > 0)
1406        desc = XkbWriteKeyTypes(xkb, rep, desc, client);
1407    if (rep->nKeySyms > 0)
1408        desc = XkbWriteKeySyms(xkb, rep, desc, client);
1409    if (rep->nKeyActs > 0)
1410        desc = XkbWriteKeyActions(xkb, rep, desc, client);
1411    if (rep->totalKeyBehaviors > 0)
1412        desc = XkbWriteKeyBehaviors(xkb, rep, desc, client);
1413    if (rep->virtualMods) {
1414        register int sz, bit;
1415
1416        for (i = sz = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
1417            if (rep->virtualMods & bit) {
1418                desc[sz++] = xkb->server->vmods[i];
1419            }
1420        }
1421        desc += XkbPaddedSize(sz);
1422    }
1423    if (rep->totalKeyExplicit > 0)
1424        desc = XkbWriteExplicit(xkb, rep, desc, client);
1425    if (rep->totalModMapKeys > 0)
1426        desc = XkbWriteModifierMap(xkb, rep, desc, client);
1427    if (rep->totalVModMapKeys > 0)
1428        desc = XkbWriteVirtualModMap(xkb, rep, desc, client);
1429    if ((desc - start) != (len)) {
1430        ErrorF
1431            ("[xkb] BOGUS LENGTH in write keyboard desc, expected %d, got %ld\n",
1432             len, (unsigned long) (desc - start));
1433    }
1434    if (client->swapped) {
1435        swaps(&rep->sequenceNumber);
1436        swapl(&rep->length);
1437        swaps(&rep->present);
1438        swaps(&rep->totalSyms);
1439        swaps(&rep->totalActs);
1440    }
1441    WriteToClient(client, (i = SIZEOF(xkbGetMapReply)), rep);
1442    WriteToClient(client, len, start);
1443    free((char *) start);
1444    return Success;
1445}
1446
1447int
1448ProcXkbGetMap(ClientPtr client)
1449{
1450    DeviceIntPtr dev;
1451    xkbGetMapReply rep;
1452    XkbDescRec *xkb;
1453    int n, status;
1454
1455    REQUEST(xkbGetMapReq);
1456    REQUEST_SIZE_MATCH(xkbGetMapReq);
1457
1458    if (!(client->xkbClientFlags & _XkbClientInitialized))
1459        return BadAccess;
1460
1461    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
1462    CHK_MASK_OVERLAP(0x01, stuff->full, stuff->partial);
1463    CHK_MASK_LEGAL(0x02, stuff->full, XkbAllMapComponentsMask);
1464    CHK_MASK_LEGAL(0x03, stuff->partial, XkbAllMapComponentsMask);
1465
1466    xkb = dev->key->xkbInfo->desc;
1467    rep = (xkbGetMapReply) {
1468        .type = X_Reply,
1469        .deviceID = dev->id,
1470        .sequenceNumber = client->sequence,
1471        .length = (SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply)) >> 2,
1472        .present = stuff->partial | stuff->full,
1473        .minKeyCode = xkb->min_key_code,
1474        .maxKeyCode = xkb->max_key_code
1475    };
1476
1477    if (stuff->full & XkbKeyTypesMask) {
1478        rep.firstType = 0;
1479        rep.nTypes = xkb->map->num_types;
1480    }
1481    else if (stuff->partial & XkbKeyTypesMask) {
1482        if (((unsigned) stuff->firstType + stuff->nTypes) > xkb->map->num_types) {
1483            client->errorValue = _XkbErrCode4(0x04, xkb->map->num_types,
1484                                              stuff->firstType, stuff->nTypes);
1485            return BadValue;
1486        }
1487        rep.firstType = stuff->firstType;
1488        rep.nTypes = stuff->nTypes;
1489    }
1490    else
1491        rep.nTypes = 0;
1492    rep.totalTypes = xkb->map->num_types;
1493
1494    n = XkbNumKeys(xkb);
1495    if (stuff->full & XkbKeySymsMask) {
1496        rep.firstKeySym = xkb->min_key_code;
1497        rep.nKeySyms = n;
1498    }
1499    else if (stuff->partial & XkbKeySymsMask) {
1500        CHK_KEY_RANGE(0x05, stuff->firstKeySym, stuff->nKeySyms, xkb);
1501        rep.firstKeySym = stuff->firstKeySym;
1502        rep.nKeySyms = stuff->nKeySyms;
1503    }
1504    else
1505        rep.nKeySyms = 0;
1506    rep.totalSyms = 0;
1507
1508    if (stuff->full & XkbKeyActionsMask) {
1509        rep.firstKeyAct = xkb->min_key_code;
1510        rep.nKeyActs = n;
1511    }
1512    else if (stuff->partial & XkbKeyActionsMask) {
1513        CHK_KEY_RANGE(0x07, stuff->firstKeyAct, stuff->nKeyActs, xkb);
1514        rep.firstKeyAct = stuff->firstKeyAct;
1515        rep.nKeyActs = stuff->nKeyActs;
1516    }
1517    else
1518        rep.nKeyActs = 0;
1519    rep.totalActs = 0;
1520
1521    if (stuff->full & XkbKeyBehaviorsMask) {
1522        rep.firstKeyBehavior = xkb->min_key_code;
1523        rep.nKeyBehaviors = n;
1524    }
1525    else if (stuff->partial & XkbKeyBehaviorsMask) {
1526        CHK_KEY_RANGE(0x09, stuff->firstKeyBehavior, stuff->nKeyBehaviors, xkb);
1527        rep.firstKeyBehavior = stuff->firstKeyBehavior;
1528        rep.nKeyBehaviors = stuff->nKeyBehaviors;
1529    }
1530    else
1531        rep.nKeyBehaviors = 0;
1532    rep.totalKeyBehaviors = 0;
1533
1534    if (stuff->full & XkbVirtualModsMask)
1535        rep.virtualMods = ~0;
1536    else if (stuff->partial & XkbVirtualModsMask)
1537        rep.virtualMods = stuff->virtualMods;
1538
1539    if (stuff->full & XkbExplicitComponentsMask) {
1540        rep.firstKeyExplicit = xkb->min_key_code;
1541        rep.nKeyExplicit = n;
1542    }
1543    else if (stuff->partial & XkbExplicitComponentsMask) {
1544        CHK_KEY_RANGE(0x0B, stuff->firstKeyExplicit, stuff->nKeyExplicit, xkb);
1545        rep.firstKeyExplicit = stuff->firstKeyExplicit;
1546        rep.nKeyExplicit = stuff->nKeyExplicit;
1547    }
1548    else
1549        rep.nKeyExplicit = 0;
1550    rep.totalKeyExplicit = 0;
1551
1552    if (stuff->full & XkbModifierMapMask) {
1553        rep.firstModMapKey = xkb->min_key_code;
1554        rep.nModMapKeys = n;
1555    }
1556    else if (stuff->partial & XkbModifierMapMask) {
1557        CHK_KEY_RANGE(0x0D, stuff->firstModMapKey, stuff->nModMapKeys, xkb);
1558        rep.firstModMapKey = stuff->firstModMapKey;
1559        rep.nModMapKeys = stuff->nModMapKeys;
1560    }
1561    else
1562        rep.nModMapKeys = 0;
1563    rep.totalModMapKeys = 0;
1564
1565    if (stuff->full & XkbVirtualModMapMask) {
1566        rep.firstVModMapKey = xkb->min_key_code;
1567        rep.nVModMapKeys = n;
1568    }
1569    else if (stuff->partial & XkbVirtualModMapMask) {
1570        CHK_KEY_RANGE(0x0F, stuff->firstVModMapKey, stuff->nVModMapKeys, xkb);
1571        rep.firstVModMapKey = stuff->firstVModMapKey;
1572        rep.nVModMapKeys = stuff->nVModMapKeys;
1573    }
1574    else
1575        rep.nVModMapKeys = 0;
1576    rep.totalVModMapKeys = 0;
1577
1578    if ((status = XkbComputeGetMapReplySize(xkb, &rep)) != Success)
1579        return status;
1580    return XkbSendMap(client, xkb, &rep);
1581}
1582
1583/***====================================================================***/
1584
1585static int
1586CheckKeyTypes(ClientPtr client,
1587              XkbDescPtr xkb,
1588              xkbSetMapReq * req,
1589              xkbKeyTypeWireDesc ** wireRtrn,
1590              int *nMapsRtrn, CARD8 *mapWidthRtrn)
1591{
1592    unsigned nMaps;
1593    register unsigned i, n;
1594    register CARD8 *map;
1595    register xkbKeyTypeWireDesc *wire = *wireRtrn;
1596
1597    if (req->firstType > ((unsigned) xkb->map->num_types)) {
1598        *nMapsRtrn = _XkbErrCode3(0x01, req->firstType, xkb->map->num_types);
1599        return 0;
1600    }
1601    if (req->flags & XkbSetMapResizeTypes) {
1602        nMaps = req->firstType + req->nTypes;
1603        if (nMaps < XkbNumRequiredTypes) {      /* canonical types must be there */
1604            *nMapsRtrn = _XkbErrCode4(0x02, req->firstType, req->nTypes, 4);
1605            return 0;
1606        }
1607    }
1608    else if (req->present & XkbKeyTypesMask) {
1609        nMaps = xkb->map->num_types;
1610        if ((req->firstType + req->nTypes) > nMaps) {
1611            *nMapsRtrn = req->firstType + req->nTypes;
1612            return 0;
1613        }
1614    }
1615    else {
1616        *nMapsRtrn = xkb->map->num_types;
1617        for (i = 0; i < xkb->map->num_types; i++) {
1618            mapWidthRtrn[i] = xkb->map->types[i].num_levels;
1619        }
1620        return 1;
1621    }
1622
1623    for (i = 0; i < req->firstType; i++) {
1624        mapWidthRtrn[i] = xkb->map->types[i].num_levels;
1625    }
1626    for (i = 0; i < req->nTypes; i++) {
1627        unsigned width;
1628
1629        if (client->swapped) {
1630            swaps(&wire->virtualMods);
1631        }
1632        n = i + req->firstType;
1633        width = wire->numLevels;
1634        if (width < 1) {
1635            *nMapsRtrn = _XkbErrCode3(0x04, n, width);
1636            return 0;
1637        }
1638        else if ((n == XkbOneLevelIndex) && (width != 1)) {     /* must be width 1 */
1639            *nMapsRtrn = _XkbErrCode3(0x05, n, width);
1640            return 0;
1641        }
1642        else if ((width != 2) &&
1643                 ((n == XkbTwoLevelIndex) || (n == XkbKeypadIndex) ||
1644                  (n == XkbAlphabeticIndex))) {
1645            /* TWO_LEVEL, ALPHABETIC and KEYPAD must be width 2 */
1646            *nMapsRtrn = _XkbErrCode3(0x05, n, width);
1647            return 0;
1648        }
1649        if (wire->nMapEntries > 0) {
1650            xkbKTSetMapEntryWireDesc *mapWire;
1651            xkbModsWireDesc *preWire;
1652
1653            mapWire = (xkbKTSetMapEntryWireDesc *) &wire[1];
1654            preWire = (xkbModsWireDesc *) &mapWire[wire->nMapEntries];
1655            for (n = 0; n < wire->nMapEntries; n++) {
1656                if (client->swapped) {
1657                    swaps(&mapWire[n].virtualMods);
1658                }
1659                if (mapWire[n].realMods & (~wire->realMods)) {
1660                    *nMapsRtrn = _XkbErrCode4(0x06, n, mapWire[n].realMods,
1661                                              wire->realMods);
1662                    return 0;
1663                }
1664                if (mapWire[n].virtualMods & (~wire->virtualMods)) {
1665                    *nMapsRtrn = _XkbErrCode3(0x07, n, mapWire[n].virtualMods);
1666                    return 0;
1667                }
1668                if (mapWire[n].level >= wire->numLevels) {
1669                    *nMapsRtrn = _XkbErrCode4(0x08, n, wire->numLevels,
1670                                              mapWire[n].level);
1671                    return 0;
1672                }
1673                if (wire->preserve) {
1674                    if (client->swapped) {
1675                        swaps(&preWire[n].virtualMods);
1676                    }
1677                    if (preWire[n].realMods & (~mapWire[n].realMods)) {
1678                        *nMapsRtrn = _XkbErrCode4(0x09, n, preWire[n].realMods,
1679                                                  mapWire[n].realMods);
1680                        return 0;
1681                    }
1682                    if (preWire[n].virtualMods & (~mapWire[n].virtualMods)) {
1683                        *nMapsRtrn =
1684                            _XkbErrCode3(0x0a, n, preWire[n].virtualMods);
1685                        return 0;
1686                    }
1687                }
1688            }
1689            if (wire->preserve)
1690                map = (CARD8 *) &preWire[wire->nMapEntries];
1691            else
1692                map = (CARD8 *) &mapWire[wire->nMapEntries];
1693        }
1694        else
1695            map = (CARD8 *) &wire[1];
1696        mapWidthRtrn[i + req->firstType] = wire->numLevels;
1697        wire = (xkbKeyTypeWireDesc *) map;
1698    }
1699    for (i = req->firstType + req->nTypes; i < nMaps; i++) {
1700        mapWidthRtrn[i] = xkb->map->types[i].num_levels;
1701    }
1702    *nMapsRtrn = nMaps;
1703    *wireRtrn = wire;
1704    return 1;
1705}
1706
1707static int
1708CheckKeySyms(ClientPtr client,
1709             XkbDescPtr xkb,
1710             xkbSetMapReq * req,
1711             int nTypes,
1712             CARD8 *mapWidths,
1713             CARD16 *symsPerKey, xkbSymMapWireDesc ** wireRtrn, int *errorRtrn)
1714{
1715    register unsigned i;
1716    XkbSymMapPtr map;
1717    xkbSymMapWireDesc *wire = *wireRtrn;
1718
1719    if (!(XkbKeySymsMask & req->present))
1720        return 1;
1721    CHK_REQ_KEY_RANGE2(0x11, req->firstKeySym, req->nKeySyms, req, (*errorRtrn),
1722                       0);
1723    for (i = 0; i < req->nKeySyms; i++) {
1724        KeySym *pSyms;
1725        register unsigned nG;
1726
1727        if (client->swapped) {
1728            swaps(&wire->nSyms);
1729        }
1730        nG = XkbNumGroups(wire->groupInfo);
1731        if (nG > XkbNumKbdGroups) {
1732            *errorRtrn = _XkbErrCode3(0x14, i + req->firstKeySym, nG);
1733            return 0;
1734        }
1735        if (nG > 0) {
1736            register int g, w;
1737
1738            for (g = w = 0; g < nG; g++) {
1739                if (wire->ktIndex[g] >= (unsigned) nTypes) {
1740                    *errorRtrn = _XkbErrCode4(0x15, i + req->firstKeySym, g,
1741                                              wire->ktIndex[g]);
1742                    return 0;
1743                }
1744                if (mapWidths[wire->ktIndex[g]] > w)
1745                    w = mapWidths[wire->ktIndex[g]];
1746            }
1747            if (wire->width != w) {
1748                *errorRtrn =
1749                    _XkbErrCode3(0x16, i + req->firstKeySym, wire->width);
1750                return 0;
1751            }
1752            w *= nG;
1753            symsPerKey[i + req->firstKeySym] = w;
1754            if (w != wire->nSyms) {
1755                *errorRtrn =
1756                    _XkbErrCode4(0x16, i + req->firstKeySym, wire->nSyms, w);
1757                return 0;
1758            }
1759        }
1760        else if (wire->nSyms != 0) {
1761            *errorRtrn = _XkbErrCode3(0x17, i + req->firstKeySym, wire->nSyms);
1762            return 0;
1763        }
1764        pSyms = (KeySym *) &wire[1];
1765        wire = (xkbSymMapWireDesc *) &pSyms[wire->nSyms];
1766    }
1767
1768    map = &xkb->map->key_sym_map[i];
1769    for (; i <= (unsigned) xkb->max_key_code; i++, map++) {
1770        register int g, nG, w;
1771
1772        nG = XkbKeyNumGroups(xkb, i);
1773        for (w = g = 0; g < nG; g++) {
1774            if (map->kt_index[g] >= (unsigned) nTypes) {
1775                *errorRtrn = _XkbErrCode4(0x18, i, g, map->kt_index[g]);
1776                return 0;
1777            }
1778            if (mapWidths[map->kt_index[g]] > w)
1779                w = mapWidths[map->kt_index[g]];
1780        }
1781        symsPerKey[i] = w * nG;
1782    }
1783    *wireRtrn = wire;
1784    return 1;
1785}
1786
1787static int
1788CheckKeyActions(XkbDescPtr xkb,
1789                xkbSetMapReq * req,
1790                int nTypes,
1791                CARD8 *mapWidths,
1792                CARD16 *symsPerKey, CARD8 **wireRtrn, int *nActsRtrn)
1793{
1794    int nActs;
1795    CARD8 *wire = *wireRtrn;
1796    register unsigned i;
1797
1798    if (!(XkbKeyActionsMask & req->present))
1799        return 1;
1800    CHK_REQ_KEY_RANGE2(0x21, req->firstKeyAct, req->nKeyActs, req, (*nActsRtrn),
1801                       0);
1802    for (nActs = i = 0; i < req->nKeyActs; i++) {
1803        if (wire[0] != 0) {
1804            if (wire[0] == symsPerKey[i + req->firstKeyAct])
1805                nActs += wire[0];
1806            else {
1807                *nActsRtrn = _XkbErrCode3(0x23, i + req->firstKeyAct, wire[0]);
1808                return 0;
1809            }
1810        }
1811        wire++;
1812    }
1813    if (req->nKeyActs % 4)
1814        wire += 4 - (req->nKeyActs % 4);
1815    *wireRtrn = (CARD8 *) (((XkbAnyAction *) wire) + nActs);
1816    *nActsRtrn = nActs;
1817    return 1;
1818}
1819
1820static int
1821CheckKeyBehaviors(XkbDescPtr xkb,
1822                  xkbSetMapReq * req,
1823                  xkbBehaviorWireDesc ** wireRtrn, int *errorRtrn)
1824{
1825    register xkbBehaviorWireDesc *wire = *wireRtrn;
1826    register XkbServerMapPtr server = xkb->server;
1827    register unsigned i;
1828    unsigned first, last;
1829
1830    if (((req->present & XkbKeyBehaviorsMask) == 0) || (req->nKeyBehaviors < 1)) {
1831        req->present &= ~XkbKeyBehaviorsMask;
1832        req->nKeyBehaviors = 0;
1833        return 1;
1834    }
1835    first = req->firstKeyBehavior;
1836    last = req->firstKeyBehavior + req->nKeyBehaviors - 1;
1837    if (first < req->minKeyCode) {
1838        *errorRtrn = _XkbErrCode3(0x31, first, req->minKeyCode);
1839        return 0;
1840    }
1841    if (last > req->maxKeyCode) {
1842        *errorRtrn = _XkbErrCode3(0x32, last, req->maxKeyCode);
1843        return 0;
1844    }
1845
1846    for (i = 0; i < req->totalKeyBehaviors; i++, wire++) {
1847        if ((wire->key < first) || (wire->key > last)) {
1848            *errorRtrn = _XkbErrCode4(0x33, first, last, wire->key);
1849            return 0;
1850        }
1851        if ((wire->type & XkbKB_Permanent) &&
1852            ((server->behaviors[wire->key].type != wire->type) ||
1853             (server->behaviors[wire->key].data != wire->data))) {
1854            *errorRtrn = _XkbErrCode3(0x33, wire->key, wire->type);
1855            return 0;
1856        }
1857        if ((wire->type == XkbKB_RadioGroup) &&
1858            ((wire->data & (~XkbKB_RGAllowNone)) > XkbMaxRadioGroups)) {
1859            *errorRtrn = _XkbErrCode4(0x34, wire->key, wire->data,
1860                                      XkbMaxRadioGroups);
1861            return 0;
1862        }
1863        if ((wire->type == XkbKB_Overlay1) || (wire->type == XkbKB_Overlay2)) {
1864            CHK_KEY_RANGE2(0x35, wire->key, 1, xkb, *errorRtrn, 0);
1865        }
1866    }
1867    *wireRtrn = wire;
1868    return 1;
1869}
1870
1871static int
1872CheckVirtualMods(XkbDescRec * xkb,
1873                 xkbSetMapReq * req, CARD8 **wireRtrn, int *errorRtrn)
1874{
1875    register CARD8 *wire = *wireRtrn;
1876    register unsigned i, nMods, bit;
1877
1878    if (((req->present & XkbVirtualModsMask) == 0) || (req->virtualMods == 0))
1879        return 1;
1880    for (i = nMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
1881        if (req->virtualMods & bit)
1882            nMods++;
1883    }
1884    *wireRtrn = (wire + XkbPaddedSize(nMods));
1885    return 1;
1886}
1887
1888static int
1889CheckKeyExplicit(XkbDescPtr xkb,
1890                 xkbSetMapReq * req, CARD8 **wireRtrn, int *errorRtrn)
1891{
1892    register CARD8 *wire = *wireRtrn;
1893    CARD8 *start;
1894    register unsigned i;
1895    int first, last;
1896
1897    if (((req->present & XkbExplicitComponentsMask) == 0) ||
1898        (req->nKeyExplicit < 1)) {
1899        req->present &= ~XkbExplicitComponentsMask;
1900        req->nKeyExplicit = 0;
1901        return 1;
1902    }
1903    first = req->firstKeyExplicit;
1904    last = first + req->nKeyExplicit - 1;
1905    if (first < req->minKeyCode) {
1906        *errorRtrn = _XkbErrCode3(0x51, first, req->minKeyCode);
1907        return 0;
1908    }
1909    if (last > req->maxKeyCode) {
1910        *errorRtrn = _XkbErrCode3(0x52, last, req->maxKeyCode);
1911        return 0;
1912    }
1913    start = wire;
1914    for (i = 0; i < req->totalKeyExplicit; i++, wire += 2) {
1915        if ((wire[0] < first) || (wire[0] > last)) {
1916            *errorRtrn = _XkbErrCode4(0x53, first, last, wire[0]);
1917            return 0;
1918        }
1919        if (wire[1] & (~XkbAllExplicitMask)) {
1920            *errorRtrn = _XkbErrCode3(0x52, ~XkbAllExplicitMask, wire[1]);
1921            return 0;
1922        }
1923    }
1924    wire += XkbPaddedSize(wire - start) - (wire - start);
1925    *wireRtrn = wire;
1926    return 1;
1927}
1928
1929static int
1930CheckModifierMap(XkbDescPtr xkb, xkbSetMapReq * req, CARD8 **wireRtrn,
1931                 int *errRtrn)
1932{
1933    register CARD8 *wire = *wireRtrn;
1934    CARD8 *start;
1935    register unsigned i;
1936    int first, last;
1937
1938    if (((req->present & XkbModifierMapMask) == 0) || (req->nModMapKeys < 1)) {
1939        req->present &= ~XkbModifierMapMask;
1940        req->nModMapKeys = 0;
1941        return 1;
1942    }
1943    first = req->firstModMapKey;
1944    last = first + req->nModMapKeys - 1;
1945    if (first < req->minKeyCode) {
1946        *errRtrn = _XkbErrCode3(0x61, first, req->minKeyCode);
1947        return 0;
1948    }
1949    if (last > req->maxKeyCode) {
1950        *errRtrn = _XkbErrCode3(0x62, last, req->maxKeyCode);
1951        return 0;
1952    }
1953    start = wire;
1954    for (i = 0; i < req->totalModMapKeys; i++, wire += 2) {
1955        if ((wire[0] < first) || (wire[0] > last)) {
1956            *errRtrn = _XkbErrCode4(0x63, first, last, wire[0]);
1957            return 0;
1958        }
1959    }
1960    wire += XkbPaddedSize(wire - start) - (wire - start);
1961    *wireRtrn = wire;
1962    return 1;
1963}
1964
1965static int
1966CheckVirtualModMap(XkbDescPtr xkb,
1967                   xkbSetMapReq * req,
1968                   xkbVModMapWireDesc ** wireRtrn, int *errRtrn)
1969{
1970    register xkbVModMapWireDesc *wire = *wireRtrn;
1971    register unsigned i;
1972    int first, last;
1973
1974    if (((req->present & XkbVirtualModMapMask) == 0) || (req->nVModMapKeys < 1)) {
1975        req->present &= ~XkbVirtualModMapMask;
1976        req->nVModMapKeys = 0;
1977        return 1;
1978    }
1979    first = req->firstVModMapKey;
1980    last = first + req->nVModMapKeys - 1;
1981    if (first < req->minKeyCode) {
1982        *errRtrn = _XkbErrCode3(0x71, first, req->minKeyCode);
1983        return 0;
1984    }
1985    if (last > req->maxKeyCode) {
1986        *errRtrn = _XkbErrCode3(0x72, last, req->maxKeyCode);
1987        return 0;
1988    }
1989    for (i = 0; i < req->totalVModMapKeys; i++, wire++) {
1990        if ((wire->key < first) || (wire->key > last)) {
1991            *errRtrn = _XkbErrCode4(0x73, first, last, wire->key);
1992            return 0;
1993        }
1994    }
1995    *wireRtrn = wire;
1996    return 1;
1997}
1998
1999static char *
2000SetKeyTypes(XkbDescPtr xkb,
2001            xkbSetMapReq * req,
2002            xkbKeyTypeWireDesc * wire, XkbChangesPtr changes)
2003{
2004    register unsigned i;
2005    unsigned first, last;
2006    CARD8 *map;
2007
2008    if ((unsigned) (req->firstType + req->nTypes) > xkb->map->size_types) {
2009        i = req->firstType + req->nTypes;
2010        if (XkbAllocClientMap(xkb, XkbKeyTypesMask, i) != Success) {
2011            return NULL;
2012        }
2013    }
2014    if ((unsigned) (req->firstType + req->nTypes) > xkb->map->num_types)
2015        xkb->map->num_types = req->firstType + req->nTypes;
2016
2017    for (i = 0; i < req->nTypes; i++) {
2018        XkbKeyTypePtr pOld;
2019        register unsigned n;
2020
2021        if (XkbResizeKeyType(xkb, i + req->firstType, wire->nMapEntries,
2022                             wire->preserve, wire->numLevels) != Success) {
2023            return NULL;
2024        }
2025        pOld = &xkb->map->types[i + req->firstType];
2026        map = (CARD8 *) &wire[1];
2027
2028        pOld->mods.real_mods = wire->realMods;
2029        pOld->mods.vmods = wire->virtualMods;
2030        pOld->num_levels = wire->numLevels;
2031        pOld->map_count = wire->nMapEntries;
2032
2033        pOld->mods.mask = pOld->mods.real_mods |
2034            XkbMaskForVMask(xkb, pOld->mods.vmods);
2035
2036        if (wire->nMapEntries) {
2037            xkbKTSetMapEntryWireDesc *mapWire;
2038            xkbModsWireDesc *preWire;
2039            unsigned tmp;
2040
2041            mapWire = (xkbKTSetMapEntryWireDesc *) map;
2042            preWire = (xkbModsWireDesc *) &mapWire[wire->nMapEntries];
2043            for (n = 0; n < wire->nMapEntries; n++) {
2044                pOld->map[n].active = 1;
2045                pOld->map[n].mods.mask = mapWire[n].realMods;
2046                pOld->map[n].mods.real_mods = mapWire[n].realMods;
2047                pOld->map[n].mods.vmods = mapWire[n].virtualMods;
2048                pOld->map[n].level = mapWire[n].level;
2049                if (mapWire[n].virtualMods != 0) {
2050                    tmp = XkbMaskForVMask(xkb, mapWire[n].virtualMods);
2051                    pOld->map[n].active = (tmp != 0);
2052                    pOld->map[n].mods.mask |= tmp;
2053                }
2054                if (wire->preserve) {
2055                    pOld->preserve[n].real_mods = preWire[n].realMods;
2056                    pOld->preserve[n].vmods = preWire[n].virtualMods;
2057                    tmp = XkbMaskForVMask(xkb, preWire[n].virtualMods);
2058                    pOld->preserve[n].mask = preWire[n].realMods | tmp;
2059                }
2060            }
2061            if (wire->preserve)
2062                map = (CARD8 *) &preWire[wire->nMapEntries];
2063            else
2064                map = (CARD8 *) &mapWire[wire->nMapEntries];
2065        }
2066        else
2067            map = (CARD8 *) &wire[1];
2068        wire = (xkbKeyTypeWireDesc *) map;
2069    }
2070    first = req->firstType;
2071    last = first + req->nTypes - 1;     /* last changed type */
2072    if (changes->map.changed & XkbKeyTypesMask) {
2073        int oldLast;
2074
2075        oldLast = changes->map.first_type + changes->map.num_types - 1;
2076        if (changes->map.first_type < first)
2077            first = changes->map.first_type;
2078        if (oldLast > last)
2079            last = oldLast;
2080    }
2081    changes->map.changed |= XkbKeyTypesMask;
2082    changes->map.first_type = first;
2083    changes->map.num_types = (last - first) + 1;
2084    return (char *) wire;
2085}
2086
2087static char *
2088SetKeySyms(ClientPtr client,
2089           XkbDescPtr xkb,
2090           xkbSetMapReq * req,
2091           xkbSymMapWireDesc * wire, XkbChangesPtr changes, DeviceIntPtr dev)
2092{
2093    register unsigned i, s;
2094    XkbSymMapPtr oldMap;
2095    KeySym *newSyms;
2096    KeySym *pSyms;
2097    unsigned first, last;
2098
2099    oldMap = &xkb->map->key_sym_map[req->firstKeySym];
2100    for (i = 0; i < req->nKeySyms; i++, oldMap++) {
2101        pSyms = (KeySym *) &wire[1];
2102        if (wire->nSyms > 0) {
2103            newSyms = XkbResizeKeySyms(xkb, i + req->firstKeySym, wire->nSyms);
2104            for (s = 0; s < wire->nSyms; s++) {
2105                newSyms[s] = pSyms[s];
2106            }
2107            if (client->swapped) {
2108                for (s = 0; s < wire->nSyms; s++) {
2109                    swapl(&newSyms[s]);
2110                }
2111            }
2112        }
2113        if (XkbKeyHasActions(xkb, i + req->firstKeySym))
2114            XkbResizeKeyActions(xkb, i + req->firstKeySym,
2115                                XkbNumGroups(wire->groupInfo) * wire->width);
2116        oldMap->kt_index[0] = wire->ktIndex[0];
2117        oldMap->kt_index[1] = wire->ktIndex[1];
2118        oldMap->kt_index[2] = wire->ktIndex[2];
2119        oldMap->kt_index[3] = wire->ktIndex[3];
2120        oldMap->group_info = wire->groupInfo;
2121        oldMap->width = wire->width;
2122        wire = (xkbSymMapWireDesc *) &pSyms[wire->nSyms];
2123    }
2124    first = req->firstKeySym;
2125    last = first + req->nKeySyms - 1;
2126    if (changes->map.changed & XkbKeySymsMask) {
2127        int oldLast =
2128            (changes->map.first_key_sym + changes->map.num_key_syms - 1);
2129        if (changes->map.first_key_sym < first)
2130            first = changes->map.first_key_sym;
2131        if (oldLast > last)
2132            last = oldLast;
2133    }
2134    changes->map.changed |= XkbKeySymsMask;
2135    changes->map.first_key_sym = first;
2136    changes->map.num_key_syms = (last - first + 1);
2137
2138    s = 0;
2139    for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
2140        if (XkbKeyNumGroups(xkb, i) > s)
2141            s = XkbKeyNumGroups(xkb, i);
2142    }
2143    if (s != xkb->ctrls->num_groups) {
2144        xkbControlsNotify cn;
2145        XkbControlsRec old;
2146
2147        cn.keycode = 0;
2148        cn.eventType = 0;
2149        cn.requestMajor = XkbReqCode;
2150        cn.requestMinor = X_kbSetMap;
2151        old = *xkb->ctrls;
2152        xkb->ctrls->num_groups = s;
2153        if (XkbComputeControlsNotify(dev, &old, xkb->ctrls, &cn, FALSE))
2154            XkbSendControlsNotify(dev, &cn);
2155    }
2156    return (char *) wire;
2157}
2158
2159static char *
2160SetKeyActions(XkbDescPtr xkb,
2161              xkbSetMapReq * req, CARD8 *wire, XkbChangesPtr changes)
2162{
2163    register unsigned i, first, last;
2164    CARD8 *nActs = wire;
2165    XkbAction *newActs;
2166
2167    wire += XkbPaddedSize(req->nKeyActs);
2168    for (i = 0; i < req->nKeyActs; i++) {
2169        if (nActs[i] == 0)
2170            xkb->server->key_acts[i + req->firstKeyAct] = 0;
2171        else {
2172            newActs = XkbResizeKeyActions(xkb, i + req->firstKeyAct, nActs[i]);
2173            memcpy((char *) newActs, (char *) wire,
2174                   nActs[i] * SIZEOF(xkbActionWireDesc));
2175            wire += nActs[i] * SIZEOF(xkbActionWireDesc);
2176        }
2177    }
2178    first = req->firstKeyAct;
2179    last = (first + req->nKeyActs - 1);
2180    if (changes->map.changed & XkbKeyActionsMask) {
2181        int oldLast;
2182
2183        oldLast = changes->map.first_key_act + changes->map.num_key_acts - 1;
2184        if (changes->map.first_key_act < first)
2185            first = changes->map.first_key_act;
2186        if (oldLast > last)
2187            last = oldLast;
2188    }
2189    changes->map.changed |= XkbKeyActionsMask;
2190    changes->map.first_key_act = first;
2191    changes->map.num_key_acts = (last - first + 1);
2192    return (char *) wire;
2193}
2194
2195static char *
2196SetKeyBehaviors(XkbSrvInfoPtr xkbi,
2197                xkbSetMapReq * req,
2198                xkbBehaviorWireDesc * wire, XkbChangesPtr changes)
2199{
2200    register unsigned i;
2201    int maxRG = -1;
2202    XkbDescPtr xkb = xkbi->desc;
2203    XkbServerMapPtr server = xkb->server;
2204    unsigned first, last;
2205
2206    first = req->firstKeyBehavior;
2207    last = req->firstKeyBehavior + req->nKeyBehaviors - 1;
2208    memset(&server->behaviors[first], 0,
2209           req->nKeyBehaviors * sizeof(XkbBehavior));
2210    for (i = 0; i < req->totalKeyBehaviors; i++) {
2211        if ((server->behaviors[wire->key].type & XkbKB_Permanent) == 0) {
2212            server->behaviors[wire->key].type = wire->type;
2213            server->behaviors[wire->key].data = wire->data;
2214            if ((wire->type == XkbKB_RadioGroup) &&
2215                (((int) wire->data) > maxRG))
2216                maxRG = wire->data + 1;
2217        }
2218        wire++;
2219    }
2220
2221    if (maxRG > (int) xkbi->nRadioGroups) {
2222        if (xkbi->radioGroups)
2223            xkbi->radioGroups = reallocarray(xkbi->radioGroups, maxRG,
2224                                             sizeof(XkbRadioGroupRec));
2225        else
2226            xkbi->radioGroups = calloc(maxRG, sizeof(XkbRadioGroupRec));
2227        if (xkbi->radioGroups) {
2228            if (xkbi->nRadioGroups)
2229                memset(&xkbi->radioGroups[xkbi->nRadioGroups], 0,
2230                       (maxRG - xkbi->nRadioGroups) * sizeof(XkbRadioGroupRec));
2231            xkbi->nRadioGroups = maxRG;
2232        }
2233        else
2234            xkbi->nRadioGroups = 0;
2235        /* should compute members here */
2236    }
2237    if (changes->map.changed & XkbKeyBehaviorsMask) {
2238        unsigned oldLast;
2239
2240        oldLast = changes->map.first_key_behavior +
2241            changes->map.num_key_behaviors - 1;
2242        if (changes->map.first_key_behavior < req->firstKeyBehavior)
2243            first = changes->map.first_key_behavior;
2244        if (oldLast > last)
2245            last = oldLast;
2246    }
2247    changes->map.changed |= XkbKeyBehaviorsMask;
2248    changes->map.first_key_behavior = first;
2249    changes->map.num_key_behaviors = (last - first + 1);
2250    return (char *) wire;
2251}
2252
2253static char *
2254SetVirtualMods(XkbSrvInfoPtr xkbi, xkbSetMapReq * req, CARD8 *wire,
2255               XkbChangesPtr changes)
2256{
2257    register int i, bit, nMods;
2258    XkbServerMapPtr srv = xkbi->desc->server;
2259
2260    if (((req->present & XkbVirtualModsMask) == 0) || (req->virtualMods == 0))
2261        return (char *) wire;
2262    for (i = nMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
2263        if (req->virtualMods & bit) {
2264            if (srv->vmods[i] != wire[nMods]) {
2265                changes->map.changed |= XkbVirtualModsMask;
2266                changes->map.vmods |= bit;
2267                srv->vmods[i] = wire[nMods];
2268            }
2269            nMods++;
2270        }
2271    }
2272    return (char *) (wire + XkbPaddedSize(nMods));
2273}
2274
2275static char *
2276SetKeyExplicit(XkbSrvInfoPtr xkbi, xkbSetMapReq * req, CARD8 *wire,
2277               XkbChangesPtr changes)
2278{
2279    register unsigned i, first, last;
2280    XkbServerMapPtr xkb = xkbi->desc->server;
2281    CARD8 *start;
2282
2283    start = wire;
2284    first = req->firstKeyExplicit;
2285    last = req->firstKeyExplicit + req->nKeyExplicit - 1;
2286    memset(&xkb->explicit[first], 0, req->nKeyExplicit);
2287    for (i = 0; i < req->totalKeyExplicit; i++, wire += 2) {
2288        xkb->explicit[wire[0]] = wire[1];
2289    }
2290    if (first > 0) {
2291        if (changes->map.changed & XkbExplicitComponentsMask) {
2292            int oldLast;
2293
2294            oldLast = changes->map.first_key_explicit +
2295                changes->map.num_key_explicit - 1;
2296            if (changes->map.first_key_explicit < first)
2297                first = changes->map.first_key_explicit;
2298            if (oldLast > last)
2299                last = oldLast;
2300        }
2301        changes->map.first_key_explicit = first;
2302        changes->map.num_key_explicit = (last - first) + 1;
2303    }
2304    wire += XkbPaddedSize(wire - start) - (wire - start);
2305    return (char *) wire;
2306}
2307
2308static char *
2309SetModifierMap(XkbSrvInfoPtr xkbi,
2310               xkbSetMapReq * req, CARD8 *wire, XkbChangesPtr changes)
2311{
2312    register unsigned i, first, last;
2313    XkbClientMapPtr xkb = xkbi->desc->map;
2314    CARD8 *start;
2315
2316    start = wire;
2317    first = req->firstModMapKey;
2318    last = req->firstModMapKey + req->nModMapKeys - 1;
2319    memset(&xkb->modmap[first], 0, req->nModMapKeys);
2320    for (i = 0; i < req->totalModMapKeys; i++, wire += 2) {
2321        xkb->modmap[wire[0]] = wire[1];
2322    }
2323    if (first > 0) {
2324        if (changes->map.changed & XkbModifierMapMask) {
2325            int oldLast;
2326
2327            oldLast = changes->map.first_modmap_key +
2328                changes->map.num_modmap_keys - 1;
2329            if (changes->map.first_modmap_key < first)
2330                first = changes->map.first_modmap_key;
2331            if (oldLast > last)
2332                last = oldLast;
2333        }
2334        changes->map.first_modmap_key = first;
2335        changes->map.num_modmap_keys = (last - first) + 1;
2336    }
2337    wire += XkbPaddedSize(wire - start) - (wire - start);
2338    return (char *) wire;
2339}
2340
2341static char *
2342SetVirtualModMap(XkbSrvInfoPtr xkbi,
2343                 xkbSetMapReq * req,
2344                 xkbVModMapWireDesc * wire, XkbChangesPtr changes)
2345{
2346    register unsigned i, first, last;
2347    XkbServerMapPtr srv = xkbi->desc->server;
2348
2349    first = req->firstVModMapKey;
2350    last = req->firstVModMapKey + req->nVModMapKeys - 1;
2351    memset(&srv->vmodmap[first], 0, req->nVModMapKeys * sizeof(unsigned short));
2352    for (i = 0; i < req->totalVModMapKeys; i++, wire++) {
2353        srv->vmodmap[wire->key] = wire->vmods;
2354    }
2355    if (first > 0) {
2356        if (changes->map.changed & XkbVirtualModMapMask) {
2357            int oldLast;
2358
2359            oldLast = changes->map.first_vmodmap_key +
2360                changes->map.num_vmodmap_keys - 1;
2361            if (changes->map.first_vmodmap_key < first)
2362                first = changes->map.first_vmodmap_key;
2363            if (oldLast > last)
2364                last = oldLast;
2365        }
2366        changes->map.first_vmodmap_key = first;
2367        changes->map.num_vmodmap_keys = (last - first) + 1;
2368    }
2369    return (char *) wire;
2370}
2371
2372/**
2373 * Check if the given request can be applied to the given device but don't
2374 * actually do anything..
2375 */
2376static int
2377_XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq * req,
2378                 char *values)
2379{
2380    XkbSrvInfoPtr xkbi;
2381    XkbDescPtr xkb;
2382    int error;
2383    int nTypes = 0, nActions;
2384    CARD8 mapWidths[XkbMaxLegalKeyCode + 1] = { 0 };
2385    CARD16 symsPerKey[XkbMaxLegalKeyCode + 1] = { 0 };
2386    XkbSymMapPtr map;
2387    int i;
2388
2389    if (!dev->key)
2390        return 0;
2391
2392    xkbi = dev->key->xkbInfo;
2393    xkb = xkbi->desc;
2394
2395    if ((xkb->min_key_code != req->minKeyCode) ||
2396        (xkb->max_key_code != req->maxKeyCode)) {
2397        if (client->xkbClientFlags & _XkbClientIsAncient) {
2398            /* pre 1.0 versions of Xlib have a bug */
2399            req->minKeyCode = xkb->min_key_code;
2400            req->maxKeyCode = xkb->max_key_code;
2401        }
2402        else {
2403            if (!XkbIsLegalKeycode(req->minKeyCode)) {
2404                client->errorValue =
2405                    _XkbErrCode3(2, req->minKeyCode, req->maxKeyCode);
2406                return BadValue;
2407            }
2408            if (req->minKeyCode > req->maxKeyCode) {
2409                client->errorValue =
2410                    _XkbErrCode3(3, req->minKeyCode, req->maxKeyCode);
2411                return BadMatch;
2412            }
2413        }
2414    }
2415
2416    if ((req->present & XkbKeyTypesMask) &&
2417        (!CheckKeyTypes(client, xkb, req, (xkbKeyTypeWireDesc **) &values,
2418                        &nTypes, mapWidths))) {
2419        client->errorValue = nTypes;
2420        return BadValue;
2421    }
2422
2423    /* symsPerKey/mapWidths must be filled regardless of client-side flags */
2424    map = &xkb->map->key_sym_map[xkb->min_key_code];
2425    for (i = xkb->min_key_code; i < xkb->max_key_code; i++, map++) {
2426        register int g, ng, w;
2427
2428        ng = XkbNumGroups(map->group_info);
2429        for (w = g = 0; g < ng; g++) {
2430            if (map->kt_index[g] >= (unsigned) nTypes) {
2431                client->errorValue = _XkbErrCode4(0x13, i, g, map->kt_index[g]);
2432                return 0;
2433            }
2434            if (mapWidths[map->kt_index[g]] > w)
2435                w = mapWidths[map->kt_index[g]];
2436        }
2437        symsPerKey[i] = w * ng;
2438    }
2439
2440    if ((req->present & XkbKeySymsMask) &&
2441        (!CheckKeySyms(client, xkb, req, nTypes, mapWidths, symsPerKey,
2442                       (xkbSymMapWireDesc **) &values, &error))) {
2443        client->errorValue = error;
2444        return BadValue;
2445    }
2446
2447    if ((req->present & XkbKeyActionsMask) &&
2448        (!CheckKeyActions(xkb, req, nTypes, mapWidths, symsPerKey,
2449                          (CARD8 **) &values, &nActions))) {
2450        client->errorValue = nActions;
2451        return BadValue;
2452    }
2453
2454    if ((req->present & XkbKeyBehaviorsMask) &&
2455        (!CheckKeyBehaviors
2456         (xkb, req, (xkbBehaviorWireDesc **) &values, &error))) {
2457        client->errorValue = error;
2458        return BadValue;
2459    }
2460
2461    if ((req->present & XkbVirtualModsMask) &&
2462        (!CheckVirtualMods(xkb, req, (CARD8 **) &values, &error))) {
2463        client->errorValue = error;
2464        return BadValue;
2465    }
2466    if ((req->present & XkbExplicitComponentsMask) &&
2467        (!CheckKeyExplicit(xkb, req, (CARD8 **) &values, &error))) {
2468        client->errorValue = error;
2469        return BadValue;
2470    }
2471    if ((req->present & XkbModifierMapMask) &&
2472        (!CheckModifierMap(xkb, req, (CARD8 **) &values, &error))) {
2473        client->errorValue = error;
2474        return BadValue;
2475    }
2476    if ((req->present & XkbVirtualModMapMask) &&
2477        (!CheckVirtualModMap
2478         (xkb, req, (xkbVModMapWireDesc **) &values, &error))) {
2479        client->errorValue = error;
2480        return BadValue;
2481    }
2482
2483    if (((values - ((char *) req)) / 4) != req->length) {
2484        ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after check)\n");
2485        client->errorValue = values - ((char *) &req[1]);
2486        return BadLength;
2487    }
2488
2489    return Success;
2490}
2491
2492/**
2493 * Apply the given request on the given device.
2494 */
2495static int
2496_XkbSetMap(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq * req, char *values)
2497{
2498    XkbEventCauseRec cause;
2499    XkbChangesRec change;
2500    Bool sentNKN;
2501    XkbSrvInfoPtr xkbi;
2502    XkbDescPtr xkb;
2503
2504    if (!dev->key)
2505        return Success;
2506
2507    xkbi = dev->key->xkbInfo;
2508    xkb = xkbi->desc;
2509
2510    XkbSetCauseXkbReq(&cause, X_kbSetMap, client);
2511    memset(&change, 0, sizeof(change));
2512    sentNKN = FALSE;
2513    if ((xkb->min_key_code != req->minKeyCode) ||
2514        (xkb->max_key_code != req->maxKeyCode)) {
2515        Status status;
2516        xkbNewKeyboardNotify nkn;
2517
2518        nkn.deviceID = nkn.oldDeviceID = dev->id;
2519        nkn.oldMinKeyCode = xkb->min_key_code;
2520        nkn.oldMaxKeyCode = xkb->max_key_code;
2521        status = XkbChangeKeycodeRange(xkb, req->minKeyCode,
2522                                       req->maxKeyCode, &change);
2523        if (status != Success)
2524            return status;      /* oh-oh. what about the other keyboards? */
2525        nkn.minKeyCode = xkb->min_key_code;
2526        nkn.maxKeyCode = xkb->max_key_code;
2527        nkn.requestMajor = XkbReqCode;
2528        nkn.requestMinor = X_kbSetMap;
2529        nkn.changed = XkbNKN_KeycodesMask;
2530        XkbSendNewKeyboardNotify(dev, &nkn);
2531        sentNKN = TRUE;
2532    }
2533
2534    if (req->present & XkbKeyTypesMask) {
2535        values = SetKeyTypes(xkb, req, (xkbKeyTypeWireDesc *) values, &change);
2536        if (!values)
2537            goto allocFailure;
2538    }
2539    if (req->present & XkbKeySymsMask) {
2540        values =
2541            SetKeySyms(client, xkb, req, (xkbSymMapWireDesc *) values, &change,
2542                       dev);
2543        if (!values)
2544            goto allocFailure;
2545    }
2546    if (req->present & XkbKeyActionsMask) {
2547        values = SetKeyActions(xkb, req, (CARD8 *) values, &change);
2548        if (!values)
2549            goto allocFailure;
2550    }
2551    if (req->present & XkbKeyBehaviorsMask) {
2552        values =
2553            SetKeyBehaviors(xkbi, req, (xkbBehaviorWireDesc *) values, &change);
2554        if (!values)
2555            goto allocFailure;
2556    }
2557    if (req->present & XkbVirtualModsMask)
2558        values = SetVirtualMods(xkbi, req, (CARD8 *) values, &change);
2559    if (req->present & XkbExplicitComponentsMask)
2560        values = SetKeyExplicit(xkbi, req, (CARD8 *) values, &change);
2561    if (req->present & XkbModifierMapMask)
2562        values = SetModifierMap(xkbi, req, (CARD8 *) values, &change);
2563    if (req->present & XkbVirtualModMapMask)
2564        values =
2565            SetVirtualModMap(xkbi, req, (xkbVModMapWireDesc *) values, &change);
2566    if (((values - ((char *) req)) / 4) != req->length) {
2567        ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after set)\n");
2568        client->errorValue = values - ((char *) &req[1]);
2569        return BadLength;
2570    }
2571    if (req->flags & XkbSetMapRecomputeActions) {
2572        KeyCode first, last, firstMM, lastMM;
2573
2574        if (change.map.num_key_syms > 0) {
2575            first = change.map.first_key_sym;
2576            last = first + change.map.num_key_syms - 1;
2577        }
2578        else
2579            first = last = 0;
2580        if (change.map.num_modmap_keys > 0) {
2581            firstMM = change.map.first_modmap_key;
2582            lastMM = firstMM + change.map.num_modmap_keys - 1;
2583        }
2584        else
2585            firstMM = lastMM = 0;
2586        if ((last > 0) && (lastMM > 0)) {
2587            if (firstMM < first)
2588                first = firstMM;
2589            if (lastMM > last)
2590                last = lastMM;
2591        }
2592        else if (lastMM > 0) {
2593            first = firstMM;
2594            last = lastMM;
2595        }
2596        if (last > 0) {
2597            unsigned check = 0;
2598
2599            XkbUpdateActions(dev, first, (last - first + 1), &change, &check,
2600                             &cause);
2601            if (check)
2602                XkbCheckSecondaryEffects(xkbi, check, &change, &cause);
2603        }
2604    }
2605    if (!sentNKN)
2606        XkbSendNotification(dev, &change, &cause);
2607
2608    return Success;
2609 allocFailure:
2610    return BadAlloc;
2611}
2612
2613int
2614ProcXkbSetMap(ClientPtr client)
2615{
2616    DeviceIntPtr dev;
2617    char *tmp;
2618    int rc;
2619
2620    REQUEST(xkbSetMapReq);
2621    REQUEST_AT_LEAST_SIZE(xkbSetMapReq);
2622
2623    if (!(client->xkbClientFlags & _XkbClientInitialized))
2624        return BadAccess;
2625
2626    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
2627    CHK_MASK_LEGAL(0x01, stuff->present, XkbAllMapComponentsMask);
2628
2629    tmp = (char *) &stuff[1];
2630
2631    /* Check if we can to the SetMap on the requested device. If this
2632       succeeds, do the same thing for all extension devices (if needed).
2633       If any of them fails, fail.  */
2634    rc = _XkbSetMapChecks(client, dev, stuff, tmp);
2635
2636    if (rc != Success)
2637        return rc;
2638
2639    DeviceIntPtr master = GetMaster(dev, MASTER_KEYBOARD);
2640
2641    if (stuff->deviceSpec == XkbUseCoreKbd) {
2642        DeviceIntPtr other;
2643
2644        for (other = inputInfo.devices; other; other = other->next) {
2645            if ((other != dev) && other->key && !IsMaster(other) &&
2646                GetMaster(other, MASTER_KEYBOARD) == dev) {
2647                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
2648                              DixManageAccess);
2649                if (rc == Success) {
2650                    rc = _XkbSetMapChecks(client, other, stuff, tmp);
2651                    if (rc != Success)
2652                        return rc;
2653                }
2654            }
2655        }
2656    } else {
2657        DeviceIntPtr other;
2658
2659        for (other = inputInfo.devices; other; other = other->next) {
2660            if (other != dev && GetMaster(other, MASTER_KEYBOARD) != dev &&
2661                (other != master || dev != master->lastSlave))
2662                continue;
2663
2664            rc = _XkbSetMapChecks(client, other, stuff, tmp);
2665            if (rc != Success)
2666                return rc;
2667        }
2668    }
2669
2670    /* We know now that we will succeed with the SetMap. In theory anyway. */
2671    rc = _XkbSetMap(client, dev, stuff, tmp);
2672    if (rc != Success)
2673        return rc;
2674
2675    if (stuff->deviceSpec == XkbUseCoreKbd) {
2676        DeviceIntPtr other;
2677
2678        for (other = inputInfo.devices; other; other = other->next) {
2679            if ((other != dev) && other->key && !IsMaster(other) &&
2680                GetMaster(other, MASTER_KEYBOARD) == dev) {
2681                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
2682                              DixManageAccess);
2683                if (rc == Success)
2684                    _XkbSetMap(client, other, stuff, tmp);
2685                /* ignore rc. if the SetMap failed although the check above
2686                   reported true there isn't much we can do. we still need to
2687                   set all other devices, hoping that at least they stay in
2688                   sync. */
2689            }
2690        }
2691    } else {
2692        DeviceIntPtr other;
2693
2694        for (other = inputInfo.devices; other; other = other->next) {
2695            if (other != dev && GetMaster(other, MASTER_KEYBOARD) != dev &&
2696                (other != master || dev != master->lastSlave))
2697                continue;
2698
2699            _XkbSetMap(client, other, stuff, tmp); //ignore rc
2700        }
2701    }
2702
2703    return Success;
2704}
2705
2706/***====================================================================***/
2707
2708static Status
2709XkbComputeGetCompatMapReplySize(XkbCompatMapPtr compat,
2710                                xkbGetCompatMapReply * rep)
2711{
2712    unsigned size, nGroups;
2713
2714    nGroups = 0;
2715    if (rep->groups != 0) {
2716        register int i, bit;
2717
2718        for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2719            if (rep->groups & bit)
2720                nGroups++;
2721        }
2722    }
2723    size = nGroups * SIZEOF(xkbModsWireDesc);
2724    size += (rep->nSI * SIZEOF(xkbSymInterpretWireDesc));
2725    rep->length = size / 4;
2726    return Success;
2727}
2728
2729static int
2730XkbSendCompatMap(ClientPtr client,
2731                 XkbCompatMapPtr compat, xkbGetCompatMapReply * rep)
2732{
2733    char *data;
2734    int size;
2735
2736    if (rep->length > 0) {
2737        data = xallocarray(rep->length, 4);
2738        if (data) {
2739            register unsigned i, bit;
2740            xkbModsWireDesc *grp;
2741            XkbSymInterpretPtr sym = &compat->sym_interpret[rep->firstSI];
2742            xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *) data;
2743
2744            size = rep->length * 4;
2745
2746            for (i = 0; i < rep->nSI; i++, sym++, wire++) {
2747                wire->sym = sym->sym;
2748                wire->mods = sym->mods;
2749                wire->match = sym->match;
2750                wire->virtualMod = sym->virtual_mod;
2751                wire->flags = sym->flags;
2752                memcpy((char *) &wire->act, (char *) &sym->act,
2753                       sz_xkbActionWireDesc);
2754                if (client->swapped) {
2755                    swapl(&wire->sym);
2756                }
2757            }
2758            if (rep->groups) {
2759                grp = (xkbModsWireDesc *) wire;
2760                for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2761                    if (rep->groups & bit) {
2762                        grp->mask = compat->groups[i].mask;
2763                        grp->realMods = compat->groups[i].real_mods;
2764                        grp->virtualMods = compat->groups[i].vmods;
2765                        if (client->swapped) {
2766                            swaps(&grp->virtualMods);
2767                        }
2768                        grp++;
2769                    }
2770                }
2771                wire = (xkbSymInterpretWireDesc *) grp;
2772            }
2773        }
2774        else
2775            return BadAlloc;
2776    }
2777    else
2778        data = NULL;
2779
2780    if (client->swapped) {
2781        swaps(&rep->sequenceNumber);
2782        swapl(&rep->length);
2783        swaps(&rep->firstSI);
2784        swaps(&rep->nSI);
2785        swaps(&rep->nTotalSI);
2786    }
2787
2788    WriteToClient(client, SIZEOF(xkbGetCompatMapReply), rep);
2789    if (data) {
2790        WriteToClient(client, size, data);
2791        free((char *) data);
2792    }
2793    return Success;
2794}
2795
2796int
2797ProcXkbGetCompatMap(ClientPtr client)
2798{
2799    xkbGetCompatMapReply rep;
2800    DeviceIntPtr dev;
2801    XkbDescPtr xkb;
2802    XkbCompatMapPtr compat;
2803
2804    REQUEST(xkbGetCompatMapReq);
2805    REQUEST_SIZE_MATCH(xkbGetCompatMapReq);
2806
2807    if (!(client->xkbClientFlags & _XkbClientInitialized))
2808        return BadAccess;
2809
2810    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
2811
2812    xkb = dev->key->xkbInfo->desc;
2813    compat = xkb->compat;
2814
2815    rep = (xkbGetCompatMapReply) {
2816        .type = X_Reply,
2817        .sequenceNumber = client->sequence,
2818        .length = 0,
2819        .deviceID = dev->id,
2820        .firstSI = stuff->firstSI,
2821        .nSI = stuff->nSI
2822    };
2823    if (stuff->getAllSI) {
2824        rep.firstSI = 0;
2825        rep.nSI = compat->num_si;
2826    }
2827    else if ((((unsigned) stuff->nSI) > 0) &&
2828             ((unsigned) (stuff->firstSI + stuff->nSI - 1) >= compat->num_si)) {
2829        client->errorValue = _XkbErrCode2(0x05, compat->num_si);
2830        return BadValue;
2831    }
2832    rep.nTotalSI = compat->num_si;
2833    rep.groups = stuff->groups;
2834    XkbComputeGetCompatMapReplySize(compat, &rep);
2835    return XkbSendCompatMap(client, compat, &rep);
2836}
2837
2838/**
2839 * Apply the given request on the given device.
2840 * If dryRun is TRUE, then value checks are performed, but the device isn't
2841 * modified.
2842 */
2843static int
2844_XkbSetCompatMap(ClientPtr client, DeviceIntPtr dev,
2845                 xkbSetCompatMapReq * req, char *data, BOOL dryRun)
2846{
2847    XkbSrvInfoPtr xkbi;
2848    XkbDescPtr xkb;
2849    XkbCompatMapPtr compat;
2850    int nGroups;
2851    unsigned i, bit;
2852
2853    xkbi = dev->key->xkbInfo;
2854    xkb = xkbi->desc;
2855    compat = xkb->compat;
2856
2857    if ((req->nSI > 0) || (req->truncateSI)) {
2858        xkbSymInterpretWireDesc *wire;
2859
2860        if (req->firstSI > compat->num_si) {
2861            client->errorValue = _XkbErrCode2(0x02, compat->num_si);
2862            return BadValue;
2863        }
2864        wire = (xkbSymInterpretWireDesc *) data;
2865        wire += req->nSI;
2866        data = (char *) wire;
2867    }
2868
2869    nGroups = 0;
2870    if (req->groups != 0) {
2871        for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2872            if (req->groups & bit)
2873                nGroups++;
2874        }
2875    }
2876    data += nGroups * SIZEOF(xkbModsWireDesc);
2877    if (((data - ((char *) req)) / 4) != req->length) {
2878        return BadLength;
2879    }
2880
2881    /* Done all the checks we can do */
2882    if (dryRun)
2883        return Success;
2884
2885    data = (char *) &req[1];
2886    if (req->nSI > 0) {
2887        xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *) data;
2888        XkbSymInterpretPtr sym;
2889        unsigned int skipped = 0;
2890
2891        if ((unsigned) (req->firstSI + req->nSI) > compat->num_si) {
2892            compat->num_si = req->firstSI + req->nSI;
2893            compat->sym_interpret = reallocarray(compat->sym_interpret,
2894                                                 compat->num_si,
2895                                                 sizeof(XkbSymInterpretRec));
2896            if (!compat->sym_interpret) {
2897                compat->num_si = 0;
2898                return BadAlloc;
2899            }
2900        }
2901        else if (req->truncateSI) {
2902            compat->num_si = req->firstSI + req->nSI;
2903        }
2904        sym = &compat->sym_interpret[req->firstSI];
2905        for (i = 0; i < req->nSI; i++, wire++) {
2906            if (client->swapped) {
2907                swapl(&wire->sym);
2908            }
2909            if (wire->sym == NoSymbol && wire->match == XkbSI_AnyOfOrNone &&
2910                (wire->mods & 0xff) == 0xff &&
2911                wire->act.type == XkbSA_XFree86Private) {
2912                ErrorF("XKB: Skipping broken Any+AnyOfOrNone(All) -> Private "
2913                       "action from client\n");
2914                skipped++;
2915                continue;
2916            }
2917            sym->sym = wire->sym;
2918            sym->mods = wire->mods;
2919            sym->match = wire->match;
2920            sym->flags = wire->flags;
2921            sym->virtual_mod = wire->virtualMod;
2922            memcpy((char *) &sym->act, (char *) &wire->act,
2923                   SIZEOF(xkbActionWireDesc));
2924            sym++;
2925        }
2926        if (skipped) {
2927            if (req->firstSI + req->nSI < compat->num_si)
2928                memmove(sym, sym + skipped,
2929                        (compat->num_si - req->firstSI - req->nSI) *
2930                        sizeof(*sym));
2931            compat->num_si -= skipped;
2932        }
2933        data = (char *) wire;
2934    }
2935    else if (req->truncateSI) {
2936        compat->num_si = req->firstSI;
2937    }
2938
2939    if (req->groups != 0) {
2940        xkbModsWireDesc *wire = (xkbModsWireDesc *) data;
2941
2942        for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2943            if (req->groups & bit) {
2944                if (client->swapped) {
2945                    swaps(&wire->virtualMods);
2946                }
2947                compat->groups[i].mask = wire->realMods;
2948                compat->groups[i].real_mods = wire->realMods;
2949                compat->groups[i].vmods = wire->virtualMods;
2950                if (wire->virtualMods != 0) {
2951                    unsigned tmp;
2952
2953                    tmp = XkbMaskForVMask(xkb, wire->virtualMods);
2954                    compat->groups[i].mask |= tmp;
2955                }
2956                data += SIZEOF(xkbModsWireDesc);
2957                wire = (xkbModsWireDesc *) data;
2958            }
2959        }
2960    }
2961    i = XkbPaddedSize((data - ((char *) req)));
2962    if ((i / 4) != req->length) {
2963        ErrorF("[xkb] Internal length error on read in _XkbSetCompatMap\n");
2964        return BadLength;
2965    }
2966
2967    if (dev->xkb_interest) {
2968        xkbCompatMapNotify ev;
2969
2970        ev.deviceID = dev->id;
2971        ev.changedGroups = req->groups;
2972        ev.firstSI = req->firstSI;
2973        ev.nSI = req->nSI;
2974        ev.nTotalSI = compat->num_si;
2975        XkbSendCompatMapNotify(dev, &ev);
2976    }
2977
2978    if (req->recomputeActions) {
2979        XkbChangesRec change;
2980        unsigned check;
2981        XkbEventCauseRec cause;
2982
2983        XkbSetCauseXkbReq(&cause, X_kbSetCompatMap, client);
2984        memset(&change, 0, sizeof(XkbChangesRec));
2985        XkbUpdateActions(dev, xkb->min_key_code, XkbNumKeys(xkb), &change,
2986                         &check, &cause);
2987        if (check)
2988            XkbCheckSecondaryEffects(xkbi, check, &change, &cause);
2989        XkbSendNotification(dev, &change, &cause);
2990    }
2991    return Success;
2992}
2993
2994int
2995ProcXkbSetCompatMap(ClientPtr client)
2996{
2997    DeviceIntPtr dev;
2998    char *data;
2999    int rc;
3000
3001    REQUEST(xkbSetCompatMapReq);
3002    REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq);
3003
3004    if (!(client->xkbClientFlags & _XkbClientInitialized))
3005        return BadAccess;
3006
3007    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
3008
3009    data = (char *) &stuff[1];
3010
3011    /* check first using a dry-run */
3012    rc = _XkbSetCompatMap(client, dev, stuff, data, TRUE);
3013    if (rc != Success)
3014        return rc;
3015    if (stuff->deviceSpec == XkbUseCoreKbd) {
3016        DeviceIntPtr other;
3017
3018        for (other = inputInfo.devices; other; other = other->next) {
3019            if ((other != dev) && other->key && !IsMaster(other) &&
3020                GetMaster(other, MASTER_KEYBOARD) == dev) {
3021                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
3022                              DixManageAccess);
3023                if (rc == Success) {
3024                    /* dry-run */
3025                    rc = _XkbSetCompatMap(client, other, stuff, data, TRUE);
3026                    if (rc != Success)
3027                        return rc;
3028                }
3029            }
3030        }
3031    }
3032
3033    /* Yay, the dry-runs succeed. Let's apply */
3034    rc = _XkbSetCompatMap(client, dev, stuff, data, FALSE);
3035    if (rc != Success)
3036        return rc;
3037    if (stuff->deviceSpec == XkbUseCoreKbd) {
3038        DeviceIntPtr other;
3039
3040        for (other = inputInfo.devices; other; other = other->next) {
3041            if ((other != dev) && other->key && !IsMaster(other) &&
3042                GetMaster(other, MASTER_KEYBOARD) == dev) {
3043                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
3044                              DixManageAccess);
3045                if (rc == Success) {
3046                    rc = _XkbSetCompatMap(client, other, stuff, data, FALSE);
3047                    if (rc != Success)
3048                        return rc;
3049                }
3050            }
3051        }
3052    }
3053
3054    return Success;
3055}
3056
3057/***====================================================================***/
3058
3059int
3060ProcXkbGetIndicatorState(ClientPtr client)
3061{
3062    xkbGetIndicatorStateReply rep;
3063    XkbSrvLedInfoPtr sli;
3064    DeviceIntPtr dev;
3065
3066    REQUEST(xkbGetIndicatorStateReq);
3067    REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq);
3068
3069    if (!(client->xkbClientFlags & _XkbClientInitialized))
3070        return BadAccess;
3071
3072    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
3073
3074    sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
3075                            XkbXI_IndicatorStateMask);
3076    if (!sli)
3077        return BadAlloc;
3078
3079    rep = (xkbGetIndicatorStateReply) {
3080        .type = X_Reply,
3081        .deviceID = dev->id,
3082        .sequenceNumber = client->sequence,
3083        .length = 0,
3084        .state = sli->effectiveState
3085    };
3086
3087    if (client->swapped) {
3088        swaps(&rep.sequenceNumber);
3089        swapl(&rep.state);
3090    }
3091    WriteToClient(client, SIZEOF(xkbGetIndicatorStateReply), &rep);
3092    return Success;
3093}
3094
3095/***====================================================================***/
3096
3097static Status
3098XkbComputeGetIndicatorMapReplySize(XkbIndicatorPtr indicators,
3099                                   xkbGetIndicatorMapReply * rep)
3100{
3101    register int i, bit;
3102    int nIndicators;
3103
3104    rep->realIndicators = indicators->phys_indicators;
3105    for (i = nIndicators = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3106        if (rep->which & bit)
3107            nIndicators++;
3108    }
3109    rep->length = (nIndicators * SIZEOF(xkbIndicatorMapWireDesc)) / 4;
3110    rep->nIndicators = nIndicators;
3111    return Success;
3112}
3113
3114static int
3115XkbSendIndicatorMap(ClientPtr client,
3116                    XkbIndicatorPtr indicators, xkbGetIndicatorMapReply * rep)
3117{
3118    int length;
3119    CARD8 *map;
3120    register int i;
3121    register unsigned bit;
3122
3123    if (rep->length > 0) {
3124        CARD8 *to;
3125
3126        to = map = xallocarray(rep->length, 4);
3127        if (map) {
3128            xkbIndicatorMapWireDesc *wire = (xkbIndicatorMapWireDesc *) to;
3129
3130            length = rep->length * 4;
3131
3132            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3133                if (rep->which & bit) {
3134                    wire->flags = indicators->maps[i].flags;
3135                    wire->whichGroups = indicators->maps[i].which_groups;
3136                    wire->groups = indicators->maps[i].groups;
3137                    wire->whichMods = indicators->maps[i].which_mods;
3138                    wire->mods = indicators->maps[i].mods.mask;
3139                    wire->realMods = indicators->maps[i].mods.real_mods;
3140                    wire->virtualMods = indicators->maps[i].mods.vmods;
3141                    wire->ctrls = indicators->maps[i].ctrls;
3142                    if (client->swapped) {
3143                        swaps(&wire->virtualMods);
3144                        swapl(&wire->ctrls);
3145                    }
3146                    wire++;
3147                }
3148            }
3149            to = (CARD8 *) wire;
3150            if ((to - map) != length) {
3151                client->errorValue = _XkbErrCode2(0xff, length);
3152                free(map);
3153                return BadLength;
3154            }
3155        }
3156        else
3157            return BadAlloc;
3158    }
3159    else
3160        map = NULL;
3161    if (client->swapped) {
3162        swaps(&rep->sequenceNumber);
3163        swapl(&rep->length);
3164        swapl(&rep->which);
3165        swapl(&rep->realIndicators);
3166    }
3167    WriteToClient(client, SIZEOF(xkbGetIndicatorMapReply), rep);
3168    if (map) {
3169        WriteToClient(client, length, map);
3170        free((char *) map);
3171    }
3172    return Success;
3173}
3174
3175int
3176ProcXkbGetIndicatorMap(ClientPtr client)
3177{
3178    xkbGetIndicatorMapReply rep;
3179    DeviceIntPtr dev;
3180    XkbDescPtr xkb;
3181    XkbIndicatorPtr leds;
3182
3183    REQUEST(xkbGetIndicatorMapReq);
3184    REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq);
3185
3186    if (!(client->xkbClientFlags & _XkbClientInitialized))
3187        return BadAccess;
3188
3189    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
3190
3191    xkb = dev->key->xkbInfo->desc;
3192    leds = xkb->indicators;
3193
3194    rep = (xkbGetIndicatorMapReply) {
3195        .type = X_Reply,
3196        .deviceID = dev->id,
3197        .sequenceNumber = client->sequence,
3198        .length = 0,
3199        .which = stuff->which
3200    };
3201    XkbComputeGetIndicatorMapReplySize(leds, &rep);
3202    return XkbSendIndicatorMap(client, leds, &rep);
3203}
3204
3205/**
3206 * Apply the given map to the given device. Which specifies which components
3207 * to apply.
3208 */
3209static int
3210_XkbSetIndicatorMap(ClientPtr client, DeviceIntPtr dev,
3211                    int which, xkbIndicatorMapWireDesc * desc)
3212{
3213    XkbSrvInfoPtr xkbi;
3214    XkbSrvLedInfoPtr sli;
3215    XkbEventCauseRec cause;
3216    int i, bit;
3217
3218    xkbi = dev->key->xkbInfo;
3219
3220    sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
3221                            XkbXI_IndicatorMapsMask);
3222    if (!sli)
3223        return BadAlloc;
3224
3225    for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3226        if (which & bit) {
3227            sli->maps[i].flags = desc->flags;
3228            sli->maps[i].which_groups = desc->whichGroups;
3229            sli->maps[i].groups = desc->groups;
3230            sli->maps[i].which_mods = desc->whichMods;
3231            sli->maps[i].mods.mask = desc->mods;
3232            sli->maps[i].mods.real_mods = desc->mods;
3233            sli->maps[i].mods.vmods = desc->virtualMods;
3234            sli->maps[i].ctrls = desc->ctrls;
3235            if (desc->virtualMods != 0) {
3236                unsigned tmp;
3237
3238                tmp = XkbMaskForVMask(xkbi->desc, desc->virtualMods);
3239                sli->maps[i].mods.mask = desc->mods | tmp;
3240            }
3241            desc++;
3242        }
3243    }
3244
3245    XkbSetCauseXkbReq(&cause, X_kbSetIndicatorMap, client);
3246    XkbApplyLedMapChanges(dev, sli, which, NULL, NULL, &cause);
3247
3248    return Success;
3249}
3250
3251int
3252ProcXkbSetIndicatorMap(ClientPtr client)
3253{
3254    int i, bit;
3255    int nIndicators;
3256    DeviceIntPtr dev;
3257    xkbIndicatorMapWireDesc *from;
3258    int rc;
3259
3260    REQUEST(xkbSetIndicatorMapReq);
3261    REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq);
3262
3263    if (!(client->xkbClientFlags & _XkbClientInitialized))
3264        return BadAccess;
3265
3266    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
3267
3268    if (stuff->which == 0)
3269        return Success;
3270
3271    for (nIndicators = i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3272        if (stuff->which & bit)
3273            nIndicators++;
3274    }
3275    if (stuff->length != ((SIZEOF(xkbSetIndicatorMapReq) +
3276                           (nIndicators * SIZEOF(xkbIndicatorMapWireDesc))) /
3277                          4)) {
3278        return BadLength;
3279    }
3280
3281    from = (xkbIndicatorMapWireDesc *) &stuff[1];
3282    for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3283        if (stuff->which & bit) {
3284            if (client->swapped) {
3285                swaps(&from->virtualMods);
3286                swapl(&from->ctrls);
3287            }
3288            CHK_MASK_LEGAL(i, from->whichGroups, XkbIM_UseAnyGroup);
3289            CHK_MASK_LEGAL(i, from->whichMods, XkbIM_UseAnyMods);
3290            from++;
3291        }
3292    }
3293
3294    from = (xkbIndicatorMapWireDesc *) &stuff[1];
3295    rc = _XkbSetIndicatorMap(client, dev, stuff->which, from);
3296    if (rc != Success)
3297        return rc;
3298
3299    if (stuff->deviceSpec == XkbUseCoreKbd) {
3300        DeviceIntPtr other;
3301
3302        for (other = inputInfo.devices; other; other = other->next) {
3303            if ((other != dev) && other->key && !IsMaster(other) &&
3304                GetMaster(other, MASTER_KEYBOARD) == dev) {
3305                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
3306                              DixSetAttrAccess);
3307                if (rc == Success)
3308                    _XkbSetIndicatorMap(client, other, stuff->which, from);
3309            }
3310        }
3311    }
3312
3313    return Success;
3314}
3315
3316/***====================================================================***/
3317
3318int
3319ProcXkbGetNamedIndicator(ClientPtr client)
3320{
3321    DeviceIntPtr dev;
3322    xkbGetNamedIndicatorReply rep;
3323    register int i = 0;
3324    XkbSrvLedInfoPtr sli;
3325    XkbIndicatorMapPtr map = NULL;
3326
3327    REQUEST(xkbGetNamedIndicatorReq);
3328    REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq);
3329
3330    if (!(client->xkbClientFlags & _XkbClientInitialized))
3331        return BadAccess;
3332
3333    CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
3334    CHK_ATOM_ONLY(stuff->indicator);
3335
3336    sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID, 0);
3337    if (!sli)
3338        return BadAlloc;
3339
3340    i = 0;
3341    map = NULL;
3342    if ((sli->names) && (sli->maps)) {
3343        for (i = 0; i < XkbNumIndicators; i++) {
3344            if (stuff->indicator == sli->names[i]) {
3345                map = &sli->maps[i];
3346                break;
3347            }
3348        }
3349    }
3350
3351    rep = (xkbGetNamedIndicatorReply) {
3352        .type = X_Reply,
3353        .sequenceNumber = client->sequence,
3354        .length = 0,
3355        .deviceID = dev->id,
3356        .indicator = stuff->indicator
3357    };
3358    if (map != NULL) {
3359        rep.found = TRUE;
3360        rep.on = ((sli->effectiveState & (1 << i)) != 0);
3361        rep.realIndicator = ((sli->physIndicators & (1 << i)) != 0);
3362        rep.ndx = i;
3363        rep.flags = map->flags;
3364        rep.whichGroups = map->which_groups;
3365        rep.groups = map->groups;
3366        rep.whichMods = map->which_mods;
3367        rep.mods = map->mods.mask;
3368        rep.realMods = map->mods.real_mods;
3369        rep.virtualMods = map->mods.vmods;
3370        rep.ctrls = map->ctrls;
3371        rep.supported = TRUE;
3372    }
3373    else {
3374        rep.found = FALSE;
3375        rep.on = FALSE;
3376        rep.realIndicator = FALSE;
3377        rep.ndx = XkbNoIndicator;
3378        rep.flags = 0;
3379        rep.whichGroups = 0;
3380        rep.groups = 0;
3381        rep.whichMods = 0;
3382        rep.mods = 0;
3383        rep.realMods = 0;
3384        rep.virtualMods = 0;
3385        rep.ctrls = 0;
3386        rep.supported = TRUE;
3387    }
3388    if (client->swapped) {
3389        swapl(&rep.length);
3390        swaps(&rep.sequenceNumber);
3391        swapl(&rep.indicator);
3392        swaps(&rep.virtualMods);
3393        swapl(&rep.ctrls);
3394    }
3395
3396    WriteToClient(client, SIZEOF(xkbGetNamedIndicatorReply), &rep);
3397    return Success;
3398}
3399
3400/**
3401 * Find the IM on the device.
3402 * Returns the map, or NULL if the map doesn't exist.
3403 * If the return value is NULL, led_return is undefined. Otherwise, led_return
3404 * is set to the led index of the map.
3405 */
3406static XkbIndicatorMapPtr
3407_XkbFindNamedIndicatorMap(XkbSrvLedInfoPtr sli, Atom indicator, int *led_return)
3408{
3409    XkbIndicatorMapPtr map;
3410
3411    /* search for the right indicator */
3412    map = NULL;
3413    if (sli->names && sli->maps) {
3414        int led;
3415
3416        for (led = 0; (led < XkbNumIndicators) && (map == NULL); led++) {
3417            if (sli->names[led] == indicator) {
3418                map = &sli->maps[led];
3419                *led_return = led;
3420                break;
3421            }
3422        }
3423    }
3424
3425    return map;
3426}
3427
3428/**
3429 * Creates an indicator map on the device. If dryRun is TRUE, it only checks
3430 * if creation is possible, but doesn't actually create it.
3431 */
3432static int
3433_XkbCreateIndicatorMap(DeviceIntPtr dev, Atom indicator,
3434                       int ledClass, int ledID,
3435                       XkbIndicatorMapPtr * map_return, int *led_return,
3436                       Bool dryRun)
3437{
3438    XkbSrvLedInfoPtr sli;
3439    XkbIndicatorMapPtr map;
3440    int led;
3441
3442    sli = XkbFindSrvLedInfo(dev, ledClass, ledID, XkbXI_IndicatorsMask);
3443    if (!sli)
3444        return BadAlloc;
3445
3446    map = _XkbFindNamedIndicatorMap(sli, indicator, &led);
3447
3448    if (!map) {
3449        /* find first unused indicator maps and assign the name to it */
3450        for (led = 0, map = NULL; (led < XkbNumIndicators) && (map == NULL);
3451             led++) {
3452            if ((sli->names) && (sli->maps) && (sli->names[led] == None) &&
3453                (!XkbIM_InUse(&sli->maps[led]))) {
3454                map = &sli->maps[led];
3455                if (!dryRun)
3456                    sli->names[led] = indicator;
3457                break;
3458            }
3459        }
3460    }
3461
3462    if (!map)
3463        return BadAlloc;
3464
3465    *led_return = led;
3466    *map_return = map;
3467    return Success;
3468}
3469
3470static int
3471_XkbSetNamedIndicator(ClientPtr client, DeviceIntPtr dev,
3472                      xkbSetNamedIndicatorReq * stuff)
3473{
3474    unsigned int extDevReason;
3475    unsigned int statec, namec, mapc;
3476    XkbSrvLedInfoPtr sli;
3477    int led = 0;
3478    XkbIndicatorMapPtr map;
3479    DeviceIntPtr kbd;
3480    XkbEventCauseRec cause;
3481    xkbExtensionDeviceNotify ed;
3482    XkbChangesRec changes;
3483    int rc;
3484
3485    rc = _XkbCreateIndicatorMap(dev, stuff->indicator, stuff->ledClass,
3486                                stuff->ledID, &map, &led, FALSE);
3487    if (rc != Success || !map)  /* oh-oh */
3488        return rc;
3489
3490    sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID,
3491                            XkbXI_IndicatorsMask);
3492    if (!sli)
3493        return BadAlloc;
3494
3495    namec = mapc = statec = 0;
3496    extDevReason = 0;
3497
3498    namec |= (1 << led);
3499    sli->namesPresent |= ((stuff->indicator != None) ? (1 << led) : 0);
3500    extDevReason |= XkbXI_IndicatorNamesMask;
3501
3502    if (stuff->setMap) {
3503        map->flags = stuff->flags;
3504        map->which_groups = stuff->whichGroups;
3505        map->groups = stuff->groups;
3506        map->which_mods = stuff->whichMods;
3507        map->mods.mask = stuff->realMods;
3508        map->mods.real_mods = stuff->realMods;
3509        map->mods.vmods = stuff->virtualMods;
3510        map->ctrls = stuff->ctrls;
3511        mapc |= (1 << led);
3512    }
3513
3514    if ((stuff->setState) && ((map->flags & XkbIM_NoExplicit) == 0)) {
3515        if (stuff->on)
3516            sli->explicitState |= (1 << led);
3517        else
3518            sli->explicitState &= ~(1 << led);
3519        statec |= ((sli->effectiveState ^ sli->explicitState) & (1 << led));
3520    }
3521
3522    memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify));
3523    memset((char *) &changes, 0, sizeof(XkbChangesRec));
3524    XkbSetCauseXkbReq(&cause, X_kbSetNamedIndicator, client);
3525    if (namec)
3526        XkbApplyLedNameChanges(dev, sli, namec, &ed, &changes, &cause);
3527    if (mapc)
3528        XkbApplyLedMapChanges(dev, sli, mapc, &ed, &changes, &cause);
3529    if (statec)
3530        XkbApplyLedStateChanges(dev, sli, statec, &ed, &changes, &cause);
3531
3532    kbd = dev;
3533    if ((sli->flags & XkbSLI_HasOwnState) == 0)
3534        kbd = inputInfo.keyboard;
3535    XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause);
3536
3537    return Success;
3538}
3539
3540int
3541ProcXkbSetNamedIndicator(ClientPtr client)
3542{
3543    int rc;
3544    DeviceIntPtr dev;
3545    int led = 0;
3546    XkbIndicatorMapPtr map;
3547
3548    REQUEST(xkbSetNamedIndicatorReq);
3549    REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq);
3550
3551    if (!(client->xkbClientFlags & _XkbClientInitialized))
3552        return BadAccess;
3553
3554    CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
3555    CHK_ATOM_ONLY(stuff->indicator);
3556    CHK_MASK_LEGAL(0x10, stuff->whichGroups, XkbIM_UseAnyGroup);
3557    CHK_MASK_LEGAL(0x11, stuff->whichMods, XkbIM_UseAnyMods);
3558
3559    /* Dry-run for checks */
3560    rc = _XkbCreateIndicatorMap(dev, stuff->indicator,
3561                                stuff->ledClass, stuff->ledID,
3562                                &map, &led, TRUE);
3563    if (rc != Success || !map)  /* couldn't be created or didn't exist */
3564        return rc;
3565
3566    if (stuff->deviceSpec == XkbUseCoreKbd ||
3567        stuff->deviceSpec == XkbUseCorePtr) {
3568        DeviceIntPtr other;
3569
3570        for (other = inputInfo.devices; other; other = other->next) {
3571            if ((other != dev) && !IsMaster(other) &&
3572                GetMaster(other, MASTER_KEYBOARD) == dev && (other->kbdfeed ||
3573                                                             other->leds) &&
3574                (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess)
3575                 == Success)) {
3576                rc = _XkbCreateIndicatorMap(other, stuff->indicator,
3577                                            stuff->ledClass, stuff->ledID, &map,
3578                                            &led, TRUE);
3579                if (rc != Success || !map)
3580                    return rc;
3581            }
3582        }
3583    }
3584
3585    /* All checks passed, let's do it */
3586    rc = _XkbSetNamedIndicator(client, dev, stuff);
3587    if (rc != Success)
3588        return rc;
3589
3590    if (stuff->deviceSpec == XkbUseCoreKbd ||
3591        stuff->deviceSpec == XkbUseCorePtr) {
3592        DeviceIntPtr other;
3593
3594        for (other = inputInfo.devices; other; other = other->next) {
3595            if ((other != dev) && !IsMaster(other) &&
3596                GetMaster(other, MASTER_KEYBOARD) == dev && (other->kbdfeed ||
3597                                                             other->leds) &&
3598                (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess)
3599                 == Success)) {
3600                _XkbSetNamedIndicator(client, other, stuff);
3601            }
3602        }
3603    }
3604
3605    return Success;
3606}
3607
3608/***====================================================================***/
3609
3610static CARD32
3611_XkbCountAtoms(Atom *atoms, int maxAtoms, int *count)
3612{
3613    register unsigned int i, bit, nAtoms;
3614    register CARD32 atomsPresent;
3615
3616    for (i = nAtoms = atomsPresent = 0, bit = 1; i < maxAtoms; i++, bit <<= 1) {
3617        if (atoms[i] != None) {
3618            atomsPresent |= bit;
3619            nAtoms++;
3620        }
3621    }
3622    if (count)
3623        *count = nAtoms;
3624    return atomsPresent;
3625}
3626
3627static char *
3628_XkbWriteAtoms(char *wire, Atom *atoms, int maxAtoms, int swap)
3629{
3630    register unsigned int i;
3631    Atom *atm;
3632
3633    atm = (Atom *) wire;
3634    for (i = 0; i < maxAtoms; i++) {
3635        if (atoms[i] != None) {
3636            *atm = atoms[i];
3637            if (swap) {
3638                swapl(atm);
3639            }
3640            atm++;
3641        }
3642    }
3643    return (char *) atm;
3644}
3645
3646static Status
3647XkbComputeGetNamesReplySize(XkbDescPtr xkb, xkbGetNamesReply * rep)
3648{
3649    register unsigned which, length;
3650    register int i;
3651
3652    rep->minKeyCode = xkb->min_key_code;
3653    rep->maxKeyCode = xkb->max_key_code;
3654    which = rep->which;
3655    length = 0;
3656    if (xkb->names != NULL) {
3657        if (which & XkbKeycodesNameMask)
3658            length++;
3659        if (which & XkbGeometryNameMask)
3660            length++;
3661        if (which & XkbSymbolsNameMask)
3662            length++;
3663        if (which & XkbPhysSymbolsNameMask)
3664            length++;
3665        if (which & XkbTypesNameMask)
3666            length++;
3667        if (which & XkbCompatNameMask)
3668            length++;
3669    }
3670    else
3671        which &= ~XkbComponentNamesMask;
3672
3673    if (xkb->map != NULL) {
3674        if (which & XkbKeyTypeNamesMask)
3675            length += xkb->map->num_types;
3676        rep->nTypes = xkb->map->num_types;
3677        if (which & XkbKTLevelNamesMask) {
3678            XkbKeyTypePtr pType = xkb->map->types;
3679            int nKTLevels = 0;
3680
3681            length += XkbPaddedSize(xkb->map->num_types) / 4;
3682            for (i = 0; i < xkb->map->num_types; i++, pType++) {
3683                if (pType->level_names != NULL)
3684                    nKTLevels += pType->num_levels;
3685            }
3686            rep->nKTLevels = nKTLevels;
3687            length += nKTLevels;
3688        }
3689    }
3690    else {
3691        rep->nTypes = 0;
3692        rep->nKTLevels = 0;
3693        which &= ~(XkbKeyTypeNamesMask | XkbKTLevelNamesMask);
3694    }
3695
3696    rep->minKeyCode = xkb->min_key_code;
3697    rep->maxKeyCode = xkb->max_key_code;
3698    rep->indicators = 0;
3699    rep->virtualMods = 0;
3700    rep->groupNames = 0;
3701    if (xkb->names != NULL) {
3702        if (which & XkbIndicatorNamesMask) {
3703            int nLeds;
3704
3705            rep->indicators =
3706                _XkbCountAtoms(xkb->names->indicators, XkbNumIndicators,
3707                               &nLeds);
3708            length += nLeds;
3709            if (nLeds == 0)
3710                which &= ~XkbIndicatorNamesMask;
3711        }
3712
3713        if (which & XkbVirtualModNamesMask) {
3714            int nVMods;
3715
3716            rep->virtualMods =
3717                _XkbCountAtoms(xkb->names->vmods, XkbNumVirtualMods, &nVMods);
3718            length += nVMods;
3719            if (nVMods == 0)
3720                which &= ~XkbVirtualModNamesMask;
3721        }
3722
3723        if (which & XkbGroupNamesMask) {
3724            int nGroups;
3725
3726            rep->groupNames =
3727                _XkbCountAtoms(xkb->names->groups, XkbNumKbdGroups, &nGroups);
3728            length += nGroups;
3729            if (nGroups == 0)
3730                which &= ~XkbGroupNamesMask;
3731        }
3732
3733        if ((which & XkbKeyNamesMask) && (xkb->names->keys))
3734            length += rep->nKeys;
3735        else
3736            which &= ~XkbKeyNamesMask;
3737
3738        if ((which & XkbKeyAliasesMask) &&
3739            (xkb->names->key_aliases) && (xkb->names->num_key_aliases > 0)) {
3740            rep->nKeyAliases = xkb->names->num_key_aliases;
3741            length += rep->nKeyAliases * 2;
3742        }
3743        else {
3744            which &= ~XkbKeyAliasesMask;
3745            rep->nKeyAliases = 0;
3746        }
3747
3748        if ((which & XkbRGNamesMask) && (xkb->names->num_rg > 0))
3749            length += xkb->names->num_rg;
3750        else
3751            which &= ~XkbRGNamesMask;
3752    }
3753    else {
3754        which &= ~(XkbIndicatorNamesMask | XkbVirtualModNamesMask);
3755        which &= ~(XkbGroupNamesMask | XkbKeyNamesMask | XkbKeyAliasesMask);
3756        which &= ~XkbRGNamesMask;
3757    }
3758
3759    rep->length = length;
3760    rep->which = which;
3761    return Success;
3762}
3763
3764static int
3765XkbSendNames(ClientPtr client, XkbDescPtr xkb, xkbGetNamesReply * rep)
3766{
3767    register unsigned i, length, which;
3768    char *start;
3769    char *desc;
3770
3771    length = rep->length * 4;
3772    which = rep->which;
3773    if (client->swapped) {
3774        swaps(&rep->sequenceNumber);
3775        swapl(&rep->length);
3776        swapl(&rep->which);
3777        swaps(&rep->virtualMods);
3778        swapl(&rep->indicators);
3779    }
3780
3781    start = desc = calloc(1, length);
3782    if (!start)
3783        return BadAlloc;
3784    if (xkb->names) {
3785        if (which & XkbKeycodesNameMask) {
3786            *((CARD32 *) desc) = xkb->names->keycodes;
3787            if (client->swapped) {
3788                swapl((int *) desc);
3789            }
3790            desc += 4;
3791        }
3792        if (which & XkbGeometryNameMask) {
3793            *((CARD32 *) desc) = xkb->names->geometry;
3794            if (client->swapped) {
3795                swapl((int *) desc);
3796            }
3797            desc += 4;
3798        }
3799        if (which & XkbSymbolsNameMask) {
3800            *((CARD32 *) desc) = xkb->names->symbols;
3801            if (client->swapped) {
3802                swapl((int *) desc);
3803            }
3804            desc += 4;
3805        }
3806        if (which & XkbPhysSymbolsNameMask) {
3807            register CARD32 *atm = (CARD32 *) desc;
3808
3809            atm[0] = (CARD32) xkb->names->phys_symbols;
3810            if (client->swapped) {
3811                swapl(&atm[0]);
3812            }
3813            desc += 4;
3814        }
3815        if (which & XkbTypesNameMask) {
3816            *((CARD32 *) desc) = (CARD32) xkb->names->types;
3817            if (client->swapped) {
3818                swapl((int *) desc);
3819            }
3820            desc += 4;
3821        }
3822        if (which & XkbCompatNameMask) {
3823            *((CARD32 *) desc) = (CARD32) xkb->names->compat;
3824            if (client->swapped) {
3825                swapl((int *) desc);
3826            }
3827            desc += 4;
3828        }
3829        if (which & XkbKeyTypeNamesMask) {
3830            register CARD32 *atm = (CARD32 *) desc;
3831            register XkbKeyTypePtr type = xkb->map->types;
3832
3833            for (i = 0; i < xkb->map->num_types; i++, atm++, type++) {
3834                *atm = (CARD32) type->name;
3835                if (client->swapped) {
3836                    swapl(atm);
3837                }
3838            }
3839            desc = (char *) atm;
3840        }
3841        if (which & XkbKTLevelNamesMask && xkb->map) {
3842            XkbKeyTypePtr type = xkb->map->types;
3843            register CARD32 *atm;
3844
3845            for (i = 0; i < rep->nTypes; i++, type++) {
3846                *desc++ = type->num_levels;
3847            }
3848            desc += XkbPaddedSize(rep->nTypes) - rep->nTypes;
3849
3850            atm = (CARD32 *) desc;
3851            type = xkb->map->types;
3852            for (i = 0; i < xkb->map->num_types; i++, type++) {
3853                register unsigned l;
3854
3855                if (type->level_names) {
3856                    for (l = 0; l < type->num_levels; l++, atm++) {
3857                        *atm = type->level_names[l];
3858                        if (client->swapped) {
3859                            swapl(atm);
3860                        }
3861                    }
3862                    desc += type->num_levels * 4;
3863                }
3864            }
3865        }
3866        if (which & XkbIndicatorNamesMask) {
3867            desc =
3868                _XkbWriteAtoms(desc, xkb->names->indicators, XkbNumIndicators,
3869                               client->swapped);
3870        }
3871        if (which & XkbVirtualModNamesMask) {
3872            desc = _XkbWriteAtoms(desc, xkb->names->vmods, XkbNumVirtualMods,
3873                                  client->swapped);
3874        }
3875        if (which & XkbGroupNamesMask) {
3876            desc = _XkbWriteAtoms(desc, xkb->names->groups, XkbNumKbdGroups,
3877                                  client->swapped);
3878        }
3879        if (which & XkbKeyNamesMask) {
3880            for (i = 0; i < rep->nKeys; i++, desc += sizeof(XkbKeyNameRec)) {
3881                *((XkbKeyNamePtr) desc) = xkb->names->keys[i + rep->firstKey];
3882            }
3883        }
3884        if (which & XkbKeyAliasesMask) {
3885            XkbKeyAliasPtr pAl;
3886
3887            pAl = xkb->names->key_aliases;
3888            for (i = 0; i < rep->nKeyAliases;
3889                 i++, pAl++, desc += 2 * XkbKeyNameLength) {
3890                *((XkbKeyAliasPtr) desc) = *pAl;
3891            }
3892        }
3893        if ((which & XkbRGNamesMask) && (rep->nRadioGroups > 0)) {
3894            register CARD32 *atm = (CARD32 *) desc;
3895
3896            for (i = 0; i < rep->nRadioGroups; i++, atm++) {
3897                *atm = (CARD32) xkb->names->radio_groups[i];
3898                if (client->swapped) {
3899                    swapl(atm);
3900                }
3901            }
3902            desc += rep->nRadioGroups * 4;
3903        }
3904    }
3905
3906    if ((desc - start) != (length)) {
3907        ErrorF("[xkb] BOGUS LENGTH in write names, expected %d, got %ld\n",
3908               length, (unsigned long) (desc - start));
3909    }
3910    WriteToClient(client, SIZEOF(xkbGetNamesReply), rep);
3911    WriteToClient(client, length, start);
3912    free((char *) start);
3913    return Success;
3914}
3915
3916int
3917ProcXkbGetNames(ClientPtr client)
3918{
3919    DeviceIntPtr dev;
3920    XkbDescPtr xkb;
3921    xkbGetNamesReply rep;
3922
3923    REQUEST(xkbGetNamesReq);
3924    REQUEST_SIZE_MATCH(xkbGetNamesReq);
3925
3926    if (!(client->xkbClientFlags & _XkbClientInitialized))
3927        return BadAccess;
3928
3929    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
3930    CHK_MASK_LEGAL(0x01, stuff->which, XkbAllNamesMask);
3931
3932    xkb = dev->key->xkbInfo->desc;
3933    rep = (xkbGetNamesReply) {
3934        .type = X_Reply,
3935        .deviceID = dev->id,
3936        .sequenceNumber = client->sequence,
3937        .length = 0,
3938        .which = stuff->which,
3939        .nTypes = xkb->map->num_types,
3940        .firstKey = xkb->min_key_code,
3941        .nKeys = XkbNumKeys(xkb),
3942        .nKeyAliases = xkb->names ? xkb->names->num_key_aliases : 0,
3943        .nRadioGroups = xkb->names ? xkb->names->num_rg : 0
3944    };
3945    XkbComputeGetNamesReplySize(xkb, &rep);
3946    return XkbSendNames(client, xkb, &rep);
3947}
3948
3949/***====================================================================***/
3950
3951static CARD32 *
3952_XkbCheckAtoms(CARD32 *wire, int nAtoms, int swapped, Atom *pError)
3953{
3954    register int i;
3955
3956    for (i = 0; i < nAtoms; i++, wire++) {
3957        if (swapped) {
3958            swapl(wire);
3959        }
3960        if ((((Atom) *wire) != None) && (!ValidAtom((Atom) *wire))) {
3961            *pError = ((Atom) *wire);
3962            return NULL;
3963        }
3964    }
3965    return wire;
3966}
3967
3968static CARD32 *
3969_XkbCheckMaskedAtoms(CARD32 *wire, int nAtoms, CARD32 present, int swapped,
3970                     Atom *pError)
3971{
3972    register unsigned i, bit;
3973
3974    for (i = 0, bit = 1; (i < nAtoms) && (present); i++, bit <<= 1) {
3975        if ((present & bit) == 0)
3976            continue;
3977        if (swapped) {
3978            swapl(wire);
3979        }
3980        if ((((Atom) *wire) != None) && (!ValidAtom(((Atom) *wire)))) {
3981            *pError = (Atom) *wire;
3982            return NULL;
3983        }
3984        wire++;
3985    }
3986    return wire;
3987}
3988
3989static Atom *
3990_XkbCopyMaskedAtoms(Atom *wire, Atom *dest, int nAtoms, CARD32 present)
3991{
3992    register int i, bit;
3993
3994    for (i = 0, bit = 1; (i < nAtoms) && (present); i++, bit <<= 1) {
3995        if ((present & bit) == 0)
3996            continue;
3997        dest[i] = *wire++;
3998    }
3999    return wire;
4000}
4001
4002static Bool
4003_XkbCheckTypeName(Atom name, int typeNdx)
4004{
4005    const char *str;
4006
4007    str = NameForAtom(name);
4008    if ((strcmp(str, "ONE_LEVEL") == 0) || (strcmp(str, "TWO_LEVEL") == 0) ||
4009        (strcmp(str, "ALPHABETIC") == 0) || (strcmp(str, "KEYPAD") == 0))
4010        return FALSE;
4011    return TRUE;
4012}
4013
4014/**
4015 * Check the device-dependent data in the request against the device. Returns
4016 * Success, or the appropriate error code.
4017 */
4018static int
4019_XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
4020                  xkbSetNamesReq * stuff, CARD32 *data)
4021{
4022    XkbDescRec *xkb;
4023    CARD32 *tmp;
4024    Atom bad = None;
4025
4026    tmp = data;
4027    xkb = dev->key->xkbInfo->desc;
4028
4029    if (stuff->which & XkbKeyTypeNamesMask) {
4030        int i;
4031        CARD32 *old;
4032
4033        if (stuff->nTypes < 1) {
4034            client->errorValue = _XkbErrCode2(0x02, stuff->nTypes);
4035            return BadValue;
4036        }
4037        if ((unsigned) (stuff->firstType + stuff->nTypes - 1) >=
4038            xkb->map->num_types) {
4039            client->errorValue =
4040                _XkbErrCode4(0x03, stuff->firstType, stuff->nTypes,
4041                             xkb->map->num_types);
4042            return BadValue;
4043        }
4044        if (((unsigned) stuff->firstType) <= XkbLastRequiredType) {
4045            client->errorValue = _XkbErrCode2(0x04, stuff->firstType);
4046            return BadAccess;
4047        }
4048        old = tmp;
4049        tmp = _XkbCheckAtoms(tmp, stuff->nTypes, client->swapped, &bad);
4050        if (!tmp) {
4051            client->errorValue = bad;
4052            return BadAtom;
4053        }
4054        for (i = 0; i < stuff->nTypes; i++, old++) {
4055            if (!_XkbCheckTypeName((Atom) *old, stuff->firstType + i))
4056                client->errorValue = _XkbErrCode2(0x05, i);
4057        }
4058    }
4059    if (stuff->which & XkbKTLevelNamesMask) {
4060        unsigned i;
4061        XkbKeyTypePtr type;
4062        CARD8 *width;
4063
4064        if (stuff->nKTLevels < 1) {
4065            client->errorValue = _XkbErrCode2(0x05, stuff->nKTLevels);
4066            return BadValue;
4067        }
4068        if ((unsigned) (stuff->firstKTLevel + stuff->nKTLevels - 1) >=
4069            xkb->map->num_types) {
4070            client->errorValue = _XkbErrCode4(0x06, stuff->firstKTLevel,
4071                                              stuff->nKTLevels,
4072                                              xkb->map->num_types);
4073            return BadValue;
4074        }
4075        width = (CARD8 *) tmp;
4076        tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels));
4077        type = &xkb->map->types[stuff->firstKTLevel];
4078        for (i = 0; i < stuff->nKTLevels; i++, type++) {
4079            if (width[i] == 0)
4080                continue;
4081            else if (width[i] != type->num_levels) {
4082                client->errorValue = _XkbErrCode4(0x07, i + stuff->firstKTLevel,
4083                                                  type->num_levels, width[i]);
4084                return BadMatch;
4085            }
4086            tmp = _XkbCheckAtoms(tmp, width[i], client->swapped, &bad);
4087            if (!tmp) {
4088                client->errorValue = bad;
4089                return BadAtom;
4090            }
4091        }
4092    }
4093    if (stuff->which & XkbIndicatorNamesMask) {
4094        if (stuff->indicators == 0) {
4095            client->errorValue = 0x08;
4096            return BadMatch;
4097        }
4098        tmp = _XkbCheckMaskedAtoms(tmp, XkbNumIndicators, stuff->indicators,
4099                                   client->swapped, &bad);
4100        if (!tmp) {
4101            client->errorValue = bad;
4102            return BadAtom;
4103        }
4104    }
4105    if (stuff->which & XkbVirtualModNamesMask) {
4106        if (stuff->virtualMods == 0) {
4107            client->errorValue = 0x09;
4108            return BadMatch;
4109        }
4110        tmp = _XkbCheckMaskedAtoms(tmp, XkbNumVirtualMods,
4111                                   (CARD32) stuff->virtualMods,
4112                                   client->swapped, &bad);
4113        if (!tmp) {
4114            client->errorValue = bad;
4115            return BadAtom;
4116        }
4117    }
4118    if (stuff->which & XkbGroupNamesMask) {
4119        if (stuff->groupNames == 0) {
4120            client->errorValue = 0x0a;
4121            return BadMatch;
4122        }
4123        tmp = _XkbCheckMaskedAtoms(tmp, XkbNumKbdGroups,
4124                                   (CARD32) stuff->groupNames,
4125                                   client->swapped, &bad);
4126        if (!tmp) {
4127            client->errorValue = bad;
4128            return BadAtom;
4129        }
4130    }
4131    if (stuff->which & XkbKeyNamesMask) {
4132        if (stuff->firstKey < (unsigned) xkb->min_key_code) {
4133            client->errorValue = _XkbErrCode3(0x0b, xkb->min_key_code,
4134                                              stuff->firstKey);
4135            return BadValue;
4136        }
4137        if (((unsigned) (stuff->firstKey + stuff->nKeys - 1) >
4138             xkb->max_key_code) || (stuff->nKeys < 1)) {
4139            client->errorValue =
4140                _XkbErrCode4(0x0c, xkb->max_key_code, stuff->firstKey,
4141                             stuff->nKeys);
4142            return BadValue;
4143        }
4144        tmp += stuff->nKeys;
4145    }
4146    if ((stuff->which & XkbKeyAliasesMask) && (stuff->nKeyAliases > 0)) {
4147        tmp += stuff->nKeyAliases * 2;
4148    }
4149    if (stuff->which & XkbRGNamesMask) {
4150        if (stuff->nRadioGroups < 1) {
4151            client->errorValue = _XkbErrCode2(0x0d, stuff->nRadioGroups);
4152            return BadValue;
4153        }
4154        tmp = _XkbCheckAtoms(tmp, stuff->nRadioGroups, client->swapped, &bad);
4155        if (!tmp) {
4156            client->errorValue = bad;
4157            return BadAtom;
4158        }
4159    }
4160    if ((tmp - ((CARD32 *) stuff)) != stuff->length) {
4161        client->errorValue = stuff->length;
4162        return BadLength;
4163    }
4164
4165    return Success;
4166}
4167
4168static int
4169_XkbSetNames(ClientPtr client, DeviceIntPtr dev, xkbSetNamesReq * stuff)
4170{
4171    XkbDescRec *xkb;
4172    XkbNamesRec *names;
4173    CARD32 *tmp;
4174    xkbNamesNotify nn;
4175
4176    tmp = (CARD32 *) &stuff[1];
4177    xkb = dev->key->xkbInfo->desc;
4178    names = xkb->names;
4179
4180    if (XkbAllocNames(xkb, stuff->which, stuff->nRadioGroups,
4181                      stuff->nKeyAliases) != Success) {
4182        return BadAlloc;
4183    }
4184
4185    memset(&nn, 0, sizeof(xkbNamesNotify));
4186    nn.changed = stuff->which;
4187    tmp = (CARD32 *) &stuff[1];
4188    if (stuff->which & XkbKeycodesNameMask)
4189        names->keycodes = *tmp++;
4190    if (stuff->which & XkbGeometryNameMask)
4191        names->geometry = *tmp++;
4192    if (stuff->which & XkbSymbolsNameMask)
4193        names->symbols = *tmp++;
4194    if (stuff->which & XkbPhysSymbolsNameMask)
4195        names->phys_symbols = *tmp++;
4196    if (stuff->which & XkbTypesNameMask)
4197        names->types = *tmp++;
4198    if (stuff->which & XkbCompatNameMask)
4199        names->compat = *tmp++;
4200    if ((stuff->which & XkbKeyTypeNamesMask) && (stuff->nTypes > 0)) {
4201        register unsigned i;
4202        register XkbKeyTypePtr type;
4203
4204        type = &xkb->map->types[stuff->firstType];
4205        for (i = 0; i < stuff->nTypes; i++, type++) {
4206            type->name = *tmp++;
4207        }
4208        nn.firstType = stuff->firstType;
4209        nn.nTypes = stuff->nTypes;
4210    }
4211    if (stuff->which & XkbKTLevelNamesMask) {
4212        register XkbKeyTypePtr type;
4213        register unsigned i;
4214        CARD8 *width;
4215
4216        width = (CARD8 *) tmp;
4217        tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels));
4218        type = &xkb->map->types[stuff->firstKTLevel];
4219        for (i = 0; i < stuff->nKTLevels; i++, type++) {
4220            if (width[i] > 0) {
4221                if (type->level_names) {
4222                    register unsigned n;
4223
4224                    for (n = 0; n < width[i]; n++) {
4225                        type->level_names[n] = tmp[n];
4226                    }
4227                }
4228                tmp += width[i];
4229            }
4230        }
4231        nn.firstLevelName = 0;
4232        nn.nLevelNames = stuff->nTypes;
4233    }
4234    if (stuff->which & XkbIndicatorNamesMask) {
4235        tmp = _XkbCopyMaskedAtoms(tmp, names->indicators, XkbNumIndicators,
4236                                  stuff->indicators);
4237        nn.changedIndicators = stuff->indicators;
4238    }
4239    if (stuff->which & XkbVirtualModNamesMask) {
4240        tmp = _XkbCopyMaskedAtoms(tmp, names->vmods, XkbNumVirtualMods,
4241                                  stuff->virtualMods);
4242        nn.changedVirtualMods = stuff->virtualMods;
4243    }
4244    if (stuff->which & XkbGroupNamesMask) {
4245        tmp = _XkbCopyMaskedAtoms(tmp, names->groups, XkbNumKbdGroups,
4246                                  stuff->groupNames);
4247        nn.changedVirtualMods = stuff->groupNames;
4248    }
4249    if (stuff->which & XkbKeyNamesMask) {
4250        memcpy((char *) &names->keys[stuff->firstKey], (char *) tmp,
4251               stuff->nKeys * XkbKeyNameLength);
4252        tmp += stuff->nKeys;
4253        nn.firstKey = stuff->firstKey;
4254        nn.nKeys = stuff->nKeys;
4255    }
4256    if (stuff->which & XkbKeyAliasesMask) {
4257        if (stuff->nKeyAliases > 0) {
4258            register int na = stuff->nKeyAliases;
4259
4260            if (XkbAllocNames(xkb, XkbKeyAliasesMask, 0, na) != Success)
4261                return BadAlloc;
4262            memcpy((char *) names->key_aliases, (char *) tmp,
4263                   stuff->nKeyAliases * sizeof(XkbKeyAliasRec));
4264            tmp += stuff->nKeyAliases * 2;
4265        }
4266        else if (names->key_aliases != NULL) {
4267            free(names->key_aliases);
4268            names->key_aliases = NULL;
4269            names->num_key_aliases = 0;
4270        }
4271        nn.nAliases = names->num_key_aliases;
4272    }
4273    if (stuff->which & XkbRGNamesMask) {
4274        if (stuff->nRadioGroups > 0) {
4275            register unsigned i, nrg;
4276
4277            nrg = stuff->nRadioGroups;
4278            if (XkbAllocNames(xkb, XkbRGNamesMask, nrg, 0) != Success)
4279                return BadAlloc;
4280
4281            for (i = 0; i < stuff->nRadioGroups; i++) {
4282                names->radio_groups[i] = tmp[i];
4283            }
4284            tmp += stuff->nRadioGroups;
4285        }
4286        else if (names->radio_groups) {
4287            free(names->radio_groups);
4288            names->radio_groups = NULL;
4289            names->num_rg = 0;
4290        }
4291        nn.nRadioGroups = names->num_rg;
4292    }
4293    if (nn.changed) {
4294        Bool needExtEvent;
4295
4296        needExtEvent = (nn.changed & XkbIndicatorNamesMask) != 0;
4297        XkbSendNamesNotify(dev, &nn);
4298        if (needExtEvent) {
4299            XkbSrvLedInfoPtr sli;
4300            xkbExtensionDeviceNotify edev;
4301            register int i;
4302            register unsigned bit;
4303
4304            sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
4305                                    XkbXI_IndicatorsMask);
4306            sli->namesPresent = 0;
4307            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
4308                if (names->indicators[i] != None)
4309                    sli->namesPresent |= bit;
4310            }
4311            memset(&edev, 0, sizeof(xkbExtensionDeviceNotify));
4312            edev.reason = XkbXI_IndicatorNamesMask;
4313            edev.ledClass = KbdFeedbackClass;
4314            edev.ledID = dev->kbdfeed->ctrl.id;
4315            edev.ledsDefined = sli->namesPresent | sli->mapsPresent;
4316            edev.ledState = sli->effectiveState;
4317            edev.firstBtn = 0;
4318            edev.nBtns = 0;
4319            edev.supported = XkbXI_AllFeaturesMask;
4320            edev.unsupported = 0;
4321            XkbSendExtensionDeviceNotify(dev, client, &edev);
4322        }
4323    }
4324    return Success;
4325}
4326
4327int
4328ProcXkbSetNames(ClientPtr client)
4329{
4330    DeviceIntPtr dev;
4331    CARD32 *tmp;
4332    Atom bad;
4333    int rc;
4334
4335    REQUEST(xkbSetNamesReq);
4336    REQUEST_AT_LEAST_SIZE(xkbSetNamesReq);
4337
4338    if (!(client->xkbClientFlags & _XkbClientInitialized))
4339        return BadAccess;
4340
4341    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
4342    CHK_MASK_LEGAL(0x01, stuff->which, XkbAllNamesMask);
4343
4344    /* check device-independent stuff */
4345    tmp = (CARD32 *) &stuff[1];
4346
4347    if (stuff->which & XkbKeycodesNameMask) {
4348        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4349        if (!tmp) {
4350            client->errorValue = bad;
4351            return BadAtom;
4352        }
4353    }
4354    if (stuff->which & XkbGeometryNameMask) {
4355        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4356        if (!tmp) {
4357            client->errorValue = bad;
4358            return BadAtom;
4359        }
4360    }
4361    if (stuff->which & XkbSymbolsNameMask) {
4362        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4363        if (!tmp) {
4364            client->errorValue = bad;
4365            return BadAtom;
4366        }
4367    }
4368    if (stuff->which & XkbPhysSymbolsNameMask) {
4369        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4370        if (!tmp) {
4371            client->errorValue = bad;
4372            return BadAtom;
4373        }
4374    }
4375    if (stuff->which & XkbTypesNameMask) {
4376        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4377        if (!tmp) {
4378            client->errorValue = bad;
4379            return BadAtom;
4380        }
4381    }
4382    if (stuff->which & XkbCompatNameMask) {
4383        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4384        if (!tmp) {
4385            client->errorValue = bad;
4386            return BadAtom;
4387        }
4388    }
4389
4390    /* start of device-dependent tests */
4391    rc = _XkbSetNamesCheck(client, dev, stuff, tmp);
4392    if (rc != Success)
4393        return rc;
4394
4395    if (stuff->deviceSpec == XkbUseCoreKbd) {
4396        DeviceIntPtr other;
4397
4398        for (other = inputInfo.devices; other; other = other->next) {
4399            if ((other != dev) && other->key && !IsMaster(other) &&
4400                GetMaster(other, MASTER_KEYBOARD) == dev) {
4401
4402                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
4403                              DixManageAccess);
4404                if (rc == Success) {
4405                    rc = _XkbSetNamesCheck(client, other, stuff, tmp);
4406                    if (rc != Success)
4407                        return rc;
4408                }
4409            }
4410        }
4411    }
4412
4413    /* everything is okay -- update names */
4414
4415    rc = _XkbSetNames(client, dev, stuff);
4416    if (rc != Success)
4417        return rc;
4418
4419    if (stuff->deviceSpec == XkbUseCoreKbd) {
4420        DeviceIntPtr other;
4421
4422        for (other = inputInfo.devices; other; other = other->next) {
4423            if ((other != dev) && other->key && !IsMaster(other) &&
4424                GetMaster(other, MASTER_KEYBOARD) == dev) {
4425
4426                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
4427                              DixManageAccess);
4428                if (rc == Success)
4429                    _XkbSetNames(client, other, stuff);
4430            }
4431        }
4432    }
4433
4434    /* everything is okay -- update names */
4435
4436    return Success;
4437}
4438
4439/***====================================================================***/
4440
4441#include "xkbgeom.h"
4442
4443#define	XkbSizeCountedString(s)  ((s)?((((2+strlen(s))+3)/4)*4):4)
4444
4445/**
4446 * Write the zero-terminated string str into wire as a pascal string with a
4447 * 16-bit length field prefixed before the actual string.
4448 *
4449 * @param wire The destination array, usually the wire struct
4450 * @param str The source string as zero-terminated C string
4451 * @param swap If TRUE, the length field is swapped.
4452 *
4453 * @return The input string in the format <string length><string> with a
4454 * (swapped) 16 bit string length, non-zero terminated.
4455 */
4456static char *
4457XkbWriteCountedString(char *wire, const char *str, Bool swap)
4458{
4459    CARD16 len, *pLen, paddedLen;
4460
4461    if (!str)
4462        return wire;
4463
4464    len = strlen(str);
4465    pLen = (CARD16 *) wire;
4466    *pLen = len;
4467    if (swap) {
4468        swaps(pLen);
4469    }
4470    paddedLen = pad_to_int32(sizeof(len) + len) - sizeof(len);
4471    strncpy(&wire[sizeof(len)], str, paddedLen);
4472    wire += sizeof(len) + paddedLen;
4473    return wire;
4474}
4475
4476static int
4477XkbSizeGeomProperties(XkbGeometryPtr geom)
4478{
4479    register int i, size;
4480    XkbPropertyPtr prop;
4481
4482    for (size = i = 0, prop = geom->properties; i < geom->num_properties;
4483         i++, prop++) {
4484        size += XkbSizeCountedString(prop->name);
4485        size += XkbSizeCountedString(prop->value);
4486    }
4487    return size;
4488}
4489
4490static char *
4491XkbWriteGeomProperties(char *wire, XkbGeometryPtr geom, Bool swap)
4492{
4493    register int i;
4494    register XkbPropertyPtr prop;
4495
4496    for (i = 0, prop = geom->properties; i < geom->num_properties; i++, prop++) {
4497        wire = XkbWriteCountedString(wire, prop->name, swap);
4498        wire = XkbWriteCountedString(wire, prop->value, swap);
4499    }
4500    return wire;
4501}
4502
4503static int
4504XkbSizeGeomKeyAliases(XkbGeometryPtr geom)
4505{
4506    return geom->num_key_aliases * (2 * XkbKeyNameLength);
4507}
4508
4509static char *
4510XkbWriteGeomKeyAliases(char *wire, XkbGeometryPtr geom, Bool swap)
4511{
4512    register int sz;
4513
4514    sz = geom->num_key_aliases * (XkbKeyNameLength * 2);
4515    if (sz > 0) {
4516        memcpy(wire, (char *) geom->key_aliases, sz);
4517        wire += sz;
4518    }
4519    return wire;
4520}
4521
4522static int
4523XkbSizeGeomColors(XkbGeometryPtr geom)
4524{
4525    register int i, size;
4526    register XkbColorPtr color;
4527
4528    for (i = size = 0, color = geom->colors; i < geom->num_colors; i++, color++) {
4529        size += XkbSizeCountedString(color->spec);
4530    }
4531    return size;
4532}
4533
4534static char *
4535XkbWriteGeomColors(char *wire, XkbGeometryPtr geom, Bool swap)
4536{
4537    register int i;
4538    register XkbColorPtr color;
4539
4540    for (i = 0, color = geom->colors; i < geom->num_colors; i++, color++) {
4541        wire = XkbWriteCountedString(wire, color->spec, swap);
4542    }
4543    return wire;
4544}
4545
4546static int
4547XkbSizeGeomShapes(XkbGeometryPtr geom)
4548{
4549    register int i, size;
4550    register XkbShapePtr shape;
4551
4552    for (i = size = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) {
4553        register int n;
4554        register XkbOutlinePtr ol;
4555
4556        size += SIZEOF(xkbShapeWireDesc);
4557        for (n = 0, ol = shape->outlines; n < shape->num_outlines; n++, ol++) {
4558            size += SIZEOF(xkbOutlineWireDesc);
4559            size += ol->num_points * SIZEOF(xkbPointWireDesc);
4560        }
4561    }
4562    return size;
4563}
4564
4565static char *
4566XkbWriteGeomShapes(char *wire, XkbGeometryPtr geom, Bool swap)
4567{
4568    int i;
4569    XkbShapePtr shape;
4570    xkbShapeWireDesc *shapeWire;
4571
4572    for (i = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) {
4573        register int o;
4574        XkbOutlinePtr ol;
4575        xkbOutlineWireDesc *olWire;
4576
4577        shapeWire = (xkbShapeWireDesc *) wire;
4578        shapeWire->name = shape->name;
4579        shapeWire->nOutlines = shape->num_outlines;
4580        if (shape->primary != NULL)
4581            shapeWire->primaryNdx = XkbOutlineIndex(shape, shape->primary);
4582        else
4583            shapeWire->primaryNdx = XkbNoShape;
4584        if (shape->approx != NULL)
4585            shapeWire->approxNdx = XkbOutlineIndex(shape, shape->approx);
4586        else
4587            shapeWire->approxNdx = XkbNoShape;
4588        shapeWire->pad = 0;
4589        if (swap) {
4590            swapl(&shapeWire->name);
4591        }
4592        wire = (char *) &shapeWire[1];
4593        for (o = 0, ol = shape->outlines; o < shape->num_outlines; o++, ol++) {
4594            register int p;
4595            XkbPointPtr pt;
4596            xkbPointWireDesc *ptWire;
4597
4598            olWire = (xkbOutlineWireDesc *) wire;
4599            olWire->nPoints = ol->num_points;
4600            olWire->cornerRadius = ol->corner_radius;
4601            olWire->pad = 0;
4602            wire = (char *) &olWire[1];
4603            ptWire = (xkbPointWireDesc *) wire;
4604            for (p = 0, pt = ol->points; p < ol->num_points; p++, pt++) {
4605                ptWire[p].x = pt->x;
4606                ptWire[p].y = pt->y;
4607                if (swap) {
4608                    swaps(&ptWire[p].x);
4609                    swaps(&ptWire[p].y);
4610                }
4611            }
4612            wire = (char *) &ptWire[ol->num_points];
4613        }
4614    }
4615    return wire;
4616}
4617
4618static int
4619XkbSizeGeomDoodads(int num_doodads, XkbDoodadPtr doodad)
4620{
4621    register int i, size;
4622
4623    for (i = size = 0; i < num_doodads; i++, doodad++) {
4624        size += SIZEOF(xkbAnyDoodadWireDesc);
4625        if (doodad->any.type == XkbTextDoodad) {
4626            size += XkbSizeCountedString(doodad->text.text);
4627            size += XkbSizeCountedString(doodad->text.font);
4628        }
4629        else if (doodad->any.type == XkbLogoDoodad) {
4630            size += XkbSizeCountedString(doodad->logo.logo_name);
4631        }
4632    }
4633    return size;
4634}
4635
4636static char *
4637XkbWriteGeomDoodads(char *wire, int num_doodads, XkbDoodadPtr doodad, Bool swap)
4638{
4639    register int i;
4640    xkbDoodadWireDesc *doodadWire;
4641
4642    for (i = 0; i < num_doodads; i++, doodad++) {
4643        doodadWire = (xkbDoodadWireDesc *) wire;
4644        wire = (char *) &doodadWire[1];
4645        memset(doodadWire, 0, SIZEOF(xkbDoodadWireDesc));
4646        doodadWire->any.name = doodad->any.name;
4647        doodadWire->any.type = doodad->any.type;
4648        doodadWire->any.priority = doodad->any.priority;
4649        doodadWire->any.top = doodad->any.top;
4650        doodadWire->any.left = doodad->any.left;
4651        if (swap) {
4652            swapl(&doodadWire->any.name);
4653            swaps(&doodadWire->any.top);
4654            swaps(&doodadWire->any.left);
4655        }
4656        switch (doodad->any.type) {
4657        case XkbOutlineDoodad:
4658        case XkbSolidDoodad:
4659            doodadWire->shape.angle = doodad->shape.angle;
4660            doodadWire->shape.colorNdx = doodad->shape.color_ndx;
4661            doodadWire->shape.shapeNdx = doodad->shape.shape_ndx;
4662            if (swap) {
4663                swaps(&doodadWire->shape.angle);
4664            }
4665            break;
4666        case XkbTextDoodad:
4667            doodadWire->text.angle = doodad->text.angle;
4668            doodadWire->text.width = doodad->text.width;
4669            doodadWire->text.height = doodad->text.height;
4670            doodadWire->text.colorNdx = doodad->text.color_ndx;
4671            if (swap) {
4672                swaps(&doodadWire->text.angle);
4673                swaps(&doodadWire->text.width);
4674                swaps(&doodadWire->text.height);
4675            }
4676            wire = XkbWriteCountedString(wire, doodad->text.text, swap);
4677            wire = XkbWriteCountedString(wire, doodad->text.font, swap);
4678            break;
4679        case XkbIndicatorDoodad:
4680            doodadWire->indicator.shapeNdx = doodad->indicator.shape_ndx;
4681            doodadWire->indicator.onColorNdx = doodad->indicator.on_color_ndx;
4682            doodadWire->indicator.offColorNdx = doodad->indicator.off_color_ndx;
4683            break;
4684        case XkbLogoDoodad:
4685            doodadWire->logo.angle = doodad->logo.angle;
4686            doodadWire->logo.colorNdx = doodad->logo.color_ndx;
4687            doodadWire->logo.shapeNdx = doodad->logo.shape_ndx;
4688            wire = XkbWriteCountedString(wire, doodad->logo.logo_name, swap);
4689            break;
4690        default:
4691            ErrorF("[xkb] Unknown doodad type %d in XkbWriteGeomDoodads\n",
4692                   doodad->any.type);
4693            ErrorF("[xkb] Ignored\n");
4694            break;
4695        }
4696    }
4697    return wire;
4698}
4699
4700static char *
4701XkbWriteGeomOverlay(char *wire, XkbOverlayPtr ol, Bool swap)
4702{
4703    register int r;
4704    XkbOverlayRowPtr row;
4705    xkbOverlayWireDesc *olWire;
4706
4707    olWire = (xkbOverlayWireDesc *) wire;
4708    olWire->name = ol->name;
4709    olWire->nRows = ol->num_rows;
4710    olWire->pad1 = 0;
4711    olWire->pad2 = 0;
4712    if (swap) {
4713        swapl(&olWire->name);
4714    }
4715    wire = (char *) &olWire[1];
4716    for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) {
4717        unsigned int k;
4718        XkbOverlayKeyPtr key;
4719        xkbOverlayRowWireDesc *rowWire;
4720
4721        rowWire = (xkbOverlayRowWireDesc *) wire;
4722        rowWire->rowUnder = row->row_under;
4723        rowWire->nKeys = row->num_keys;
4724        rowWire->pad1 = 0;
4725        wire = (char *) &rowWire[1];
4726        for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
4727            xkbOverlayKeyWireDesc *keyWire;
4728
4729            keyWire = (xkbOverlayKeyWireDesc *) wire;
4730            memcpy(keyWire->over, key->over.name, XkbKeyNameLength);
4731            memcpy(keyWire->under, key->under.name, XkbKeyNameLength);
4732            wire = (char *) &keyWire[1];
4733        }
4734    }
4735    return wire;
4736}
4737
4738static int
4739XkbSizeGeomSections(XkbGeometryPtr geom)
4740{
4741    register int i, size;
4742    XkbSectionPtr section;
4743
4744    for (i = size = 0, section = geom->sections; i < geom->num_sections;
4745         i++, section++) {
4746        size += SIZEOF(xkbSectionWireDesc);
4747        if (section->rows) {
4748            int r;
4749            XkbRowPtr row;
4750
4751            for (r = 0, row = section->rows; r < section->num_rows; row++, r++) {
4752                size += SIZEOF(xkbRowWireDesc);
4753                size += row->num_keys * SIZEOF(xkbKeyWireDesc);
4754            }
4755        }
4756        if (section->doodads)
4757            size += XkbSizeGeomDoodads(section->num_doodads, section->doodads);
4758        if (section->overlays) {
4759            int o;
4760            XkbOverlayPtr ol;
4761
4762            for (o = 0, ol = section->overlays; o < section->num_overlays;
4763                 o++, ol++) {
4764                int r;
4765                XkbOverlayRowPtr row;
4766
4767                size += SIZEOF(xkbOverlayWireDesc);
4768                for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) {
4769                    size += SIZEOF(xkbOverlayRowWireDesc);
4770                    size += row->num_keys * SIZEOF(xkbOverlayKeyWireDesc);
4771                }
4772            }
4773        }
4774    }
4775    return size;
4776}
4777
4778static char *
4779XkbWriteGeomSections(char *wire, XkbGeometryPtr geom, Bool swap)
4780{
4781    register int i;
4782    XkbSectionPtr section;
4783    xkbSectionWireDesc *sectionWire;
4784
4785    for (i = 0, section = geom->sections; i < geom->num_sections;
4786         i++, section++) {
4787        sectionWire = (xkbSectionWireDesc *) wire;
4788        sectionWire->name = section->name;
4789        sectionWire->top = section->top;
4790        sectionWire->left = section->left;
4791        sectionWire->width = section->width;
4792        sectionWire->height = section->height;
4793        sectionWire->angle = section->angle;
4794        sectionWire->priority = section->priority;
4795        sectionWire->nRows = section->num_rows;
4796        sectionWire->nDoodads = section->num_doodads;
4797        sectionWire->nOverlays = section->num_overlays;
4798        sectionWire->pad = 0;
4799        if (swap) {
4800            swapl(&sectionWire->name);
4801            swaps(&sectionWire->top);
4802            swaps(&sectionWire->left);
4803            swaps(&sectionWire->width);
4804            swaps(&sectionWire->height);
4805            swaps(&sectionWire->angle);
4806        }
4807        wire = (char *) &sectionWire[1];
4808        if (section->rows) {
4809            int r;
4810            XkbRowPtr row;
4811            xkbRowWireDesc *rowWire;
4812
4813            for (r = 0, row = section->rows; r < section->num_rows; r++, row++) {
4814                rowWire = (xkbRowWireDesc *) wire;
4815                rowWire->top = row->top;
4816                rowWire->left = row->left;
4817                rowWire->nKeys = row->num_keys;
4818                rowWire->vertical = row->vertical;
4819                rowWire->pad = 0;
4820                if (swap) {
4821                    swaps(&rowWire->top);
4822                    swaps(&rowWire->left);
4823                }
4824                wire = (char *) &rowWire[1];
4825                if (row->keys) {
4826                    int k;
4827                    XkbKeyPtr key;
4828                    xkbKeyWireDesc *keyWire;
4829
4830                    keyWire = (xkbKeyWireDesc *) wire;
4831                    for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
4832                        memcpy(keyWire[k].name, key->name.name,
4833                               XkbKeyNameLength);
4834                        keyWire[k].gap = key->gap;
4835                        keyWire[k].shapeNdx = key->shape_ndx;
4836                        keyWire[k].colorNdx = key->color_ndx;
4837                        if (swap) {
4838                            swaps(&keyWire[k].gap);
4839                        }
4840                    }
4841                    wire = (char *) &keyWire[row->num_keys];
4842                }
4843            }
4844        }
4845        if (section->doodads) {
4846            wire = XkbWriteGeomDoodads(wire,
4847                                       section->num_doodads, section->doodads,
4848                                       swap);
4849        }
4850        if (section->overlays) {
4851            register int o;
4852
4853            for (o = 0; o < section->num_overlays; o++) {
4854                wire = XkbWriteGeomOverlay(wire, &section->overlays[o], swap);
4855            }
4856        }
4857    }
4858    return wire;
4859}
4860
4861static Status
4862XkbComputeGetGeometryReplySize(XkbGeometryPtr geom,
4863                               xkbGetGeometryReply * rep, Atom name)
4864{
4865    int len;
4866
4867    if (geom != NULL) {
4868        len = XkbSizeCountedString(geom->label_font);
4869        len += XkbSizeGeomProperties(geom);
4870        len += XkbSizeGeomColors(geom);
4871        len += XkbSizeGeomShapes(geom);
4872        len += XkbSizeGeomSections(geom);
4873        len += XkbSizeGeomDoodads(geom->num_doodads, geom->doodads);
4874        len += XkbSizeGeomKeyAliases(geom);
4875        rep->length = len / 4;
4876        rep->found = TRUE;
4877        rep->name = geom->name;
4878        rep->widthMM = geom->width_mm;
4879        rep->heightMM = geom->height_mm;
4880        rep->nProperties = geom->num_properties;
4881        rep->nColors = geom->num_colors;
4882        rep->nShapes = geom->num_shapes;
4883        rep->nSections = geom->num_sections;
4884        rep->nDoodads = geom->num_doodads;
4885        rep->nKeyAliases = geom->num_key_aliases;
4886        rep->baseColorNdx = XkbGeomColorIndex(geom, geom->base_color);
4887        rep->labelColorNdx = XkbGeomColorIndex(geom, geom->label_color);
4888    }
4889    else {
4890        rep->length = 0;
4891        rep->found = FALSE;
4892        rep->name = name;
4893        rep->widthMM = rep->heightMM = 0;
4894        rep->nProperties = rep->nColors = rep->nShapes = 0;
4895        rep->nSections = rep->nDoodads = 0;
4896        rep->nKeyAliases = 0;
4897        rep->labelColorNdx = rep->baseColorNdx = 0;
4898    }
4899    return Success;
4900}
4901static int
4902XkbSendGeometry(ClientPtr client,
4903                XkbGeometryPtr geom, xkbGetGeometryReply * rep, Bool freeGeom)
4904{
4905    char *desc, *start;
4906    int len;
4907
4908    if (geom != NULL) {
4909        start = desc = xallocarray(rep->length, 4);
4910        if (!start)
4911            return BadAlloc;
4912        len = rep->length * 4;
4913        desc = XkbWriteCountedString(desc, geom->label_font, client->swapped);
4914        if (rep->nProperties > 0)
4915            desc = XkbWriteGeomProperties(desc, geom, client->swapped);
4916        if (rep->nColors > 0)
4917            desc = XkbWriteGeomColors(desc, geom, client->swapped);
4918        if (rep->nShapes > 0)
4919            desc = XkbWriteGeomShapes(desc, geom, client->swapped);
4920        if (rep->nSections > 0)
4921            desc = XkbWriteGeomSections(desc, geom, client->swapped);
4922        if (rep->nDoodads > 0)
4923            desc = XkbWriteGeomDoodads(desc, geom->num_doodads, geom->doodads,
4924                                       client->swapped);
4925        if (rep->nKeyAliases > 0)
4926            desc = XkbWriteGeomKeyAliases(desc, geom, client->swapped);
4927        if ((desc - start) != (len)) {
4928            ErrorF
4929                ("[xkb] BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n",
4930                 len, (unsigned long) (desc - start));
4931        }
4932    }
4933    else {
4934        len = 0;
4935        start = NULL;
4936    }
4937    if (client->swapped) {
4938        swaps(&rep->sequenceNumber);
4939        swapl(&rep->length);
4940        swapl(&rep->name);
4941        swaps(&rep->widthMM);
4942        swaps(&rep->heightMM);
4943        swaps(&rep->nProperties);
4944        swaps(&rep->nColors);
4945        swaps(&rep->nShapes);
4946        swaps(&rep->nSections);
4947        swaps(&rep->nDoodads);
4948        swaps(&rep->nKeyAliases);
4949    }
4950    WriteToClient(client, SIZEOF(xkbGetGeometryReply), rep);
4951    if (len > 0)
4952        WriteToClient(client, len, start);
4953    if (start != NULL)
4954        free((char *) start);
4955    if (freeGeom)
4956        XkbFreeGeometry(geom, XkbGeomAllMask, TRUE);
4957    return Success;
4958}
4959
4960int
4961ProcXkbGetGeometry(ClientPtr client)
4962{
4963    DeviceIntPtr dev;
4964    xkbGetGeometryReply rep;
4965    XkbGeometryPtr geom;
4966    Bool shouldFree;
4967    Status status;
4968
4969    REQUEST(xkbGetGeometryReq);
4970    REQUEST_SIZE_MATCH(xkbGetGeometryReq);
4971
4972    if (!(client->xkbClientFlags & _XkbClientInitialized))
4973        return BadAccess;
4974
4975    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
4976    CHK_ATOM_OR_NONE(stuff->name);
4977
4978    geom = XkbLookupNamedGeometry(dev, stuff->name, &shouldFree);
4979    rep = (xkbGetGeometryReply) {
4980        .type = X_Reply,
4981        .deviceID = dev->id,
4982        .sequenceNumber = client->sequence,
4983        .length = 0
4984    };
4985    status = XkbComputeGetGeometryReplySize(geom, &rep, stuff->name);
4986    if (status != Success)
4987        return status;
4988    else
4989        return XkbSendGeometry(client, geom, &rep, shouldFree);
4990}
4991
4992/***====================================================================***/
4993
4994static Status
4995_GetCountedString(char **wire_inout, ClientPtr client, char **str)
4996{
4997    char *wire, *next;
4998    CARD16 len;
4999
5000    wire = *wire_inout;
5001    len = *(CARD16 *) wire;
5002    if (client->swapped) {
5003        swaps(&len);
5004    }
5005    next = wire + XkbPaddedSize(len + 2);
5006    /* Check we're still within the size of the request */
5007    if (client->req_len <
5008        bytes_to_int32(next - (char *) client->requestBuffer))
5009        return BadValue;
5010    *str = malloc(len + 1);
5011    if (!*str)
5012        return BadAlloc;
5013    memcpy(*str, &wire[2], len);
5014    *(*str + len) = '\0';
5015    *wire_inout = next;
5016    return Success;
5017}
5018
5019static Status
5020_CheckSetDoodad(char **wire_inout,
5021                XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client)
5022{
5023    char *wire;
5024    xkbDoodadWireDesc *dWire;
5025    xkbAnyDoodadWireDesc any;
5026    xkbTextDoodadWireDesc text;
5027    XkbDoodadPtr doodad;
5028    Status status;
5029
5030    dWire = (xkbDoodadWireDesc *) (*wire_inout);
5031    any = dWire->any;
5032    wire = (char *) &dWire[1];
5033    if (client->swapped) {
5034        swapl(&any.name);
5035        swaps(&any.top);
5036        swaps(&any.left);
5037        swaps(&any.angle);
5038    }
5039    CHK_ATOM_ONLY(dWire->any.name);
5040    doodad = XkbAddGeomDoodad(geom, section, any.name);
5041    if (!doodad)
5042        return BadAlloc;
5043    doodad->any.type = dWire->any.type;
5044    doodad->any.priority = dWire->any.priority;
5045    doodad->any.top = any.top;
5046    doodad->any.left = any.left;
5047    doodad->any.angle = any.angle;
5048    switch (doodad->any.type) {
5049    case XkbOutlineDoodad:
5050    case XkbSolidDoodad:
5051        if (dWire->shape.colorNdx >= geom->num_colors) {
5052            client->errorValue = _XkbErrCode3(0x40, geom->num_colors,
5053                                              dWire->shape.colorNdx);
5054            return BadMatch;
5055        }
5056        if (dWire->shape.shapeNdx >= geom->num_shapes) {
5057            client->errorValue = _XkbErrCode3(0x41, geom->num_shapes,
5058                                              dWire->shape.shapeNdx);
5059            return BadMatch;
5060        }
5061        doodad->shape.color_ndx = dWire->shape.colorNdx;
5062        doodad->shape.shape_ndx = dWire->shape.shapeNdx;
5063        break;
5064    case XkbTextDoodad:
5065        if (dWire->text.colorNdx >= geom->num_colors) {
5066            client->errorValue = _XkbErrCode3(0x42, geom->num_colors,
5067                                              dWire->text.colorNdx);
5068            return BadMatch;
5069        }
5070        text = dWire->text;
5071        if (client->swapped) {
5072            swaps(&text.width);
5073            swaps(&text.height);
5074        }
5075        doodad->text.width = text.width;
5076        doodad->text.height = text.height;
5077        doodad->text.color_ndx = dWire->text.colorNdx;
5078        status = _GetCountedString(&wire, client, &doodad->text.text);
5079        if (status != Success)
5080            return status;
5081        status = _GetCountedString(&wire, client, &doodad->text.font);
5082        if (status != Success) {
5083            free (doodad->text.text);
5084            return status;
5085        }
5086        break;
5087    case XkbIndicatorDoodad:
5088        if (dWire->indicator.onColorNdx >= geom->num_colors) {
5089            client->errorValue = _XkbErrCode3(0x43, geom->num_colors,
5090                                              dWire->indicator.onColorNdx);
5091            return BadMatch;
5092        }
5093        if (dWire->indicator.offColorNdx >= geom->num_colors) {
5094            client->errorValue = _XkbErrCode3(0x44, geom->num_colors,
5095                                              dWire->indicator.offColorNdx);
5096            return BadMatch;
5097        }
5098        if (dWire->indicator.shapeNdx >= geom->num_shapes) {
5099            client->errorValue = _XkbErrCode3(0x45, geom->num_shapes,
5100                                              dWire->indicator.shapeNdx);
5101            return BadMatch;
5102        }
5103        doodad->indicator.shape_ndx = dWire->indicator.shapeNdx;
5104        doodad->indicator.on_color_ndx = dWire->indicator.onColorNdx;
5105        doodad->indicator.off_color_ndx = dWire->indicator.offColorNdx;
5106        break;
5107    case XkbLogoDoodad:
5108        if (dWire->logo.colorNdx >= geom->num_colors) {
5109            client->errorValue = _XkbErrCode3(0x46, geom->num_colors,
5110                                              dWire->logo.colorNdx);
5111            return BadMatch;
5112        }
5113        if (dWire->logo.shapeNdx >= geom->num_shapes) {
5114            client->errorValue = _XkbErrCode3(0x47, geom->num_shapes,
5115                                              dWire->logo.shapeNdx);
5116            return BadMatch;
5117        }
5118        doodad->logo.color_ndx = dWire->logo.colorNdx;
5119        doodad->logo.shape_ndx = dWire->logo.shapeNdx;
5120        status = _GetCountedString(&wire, client, &doodad->logo.logo_name);
5121        if (status != Success)
5122            return status;
5123        break;
5124    default:
5125        client->errorValue = _XkbErrCode2(0x4F, dWire->any.type);
5126        return BadValue;
5127    }
5128    *wire_inout = wire;
5129    return Success;
5130}
5131
5132static Status
5133_CheckSetOverlay(char **wire_inout,
5134                 XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client)
5135{
5136    register int r;
5137    char *wire;
5138    XkbOverlayPtr ol;
5139    xkbOverlayWireDesc *olWire;
5140    xkbOverlayRowWireDesc *rWire;
5141
5142    wire = *wire_inout;
5143    olWire = (xkbOverlayWireDesc *) wire;
5144    if (client->swapped) {
5145        swapl(&olWire->name);
5146    }
5147    CHK_ATOM_ONLY(olWire->name);
5148    ol = XkbAddGeomOverlay(section, olWire->name, olWire->nRows);
5149    rWire = (xkbOverlayRowWireDesc *) &olWire[1];
5150    for (r = 0; r < olWire->nRows; r++) {
5151        register int k;
5152        xkbOverlayKeyWireDesc *kWire;
5153        XkbOverlayRowPtr row;
5154
5155        if (rWire->rowUnder > section->num_rows) {
5156            client->errorValue = _XkbErrCode4(0x20, r, section->num_rows,
5157                                              rWire->rowUnder);
5158            return BadMatch;
5159        }
5160        row = XkbAddGeomOverlayRow(ol, rWire->rowUnder, rWire->nKeys);
5161        kWire = (xkbOverlayKeyWireDesc *) &rWire[1];
5162        for (k = 0; k < rWire->nKeys; k++, kWire++) {
5163            if (XkbAddGeomOverlayKey(ol, row,
5164                                     (char *) kWire->over,
5165                                     (char *) kWire->under) == NULL) {
5166                client->errorValue = _XkbErrCode3(0x21, r, k);
5167                return BadMatch;
5168            }
5169        }
5170        rWire = (xkbOverlayRowWireDesc *) kWire;
5171    }
5172    olWire = (xkbOverlayWireDesc *) rWire;
5173    wire = (char *) olWire;
5174    *wire_inout = wire;
5175    return Success;
5176}
5177
5178static Status
5179_CheckSetSections(XkbGeometryPtr geom,
5180                  xkbSetGeometryReq * req, char **wire_inout, ClientPtr client)
5181{
5182    Status status;
5183    register int s;
5184    char *wire;
5185    xkbSectionWireDesc *sWire;
5186    XkbSectionPtr section;
5187
5188    wire = *wire_inout;
5189    if (req->nSections < 1)
5190        return Success;
5191    sWire = (xkbSectionWireDesc *) wire;
5192    for (s = 0; s < req->nSections; s++) {
5193        register int r;
5194        xkbRowWireDesc *rWire;
5195
5196        if (client->swapped) {
5197            swapl(&sWire->name);
5198            swaps(&sWire->top);
5199            swaps(&sWire->left);
5200            swaps(&sWire->width);
5201            swaps(&sWire->height);
5202            swaps(&sWire->angle);
5203        }
5204        CHK_ATOM_ONLY(sWire->name);
5205        section = XkbAddGeomSection(geom, sWire->name, sWire->nRows,
5206                                    sWire->nDoodads, sWire->nOverlays);
5207        if (!section)
5208            return BadAlloc;
5209        section->priority = sWire->priority;
5210        section->top = sWire->top;
5211        section->left = sWire->left;
5212        section->width = sWire->width;
5213        section->height = sWire->height;
5214        section->angle = sWire->angle;
5215        rWire = (xkbRowWireDesc *) &sWire[1];
5216        for (r = 0; r < sWire->nRows; r++) {
5217            register int k;
5218            XkbRowPtr row;
5219            xkbKeyWireDesc *kWire;
5220
5221            if (client->swapped) {
5222                swaps(&rWire->top);
5223                swaps(&rWire->left);
5224            }
5225            row = XkbAddGeomRow(section, rWire->nKeys);
5226            if (!row)
5227                return BadAlloc;
5228            row->top = rWire->top;
5229            row->left = rWire->left;
5230            row->vertical = rWire->vertical;
5231            kWire = (xkbKeyWireDesc *) &rWire[1];
5232            for (k = 0; k < rWire->nKeys; k++) {
5233                XkbKeyPtr key;
5234
5235                key = XkbAddGeomKey(row);
5236                if (!key)
5237                    return BadAlloc;
5238                memcpy(key->name.name, kWire[k].name, XkbKeyNameLength);
5239                key->gap = kWire[k].gap;
5240                key->shape_ndx = kWire[k].shapeNdx;
5241                key->color_ndx = kWire[k].colorNdx;
5242                if (key->shape_ndx >= geom->num_shapes) {
5243                    client->errorValue = _XkbErrCode3(0x10, key->shape_ndx,
5244                                                      geom->num_shapes);
5245                    return BadMatch;
5246                }
5247                if (key->color_ndx >= geom->num_colors) {
5248                    client->errorValue = _XkbErrCode3(0x11, key->color_ndx,
5249                                                      geom->num_colors);
5250                    return BadMatch;
5251                }
5252            }
5253            rWire = (xkbRowWireDesc *) &kWire[rWire->nKeys];
5254        }
5255        wire = (char *) rWire;
5256        if (sWire->nDoodads > 0) {
5257            register int d;
5258
5259            for (d = 0; d < sWire->nDoodads; d++) {
5260                status = _CheckSetDoodad(&wire, geom, section, client);
5261                if (status != Success)
5262                    return status;
5263            }
5264        }
5265        if (sWire->nOverlays > 0) {
5266            register int o;
5267
5268            for (o = 0; o < sWire->nOverlays; o++) {
5269                status = _CheckSetOverlay(&wire, geom, section, client);
5270                if (status != Success)
5271                    return status;
5272            }
5273        }
5274        sWire = (xkbSectionWireDesc *) wire;
5275    }
5276    wire = (char *) sWire;
5277    *wire_inout = wire;
5278    return Success;
5279}
5280
5281static Status
5282_CheckSetShapes(XkbGeometryPtr geom,
5283                xkbSetGeometryReq * req, char **wire_inout, ClientPtr client)
5284{
5285    register int i;
5286    char *wire;
5287
5288    wire = *wire_inout;
5289    if (req->nShapes < 1) {
5290        client->errorValue = _XkbErrCode2(0x06, req->nShapes);
5291        return BadValue;
5292    }
5293    else {
5294        xkbShapeWireDesc *shapeWire;
5295        XkbShapePtr shape;
5296        register int o;
5297
5298        shapeWire = (xkbShapeWireDesc *) wire;
5299        for (i = 0; i < req->nShapes; i++) {
5300            xkbOutlineWireDesc *olWire;
5301            XkbOutlinePtr ol;
5302
5303            shape =
5304                XkbAddGeomShape(geom, shapeWire->name, shapeWire->nOutlines);
5305            if (!shape)
5306                return BadAlloc;
5307            olWire = (xkbOutlineWireDesc *) (&shapeWire[1]);
5308            for (o = 0; o < shapeWire->nOutlines; o++) {
5309                register int p;
5310                XkbPointPtr pt;
5311                xkbPointWireDesc *ptWire;
5312
5313                ol = XkbAddGeomOutline(shape, olWire->nPoints);
5314                if (!ol)
5315                    return BadAlloc;
5316                ol->corner_radius = olWire->cornerRadius;
5317                ptWire = (xkbPointWireDesc *) &olWire[1];
5318                for (p = 0, pt = ol->points; p < olWire->nPoints; p++, pt++) {
5319                    pt->x = ptWire[p].x;
5320                    pt->y = ptWire[p].y;
5321                    if (client->swapped) {
5322                        swaps(&pt->x);
5323                        swaps(&pt->y);
5324                    }
5325                }
5326                ol->num_points = olWire->nPoints;
5327                olWire = (xkbOutlineWireDesc *) (&ptWire[olWire->nPoints]);
5328            }
5329            if (shapeWire->primaryNdx != XkbNoShape)
5330                shape->primary = &shape->outlines[shapeWire->primaryNdx];
5331            if (shapeWire->approxNdx != XkbNoShape)
5332                shape->approx = &shape->outlines[shapeWire->approxNdx];
5333            shapeWire = (xkbShapeWireDesc *) olWire;
5334        }
5335        wire = (char *) shapeWire;
5336    }
5337    if (geom->num_shapes != req->nShapes) {
5338        client->errorValue = _XkbErrCode3(0x07, geom->num_shapes, req->nShapes);
5339        return BadMatch;
5340    }
5341
5342    *wire_inout = wire;
5343    return Success;
5344}
5345
5346static Status
5347_CheckSetGeom(XkbGeometryPtr geom, xkbSetGeometryReq * req, ClientPtr client)
5348{
5349    register int i;
5350    Status status;
5351    char *wire;
5352
5353    wire = (char *) &req[1];
5354    status = _GetCountedString(&wire, client, &geom->label_font);
5355    if (status != Success)
5356        return status;
5357
5358    for (i = 0; i < req->nProperties; i++) {
5359        char *name, *val;
5360
5361        status = _GetCountedString(&wire, client, &name);
5362        if (status != Success)
5363            return status;
5364        status = _GetCountedString(&wire, client, &val);
5365        if (status != Success) {
5366            free(name);
5367            return status;
5368        }
5369        if (XkbAddGeomProperty(geom, name, val) == NULL) {
5370            free(name);
5371            free(val);
5372            return BadAlloc;
5373        }
5374        free(name);
5375        free(val);
5376    }
5377
5378    if (req->nColors < 2) {
5379        client->errorValue = _XkbErrCode3(0x01, 2, req->nColors);
5380        return BadValue;
5381    }
5382    if (req->baseColorNdx > req->nColors) {
5383        client->errorValue =
5384            _XkbErrCode3(0x03, req->nColors, req->baseColorNdx);
5385        return BadMatch;
5386    }
5387    if (req->labelColorNdx > req->nColors) {
5388        client->errorValue =
5389            _XkbErrCode3(0x03, req->nColors, req->labelColorNdx);
5390        return BadMatch;
5391    }
5392    if (req->labelColorNdx == req->baseColorNdx) {
5393        client->errorValue = _XkbErrCode3(0x04, req->baseColorNdx,
5394                                          req->labelColorNdx);
5395        return BadMatch;
5396    }
5397
5398    for (i = 0; i < req->nColors; i++) {
5399        char *name;
5400
5401        status = _GetCountedString(&wire, client, &name);
5402        if (status != Success)
5403            return status;
5404        if (!XkbAddGeomColor(geom, name, geom->num_colors)) {
5405            free(name);
5406            return BadAlloc;
5407        }
5408        free(name);
5409    }
5410    if (req->nColors != geom->num_colors) {
5411        client->errorValue = _XkbErrCode3(0x05, req->nColors, geom->num_colors);
5412        return BadMatch;
5413    }
5414    geom->label_color = &geom->colors[req->labelColorNdx];
5415    geom->base_color = &geom->colors[req->baseColorNdx];
5416
5417    if ((status = _CheckSetShapes(geom, req, &wire, client)) != Success)
5418        return status;
5419
5420    if ((status = _CheckSetSections(geom, req, &wire, client)) != Success)
5421        return status;
5422
5423    for (i = 0; i < req->nDoodads; i++) {
5424        status = _CheckSetDoodad(&wire, geom, NULL, client);
5425        if (status != Success)
5426            return status;
5427    }
5428
5429    for (i = 0; i < req->nKeyAliases; i++) {
5430        if (XkbAddGeomKeyAlias(geom, &wire[XkbKeyNameLength], wire) == NULL)
5431            return BadAlloc;
5432        wire += 2 * XkbKeyNameLength;
5433    }
5434    return Success;
5435}
5436
5437static int
5438_XkbSetGeometry(ClientPtr client, DeviceIntPtr dev, xkbSetGeometryReq * stuff)
5439{
5440    XkbDescPtr xkb;
5441    Bool new_name;
5442    xkbNewKeyboardNotify nkn;
5443    XkbGeometryPtr geom, old;
5444    XkbGeometrySizesRec sizes;
5445    Status status;
5446
5447    xkb = dev->key->xkbInfo->desc;
5448    old = xkb->geom;
5449    xkb->geom = NULL;
5450
5451    sizes.which = XkbGeomAllMask;
5452    sizes.num_properties = stuff->nProperties;
5453    sizes.num_colors = stuff->nColors;
5454    sizes.num_shapes = stuff->nShapes;
5455    sizes.num_sections = stuff->nSections;
5456    sizes.num_doodads = stuff->nDoodads;
5457    sizes.num_key_aliases = stuff->nKeyAliases;
5458    if ((status = XkbAllocGeometry(xkb, &sizes)) != Success) {
5459        xkb->geom = old;
5460        return status;
5461    }
5462    geom = xkb->geom;
5463    geom->name = stuff->name;
5464    geom->width_mm = stuff->widthMM;
5465    geom->height_mm = stuff->heightMM;
5466    if ((status = _CheckSetGeom(geom, stuff, client)) != Success) {
5467        XkbFreeGeometry(geom, XkbGeomAllMask, TRUE);
5468        xkb->geom = old;
5469        return status;
5470    }
5471    new_name = (xkb->names->geometry != geom->name);
5472    xkb->names->geometry = geom->name;
5473    if (old)
5474        XkbFreeGeometry(old, XkbGeomAllMask, TRUE);
5475    if (new_name) {
5476        xkbNamesNotify nn;
5477
5478        memset(&nn, 0, sizeof(xkbNamesNotify));
5479        nn.changed = XkbGeometryNameMask;
5480        XkbSendNamesNotify(dev, &nn);
5481    }
5482    nkn.deviceID = nkn.oldDeviceID = dev->id;
5483    nkn.minKeyCode = nkn.oldMinKeyCode = xkb->min_key_code;
5484    nkn.maxKeyCode = nkn.oldMaxKeyCode = xkb->max_key_code;
5485    nkn.requestMajor = XkbReqCode;
5486    nkn.requestMinor = X_kbSetGeometry;
5487    nkn.changed = XkbNKN_GeometryMask;
5488    XkbSendNewKeyboardNotify(dev, &nkn);
5489    return Success;
5490}
5491
5492int
5493ProcXkbSetGeometry(ClientPtr client)
5494{
5495    DeviceIntPtr dev;
5496    int rc;
5497
5498    REQUEST(xkbSetGeometryReq);
5499    REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq);
5500
5501    if (!(client->xkbClientFlags & _XkbClientInitialized))
5502        return BadAccess;
5503
5504    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
5505    CHK_ATOM_OR_NONE(stuff->name);
5506
5507    rc = _XkbSetGeometry(client, dev, stuff);
5508    if (rc != Success)
5509        return rc;
5510
5511    if (stuff->deviceSpec == XkbUseCoreKbd) {
5512        DeviceIntPtr other;
5513
5514        for (other = inputInfo.devices; other; other = other->next) {
5515            if ((other != dev) && other->key && !IsMaster(other) &&
5516                GetMaster(other, MASTER_KEYBOARD) == dev) {
5517                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
5518                              DixManageAccess);
5519                if (rc == Success)
5520                    _XkbSetGeometry(client, other, stuff);
5521            }
5522        }
5523    }
5524
5525    return Success;
5526}
5527
5528/***====================================================================***/
5529
5530int
5531ProcXkbPerClientFlags(ClientPtr client)
5532{
5533    DeviceIntPtr dev;
5534    xkbPerClientFlagsReply rep;
5535    XkbInterestPtr interest;
5536    Mask access_mode = DixGetAttrAccess | DixSetAttrAccess;
5537
5538    REQUEST(xkbPerClientFlagsReq);
5539    REQUEST_SIZE_MATCH(xkbPerClientFlagsReq);
5540
5541    if (!(client->xkbClientFlags & _XkbClientInitialized))
5542        return BadAccess;
5543
5544    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
5545    CHK_MASK_LEGAL(0x01, stuff->change, XkbPCF_AllFlagsMask);
5546    CHK_MASK_MATCH(0x02, stuff->change, stuff->value);
5547
5548    interest = XkbFindClientResource((DevicePtr) dev, client);
5549    if (stuff->change) {
5550        client->xkbClientFlags &= ~stuff->change;
5551        client->xkbClientFlags |= stuff->value;
5552    }
5553    if (stuff->change & XkbPCF_AutoResetControlsMask) {
5554        Bool want;
5555
5556        want = stuff->value & XkbPCF_AutoResetControlsMask;
5557        if (interest && !want) {
5558            interest->autoCtrls = interest->autoCtrlValues = 0;
5559        }
5560        else if (want && (!interest)) {
5561            XID id = FakeClientID(client->index);
5562
5563            if (!AddResource(id, RT_XKBCLIENT, dev))
5564                return BadAlloc;
5565            interest = XkbAddClientResource((DevicePtr) dev, client, id);
5566            if (!interest)
5567                return BadAlloc;
5568        }
5569        if (interest && want) {
5570            register unsigned affect;
5571
5572            affect = stuff->ctrlsToChange;
5573
5574            CHK_MASK_LEGAL(0x03, affect, XkbAllBooleanCtrlsMask);
5575            CHK_MASK_MATCH(0x04, affect, stuff->autoCtrls);
5576            CHK_MASK_MATCH(0x05, stuff->autoCtrls, stuff->autoCtrlValues);
5577
5578            interest->autoCtrls &= ~affect;
5579            interest->autoCtrlValues &= ~affect;
5580            interest->autoCtrls |= stuff->autoCtrls & affect;
5581            interest->autoCtrlValues |= stuff->autoCtrlValues & affect;
5582        }
5583    }
5584
5585    rep = (xkbPerClientFlagsReply) {
5586        .type = X_Reply,
5587        .sequenceNumber = client->sequence,
5588        .length = 0,
5589        .supported = XkbPCF_AllFlagsMask,
5590        .value = client->xkbClientFlags & XkbPCF_AllFlagsMask,
5591        .autoCtrls = interest ? interest->autoCtrls : 0,
5592        .autoCtrlValues =  interest ? interest->autoCtrlValues : 0,
5593    };
5594    if (client->swapped) {
5595        swaps(&rep.sequenceNumber);
5596        swapl(&rep.supported);
5597        swapl(&rep.value);
5598        swapl(&rep.autoCtrls);
5599        swapl(&rep.autoCtrlValues);
5600    }
5601    WriteToClient(client, SIZEOF(xkbPerClientFlagsReply), &rep);
5602    return Success;
5603}
5604
5605/***====================================================================***/
5606
5607/* all latin-1 alphanumerics, plus parens, minus, underscore, slash */
5608/* and wildcards */
5609static unsigned char componentSpecLegal[] = {
5610    0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x87,
5611    0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07,
5612    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5613    0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
5614};
5615
5616/* same as above but accepts percent, plus and bar too */
5617static unsigned char componentExprLegal[] = {
5618    0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0xff, 0x87,
5619    0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x17,
5620    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5621    0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
5622};
5623
5624static char *
5625GetComponentSpec(unsigned char **pWire, Bool allowExpr, int *errRtrn)
5626{
5627    int len;
5628    register int i;
5629    unsigned char *wire, *str, *tmp, *legal;
5630
5631    if (allowExpr)
5632        legal = &componentExprLegal[0];
5633    else
5634        legal = &componentSpecLegal[0];
5635
5636    wire = *pWire;
5637    len = (*(unsigned char *) wire++);
5638    if (len > 0) {
5639        str = calloc(1, len + 1);
5640        if (str) {
5641            tmp = str;
5642            for (i = 0; i < len; i++) {
5643                if (legal[(*wire) / 8] & (1 << ((*wire) % 8)))
5644                    *tmp++ = *wire++;
5645                else
5646                    wire++;
5647            }
5648            if (tmp != str)
5649                *tmp++ = '\0';
5650            else {
5651                free(str);
5652                str = NULL;
5653            }
5654        }
5655        else {
5656            *errRtrn = BadAlloc;
5657        }
5658    }
5659    else {
5660        str = NULL;
5661    }
5662    *pWire = wire;
5663    return (char *) str;
5664}
5665
5666/***====================================================================***/
5667
5668int
5669ProcXkbListComponents(ClientPtr client)
5670{
5671    DeviceIntPtr dev;
5672    xkbListComponentsReply rep;
5673    unsigned len;
5674    unsigned char *str;
5675    uint8_t size;
5676    int i;
5677
5678    REQUEST(xkbListComponentsReq);
5679    REQUEST_AT_LEAST_SIZE(xkbListComponentsReq);
5680
5681    if (!(client->xkbClientFlags & _XkbClientInitialized))
5682        return BadAccess;
5683
5684    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
5685
5686    /* The request is followed by six Pascal strings (i.e. size in characters
5687     * followed by a string pattern) describing what the client wants us to
5688     * list.  We don't care, but might as well check they haven't got the
5689     * length wrong. */
5690    str = (unsigned char *) &stuff[1];
5691    for (i = 0; i < 6; i++) {
5692        size = *((uint8_t *)str);
5693        len = (str + size + 1) - ((unsigned char *) stuff);
5694        if ((XkbPaddedSize(len) / 4) > stuff->length)
5695            return BadLength;
5696        str += (size + 1);
5697    }
5698    if ((XkbPaddedSize(len) / 4) != stuff->length)
5699        return BadLength;
5700    rep = (xkbListComponentsReply) {
5701        .type = X_Reply,
5702        .deviceID = dev->id,
5703        .sequenceNumber = client->sequence,
5704        .length = 0,
5705        .nKeymaps = 0,
5706        .nKeycodes = 0,
5707        .nTypes = 0,
5708        .nCompatMaps = 0,
5709        .nSymbols = 0,
5710        .nGeometries = 0,
5711        .extra = 0
5712    };
5713    if (client->swapped) {
5714        swaps(&rep.sequenceNumber);
5715        swapl(&rep.length);
5716        swaps(&rep.nKeymaps);
5717        swaps(&rep.nKeycodes);
5718        swaps(&rep.nTypes);
5719        swaps(&rep.nCompatMaps);
5720        swaps(&rep.nSymbols);
5721        swaps(&rep.nGeometries);
5722        swaps(&rep.extra);
5723    }
5724    WriteToClient(client, SIZEOF(xkbListComponentsReply), &rep);
5725    return Success;
5726}
5727
5728/***====================================================================***/
5729int
5730ProcXkbGetKbdByName(ClientPtr client)
5731{
5732    DeviceIntPtr dev;
5733    DeviceIntPtr tmpd;
5734    DeviceIntPtr master;
5735    xkbGetKbdByNameReply rep = { 0 };
5736    xkbGetMapReply mrep = { 0 };
5737    xkbGetCompatMapReply crep = { 0 };
5738    xkbGetIndicatorMapReply irep = { 0 };
5739    xkbGetNamesReply nrep = { 0 };
5740    xkbGetGeometryReply grep = { 0 };
5741    XkbComponentNamesRec names = { 0 };
5742    XkbDescPtr xkb, new;
5743    XkbEventCauseRec cause;
5744    unsigned char *str;
5745    char mapFile[PATH_MAX];
5746    unsigned len;
5747    unsigned fwant, fneed, reported;
5748    int status;
5749    Bool geom_changed;
5750    XkbSrvLedInfoPtr old_sli;
5751    XkbSrvLedInfoPtr sli;
5752    Mask access_mode = DixGetAttrAccess | DixManageAccess;
5753
5754    REQUEST(xkbGetKbdByNameReq);
5755    REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq);
5756
5757    if (!(client->xkbClientFlags & _XkbClientInitialized))
5758        return BadAccess;
5759
5760    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
5761    master = GetMaster(dev, MASTER_KEYBOARD);
5762
5763    xkb = dev->key->xkbInfo->desc;
5764    status = Success;
5765    str = (unsigned char *) &stuff[1];
5766    if (GetComponentSpec(&str, TRUE, &status))  /* keymap, unsupported */
5767        return BadMatch;
5768    names.keycodes = GetComponentSpec(&str, TRUE, &status);
5769    names.types = GetComponentSpec(&str, TRUE, &status);
5770    names.compat = GetComponentSpec(&str, TRUE, &status);
5771    names.symbols = GetComponentSpec(&str, TRUE, &status);
5772    names.geometry = GetComponentSpec(&str, TRUE, &status);
5773    if (status != Success)
5774        return status;
5775    len = str - ((unsigned char *) stuff);
5776    if ((XkbPaddedSize(len) / 4) != stuff->length)
5777        return BadLength;
5778
5779    CHK_MASK_LEGAL(0x01, stuff->want, XkbGBN_AllComponentsMask);
5780    CHK_MASK_LEGAL(0x02, stuff->need, XkbGBN_AllComponentsMask);
5781
5782    if (stuff->load)
5783        fwant = XkbGBN_AllComponentsMask;
5784    else
5785        fwant = stuff->want | stuff->need;
5786    if ((!names.compat) &&
5787        (fwant & (XkbGBN_CompatMapMask | XkbGBN_IndicatorMapMask))) {
5788        names.compat = Xstrdup("%");
5789    }
5790    if ((!names.types) && (fwant & (XkbGBN_TypesMask))) {
5791        names.types = Xstrdup("%");
5792    }
5793    if ((!names.symbols) && (fwant & XkbGBN_SymbolsMask)) {
5794        names.symbols = Xstrdup("%");
5795    }
5796    geom_changed = ((names.geometry != NULL) &&
5797                    (strcmp(names.geometry, "%") != 0));
5798    if ((!names.geometry) && (fwant & XkbGBN_GeometryMask)) {
5799        names.geometry = Xstrdup("%");
5800        geom_changed = FALSE;
5801    }
5802
5803    memset(mapFile, 0, PATH_MAX);
5804    rep.type = X_Reply;
5805    rep.deviceID = dev->id;
5806    rep.sequenceNumber = client->sequence;
5807    rep.length = 0;
5808    rep.minKeyCode = xkb->min_key_code;
5809    rep.maxKeyCode = xkb->max_key_code;
5810    rep.loaded = FALSE;
5811    fwant =
5812        XkbConvertGetByNameComponents(TRUE, stuff->want) | XkmVirtualModsMask;
5813    fneed = XkbConvertGetByNameComponents(TRUE, stuff->need);
5814    rep.reported = XkbConvertGetByNameComponents(FALSE, fwant | fneed);
5815    if (stuff->load) {
5816        fneed |= XkmKeymapRequired;
5817        fwant |= XkmKeymapLegal;
5818    }
5819    if ((fwant | fneed) & XkmSymbolsMask) {
5820        fneed |= XkmKeyNamesIndex | XkmTypesIndex;
5821        fwant |= XkmIndicatorsIndex;
5822    }
5823
5824    /* We pass dev in here so we can get the old names out if needed. */
5825    rep.found = XkbDDXLoadKeymapByNames(dev, &names, fwant, fneed, &new,
5826                                        mapFile, PATH_MAX);
5827    rep.newKeyboard = FALSE;
5828    rep.pad1 = rep.pad2 = rep.pad3 = rep.pad4 = 0;
5829
5830    stuff->want |= stuff->need;
5831    if (new == NULL)
5832        rep.reported = 0;
5833    else {
5834        if (stuff->load)
5835            rep.loaded = TRUE;
5836        if (stuff->load ||
5837            ((rep.reported & XkbGBN_SymbolsMask) && (new->compat))) {
5838            XkbChangesRec changes;
5839
5840            memset(&changes, 0, sizeof(changes));
5841            XkbUpdateDescActions(new,
5842                                 new->min_key_code, XkbNumKeys(new), &changes);
5843        }
5844
5845        if (new->map == NULL)
5846            rep.reported &= ~(XkbGBN_SymbolsMask | XkbGBN_TypesMask);
5847        else if (rep.reported & (XkbGBN_SymbolsMask | XkbGBN_TypesMask)) {
5848            mrep.type = X_Reply;
5849            mrep.deviceID = dev->id;
5850            mrep.sequenceNumber = client->sequence;
5851            mrep.length =
5852                ((SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply)) >> 2);
5853            mrep.minKeyCode = new->min_key_code;
5854            mrep.maxKeyCode = new->max_key_code;
5855            mrep.present = 0;
5856            mrep.totalSyms = mrep.totalActs =
5857                mrep.totalKeyBehaviors = mrep.totalKeyExplicit =
5858                mrep.totalModMapKeys = mrep.totalVModMapKeys = 0;
5859            if (rep.reported & (XkbGBN_TypesMask | XkbGBN_ClientSymbolsMask)) {
5860                mrep.present |= XkbKeyTypesMask;
5861                mrep.firstType = 0;
5862                mrep.nTypes = mrep.totalTypes = new->map->num_types;
5863            }
5864            else {
5865                mrep.firstType = mrep.nTypes = 0;
5866                mrep.totalTypes = 0;
5867            }
5868            if (rep.reported & XkbGBN_ClientSymbolsMask) {
5869                mrep.present |= (XkbKeySymsMask | XkbModifierMapMask);
5870                mrep.firstKeySym = mrep.firstModMapKey = new->min_key_code;
5871                mrep.nKeySyms = mrep.nModMapKeys = XkbNumKeys(new);
5872            }
5873            else {
5874                mrep.firstKeySym = mrep.firstModMapKey = 0;
5875                mrep.nKeySyms = mrep.nModMapKeys = 0;
5876            }
5877            if (rep.reported & XkbGBN_ServerSymbolsMask) {
5878                mrep.present |= XkbAllServerInfoMask;
5879                mrep.virtualMods = ~0;
5880                mrep.firstKeyAct = mrep.firstKeyBehavior =
5881                    mrep.firstKeyExplicit = new->min_key_code;
5882                mrep.nKeyActs = mrep.nKeyBehaviors =
5883                    mrep.nKeyExplicit = XkbNumKeys(new);
5884                mrep.firstVModMapKey = new->min_key_code;
5885                mrep.nVModMapKeys = XkbNumKeys(new);
5886            }
5887            else {
5888                mrep.virtualMods = 0;
5889                mrep.firstKeyAct = mrep.firstKeyBehavior =
5890                    mrep.firstKeyExplicit = 0;
5891                mrep.nKeyActs = mrep.nKeyBehaviors = mrep.nKeyExplicit = 0;
5892            }
5893            XkbComputeGetMapReplySize(new, &mrep);
5894            rep.length += SIZEOF(xGenericReply) / 4 + mrep.length;
5895        }
5896        if (new->compat == NULL)
5897            rep.reported &= ~XkbGBN_CompatMapMask;
5898        else if (rep.reported & XkbGBN_CompatMapMask) {
5899            crep.type = X_Reply;
5900            crep.deviceID = dev->id;
5901            crep.sequenceNumber = client->sequence;
5902            crep.length = 0;
5903            crep.groups = XkbAllGroupsMask;
5904            crep.firstSI = 0;
5905            crep.nSI = crep.nTotalSI = new->compat->num_si;
5906            XkbComputeGetCompatMapReplySize(new->compat, &crep);
5907            rep.length += SIZEOF(xGenericReply) / 4 + crep.length;
5908        }
5909        if (new->indicators == NULL)
5910            rep.reported &= ~XkbGBN_IndicatorMapMask;
5911        else if (rep.reported & XkbGBN_IndicatorMapMask) {
5912            irep.type = X_Reply;
5913            irep.deviceID = dev->id;
5914            irep.sequenceNumber = client->sequence;
5915            irep.length = 0;
5916            irep.which = XkbAllIndicatorsMask;
5917            XkbComputeGetIndicatorMapReplySize(new->indicators, &irep);
5918            rep.length += SIZEOF(xGenericReply) / 4 + irep.length;
5919        }
5920        if (new->names == NULL)
5921            rep.reported &= ~(XkbGBN_OtherNamesMask | XkbGBN_KeyNamesMask);
5922        else if (rep.reported & (XkbGBN_OtherNamesMask | XkbGBN_KeyNamesMask)) {
5923            nrep.type = X_Reply;
5924            nrep.deviceID = dev->id;
5925            nrep.sequenceNumber = client->sequence;
5926            nrep.length = 0;
5927            nrep.minKeyCode = new->min_key_code;
5928            nrep.maxKeyCode = new->max_key_code;
5929            if (rep.reported & XkbGBN_OtherNamesMask) {
5930                nrep.which = XkbAllNamesMask;
5931                if (new->map != NULL)
5932                    nrep.nTypes = new->map->num_types;
5933                else
5934                    nrep.nTypes = 0;
5935                nrep.nKTLevels = 0;
5936                nrep.groupNames = XkbAllGroupsMask;
5937                nrep.virtualMods = XkbAllVirtualModsMask;
5938                nrep.indicators = XkbAllIndicatorsMask;
5939                nrep.nRadioGroups = new->names->num_rg;
5940            }
5941            else {
5942                nrep.which = 0;
5943                nrep.nTypes = 0;
5944                nrep.nKTLevels = 0;
5945                nrep.groupNames = 0;
5946                nrep.virtualMods = 0;
5947                nrep.indicators = 0;
5948                nrep.nRadioGroups = 0;
5949            }
5950            if (rep.reported & XkbGBN_KeyNamesMask) {
5951                nrep.which |= XkbKeyNamesMask;
5952                nrep.firstKey = new->min_key_code;
5953                nrep.nKeys = XkbNumKeys(new);
5954                nrep.nKeyAliases = new->names->num_key_aliases;
5955                if (nrep.nKeyAliases)
5956                    nrep.which |= XkbKeyAliasesMask;
5957            }
5958            else {
5959                nrep.which &= ~(XkbKeyNamesMask | XkbKeyAliasesMask);
5960                nrep.firstKey = nrep.nKeys = 0;
5961                nrep.nKeyAliases = 0;
5962            }
5963            XkbComputeGetNamesReplySize(new, &nrep);
5964            rep.length += SIZEOF(xGenericReply) / 4 + nrep.length;
5965        }
5966        if (new->geom == NULL)
5967            rep.reported &= ~XkbGBN_GeometryMask;
5968        else if (rep.reported & XkbGBN_GeometryMask) {
5969            grep.type = X_Reply;
5970            grep.deviceID = dev->id;
5971            grep.sequenceNumber = client->sequence;
5972            grep.length = 0;
5973            grep.found = TRUE;
5974            grep.pad = 0;
5975            grep.widthMM = grep.heightMM = 0;
5976            grep.nProperties = grep.nColors = grep.nShapes = 0;
5977            grep.nSections = grep.nDoodads = 0;
5978            grep.baseColorNdx = grep.labelColorNdx = 0;
5979            XkbComputeGetGeometryReplySize(new->geom, &grep, None);
5980            rep.length += SIZEOF(xGenericReply) / 4 + grep.length;
5981        }
5982    }
5983
5984    reported = rep.reported;
5985    if (client->swapped) {
5986        swaps(&rep.sequenceNumber);
5987        swapl(&rep.length);
5988        swaps(&rep.found);
5989        swaps(&rep.reported);
5990    }
5991    WriteToClient(client, SIZEOF(xkbGetKbdByNameReply), &rep);
5992    if (reported & (XkbGBN_SymbolsMask | XkbGBN_TypesMask))
5993        XkbSendMap(client, new, &mrep);
5994    if (reported & XkbGBN_CompatMapMask)
5995        XkbSendCompatMap(client, new->compat, &crep);
5996    if (reported & XkbGBN_IndicatorMapMask)
5997        XkbSendIndicatorMap(client, new->indicators, &irep);
5998    if (reported & (XkbGBN_KeyNamesMask | XkbGBN_OtherNamesMask))
5999        XkbSendNames(client, new, &nrep);
6000    if (reported & XkbGBN_GeometryMask)
6001        XkbSendGeometry(client, new->geom, &grep, FALSE);
6002    if (rep.loaded) {
6003        XkbDescPtr old_xkb;
6004        xkbNewKeyboardNotify nkn;
6005
6006        old_xkb = xkb;
6007        xkb = new;
6008        dev->key->xkbInfo->desc = xkb;
6009        new = old_xkb;          /* so it'll get freed automatically */
6010
6011        XkbCopyControls(xkb, old_xkb);
6012
6013        nkn.deviceID = nkn.oldDeviceID = dev->id;
6014        nkn.minKeyCode = new->min_key_code;
6015        nkn.maxKeyCode = new->max_key_code;
6016        nkn.oldMinKeyCode = xkb->min_key_code;
6017        nkn.oldMaxKeyCode = xkb->max_key_code;
6018        nkn.requestMajor = XkbReqCode;
6019        nkn.requestMinor = X_kbGetKbdByName;
6020        nkn.changed = XkbNKN_KeycodesMask;
6021        if (geom_changed)
6022            nkn.changed |= XkbNKN_GeometryMask;
6023        XkbSendNewKeyboardNotify(dev, &nkn);
6024
6025        /* Update the map and LED info on the device itself, as well as
6026         * any slaves if it's an MD, or its MD if it's an SD and was the
6027         * last device used on that MD. */
6028        for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
6029            if (tmpd != dev && GetMaster(tmpd, MASTER_KEYBOARD) != dev &&
6030                (tmpd != master || dev != master->lastSlave))
6031                continue;
6032
6033            if (tmpd != dev)
6034                XkbDeviceApplyKeymap(tmpd, xkb);
6035
6036            if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) {
6037                old_sli = tmpd->kbdfeed->xkb_sli;
6038                tmpd->kbdfeed->xkb_sli = NULL;
6039                sli = XkbAllocSrvLedInfo(tmpd, tmpd->kbdfeed, NULL, 0);
6040                if (sli) {
6041                    sli->explicitState = old_sli->explicitState;
6042                    sli->effectiveState = old_sli->effectiveState;
6043                }
6044                tmpd->kbdfeed->xkb_sli = sli;
6045                XkbFreeSrvLedInfo(old_sli);
6046            }
6047        }
6048    }
6049    if ((new != NULL) && (new != xkb)) {
6050        XkbFreeKeyboard(new, XkbAllComponentsMask, TRUE);
6051        new = NULL;
6052    }
6053    XkbFreeComponentNames(&names, FALSE);
6054    XkbSetCauseXkbReq(&cause, X_kbGetKbdByName, client);
6055    XkbUpdateAllDeviceIndicators(NULL, &cause);
6056
6057    return Success;
6058}
6059
6060/***====================================================================***/
6061
6062static int
6063ComputeDeviceLedInfoSize(DeviceIntPtr dev,
6064                         unsigned int what, XkbSrvLedInfoPtr sli)
6065{
6066    int nNames, nMaps;
6067    register unsigned n, bit;
6068
6069    if (sli == NULL)
6070        return 0;
6071    nNames = nMaps = 0;
6072    if ((what & XkbXI_IndicatorNamesMask) == 0)
6073        sli->namesPresent = 0;
6074    if ((what & XkbXI_IndicatorMapsMask) == 0)
6075        sli->mapsPresent = 0;
6076
6077    for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6078        if (sli->names && sli->names[n] != None) {
6079            sli->namesPresent |= bit;
6080            nNames++;
6081        }
6082        if (sli->maps && XkbIM_InUse(&sli->maps[n])) {
6083            sli->mapsPresent |= bit;
6084            nMaps++;
6085        }
6086    }
6087    return (nNames * 4) + (nMaps * SIZEOF(xkbIndicatorMapWireDesc));
6088}
6089
6090static int
6091CheckDeviceLedFBs(DeviceIntPtr dev,
6092                  int class,
6093                  int id, xkbGetDeviceInfoReply * rep, ClientPtr client)
6094{
6095    int nFBs = 0;
6096    int length = 0;
6097    Bool classOk;
6098
6099    if (class == XkbDfltXIClass) {
6100        if (dev->kbdfeed)
6101            class = KbdFeedbackClass;
6102        else if (dev->leds)
6103            class = LedFeedbackClass;
6104        else {
6105            client->errorValue = _XkbErrCode2(XkbErr_BadClass, class);
6106            return XkbKeyboardErrorCode;
6107        }
6108    }
6109    classOk = FALSE;
6110    if ((dev->kbdfeed) &&
6111        ((class == KbdFeedbackClass) || (class == XkbAllXIClasses))) {
6112        KbdFeedbackPtr kf;
6113
6114        classOk = TRUE;
6115        for (kf = dev->kbdfeed; (kf); kf = kf->next) {
6116            if ((id != XkbAllXIIds) && (id != XkbDfltXIId) &&
6117                (id != kf->ctrl.id))
6118                continue;
6119            nFBs++;
6120            length += SIZEOF(xkbDeviceLedsWireDesc);
6121            if (!kf->xkb_sli)
6122                kf->xkb_sli = XkbAllocSrvLedInfo(dev, kf, NULL, 0);
6123            length += ComputeDeviceLedInfoSize(dev, rep->present, kf->xkb_sli);
6124            if (id != XkbAllXIIds)
6125                break;
6126        }
6127    }
6128    if ((dev->leds) &&
6129        ((class == LedFeedbackClass) || (class == XkbAllXIClasses))) {
6130        LedFeedbackPtr lf;
6131
6132        classOk = TRUE;
6133        for (lf = dev->leds; (lf); lf = lf->next) {
6134            if ((id != XkbAllXIIds) && (id != XkbDfltXIId) &&
6135                (id != lf->ctrl.id))
6136                continue;
6137            nFBs++;
6138            length += SIZEOF(xkbDeviceLedsWireDesc);
6139            if (!lf->xkb_sli)
6140                lf->xkb_sli = XkbAllocSrvLedInfo(dev, NULL, lf, 0);
6141            length += ComputeDeviceLedInfoSize(dev, rep->present, lf->xkb_sli);
6142            if (id != XkbAllXIIds)
6143                break;
6144        }
6145    }
6146    if (nFBs > 0) {
6147        rep->nDeviceLedFBs = nFBs;
6148        rep->length += (length / 4);
6149        return Success;
6150    }
6151    if (classOk)
6152        client->errorValue = _XkbErrCode2(XkbErr_BadId, id);
6153    else
6154        client->errorValue = _XkbErrCode2(XkbErr_BadClass, class);
6155    return XkbKeyboardErrorCode;
6156}
6157
6158static int
6159SendDeviceLedInfo(XkbSrvLedInfoPtr sli, ClientPtr client)
6160{
6161    xkbDeviceLedsWireDesc wire;
6162    int length;
6163
6164    length = 0;
6165    wire.ledClass = sli->class;
6166    wire.ledID = sli->id;
6167    wire.namesPresent = sli->namesPresent;
6168    wire.mapsPresent = sli->mapsPresent;
6169    wire.physIndicators = sli->physIndicators;
6170    wire.state = sli->effectiveState;
6171    if (client->swapped) {
6172        swaps(&wire.ledClass);
6173        swaps(&wire.ledID);
6174        swapl(&wire.namesPresent);
6175        swapl(&wire.mapsPresent);
6176        swapl(&wire.physIndicators);
6177        swapl(&wire.state);
6178    }
6179    WriteToClient(client, SIZEOF(xkbDeviceLedsWireDesc), &wire);
6180    length += SIZEOF(xkbDeviceLedsWireDesc);
6181    if (sli->namesPresent | sli->mapsPresent) {
6182        register unsigned i, bit;
6183
6184        if (sli->namesPresent) {
6185            CARD32 awire;
6186
6187            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
6188                if (sli->namesPresent & bit) {
6189                    awire = (CARD32) sli->names[i];
6190                    if (client->swapped) {
6191                        swapl(&awire);
6192                    }
6193                    WriteToClient(client, 4, &awire);
6194                    length += 4;
6195                }
6196            }
6197        }
6198        if (sli->mapsPresent) {
6199            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
6200                xkbIndicatorMapWireDesc iwire;
6201
6202                if (sli->mapsPresent & bit) {
6203                    iwire.flags = sli->maps[i].flags;
6204                    iwire.whichGroups = sli->maps[i].which_groups;
6205                    iwire.groups = sli->maps[i].groups;
6206                    iwire.whichMods = sli->maps[i].which_mods;
6207                    iwire.mods = sli->maps[i].mods.mask;
6208                    iwire.realMods = sli->maps[i].mods.real_mods;
6209                    iwire.virtualMods = sli->maps[i].mods.vmods;
6210                    iwire.ctrls = sli->maps[i].ctrls;
6211                    if (client->swapped) {
6212                        swaps(&iwire.virtualMods);
6213                        swapl(&iwire.ctrls);
6214                    }
6215                    WriteToClient(client, SIZEOF(xkbIndicatorMapWireDesc),
6216                                  &iwire);
6217                    length += SIZEOF(xkbIndicatorMapWireDesc);
6218                }
6219            }
6220        }
6221    }
6222    return length;
6223}
6224
6225static int
6226SendDeviceLedFBs(DeviceIntPtr dev,
6227                 int class, int id, unsigned wantLength, ClientPtr client)
6228{
6229    int length = 0;
6230
6231    if (class == XkbDfltXIClass) {
6232        if (dev->kbdfeed)
6233            class = KbdFeedbackClass;
6234        else if (dev->leds)
6235            class = LedFeedbackClass;
6236    }
6237    if ((dev->kbdfeed) &&
6238        ((class == KbdFeedbackClass) || (class == XkbAllXIClasses))) {
6239        KbdFeedbackPtr kf;
6240
6241        for (kf = dev->kbdfeed; (kf); kf = kf->next) {
6242            if ((id == XkbAllXIIds) || (id == XkbDfltXIId) ||
6243                (id == kf->ctrl.id)) {
6244                length += SendDeviceLedInfo(kf->xkb_sli, client);
6245                if (id != XkbAllXIIds)
6246                    break;
6247            }
6248        }
6249    }
6250    if ((dev->leds) &&
6251        ((class == LedFeedbackClass) || (class == XkbAllXIClasses))) {
6252        LedFeedbackPtr lf;
6253
6254        for (lf = dev->leds; (lf); lf = lf->next) {
6255            if ((id == XkbAllXIIds) || (id == XkbDfltXIId) ||
6256                (id == lf->ctrl.id)) {
6257                length += SendDeviceLedInfo(lf->xkb_sli, client);
6258                if (id != XkbAllXIIds)
6259                    break;
6260            }
6261        }
6262    }
6263    if (length == wantLength)
6264        return Success;
6265    else
6266        return BadLength;
6267}
6268
6269int
6270ProcXkbGetDeviceInfo(ClientPtr client)
6271{
6272    DeviceIntPtr dev;
6273    xkbGetDeviceInfoReply rep;
6274    int status, nDeviceLedFBs;
6275    unsigned length, nameLen;
6276    CARD16 ledClass, ledID;
6277    unsigned wanted;
6278    char *str;
6279
6280    REQUEST(xkbGetDeviceInfoReq);
6281    REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq);
6282
6283    if (!(client->xkbClientFlags & _XkbClientInitialized))
6284        return BadAccess;
6285
6286    wanted = stuff->wanted;
6287
6288    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
6289    CHK_MASK_LEGAL(0x01, wanted, XkbXI_AllDeviceFeaturesMask);
6290
6291    if ((!dev->button) || ((stuff->nBtns < 1) && (!stuff->allBtns)))
6292        wanted &= ~XkbXI_ButtonActionsMask;
6293    if ((!dev->kbdfeed) && (!dev->leds))
6294        wanted &= ~XkbXI_IndicatorsMask;
6295
6296    nameLen = XkbSizeCountedString(dev->name);
6297    rep = (xkbGetDeviceInfoReply) {
6298        .type = X_Reply,
6299        .deviceID = dev->id,
6300        .sequenceNumber = client->sequence,
6301        .length = nameLen / 4,
6302        .present = wanted,
6303        .supported = XkbXI_AllDeviceFeaturesMask,
6304        .unsupported = 0,
6305        .nDeviceLedFBs = 0,
6306        .firstBtnWanted = 0,
6307        .nBtnsWanted = 0,
6308        .firstBtnRtrn = 0,
6309        .nBtnsRtrn = 0,
6310        .totalBtns = dev->button ? dev->button->numButtons : 0,
6311        .hasOwnState = (dev->key && dev->key->xkbInfo),
6312        .dfltKbdFB = dev->kbdfeed ? dev->kbdfeed->ctrl.id : XkbXINone,
6313        .dfltLedFB = dev->leds ? dev->leds->ctrl.id : XkbXINone,
6314        .devType = dev->xinput_type
6315    };
6316
6317    ledClass = stuff->ledClass;
6318    ledID = stuff->ledID;
6319
6320    if (wanted & XkbXI_ButtonActionsMask) {
6321        if (stuff->allBtns) {
6322            stuff->firstBtn = 0;
6323            stuff->nBtns = dev->button->numButtons;
6324        }
6325
6326        if ((stuff->firstBtn + stuff->nBtns) > dev->button->numButtons) {
6327            client->errorValue = _XkbErrCode4(0x02, dev->button->numButtons,
6328                                              stuff->firstBtn, stuff->nBtns);
6329            return BadValue;
6330        }
6331        else {
6332            rep.firstBtnWanted = stuff->firstBtn;
6333            rep.nBtnsWanted = stuff->nBtns;
6334            if (dev->button->xkb_acts != NULL) {
6335                XkbAction *act;
6336                register int i;
6337
6338                rep.firstBtnRtrn = stuff->firstBtn;
6339                rep.nBtnsRtrn = stuff->nBtns;
6340                act = &dev->button->xkb_acts[rep.firstBtnWanted];
6341                for (i = 0; i < rep.nBtnsRtrn; i++, act++) {
6342                    if (act->type != XkbSA_NoAction)
6343                        break;
6344                }
6345                rep.firstBtnRtrn += i;
6346                rep.nBtnsRtrn -= i;
6347                act =
6348                    &dev->button->xkb_acts[rep.firstBtnRtrn + rep.nBtnsRtrn -
6349                                           1];
6350                for (i = 0; i < rep.nBtnsRtrn; i++, act--) {
6351                    if (act->type != XkbSA_NoAction)
6352                        break;
6353                }
6354                rep.nBtnsRtrn -= i;
6355            }
6356            rep.length += (rep.nBtnsRtrn * SIZEOF(xkbActionWireDesc)) / 4;
6357        }
6358    }
6359
6360    if (wanted & XkbXI_IndicatorsMask) {
6361        status = CheckDeviceLedFBs(dev, ledClass, ledID, &rep, client);
6362        if (status != Success)
6363            return status;
6364    }
6365    length = rep.length * 4;
6366    nDeviceLedFBs = rep.nDeviceLedFBs;
6367    if (client->swapped) {
6368        swaps(&rep.sequenceNumber);
6369        swapl(&rep.length);
6370        swaps(&rep.present);
6371        swaps(&rep.supported);
6372        swaps(&rep.unsupported);
6373        swaps(&rep.nDeviceLedFBs);
6374        swaps(&rep.dfltKbdFB);
6375        swaps(&rep.dfltLedFB);
6376        swapl(&rep.devType);
6377    }
6378    WriteToClient(client, SIZEOF(xkbGetDeviceInfoReply), &rep);
6379
6380    str = malloc(nameLen);
6381    if (!str)
6382        return BadAlloc;
6383    XkbWriteCountedString(str, dev->name, client->swapped);
6384    WriteToClient(client, nameLen, str);
6385    free(str);
6386    length -= nameLen;
6387
6388    if (rep.nBtnsRtrn > 0) {
6389        int sz;
6390        xkbActionWireDesc *awire;
6391
6392        sz = rep.nBtnsRtrn * SIZEOF(xkbActionWireDesc);
6393        awire = (xkbActionWireDesc *) &dev->button->xkb_acts[rep.firstBtnRtrn];
6394        WriteToClient(client, sz, awire);
6395        length -= sz;
6396    }
6397    if (nDeviceLedFBs > 0) {
6398        status = SendDeviceLedFBs(dev, ledClass, ledID, length, client);
6399        if (status != Success)
6400            return status;
6401    }
6402    else if (length != 0) {
6403        ErrorF("[xkb] Internal Error!  BadLength in ProcXkbGetDeviceInfo\n");
6404        ErrorF("[xkb]                  Wrote %d fewer bytes than expected\n",
6405               length);
6406        return BadLength;
6407    }
6408    return Success;
6409}
6410
6411static char *
6412CheckSetDeviceIndicators(char *wire,
6413                         DeviceIntPtr dev,
6414                         int num, int *status_rtrn, ClientPtr client)
6415{
6416    xkbDeviceLedsWireDesc *ledWire;
6417    int i;
6418    XkbSrvLedInfoPtr sli;
6419
6420    ledWire = (xkbDeviceLedsWireDesc *) wire;
6421    for (i = 0; i < num; i++) {
6422        if (client->swapped) {
6423            swaps(&ledWire->ledClass);
6424            swaps(&ledWire->ledID);
6425            swapl(&ledWire->namesPresent);
6426            swapl(&ledWire->mapsPresent);
6427            swapl(&ledWire->physIndicators);
6428        }
6429
6430        sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID,
6431                                XkbXI_IndicatorsMask);
6432        if (sli != NULL) {
6433            register int n;
6434            register unsigned bit;
6435            int nMaps, nNames;
6436            CARD32 *atomWire;
6437            xkbIndicatorMapWireDesc *mapWire;
6438
6439            nMaps = nNames = 0;
6440            for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6441                if (ledWire->namesPresent & bit)
6442                    nNames++;
6443                if (ledWire->mapsPresent & bit)
6444                    nMaps++;
6445            }
6446            atomWire = (CARD32 *) &ledWire[1];
6447            if (nNames > 0) {
6448                for (n = 0; n < nNames; n++) {
6449                    if (client->swapped) {
6450                        swapl(atomWire);
6451                    }
6452                    CHK_ATOM_OR_NONE3(((Atom) (*atomWire)), client->errorValue,
6453                                      *status_rtrn, NULL);
6454                    atomWire++;
6455                }
6456            }
6457            mapWire = (xkbIndicatorMapWireDesc *) atomWire;
6458            if (nMaps > 0) {
6459                for (n = 0; n < nMaps; n++) {
6460                    if (client->swapped) {
6461                        swaps(&mapWire->virtualMods);
6462                        swapl(&mapWire->ctrls);
6463                    }
6464                    CHK_MASK_LEGAL3(0x21, mapWire->whichGroups,
6465                                    XkbIM_UseAnyGroup,
6466                                    client->errorValue, *status_rtrn, NULL);
6467                    CHK_MASK_LEGAL3(0x22, mapWire->whichMods, XkbIM_UseAnyMods,
6468                                    client->errorValue, *status_rtrn, NULL);
6469                    mapWire++;
6470                }
6471            }
6472            ledWire = (xkbDeviceLedsWireDesc *) mapWire;
6473        }
6474        else {
6475            /* SHOULD NEVER HAPPEN */
6476            return (char *) ledWire;
6477        }
6478    }
6479    return (char *) ledWire;
6480}
6481
6482static char *
6483SetDeviceIndicators(char *wire,
6484                    DeviceIntPtr dev,
6485                    unsigned changed,
6486                    int num,
6487                    int *status_rtrn,
6488                    ClientPtr client, xkbExtensionDeviceNotify * ev)
6489{
6490    xkbDeviceLedsWireDesc *ledWire;
6491    int i;
6492    XkbEventCauseRec cause;
6493    unsigned namec, mapc, statec;
6494    xkbExtensionDeviceNotify ed;
6495    XkbChangesRec changes;
6496    DeviceIntPtr kbd;
6497
6498    memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify));
6499    memset((char *) &changes, 0, sizeof(XkbChangesRec));
6500    XkbSetCauseXkbReq(&cause, X_kbSetDeviceInfo, client);
6501    ledWire = (xkbDeviceLedsWireDesc *) wire;
6502    for (i = 0; i < num; i++) {
6503        register int n;
6504        register unsigned bit;
6505        CARD32 *atomWire;
6506        xkbIndicatorMapWireDesc *mapWire;
6507        XkbSrvLedInfoPtr sli;
6508
6509        namec = mapc = statec = 0;
6510        sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID,
6511                                XkbXI_IndicatorMapsMask);
6512        if (!sli) {
6513            /* SHOULD NEVER HAPPEN!! */
6514            return (char *) ledWire;
6515        }
6516
6517        atomWire = (CARD32 *) &ledWire[1];
6518        if (changed & XkbXI_IndicatorNamesMask) {
6519            namec = sli->namesPresent | ledWire->namesPresent;
6520            memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom));
6521        }
6522        if (ledWire->namesPresent) {
6523            sli->namesPresent = ledWire->namesPresent;
6524            memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom));
6525            for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6526                if (ledWire->namesPresent & bit) {
6527                    sli->names[n] = (Atom) *atomWire;
6528                    if (sli->names[n] == None)
6529                        ledWire->namesPresent &= ~bit;
6530                    atomWire++;
6531                }
6532            }
6533        }
6534        mapWire = (xkbIndicatorMapWireDesc *) atomWire;
6535        if (changed & XkbXI_IndicatorMapsMask) {
6536            mapc = sli->mapsPresent | ledWire->mapsPresent;
6537            sli->mapsPresent = ledWire->mapsPresent;
6538            memset((char *) sli->maps, 0,
6539                   XkbNumIndicators * sizeof(XkbIndicatorMapRec));
6540        }
6541        if (ledWire->mapsPresent) {
6542            for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6543                if (ledWire->mapsPresent & bit) {
6544                    sli->maps[n].flags = mapWire->flags;
6545                    sli->maps[n].which_groups = mapWire->whichGroups;
6546                    sli->maps[n].groups = mapWire->groups;
6547                    sli->maps[n].which_mods = mapWire->whichMods;
6548                    sli->maps[n].mods.mask = mapWire->mods;
6549                    sli->maps[n].mods.real_mods = mapWire->realMods;
6550                    sli->maps[n].mods.vmods = mapWire->virtualMods;
6551                    sli->maps[n].ctrls = mapWire->ctrls;
6552                    mapWire++;
6553                }
6554            }
6555        }
6556        if (changed & XkbXI_IndicatorStateMask) {
6557            statec = sli->effectiveState ^ ledWire->state;
6558            sli->explicitState &= ~statec;
6559            sli->explicitState |= (ledWire->state & statec);
6560        }
6561        if (namec)
6562            XkbApplyLedNameChanges(dev, sli, namec, &ed, &changes, &cause);
6563        if (mapc)
6564            XkbApplyLedMapChanges(dev, sli, mapc, &ed, &changes, &cause);
6565        if (statec)
6566            XkbApplyLedStateChanges(dev, sli, statec, &ed, &changes, &cause);
6567
6568        kbd = dev;
6569        if ((sli->flags & XkbSLI_HasOwnState) == 0)
6570            kbd = inputInfo.keyboard;
6571
6572        XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause);
6573        ledWire = (xkbDeviceLedsWireDesc *) mapWire;
6574    }
6575    return (char *) ledWire;
6576}
6577
6578static int
6579_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev,
6580                  xkbSetDeviceInfoReq * stuff)
6581{
6582    char *wire;
6583
6584    wire = (char *) &stuff[1];
6585    if (stuff->change & XkbXI_ButtonActionsMask) {
6586        if (!dev->button) {
6587            client->errorValue = _XkbErrCode2(XkbErr_BadClass, ButtonClass);
6588            return XkbKeyboardErrorCode;
6589        }
6590        if ((stuff->firstBtn + stuff->nBtns) > dev->button->numButtons) {
6591            client->errorValue =
6592                _XkbErrCode4(0x02, stuff->firstBtn, stuff->nBtns,
6593                             dev->button->numButtons);
6594            return BadMatch;
6595        }
6596        wire += (stuff->nBtns * SIZEOF(xkbActionWireDesc));
6597    }
6598    if (stuff->change & XkbXI_IndicatorsMask) {
6599        int status = Success;
6600
6601        wire = CheckSetDeviceIndicators(wire, dev, stuff->nDeviceLedFBs,
6602                                        &status, client);
6603        if (status != Success)
6604            return status;
6605    }
6606    if (((wire - ((char *) stuff)) / 4) != stuff->length)
6607        return BadLength;
6608
6609    return Success;
6610}
6611
6612static int
6613_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev,
6614                       xkbSetDeviceInfoReq * stuff)
6615{
6616    char *wire;
6617    xkbExtensionDeviceNotify ed;
6618
6619    memset((char *) &ed, 0, SIZEOF(xkbExtensionDeviceNotify));
6620    ed.deviceID = dev->id;
6621    wire = (char *) &stuff[1];
6622    if (stuff->change & XkbXI_ButtonActionsMask) {
6623        int nBtns, sz, i;
6624        XkbAction *acts;
6625        DeviceIntPtr kbd;
6626
6627        nBtns = dev->button->numButtons;
6628        acts = dev->button->xkb_acts;
6629        if (acts == NULL) {
6630            acts = calloc(nBtns, sizeof(XkbAction));
6631            if (!acts)
6632                return BadAlloc;
6633            dev->button->xkb_acts = acts;
6634        }
6635        sz = stuff->nBtns * SIZEOF(xkbActionWireDesc);
6636        memcpy((char *) &acts[stuff->firstBtn], (char *) wire, sz);
6637        wire += sz;
6638        ed.reason |= XkbXI_ButtonActionsMask;
6639        ed.firstBtn = stuff->firstBtn;
6640        ed.nBtns = stuff->nBtns;
6641
6642        if (dev->key)
6643            kbd = dev;
6644        else
6645            kbd = inputInfo.keyboard;
6646        acts = &dev->button->xkb_acts[stuff->firstBtn];
6647        for (i = 0; i < stuff->nBtns; i++, acts++) {
6648            if (acts->type != XkbSA_NoAction)
6649                XkbSetActionKeyMods(kbd->key->xkbInfo->desc, acts, 0);
6650        }
6651    }
6652    if (stuff->change & XkbXI_IndicatorsMask) {
6653        int status = Success;
6654
6655        wire = SetDeviceIndicators(wire, dev, stuff->change,
6656                                   stuff->nDeviceLedFBs, &status, client, &ed);
6657        if (status != Success)
6658            return status;
6659    }
6660    if ((stuff->change) && (ed.reason))
6661        XkbSendExtensionDeviceNotify(dev, client, &ed);
6662    return Success;
6663}
6664
6665int
6666ProcXkbSetDeviceInfo(ClientPtr client)
6667{
6668    DeviceIntPtr dev;
6669    int rc;
6670
6671    REQUEST(xkbSetDeviceInfoReq);
6672    REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq);
6673
6674    if (!(client->xkbClientFlags & _XkbClientInitialized))
6675        return BadAccess;
6676
6677    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
6678    CHK_MASK_LEGAL(0x01, stuff->change, XkbXI_AllFeaturesMask);
6679
6680    rc = _XkbSetDeviceInfoCheck(client, dev, stuff);
6681
6682    if (rc != Success)
6683        return rc;
6684
6685    if (stuff->deviceSpec == XkbUseCoreKbd ||
6686        stuff->deviceSpec == XkbUseCorePtr) {
6687        DeviceIntPtr other;
6688
6689        for (other = inputInfo.devices; other; other = other->next) {
6690            if (((other != dev) && !IsMaster(other) &&
6691                 GetMaster(other, MASTER_KEYBOARD) == dev) &&
6692                ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
6693                 (stuff->deviceSpec == XkbUseCorePtr && other->button))) {
6694                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
6695                              DixManageAccess);
6696                if (rc == Success) {
6697                    rc = _XkbSetDeviceInfoCheck(client, other, stuff);
6698                    if (rc != Success)
6699                        return rc;
6700                }
6701            }
6702        }
6703    }
6704
6705    /* checks done, apply */
6706    rc = _XkbSetDeviceInfo(client, dev, stuff);
6707    if (rc != Success)
6708        return rc;
6709
6710    if (stuff->deviceSpec == XkbUseCoreKbd ||
6711        stuff->deviceSpec == XkbUseCorePtr) {
6712        DeviceIntPtr other;
6713
6714        for (other = inputInfo.devices; other; other = other->next) {
6715            if (((other != dev) && !IsMaster(other) &&
6716                 GetMaster(other, MASTER_KEYBOARD) == dev) &&
6717                ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
6718                 (stuff->deviceSpec == XkbUseCorePtr && other->button))) {
6719                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
6720                              DixManageAccess);
6721                if (rc == Success) {
6722                    rc = _XkbSetDeviceInfo(client, other, stuff);
6723                    if (rc != Success)
6724                        return rc;
6725                }
6726            }
6727        }
6728    }
6729
6730    return Success;
6731}
6732
6733/***====================================================================***/
6734
6735int
6736ProcXkbSetDebuggingFlags(ClientPtr client)
6737{
6738    CARD32 newFlags, newCtrls, extraLength;
6739    xkbSetDebuggingFlagsReply rep;
6740    int rc;
6741
6742    REQUEST(xkbSetDebuggingFlagsReq);
6743    REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq);
6744
6745    rc = XaceHook(XACE_SERVER_ACCESS, client, DixDebugAccess);
6746    if (rc != Success)
6747        return rc;
6748
6749    newFlags = xkbDebugFlags & (~stuff->affectFlags);
6750    newFlags |= (stuff->flags & stuff->affectFlags);
6751    newCtrls = xkbDebugCtrls & (~stuff->affectCtrls);
6752    newCtrls |= (stuff->ctrls & stuff->affectCtrls);
6753    if (xkbDebugFlags || newFlags || stuff->msgLength) {
6754        ErrorF("[xkb] XkbDebug: Setting debug flags to 0x%lx\n",
6755               (long) newFlags);
6756        if (newCtrls != xkbDebugCtrls)
6757            ErrorF("[xkb] XkbDebug: Setting debug controls to 0x%lx\n",
6758                   (long) newCtrls);
6759    }
6760    extraLength = (stuff->length << 2) - sz_xkbSetDebuggingFlagsReq;
6761    if (stuff->msgLength > 0) {
6762        char *msg;
6763
6764        if (extraLength < XkbPaddedSize(stuff->msgLength)) {
6765            ErrorF
6766                ("[xkb] XkbDebug: msgLength= %d, length= %ld (should be %d)\n",
6767                 stuff->msgLength, (long) extraLength,
6768                 XkbPaddedSize(stuff->msgLength));
6769            return BadLength;
6770        }
6771        msg = (char *) &stuff[1];
6772        if (msg[stuff->msgLength - 1] != '\0') {
6773            ErrorF("[xkb] XkbDebug: message not null-terminated\n");
6774            return BadValue;
6775        }
6776        ErrorF("[xkb] XkbDebug: %s\n", msg);
6777    }
6778    xkbDebugFlags = newFlags;
6779    xkbDebugCtrls = newCtrls;
6780
6781    rep = (xkbSetDebuggingFlagsReply) {
6782        .type = X_Reply,
6783        .sequenceNumber = client->sequence,
6784        .length = 0,
6785        .currentFlags = newFlags,
6786        .currentCtrls = newCtrls,
6787        .supportedFlags = ~0,
6788        .supportedCtrls = ~0
6789    };
6790    if (client->swapped) {
6791        swaps(&rep.sequenceNumber);
6792        swapl(&rep.currentFlags);
6793        swapl(&rep.currentCtrls);
6794        swapl(&rep.supportedFlags);
6795        swapl(&rep.supportedCtrls);
6796    }
6797    WriteToClient(client, SIZEOF(xkbSetDebuggingFlagsReply), &rep);
6798    return Success;
6799}
6800
6801/***====================================================================***/
6802
6803static int
6804ProcXkbDispatch(ClientPtr client)
6805{
6806    REQUEST(xReq);
6807    switch (stuff->data) {
6808    case X_kbUseExtension:
6809        return ProcXkbUseExtension(client);
6810    case X_kbSelectEvents:
6811        return ProcXkbSelectEvents(client);
6812    case X_kbBell:
6813        return ProcXkbBell(client);
6814    case X_kbGetState:
6815        return ProcXkbGetState(client);
6816    case X_kbLatchLockState:
6817        return ProcXkbLatchLockState(client);
6818    case X_kbGetControls:
6819        return ProcXkbGetControls(client);
6820    case X_kbSetControls:
6821        return ProcXkbSetControls(client);
6822    case X_kbGetMap:
6823        return ProcXkbGetMap(client);
6824    case X_kbSetMap:
6825        return ProcXkbSetMap(client);
6826    case X_kbGetCompatMap:
6827        return ProcXkbGetCompatMap(client);
6828    case X_kbSetCompatMap:
6829        return ProcXkbSetCompatMap(client);
6830    case X_kbGetIndicatorState:
6831        return ProcXkbGetIndicatorState(client);
6832    case X_kbGetIndicatorMap:
6833        return ProcXkbGetIndicatorMap(client);
6834    case X_kbSetIndicatorMap:
6835        return ProcXkbSetIndicatorMap(client);
6836    case X_kbGetNamedIndicator:
6837        return ProcXkbGetNamedIndicator(client);
6838    case X_kbSetNamedIndicator:
6839        return ProcXkbSetNamedIndicator(client);
6840    case X_kbGetNames:
6841        return ProcXkbGetNames(client);
6842    case X_kbSetNames:
6843        return ProcXkbSetNames(client);
6844    case X_kbGetGeometry:
6845        return ProcXkbGetGeometry(client);
6846    case X_kbSetGeometry:
6847        return ProcXkbSetGeometry(client);
6848    case X_kbPerClientFlags:
6849        return ProcXkbPerClientFlags(client);
6850    case X_kbListComponents:
6851        return ProcXkbListComponents(client);
6852    case X_kbGetKbdByName:
6853        return ProcXkbGetKbdByName(client);
6854    case X_kbGetDeviceInfo:
6855        return ProcXkbGetDeviceInfo(client);
6856    case X_kbSetDeviceInfo:
6857        return ProcXkbSetDeviceInfo(client);
6858    case X_kbSetDebuggingFlags:
6859        return ProcXkbSetDebuggingFlags(client);
6860    default:
6861        return BadRequest;
6862    }
6863}
6864
6865static int
6866XkbClientGone(void *data, XID id)
6867{
6868    DevicePtr pXDev = (DevicePtr) data;
6869
6870    if (!XkbRemoveResourceClient(pXDev, id)) {
6871        ErrorF
6872            ("[xkb] Internal Error! bad RemoveResourceClient in XkbClientGone\n");
6873    }
6874    return 1;
6875}
6876
6877void
6878XkbExtensionInit(void)
6879{
6880    ExtensionEntry *extEntry;
6881
6882    RT_XKBCLIENT = CreateNewResourceType(XkbClientGone, "XkbClient");
6883    if (!RT_XKBCLIENT)
6884        return;
6885
6886    if (!XkbInitPrivates())
6887        return;
6888
6889    if ((extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors,
6890                                 ProcXkbDispatch, SProcXkbDispatch,
6891                                 NULL, StandardMinorOpcode))) {
6892        XkbReqCode = (unsigned char) extEntry->base;
6893        XkbEventBase = (unsigned char) extEntry->eventBase;
6894        XkbErrorBase = (unsigned char) extEntry->errorBase;
6895        XkbKeyboardErrorCode = XkbErrorBase + XkbKeyboard;
6896    }
6897    return;
6898}
6899