xkb.c revision 7e31ba66
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        oldMap->kt_index[0] = wire->ktIndex[0];
2114        oldMap->kt_index[1] = wire->ktIndex[1];
2115        oldMap->kt_index[2] = wire->ktIndex[2];
2116        oldMap->kt_index[3] = wire->ktIndex[3];
2117        oldMap->group_info = wire->groupInfo;
2118        oldMap->width = wire->width;
2119        wire = (xkbSymMapWireDesc *) &pSyms[wire->nSyms];
2120    }
2121    first = req->firstKeySym;
2122    last = first + req->nKeySyms - 1;
2123    if (changes->map.changed & XkbKeySymsMask) {
2124        int oldLast =
2125            (changes->map.first_key_sym + changes->map.num_key_syms - 1);
2126        if (changes->map.first_key_sym < first)
2127            first = changes->map.first_key_sym;
2128        if (oldLast > last)
2129            last = oldLast;
2130    }
2131    changes->map.changed |= XkbKeySymsMask;
2132    changes->map.first_key_sym = first;
2133    changes->map.num_key_syms = (last - first + 1);
2134
2135    s = 0;
2136    for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
2137        if (XkbKeyNumGroups(xkb, i) > s)
2138            s = XkbKeyNumGroups(xkb, i);
2139    }
2140    if (s != xkb->ctrls->num_groups) {
2141        xkbControlsNotify cn;
2142        XkbControlsRec old;
2143
2144        cn.keycode = 0;
2145        cn.eventType = 0;
2146        cn.requestMajor = XkbReqCode;
2147        cn.requestMinor = X_kbSetMap;
2148        old = *xkb->ctrls;
2149        xkb->ctrls->num_groups = s;
2150        if (XkbComputeControlsNotify(dev, &old, xkb->ctrls, &cn, FALSE))
2151            XkbSendControlsNotify(dev, &cn);
2152    }
2153    return (char *) wire;
2154}
2155
2156static char *
2157SetKeyActions(XkbDescPtr xkb,
2158              xkbSetMapReq * req, CARD8 *wire, XkbChangesPtr changes)
2159{
2160    register unsigned i, first, last;
2161    CARD8 *nActs = wire;
2162    XkbAction *newActs;
2163
2164    wire += XkbPaddedSize(req->nKeyActs);
2165    for (i = 0; i < req->nKeyActs; i++) {
2166        if (nActs[i] == 0)
2167            xkb->server->key_acts[i + req->firstKeyAct] = 0;
2168        else {
2169            newActs = XkbResizeKeyActions(xkb, i + req->firstKeyAct, nActs[i]);
2170            memcpy((char *) newActs, (char *) wire,
2171                   nActs[i] * SIZEOF(xkbActionWireDesc));
2172            wire += nActs[i] * SIZEOF(xkbActionWireDesc);
2173        }
2174    }
2175    first = req->firstKeyAct;
2176    last = (first + req->nKeyActs - 1);
2177    if (changes->map.changed & XkbKeyActionsMask) {
2178        int oldLast;
2179
2180        oldLast = changes->map.first_key_act + changes->map.num_key_acts - 1;
2181        if (changes->map.first_key_act < first)
2182            first = changes->map.first_key_act;
2183        if (oldLast > last)
2184            last = oldLast;
2185    }
2186    changes->map.changed |= XkbKeyActionsMask;
2187    changes->map.first_key_act = first;
2188    changes->map.num_key_acts = (last - first + 1);
2189    return (char *) wire;
2190}
2191
2192static char *
2193SetKeyBehaviors(XkbSrvInfoPtr xkbi,
2194                xkbSetMapReq * req,
2195                xkbBehaviorWireDesc * wire, XkbChangesPtr changes)
2196{
2197    register unsigned i;
2198    int maxRG = -1;
2199    XkbDescPtr xkb = xkbi->desc;
2200    XkbServerMapPtr server = xkb->server;
2201    unsigned first, last;
2202
2203    first = req->firstKeyBehavior;
2204    last = req->firstKeyBehavior + req->nKeyBehaviors - 1;
2205    memset(&server->behaviors[first], 0,
2206           req->nKeyBehaviors * sizeof(XkbBehavior));
2207    for (i = 0; i < req->totalKeyBehaviors; i++) {
2208        if ((server->behaviors[wire->key].type & XkbKB_Permanent) == 0) {
2209            server->behaviors[wire->key].type = wire->type;
2210            server->behaviors[wire->key].data = wire->data;
2211            if ((wire->type == XkbKB_RadioGroup) &&
2212                (((int) wire->data) > maxRG))
2213                maxRG = wire->data + 1;
2214        }
2215        wire++;
2216    }
2217
2218    if (maxRG > (int) xkbi->nRadioGroups) {
2219        if (xkbi->radioGroups)
2220            xkbi->radioGroups = reallocarray(xkbi->radioGroups, maxRG,
2221                                             sizeof(XkbRadioGroupRec));
2222        else
2223            xkbi->radioGroups = calloc(maxRG, sizeof(XkbRadioGroupRec));
2224        if (xkbi->radioGroups) {
2225            if (xkbi->nRadioGroups)
2226                memset(&xkbi->radioGroups[xkbi->nRadioGroups], 0,
2227                       (maxRG - xkbi->nRadioGroups) * sizeof(XkbRadioGroupRec));
2228            xkbi->nRadioGroups = maxRG;
2229        }
2230        else
2231            xkbi->nRadioGroups = 0;
2232        /* should compute members here */
2233    }
2234    if (changes->map.changed & XkbKeyBehaviorsMask) {
2235        unsigned oldLast;
2236
2237        oldLast = changes->map.first_key_behavior +
2238            changes->map.num_key_behaviors - 1;
2239        if (changes->map.first_key_behavior < req->firstKeyBehavior)
2240            first = changes->map.first_key_behavior;
2241        if (oldLast > last)
2242            last = oldLast;
2243    }
2244    changes->map.changed |= XkbKeyBehaviorsMask;
2245    changes->map.first_key_behavior = first;
2246    changes->map.num_key_behaviors = (last - first + 1);
2247    return (char *) wire;
2248}
2249
2250static char *
2251SetVirtualMods(XkbSrvInfoPtr xkbi, xkbSetMapReq * req, CARD8 *wire,
2252               XkbChangesPtr changes)
2253{
2254    register int i, bit, nMods;
2255    XkbServerMapPtr srv = xkbi->desc->server;
2256
2257    if (((req->present & XkbVirtualModsMask) == 0) || (req->virtualMods == 0))
2258        return (char *) wire;
2259    for (i = nMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
2260        if (req->virtualMods & bit) {
2261            if (srv->vmods[i] != wire[nMods]) {
2262                changes->map.changed |= XkbVirtualModsMask;
2263                changes->map.vmods |= bit;
2264                srv->vmods[i] = wire[nMods];
2265            }
2266            nMods++;
2267        }
2268    }
2269    return (char *) (wire + XkbPaddedSize(nMods));
2270}
2271
2272static char *
2273SetKeyExplicit(XkbSrvInfoPtr xkbi, xkbSetMapReq * req, CARD8 *wire,
2274               XkbChangesPtr changes)
2275{
2276    register unsigned i, first, last;
2277    XkbServerMapPtr xkb = xkbi->desc->server;
2278    CARD8 *start;
2279
2280    start = wire;
2281    first = req->firstKeyExplicit;
2282    last = req->firstKeyExplicit + req->nKeyExplicit - 1;
2283    memset(&xkb->explicit[first], 0, req->nKeyExplicit);
2284    for (i = 0; i < req->totalKeyExplicit; i++, wire += 2) {
2285        xkb->explicit[wire[0]] = wire[1];
2286    }
2287    if (first > 0) {
2288        if (changes->map.changed & XkbExplicitComponentsMask) {
2289            int oldLast;
2290
2291            oldLast = changes->map.first_key_explicit +
2292                changes->map.num_key_explicit - 1;
2293            if (changes->map.first_key_explicit < first)
2294                first = changes->map.first_key_explicit;
2295            if (oldLast > last)
2296                last = oldLast;
2297        }
2298        changes->map.first_key_explicit = first;
2299        changes->map.num_key_explicit = (last - first) + 1;
2300    }
2301    wire += XkbPaddedSize(wire - start) - (wire - start);
2302    return (char *) wire;
2303}
2304
2305static char *
2306SetModifierMap(XkbSrvInfoPtr xkbi,
2307               xkbSetMapReq * req, CARD8 *wire, XkbChangesPtr changes)
2308{
2309    register unsigned i, first, last;
2310    XkbClientMapPtr xkb = xkbi->desc->map;
2311    CARD8 *start;
2312
2313    start = wire;
2314    first = req->firstModMapKey;
2315    last = req->firstModMapKey + req->nModMapKeys - 1;
2316    memset(&xkb->modmap[first], 0, req->nModMapKeys);
2317    for (i = 0; i < req->totalModMapKeys; i++, wire += 2) {
2318        xkb->modmap[wire[0]] = wire[1];
2319    }
2320    if (first > 0) {
2321        if (changes->map.changed & XkbModifierMapMask) {
2322            int oldLast;
2323
2324            oldLast = changes->map.first_modmap_key +
2325                changes->map.num_modmap_keys - 1;
2326            if (changes->map.first_modmap_key < first)
2327                first = changes->map.first_modmap_key;
2328            if (oldLast > last)
2329                last = oldLast;
2330        }
2331        changes->map.first_modmap_key = first;
2332        changes->map.num_modmap_keys = (last - first) + 1;
2333    }
2334    wire += XkbPaddedSize(wire - start) - (wire - start);
2335    return (char *) wire;
2336}
2337
2338static char *
2339SetVirtualModMap(XkbSrvInfoPtr xkbi,
2340                 xkbSetMapReq * req,
2341                 xkbVModMapWireDesc * wire, XkbChangesPtr changes)
2342{
2343    register unsigned i, first, last;
2344    XkbServerMapPtr srv = xkbi->desc->server;
2345
2346    first = req->firstVModMapKey;
2347    last = req->firstVModMapKey + req->nVModMapKeys - 1;
2348    memset(&srv->vmodmap[first], 0, req->nVModMapKeys * sizeof(unsigned short));
2349    for (i = 0; i < req->totalVModMapKeys; i++, wire++) {
2350        srv->vmodmap[wire->key] = wire->vmods;
2351    }
2352    if (first > 0) {
2353        if (changes->map.changed & XkbVirtualModMapMask) {
2354            int oldLast;
2355
2356            oldLast = changes->map.first_vmodmap_key +
2357                changes->map.num_vmodmap_keys - 1;
2358            if (changes->map.first_vmodmap_key < first)
2359                first = changes->map.first_vmodmap_key;
2360            if (oldLast > last)
2361                last = oldLast;
2362        }
2363        changes->map.first_vmodmap_key = first;
2364        changes->map.num_vmodmap_keys = (last - first) + 1;
2365    }
2366    return (char *) wire;
2367}
2368
2369/**
2370 * Check if the given request can be applied to the given device but don't
2371 * actually do anything..
2372 */
2373static int
2374_XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq * req,
2375                 char *values)
2376{
2377    XkbSrvInfoPtr xkbi;
2378    XkbDescPtr xkb;
2379    int error;
2380    int nTypes = 0, nActions;
2381    CARD8 mapWidths[XkbMaxLegalKeyCode + 1] = { 0 };
2382    CARD16 symsPerKey[XkbMaxLegalKeyCode + 1] = { 0 };
2383    XkbSymMapPtr map;
2384    int i;
2385
2386    xkbi = dev->key->xkbInfo;
2387    xkb = xkbi->desc;
2388
2389    if ((xkb->min_key_code != req->minKeyCode) ||
2390        (xkb->max_key_code != req->maxKeyCode)) {
2391        if (client->xkbClientFlags & _XkbClientIsAncient) {
2392            /* pre 1.0 versions of Xlib have a bug */
2393            req->minKeyCode = xkb->min_key_code;
2394            req->maxKeyCode = xkb->max_key_code;
2395        }
2396        else {
2397            if (!XkbIsLegalKeycode(req->minKeyCode)) {
2398                client->errorValue =
2399                    _XkbErrCode3(2, req->minKeyCode, req->maxKeyCode);
2400                return BadValue;
2401            }
2402            if (req->minKeyCode > req->maxKeyCode) {
2403                client->errorValue =
2404                    _XkbErrCode3(3, req->minKeyCode, req->maxKeyCode);
2405                return BadMatch;
2406            }
2407        }
2408    }
2409
2410    if ((req->present & XkbKeyTypesMask) &&
2411        (!CheckKeyTypes(client, xkb, req, (xkbKeyTypeWireDesc **) &values,
2412                        &nTypes, mapWidths))) {
2413        client->errorValue = nTypes;
2414        return BadValue;
2415    }
2416
2417    /* symsPerKey/mapWidths must be filled regardless of client-side flags */
2418    map = &xkb->map->key_sym_map[xkb->min_key_code];
2419    for (i = xkb->min_key_code; i < xkb->max_key_code; i++, map++) {
2420        register int g, ng, w;
2421
2422        ng = XkbNumGroups(map->group_info);
2423        for (w = g = 0; g < ng; g++) {
2424            if (map->kt_index[g] >= (unsigned) nTypes) {
2425                client->errorValue = _XkbErrCode4(0x13, i, g, map->kt_index[g]);
2426                return 0;
2427            }
2428            if (mapWidths[map->kt_index[g]] > w)
2429                w = mapWidths[map->kt_index[g]];
2430        }
2431        symsPerKey[i] = w * ng;
2432    }
2433
2434    if ((req->present & XkbKeySymsMask) &&
2435        (!CheckKeySyms(client, xkb, req, nTypes, mapWidths, symsPerKey,
2436                       (xkbSymMapWireDesc **) &values, &error))) {
2437        client->errorValue = error;
2438        return BadValue;
2439    }
2440
2441    if ((req->present & XkbKeyActionsMask) &&
2442        (!CheckKeyActions(xkb, req, nTypes, mapWidths, symsPerKey,
2443                          (CARD8 **) &values, &nActions))) {
2444        client->errorValue = nActions;
2445        return BadValue;
2446    }
2447
2448    if ((req->present & XkbKeyBehaviorsMask) &&
2449        (!CheckKeyBehaviors
2450         (xkb, req, (xkbBehaviorWireDesc **) &values, &error))) {
2451        client->errorValue = error;
2452        return BadValue;
2453    }
2454
2455    if ((req->present & XkbVirtualModsMask) &&
2456        (!CheckVirtualMods(xkb, req, (CARD8 **) &values, &error))) {
2457        client->errorValue = error;
2458        return BadValue;
2459    }
2460    if ((req->present & XkbExplicitComponentsMask) &&
2461        (!CheckKeyExplicit(xkb, req, (CARD8 **) &values, &error))) {
2462        client->errorValue = error;
2463        return BadValue;
2464    }
2465    if ((req->present & XkbModifierMapMask) &&
2466        (!CheckModifierMap(xkb, req, (CARD8 **) &values, &error))) {
2467        client->errorValue = error;
2468        return BadValue;
2469    }
2470    if ((req->present & XkbVirtualModMapMask) &&
2471        (!CheckVirtualModMap
2472         (xkb, req, (xkbVModMapWireDesc **) &values, &error))) {
2473        client->errorValue = error;
2474        return BadValue;
2475    }
2476
2477    if (((values - ((char *) req)) / 4) != req->length) {
2478        ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after check)\n");
2479        client->errorValue = values - ((char *) &req[1]);
2480        return BadLength;
2481    }
2482
2483    return Success;
2484}
2485
2486/**
2487 * Apply the given request on the given device.
2488 */
2489static int
2490_XkbSetMap(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq * req, char *values)
2491{
2492    XkbEventCauseRec cause;
2493    XkbChangesRec change;
2494    Bool sentNKN;
2495    XkbSrvInfoPtr xkbi;
2496    XkbDescPtr xkb;
2497
2498    xkbi = dev->key->xkbInfo;
2499    xkb = xkbi->desc;
2500
2501    XkbSetCauseXkbReq(&cause, X_kbSetMap, client);
2502    memset(&change, 0, sizeof(change));
2503    sentNKN = FALSE;
2504    if ((xkb->min_key_code != req->minKeyCode) ||
2505        (xkb->max_key_code != req->maxKeyCode)) {
2506        Status status;
2507        xkbNewKeyboardNotify nkn;
2508
2509        nkn.deviceID = nkn.oldDeviceID = dev->id;
2510        nkn.oldMinKeyCode = xkb->min_key_code;
2511        nkn.oldMaxKeyCode = xkb->max_key_code;
2512        status = XkbChangeKeycodeRange(xkb, req->minKeyCode,
2513                                       req->maxKeyCode, &change);
2514        if (status != Success)
2515            return status;      /* oh-oh. what about the other keyboards? */
2516        nkn.minKeyCode = xkb->min_key_code;
2517        nkn.maxKeyCode = xkb->max_key_code;
2518        nkn.requestMajor = XkbReqCode;
2519        nkn.requestMinor = X_kbSetMap;
2520        nkn.changed = XkbNKN_KeycodesMask;
2521        XkbSendNewKeyboardNotify(dev, &nkn);
2522        sentNKN = TRUE;
2523    }
2524
2525    if (req->present & XkbKeyTypesMask) {
2526        values = SetKeyTypes(xkb, req, (xkbKeyTypeWireDesc *) values, &change);
2527        if (!values)
2528            goto allocFailure;
2529    }
2530    if (req->present & XkbKeySymsMask) {
2531        values =
2532            SetKeySyms(client, xkb, req, (xkbSymMapWireDesc *) values, &change,
2533                       dev);
2534        if (!values)
2535            goto allocFailure;
2536    }
2537    if (req->present & XkbKeyActionsMask) {
2538        values = SetKeyActions(xkb, req, (CARD8 *) values, &change);
2539        if (!values)
2540            goto allocFailure;
2541    }
2542    if (req->present & XkbKeyBehaviorsMask) {
2543        values =
2544            SetKeyBehaviors(xkbi, req, (xkbBehaviorWireDesc *) values, &change);
2545        if (!values)
2546            goto allocFailure;
2547    }
2548    if (req->present & XkbVirtualModsMask)
2549        values = SetVirtualMods(xkbi, req, (CARD8 *) values, &change);
2550    if (req->present & XkbExplicitComponentsMask)
2551        values = SetKeyExplicit(xkbi, req, (CARD8 *) values, &change);
2552    if (req->present & XkbModifierMapMask)
2553        values = SetModifierMap(xkbi, req, (CARD8 *) values, &change);
2554    if (req->present & XkbVirtualModMapMask)
2555        values =
2556            SetVirtualModMap(xkbi, req, (xkbVModMapWireDesc *) values, &change);
2557    if (((values - ((char *) req)) / 4) != req->length) {
2558        ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after set)\n");
2559        client->errorValue = values - ((char *) &req[1]);
2560        return BadLength;
2561    }
2562    if (req->flags & XkbSetMapRecomputeActions) {
2563        KeyCode first, last, firstMM, lastMM;
2564
2565        if (change.map.num_key_syms > 0) {
2566            first = change.map.first_key_sym;
2567            last = first + change.map.num_key_syms - 1;
2568        }
2569        else
2570            first = last = 0;
2571        if (change.map.num_modmap_keys > 0) {
2572            firstMM = change.map.first_modmap_key;
2573            lastMM = firstMM + change.map.num_modmap_keys - 1;
2574        }
2575        else
2576            firstMM = lastMM = 0;
2577        if ((last > 0) && (lastMM > 0)) {
2578            if (firstMM < first)
2579                first = firstMM;
2580            if (lastMM > last)
2581                last = lastMM;
2582        }
2583        else if (lastMM > 0) {
2584            first = firstMM;
2585            last = lastMM;
2586        }
2587        if (last > 0) {
2588            unsigned check = 0;
2589
2590            XkbUpdateActions(dev, first, (last - first + 1), &change, &check,
2591                             &cause);
2592            if (check)
2593                XkbCheckSecondaryEffects(xkbi, check, &change, &cause);
2594        }
2595    }
2596    if (!sentNKN)
2597        XkbSendNotification(dev, &change, &cause);
2598
2599    return Success;
2600 allocFailure:
2601    return BadAlloc;
2602}
2603
2604int
2605ProcXkbSetMap(ClientPtr client)
2606{
2607    DeviceIntPtr dev;
2608    char *tmp;
2609    int rc;
2610
2611    REQUEST(xkbSetMapReq);
2612    REQUEST_AT_LEAST_SIZE(xkbSetMapReq);
2613
2614    if (!(client->xkbClientFlags & _XkbClientInitialized))
2615        return BadAccess;
2616
2617    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
2618    CHK_MASK_LEGAL(0x01, stuff->present, XkbAllMapComponentsMask);
2619
2620    tmp = (char *) &stuff[1];
2621
2622    /* Check if we can to the SetMap on the requested device. If this
2623       succeeds, do the same thing for all extension devices (if needed).
2624       If any of them fails, fail.  */
2625    rc = _XkbSetMapChecks(client, dev, stuff, tmp);
2626
2627    if (rc != Success)
2628        return rc;
2629
2630    DeviceIntPtr master = GetMaster(dev, MASTER_KEYBOARD);
2631
2632    if (stuff->deviceSpec == XkbUseCoreKbd) {
2633        DeviceIntPtr other;
2634
2635        for (other = inputInfo.devices; other; other = other->next) {
2636            if ((other != dev) && other->key && !IsMaster(other) &&
2637                GetMaster(other, MASTER_KEYBOARD) == dev) {
2638                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
2639                              DixManageAccess);
2640                if (rc == Success) {
2641                    rc = _XkbSetMapChecks(client, other, stuff, tmp);
2642                    if (rc != Success)
2643                        return rc;
2644                }
2645            }
2646        }
2647    } else {
2648        DeviceIntPtr other;
2649
2650        for (other = inputInfo.devices; other; other = other->next) {
2651            if (other != dev && GetMaster(other, MASTER_KEYBOARD) != dev &&
2652                (other != master || dev != master->lastSlave))
2653                continue;
2654
2655            rc = _XkbSetMapChecks(client, other, stuff, tmp);
2656            if (rc != Success)
2657                return rc;
2658        }
2659    }
2660
2661    /* We know now that we will succeed with the SetMap. In theory anyway. */
2662    rc = _XkbSetMap(client, dev, stuff, tmp);
2663    if (rc != Success)
2664        return rc;
2665
2666    if (stuff->deviceSpec == XkbUseCoreKbd) {
2667        DeviceIntPtr other;
2668
2669        for (other = inputInfo.devices; other; other = other->next) {
2670            if ((other != dev) && other->key && !IsMaster(other) &&
2671                GetMaster(other, MASTER_KEYBOARD) == dev) {
2672                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
2673                              DixManageAccess);
2674                if (rc == Success)
2675                    _XkbSetMap(client, other, stuff, tmp);
2676                /* ignore rc. if the SetMap failed although the check above
2677                   reported true there isn't much we can do. we still need to
2678                   set all other devices, hoping that at least they stay in
2679                   sync. */
2680            }
2681        }
2682    } else {
2683        DeviceIntPtr other;
2684
2685        for (other = inputInfo.devices; other; other = other->next) {
2686            if (other != dev && GetMaster(other, MASTER_KEYBOARD) != dev &&
2687                (other != master || dev != master->lastSlave))
2688                continue;
2689
2690            _XkbSetMap(client, other, stuff, tmp); //ignore rc
2691        }
2692    }
2693
2694    return Success;
2695}
2696
2697/***====================================================================***/
2698
2699static Status
2700XkbComputeGetCompatMapReplySize(XkbCompatMapPtr compat,
2701                                xkbGetCompatMapReply * rep)
2702{
2703    unsigned size, nGroups;
2704
2705    nGroups = 0;
2706    if (rep->groups != 0) {
2707        register int i, bit;
2708
2709        for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2710            if (rep->groups & bit)
2711                nGroups++;
2712        }
2713    }
2714    size = nGroups * SIZEOF(xkbModsWireDesc);
2715    size += (rep->nSI * SIZEOF(xkbSymInterpretWireDesc));
2716    rep->length = size / 4;
2717    return Success;
2718}
2719
2720static int
2721XkbSendCompatMap(ClientPtr client,
2722                 XkbCompatMapPtr compat, xkbGetCompatMapReply * rep)
2723{
2724    char *data;
2725    int size;
2726
2727    if (rep->length > 0) {
2728        data = xallocarray(rep->length, 4);
2729        if (data) {
2730            register unsigned i, bit;
2731            xkbModsWireDesc *grp;
2732            XkbSymInterpretPtr sym = &compat->sym_interpret[rep->firstSI];
2733            xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *) data;
2734
2735            size = rep->length * 4;
2736
2737            for (i = 0; i < rep->nSI; i++, sym++, wire++) {
2738                wire->sym = sym->sym;
2739                wire->mods = sym->mods;
2740                wire->match = sym->match;
2741                wire->virtualMod = sym->virtual_mod;
2742                wire->flags = sym->flags;
2743                memcpy((char *) &wire->act, (char *) &sym->act,
2744                       sz_xkbActionWireDesc);
2745                if (client->swapped) {
2746                    swapl(&wire->sym);
2747                }
2748            }
2749            if (rep->groups) {
2750                grp = (xkbModsWireDesc *) wire;
2751                for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2752                    if (rep->groups & bit) {
2753                        grp->mask = compat->groups[i].mask;
2754                        grp->realMods = compat->groups[i].real_mods;
2755                        grp->virtualMods = compat->groups[i].vmods;
2756                        if (client->swapped) {
2757                            swaps(&grp->virtualMods);
2758                        }
2759                        grp++;
2760                    }
2761                }
2762                wire = (xkbSymInterpretWireDesc *) grp;
2763            }
2764        }
2765        else
2766            return BadAlloc;
2767    }
2768    else
2769        data = NULL;
2770
2771    if (client->swapped) {
2772        swaps(&rep->sequenceNumber);
2773        swapl(&rep->length);
2774        swaps(&rep->firstSI);
2775        swaps(&rep->nSI);
2776        swaps(&rep->nTotalSI);
2777    }
2778
2779    WriteToClient(client, SIZEOF(xkbGetCompatMapReply), rep);
2780    if (data) {
2781        WriteToClient(client, size, data);
2782        free((char *) data);
2783    }
2784    return Success;
2785}
2786
2787int
2788ProcXkbGetCompatMap(ClientPtr client)
2789{
2790    xkbGetCompatMapReply rep;
2791    DeviceIntPtr dev;
2792    XkbDescPtr xkb;
2793    XkbCompatMapPtr compat;
2794
2795    REQUEST(xkbGetCompatMapReq);
2796    REQUEST_SIZE_MATCH(xkbGetCompatMapReq);
2797
2798    if (!(client->xkbClientFlags & _XkbClientInitialized))
2799        return BadAccess;
2800
2801    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
2802
2803    xkb = dev->key->xkbInfo->desc;
2804    compat = xkb->compat;
2805
2806    rep = (xkbGetCompatMapReply) {
2807        .type = X_Reply,
2808        .sequenceNumber = client->sequence,
2809        .length = 0,
2810        .deviceID = dev->id,
2811        .firstSI = stuff->firstSI,
2812        .nSI = stuff->nSI
2813    };
2814    if (stuff->getAllSI) {
2815        rep.firstSI = 0;
2816        rep.nSI = compat->num_si;
2817    }
2818    else if ((((unsigned) stuff->nSI) > 0) &&
2819             ((unsigned) (stuff->firstSI + stuff->nSI - 1) >= compat->num_si)) {
2820        client->errorValue = _XkbErrCode2(0x05, compat->num_si);
2821        return BadValue;
2822    }
2823    rep.nTotalSI = compat->num_si;
2824    rep.groups = stuff->groups;
2825    XkbComputeGetCompatMapReplySize(compat, &rep);
2826    return XkbSendCompatMap(client, compat, &rep);
2827}
2828
2829/**
2830 * Apply the given request on the given device.
2831 * If dryRun is TRUE, then value checks are performed, but the device isn't
2832 * modified.
2833 */
2834static int
2835_XkbSetCompatMap(ClientPtr client, DeviceIntPtr dev,
2836                 xkbSetCompatMapReq * req, char *data, BOOL dryRun)
2837{
2838    XkbSrvInfoPtr xkbi;
2839    XkbDescPtr xkb;
2840    XkbCompatMapPtr compat;
2841    int nGroups;
2842    unsigned i, bit;
2843
2844    xkbi = dev->key->xkbInfo;
2845    xkb = xkbi->desc;
2846    compat = xkb->compat;
2847
2848    if ((req->nSI > 0) || (req->truncateSI)) {
2849        xkbSymInterpretWireDesc *wire;
2850
2851        if (req->firstSI > compat->num_si) {
2852            client->errorValue = _XkbErrCode2(0x02, compat->num_si);
2853            return BadValue;
2854        }
2855        wire = (xkbSymInterpretWireDesc *) data;
2856        wire += req->nSI;
2857        data = (char *) wire;
2858    }
2859
2860    nGroups = 0;
2861    if (req->groups != 0) {
2862        for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2863            if (req->groups & bit)
2864                nGroups++;
2865        }
2866    }
2867    data += nGroups * SIZEOF(xkbModsWireDesc);
2868    if (((data - ((char *) req)) / 4) != req->length) {
2869        return BadLength;
2870    }
2871
2872    /* Done all the checks we can do */
2873    if (dryRun)
2874        return Success;
2875
2876    data = (char *) &req[1];
2877    if (req->nSI > 0) {
2878        xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *) data;
2879        XkbSymInterpretPtr sym;
2880        unsigned int skipped = 0;
2881
2882        if ((unsigned) (req->firstSI + req->nSI) > compat->num_si) {
2883            compat->num_si = req->firstSI + req->nSI;
2884            compat->sym_interpret = reallocarray(compat->sym_interpret,
2885                                                 compat->num_si,
2886                                                 sizeof(XkbSymInterpretRec));
2887            if (!compat->sym_interpret) {
2888                compat->num_si = 0;
2889                return BadAlloc;
2890            }
2891        }
2892        else if (req->truncateSI) {
2893            compat->num_si = req->firstSI + req->nSI;
2894        }
2895        sym = &compat->sym_interpret[req->firstSI];
2896        for (i = 0; i < req->nSI; i++, wire++) {
2897            if (client->swapped) {
2898                swapl(&wire->sym);
2899            }
2900            if (wire->sym == NoSymbol && wire->match == XkbSI_AnyOfOrNone &&
2901                (wire->mods & 0xff) == 0xff &&
2902                wire->act.type == XkbSA_XFree86Private) {
2903                ErrorF("XKB: Skipping broken Any+AnyOfOrNone(All) -> Private "
2904                       "action from client\n");
2905                skipped++;
2906                continue;
2907            }
2908            sym->sym = wire->sym;
2909            sym->mods = wire->mods;
2910            sym->match = wire->match;
2911            sym->flags = wire->flags;
2912            sym->virtual_mod = wire->virtualMod;
2913            memcpy((char *) &sym->act, (char *) &wire->act,
2914                   SIZEOF(xkbActionWireDesc));
2915            sym++;
2916        }
2917        if (skipped) {
2918            if (req->firstSI + req->nSI < compat->num_si)
2919                memmove(sym, sym + skipped,
2920                        (compat->num_si - req->firstSI - req->nSI) *
2921                        sizeof(*sym));
2922            compat->num_si -= skipped;
2923        }
2924        data = (char *) wire;
2925    }
2926    else if (req->truncateSI) {
2927        compat->num_si = req->firstSI;
2928    }
2929
2930    if (req->groups != 0) {
2931        xkbModsWireDesc *wire = (xkbModsWireDesc *) data;
2932
2933        for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2934            if (req->groups & bit) {
2935                if (client->swapped) {
2936                    swaps(&wire->virtualMods);
2937                }
2938                compat->groups[i].mask = wire->realMods;
2939                compat->groups[i].real_mods = wire->realMods;
2940                compat->groups[i].vmods = wire->virtualMods;
2941                if (wire->virtualMods != 0) {
2942                    unsigned tmp;
2943
2944                    tmp = XkbMaskForVMask(xkb, wire->virtualMods);
2945                    compat->groups[i].mask |= tmp;
2946                }
2947                data += SIZEOF(xkbModsWireDesc);
2948                wire = (xkbModsWireDesc *) data;
2949            }
2950        }
2951    }
2952    i = XkbPaddedSize((data - ((char *) req)));
2953    if ((i / 4) != req->length) {
2954        ErrorF("[xkb] Internal length error on read in _XkbSetCompatMap\n");
2955        return BadLength;
2956    }
2957
2958    if (dev->xkb_interest) {
2959        xkbCompatMapNotify ev;
2960
2961        ev.deviceID = dev->id;
2962        ev.changedGroups = req->groups;
2963        ev.firstSI = req->firstSI;
2964        ev.nSI = req->nSI;
2965        ev.nTotalSI = compat->num_si;
2966        XkbSendCompatMapNotify(dev, &ev);
2967    }
2968
2969    if (req->recomputeActions) {
2970        XkbChangesRec change;
2971        unsigned check;
2972        XkbEventCauseRec cause;
2973
2974        XkbSetCauseXkbReq(&cause, X_kbSetCompatMap, client);
2975        memset(&change, 0, sizeof(XkbChangesRec));
2976        XkbUpdateActions(dev, xkb->min_key_code, XkbNumKeys(xkb), &change,
2977                         &check, &cause);
2978        if (check)
2979            XkbCheckSecondaryEffects(xkbi, check, &change, &cause);
2980        XkbSendNotification(dev, &change, &cause);
2981    }
2982    return Success;
2983}
2984
2985int
2986ProcXkbSetCompatMap(ClientPtr client)
2987{
2988    DeviceIntPtr dev;
2989    char *data;
2990    int rc;
2991
2992    REQUEST(xkbSetCompatMapReq);
2993    REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq);
2994
2995    if (!(client->xkbClientFlags & _XkbClientInitialized))
2996        return BadAccess;
2997
2998    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
2999
3000    data = (char *) &stuff[1];
3001
3002    /* check first using a dry-run */
3003    rc = _XkbSetCompatMap(client, dev, stuff, data, TRUE);
3004    if (rc != Success)
3005        return rc;
3006    if (stuff->deviceSpec == XkbUseCoreKbd) {
3007        DeviceIntPtr other;
3008
3009        for (other = inputInfo.devices; other; other = other->next) {
3010            if ((other != dev) && other->key && !IsMaster(other) &&
3011                GetMaster(other, MASTER_KEYBOARD) == dev) {
3012                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
3013                              DixManageAccess);
3014                if (rc == Success) {
3015                    /* dry-run */
3016                    rc = _XkbSetCompatMap(client, other, stuff, data, TRUE);
3017                    if (rc != Success)
3018                        return rc;
3019                }
3020            }
3021        }
3022    }
3023
3024    /* Yay, the dry-runs succeed. Let's apply */
3025    rc = _XkbSetCompatMap(client, dev, stuff, data, FALSE);
3026    if (rc != Success)
3027        return rc;
3028    if (stuff->deviceSpec == XkbUseCoreKbd) {
3029        DeviceIntPtr other;
3030
3031        for (other = inputInfo.devices; other; other = other->next) {
3032            if ((other != dev) && other->key && !IsMaster(other) &&
3033                GetMaster(other, MASTER_KEYBOARD) == dev) {
3034                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
3035                              DixManageAccess);
3036                if (rc == Success) {
3037                    rc = _XkbSetCompatMap(client, other, stuff, data, FALSE);
3038                    if (rc != Success)
3039                        return rc;
3040                }
3041            }
3042        }
3043    }
3044
3045    return Success;
3046}
3047
3048/***====================================================================***/
3049
3050int
3051ProcXkbGetIndicatorState(ClientPtr client)
3052{
3053    xkbGetIndicatorStateReply rep;
3054    XkbSrvLedInfoPtr sli;
3055    DeviceIntPtr dev;
3056
3057    REQUEST(xkbGetIndicatorStateReq);
3058    REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq);
3059
3060    if (!(client->xkbClientFlags & _XkbClientInitialized))
3061        return BadAccess;
3062
3063    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
3064
3065    sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
3066                            XkbXI_IndicatorStateMask);
3067    if (!sli)
3068        return BadAlloc;
3069
3070    rep = (xkbGetIndicatorStateReply) {
3071        .type = X_Reply,
3072        .deviceID = dev->id,
3073        .sequenceNumber = client->sequence,
3074        .length = 0,
3075        .state = sli->effectiveState
3076    };
3077
3078    if (client->swapped) {
3079        swaps(&rep.sequenceNumber);
3080        swapl(&rep.state);
3081    }
3082    WriteToClient(client, SIZEOF(xkbGetIndicatorStateReply), &rep);
3083    return Success;
3084}
3085
3086/***====================================================================***/
3087
3088static Status
3089XkbComputeGetIndicatorMapReplySize(XkbIndicatorPtr indicators,
3090                                   xkbGetIndicatorMapReply * rep)
3091{
3092    register int i, bit;
3093    int nIndicators;
3094
3095    rep->realIndicators = indicators->phys_indicators;
3096    for (i = nIndicators = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3097        if (rep->which & bit)
3098            nIndicators++;
3099    }
3100    rep->length = (nIndicators * SIZEOF(xkbIndicatorMapWireDesc)) / 4;
3101    rep->nIndicators = nIndicators;
3102    return Success;
3103}
3104
3105static int
3106XkbSendIndicatorMap(ClientPtr client,
3107                    XkbIndicatorPtr indicators, xkbGetIndicatorMapReply * rep)
3108{
3109    int length;
3110    CARD8 *map;
3111    register int i;
3112    register unsigned bit;
3113
3114    if (rep->length > 0) {
3115        CARD8 *to;
3116
3117        to = map = xallocarray(rep->length, 4);
3118        if (map) {
3119            xkbIndicatorMapWireDesc *wire = (xkbIndicatorMapWireDesc *) to;
3120
3121            length = rep->length * 4;
3122
3123            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3124                if (rep->which & bit) {
3125                    wire->flags = indicators->maps[i].flags;
3126                    wire->whichGroups = indicators->maps[i].which_groups;
3127                    wire->groups = indicators->maps[i].groups;
3128                    wire->whichMods = indicators->maps[i].which_mods;
3129                    wire->mods = indicators->maps[i].mods.mask;
3130                    wire->realMods = indicators->maps[i].mods.real_mods;
3131                    wire->virtualMods = indicators->maps[i].mods.vmods;
3132                    wire->ctrls = indicators->maps[i].ctrls;
3133                    if (client->swapped) {
3134                        swaps(&wire->virtualMods);
3135                        swapl(&wire->ctrls);
3136                    }
3137                    wire++;
3138                }
3139            }
3140            to = (CARD8 *) wire;
3141            if ((to - map) != length) {
3142                client->errorValue = _XkbErrCode2(0xff, length);
3143                free(map);
3144                return BadLength;
3145            }
3146        }
3147        else
3148            return BadAlloc;
3149    }
3150    else
3151        map = NULL;
3152    if (client->swapped) {
3153        swaps(&rep->sequenceNumber);
3154        swapl(&rep->length);
3155        swapl(&rep->which);
3156        swapl(&rep->realIndicators);
3157    }
3158    WriteToClient(client, SIZEOF(xkbGetIndicatorMapReply), rep);
3159    if (map) {
3160        WriteToClient(client, length, map);
3161        free((char *) map);
3162    }
3163    return Success;
3164}
3165
3166int
3167ProcXkbGetIndicatorMap(ClientPtr client)
3168{
3169    xkbGetIndicatorMapReply rep;
3170    DeviceIntPtr dev;
3171    XkbDescPtr xkb;
3172    XkbIndicatorPtr leds;
3173
3174    REQUEST(xkbGetIndicatorMapReq);
3175    REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq);
3176
3177    if (!(client->xkbClientFlags & _XkbClientInitialized))
3178        return BadAccess;
3179
3180    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
3181
3182    xkb = dev->key->xkbInfo->desc;
3183    leds = xkb->indicators;
3184
3185    rep = (xkbGetIndicatorMapReply) {
3186        .type = X_Reply,
3187        .deviceID = dev->id,
3188        .sequenceNumber = client->sequence,
3189        .length = 0,
3190        .which = stuff->which
3191    };
3192    XkbComputeGetIndicatorMapReplySize(leds, &rep);
3193    return XkbSendIndicatorMap(client, leds, &rep);
3194}
3195
3196/**
3197 * Apply the given map to the given device. Which specifies which components
3198 * to apply.
3199 */
3200static int
3201_XkbSetIndicatorMap(ClientPtr client, DeviceIntPtr dev,
3202                    int which, xkbIndicatorMapWireDesc * desc)
3203{
3204    XkbSrvInfoPtr xkbi;
3205    XkbSrvLedInfoPtr sli;
3206    XkbEventCauseRec cause;
3207    int i, bit;
3208
3209    xkbi = dev->key->xkbInfo;
3210
3211    sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
3212                            XkbXI_IndicatorMapsMask);
3213    if (!sli)
3214        return BadAlloc;
3215
3216    for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3217        if (which & bit) {
3218            sli->maps[i].flags = desc->flags;
3219            sli->maps[i].which_groups = desc->whichGroups;
3220            sli->maps[i].groups = desc->groups;
3221            sli->maps[i].which_mods = desc->whichMods;
3222            sli->maps[i].mods.mask = desc->mods;
3223            sli->maps[i].mods.real_mods = desc->mods;
3224            sli->maps[i].mods.vmods = desc->virtualMods;
3225            sli->maps[i].ctrls = desc->ctrls;
3226            if (desc->virtualMods != 0) {
3227                unsigned tmp;
3228
3229                tmp = XkbMaskForVMask(xkbi->desc, desc->virtualMods);
3230                sli->maps[i].mods.mask = desc->mods | tmp;
3231            }
3232            desc++;
3233        }
3234    }
3235
3236    XkbSetCauseXkbReq(&cause, X_kbSetIndicatorMap, client);
3237    XkbApplyLedMapChanges(dev, sli, which, NULL, NULL, &cause);
3238
3239    return Success;
3240}
3241
3242int
3243ProcXkbSetIndicatorMap(ClientPtr client)
3244{
3245    int i, bit;
3246    int nIndicators;
3247    DeviceIntPtr dev;
3248    xkbIndicatorMapWireDesc *from;
3249    int rc;
3250
3251    REQUEST(xkbSetIndicatorMapReq);
3252    REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq);
3253
3254    if (!(client->xkbClientFlags & _XkbClientInitialized))
3255        return BadAccess;
3256
3257    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
3258
3259    if (stuff->which == 0)
3260        return Success;
3261
3262    for (nIndicators = i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3263        if (stuff->which & bit)
3264            nIndicators++;
3265    }
3266    if (stuff->length != ((SIZEOF(xkbSetIndicatorMapReq) +
3267                           (nIndicators * SIZEOF(xkbIndicatorMapWireDesc))) /
3268                          4)) {
3269        return BadLength;
3270    }
3271
3272    from = (xkbIndicatorMapWireDesc *) &stuff[1];
3273    for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3274        if (stuff->which & bit) {
3275            if (client->swapped) {
3276                swaps(&from->virtualMods);
3277                swapl(&from->ctrls);
3278            }
3279            CHK_MASK_LEGAL(i, from->whichGroups, XkbIM_UseAnyGroup);
3280            CHK_MASK_LEGAL(i, from->whichMods, XkbIM_UseAnyMods);
3281            from++;
3282        }
3283    }
3284
3285    from = (xkbIndicatorMapWireDesc *) &stuff[1];
3286    rc = _XkbSetIndicatorMap(client, dev, stuff->which, from);
3287    if (rc != Success)
3288        return rc;
3289
3290    if (stuff->deviceSpec == XkbUseCoreKbd) {
3291        DeviceIntPtr other;
3292
3293        for (other = inputInfo.devices; other; other = other->next) {
3294            if ((other != dev) && other->key && !IsMaster(other) &&
3295                GetMaster(other, MASTER_KEYBOARD) == dev) {
3296                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
3297                              DixSetAttrAccess);
3298                if (rc == Success)
3299                    _XkbSetIndicatorMap(client, other, stuff->which, from);
3300            }
3301        }
3302    }
3303
3304    return Success;
3305}
3306
3307/***====================================================================***/
3308
3309int
3310ProcXkbGetNamedIndicator(ClientPtr client)
3311{
3312    DeviceIntPtr dev;
3313    xkbGetNamedIndicatorReply rep;
3314    register int i = 0;
3315    XkbSrvLedInfoPtr sli;
3316    XkbIndicatorMapPtr map = NULL;
3317
3318    REQUEST(xkbGetNamedIndicatorReq);
3319    REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq);
3320
3321    if (!(client->xkbClientFlags & _XkbClientInitialized))
3322        return BadAccess;
3323
3324    CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
3325    CHK_ATOM_ONLY(stuff->indicator);
3326
3327    sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID, 0);
3328    if (!sli)
3329        return BadAlloc;
3330
3331    i = 0;
3332    map = NULL;
3333    if ((sli->names) && (sli->maps)) {
3334        for (i = 0; i < XkbNumIndicators; i++) {
3335            if (stuff->indicator == sli->names[i]) {
3336                map = &sli->maps[i];
3337                break;
3338            }
3339        }
3340    }
3341
3342    rep = (xkbGetNamedIndicatorReply) {
3343        .type = X_Reply,
3344        .sequenceNumber = client->sequence,
3345        .length = 0,
3346        .deviceID = dev->id,
3347        .indicator = stuff->indicator
3348    };
3349    if (map != NULL) {
3350        rep.found = TRUE;
3351        rep.on = ((sli->effectiveState & (1 << i)) != 0);
3352        rep.realIndicator = ((sli->physIndicators & (1 << i)) != 0);
3353        rep.ndx = i;
3354        rep.flags = map->flags;
3355        rep.whichGroups = map->which_groups;
3356        rep.groups = map->groups;
3357        rep.whichMods = map->which_mods;
3358        rep.mods = map->mods.mask;
3359        rep.realMods = map->mods.real_mods;
3360        rep.virtualMods = map->mods.vmods;
3361        rep.ctrls = map->ctrls;
3362        rep.supported = TRUE;
3363    }
3364    else {
3365        rep.found = FALSE;
3366        rep.on = FALSE;
3367        rep.realIndicator = FALSE;
3368        rep.ndx = XkbNoIndicator;
3369        rep.flags = 0;
3370        rep.whichGroups = 0;
3371        rep.groups = 0;
3372        rep.whichMods = 0;
3373        rep.mods = 0;
3374        rep.realMods = 0;
3375        rep.virtualMods = 0;
3376        rep.ctrls = 0;
3377        rep.supported = TRUE;
3378    }
3379    if (client->swapped) {
3380        swapl(&rep.length);
3381        swaps(&rep.sequenceNumber);
3382        swapl(&rep.indicator);
3383        swaps(&rep.virtualMods);
3384        swapl(&rep.ctrls);
3385    }
3386
3387    WriteToClient(client, SIZEOF(xkbGetNamedIndicatorReply), &rep);
3388    return Success;
3389}
3390
3391/**
3392 * Find the IM on the device.
3393 * Returns the map, or NULL if the map doesn't exist.
3394 * If the return value is NULL, led_return is undefined. Otherwise, led_return
3395 * is set to the led index of the map.
3396 */
3397static XkbIndicatorMapPtr
3398_XkbFindNamedIndicatorMap(XkbSrvLedInfoPtr sli, Atom indicator, int *led_return)
3399{
3400    XkbIndicatorMapPtr map;
3401
3402    /* search for the right indicator */
3403    map = NULL;
3404    if (sli->names && sli->maps) {
3405        int led;
3406
3407        for (led = 0; (led < XkbNumIndicators) && (map == NULL); led++) {
3408            if (sli->names[led] == indicator) {
3409                map = &sli->maps[led];
3410                *led_return = led;
3411                break;
3412            }
3413        }
3414    }
3415
3416    return map;
3417}
3418
3419/**
3420 * Creates an indicator map on the device. If dryRun is TRUE, it only checks
3421 * if creation is possible, but doesn't actually create it.
3422 */
3423static int
3424_XkbCreateIndicatorMap(DeviceIntPtr dev, Atom indicator,
3425                       int ledClass, int ledID,
3426                       XkbIndicatorMapPtr * map_return, int *led_return,
3427                       Bool dryRun)
3428{
3429    XkbSrvLedInfoPtr sli;
3430    XkbIndicatorMapPtr map;
3431    int led;
3432
3433    sli = XkbFindSrvLedInfo(dev, ledClass, ledID, XkbXI_IndicatorsMask);
3434    if (!sli)
3435        return BadAlloc;
3436
3437    map = _XkbFindNamedIndicatorMap(sli, indicator, &led);
3438
3439    if (!map) {
3440        /* find first unused indicator maps and assign the name to it */
3441        for (led = 0, map = NULL; (led < XkbNumIndicators) && (map == NULL);
3442             led++) {
3443            if ((sli->names) && (sli->maps) && (sli->names[led] == None) &&
3444                (!XkbIM_InUse(&sli->maps[led]))) {
3445                map = &sli->maps[led];
3446                if (!dryRun)
3447                    sli->names[led] = indicator;
3448                break;
3449            }
3450        }
3451    }
3452
3453    if (!map)
3454        return BadAlloc;
3455
3456    *led_return = led;
3457    *map_return = map;
3458    return Success;
3459}
3460
3461static int
3462_XkbSetNamedIndicator(ClientPtr client, DeviceIntPtr dev,
3463                      xkbSetNamedIndicatorReq * stuff)
3464{
3465    unsigned int extDevReason;
3466    unsigned int statec, namec, mapc;
3467    XkbSrvLedInfoPtr sli;
3468    int led = 0;
3469    XkbIndicatorMapPtr map;
3470    DeviceIntPtr kbd;
3471    XkbEventCauseRec cause;
3472    xkbExtensionDeviceNotify ed;
3473    XkbChangesRec changes;
3474    int rc;
3475
3476    rc = _XkbCreateIndicatorMap(dev, stuff->indicator, stuff->ledClass,
3477                                stuff->ledID, &map, &led, FALSE);
3478    if (rc != Success || !map)  /* oh-oh */
3479        return rc;
3480
3481    sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID,
3482                            XkbXI_IndicatorsMask);
3483    if (!sli)
3484        return BadAlloc;
3485
3486    namec = mapc = statec = 0;
3487    extDevReason = 0;
3488
3489    namec |= (1 << led);
3490    sli->namesPresent |= ((stuff->indicator != None) ? (1 << led) : 0);
3491    extDevReason |= XkbXI_IndicatorNamesMask;
3492
3493    if (stuff->setMap) {
3494        map->flags = stuff->flags;
3495        map->which_groups = stuff->whichGroups;
3496        map->groups = stuff->groups;
3497        map->which_mods = stuff->whichMods;
3498        map->mods.mask = stuff->realMods;
3499        map->mods.real_mods = stuff->realMods;
3500        map->mods.vmods = stuff->virtualMods;
3501        map->ctrls = stuff->ctrls;
3502        mapc |= (1 << led);
3503    }
3504
3505    if ((stuff->setState) && ((map->flags & XkbIM_NoExplicit) == 0)) {
3506        if (stuff->on)
3507            sli->explicitState |= (1 << led);
3508        else
3509            sli->explicitState &= ~(1 << led);
3510        statec |= ((sli->effectiveState ^ sli->explicitState) & (1 << led));
3511    }
3512
3513    memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify));
3514    memset((char *) &changes, 0, sizeof(XkbChangesRec));
3515    XkbSetCauseXkbReq(&cause, X_kbSetNamedIndicator, client);
3516    if (namec)
3517        XkbApplyLedNameChanges(dev, sli, namec, &ed, &changes, &cause);
3518    if (mapc)
3519        XkbApplyLedMapChanges(dev, sli, mapc, &ed, &changes, &cause);
3520    if (statec)
3521        XkbApplyLedStateChanges(dev, sli, statec, &ed, &changes, &cause);
3522
3523    kbd = dev;
3524    if ((sli->flags & XkbSLI_HasOwnState) == 0)
3525        kbd = inputInfo.keyboard;
3526    XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause);
3527
3528    return Success;
3529}
3530
3531int
3532ProcXkbSetNamedIndicator(ClientPtr client)
3533{
3534    int rc;
3535    DeviceIntPtr dev;
3536    int led = 0;
3537    XkbIndicatorMapPtr map;
3538
3539    REQUEST(xkbSetNamedIndicatorReq);
3540    REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq);
3541
3542    if (!(client->xkbClientFlags & _XkbClientInitialized))
3543        return BadAccess;
3544
3545    CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
3546    CHK_ATOM_ONLY(stuff->indicator);
3547    CHK_MASK_LEGAL(0x10, stuff->whichGroups, XkbIM_UseAnyGroup);
3548    CHK_MASK_LEGAL(0x11, stuff->whichMods, XkbIM_UseAnyMods);
3549
3550    /* Dry-run for checks */
3551    rc = _XkbCreateIndicatorMap(dev, stuff->indicator,
3552                                stuff->ledClass, stuff->ledID,
3553                                &map, &led, TRUE);
3554    if (rc != Success || !map)  /* couldn't be created or didn't exist */
3555        return rc;
3556
3557    if (stuff->deviceSpec == XkbUseCoreKbd ||
3558        stuff->deviceSpec == XkbUseCorePtr) {
3559        DeviceIntPtr other;
3560
3561        for (other = inputInfo.devices; other; other = other->next) {
3562            if ((other != dev) && !IsMaster(other) &&
3563                GetMaster(other, MASTER_KEYBOARD) == dev && (other->kbdfeed ||
3564                                                             other->leds) &&
3565                (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess)
3566                 == Success)) {
3567                rc = _XkbCreateIndicatorMap(other, stuff->indicator,
3568                                            stuff->ledClass, stuff->ledID, &map,
3569                                            &led, TRUE);
3570                if (rc != Success || !map)
3571                    return rc;
3572            }
3573        }
3574    }
3575
3576    /* All checks passed, let's do it */
3577    rc = _XkbSetNamedIndicator(client, dev, stuff);
3578    if (rc != Success)
3579        return rc;
3580
3581    if (stuff->deviceSpec == XkbUseCoreKbd ||
3582        stuff->deviceSpec == XkbUseCorePtr) {
3583        DeviceIntPtr other;
3584
3585        for (other = inputInfo.devices; other; other = other->next) {
3586            if ((other != dev) && !IsMaster(other) &&
3587                GetMaster(other, MASTER_KEYBOARD) == dev && (other->kbdfeed ||
3588                                                             other->leds) &&
3589                (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess)
3590                 == Success)) {
3591                _XkbSetNamedIndicator(client, other, stuff);
3592            }
3593        }
3594    }
3595
3596    return Success;
3597}
3598
3599/***====================================================================***/
3600
3601static CARD32
3602_XkbCountAtoms(Atom *atoms, int maxAtoms, int *count)
3603{
3604    register unsigned int i, bit, nAtoms;
3605    register CARD32 atomsPresent;
3606
3607    for (i = nAtoms = atomsPresent = 0, bit = 1; i < maxAtoms; i++, bit <<= 1) {
3608        if (atoms[i] != None) {
3609            atomsPresent |= bit;
3610            nAtoms++;
3611        }
3612    }
3613    if (count)
3614        *count = nAtoms;
3615    return atomsPresent;
3616}
3617
3618static char *
3619_XkbWriteAtoms(char *wire, Atom *atoms, int maxAtoms, int swap)
3620{
3621    register unsigned int i;
3622    Atom *atm;
3623
3624    atm = (Atom *) wire;
3625    for (i = 0; i < maxAtoms; i++) {
3626        if (atoms[i] != None) {
3627            *atm = atoms[i];
3628            if (swap) {
3629                swapl(atm);
3630            }
3631            atm++;
3632        }
3633    }
3634    return (char *) atm;
3635}
3636
3637static Status
3638XkbComputeGetNamesReplySize(XkbDescPtr xkb, xkbGetNamesReply * rep)
3639{
3640    register unsigned which, length;
3641    register int i;
3642
3643    rep->minKeyCode = xkb->min_key_code;
3644    rep->maxKeyCode = xkb->max_key_code;
3645    which = rep->which;
3646    length = 0;
3647    if (xkb->names != NULL) {
3648        if (which & XkbKeycodesNameMask)
3649            length++;
3650        if (which & XkbGeometryNameMask)
3651            length++;
3652        if (which & XkbSymbolsNameMask)
3653            length++;
3654        if (which & XkbPhysSymbolsNameMask)
3655            length++;
3656        if (which & XkbTypesNameMask)
3657            length++;
3658        if (which & XkbCompatNameMask)
3659            length++;
3660    }
3661    else
3662        which &= ~XkbComponentNamesMask;
3663
3664    if (xkb->map != NULL) {
3665        if (which & XkbKeyTypeNamesMask)
3666            length += xkb->map->num_types;
3667        rep->nTypes = xkb->map->num_types;
3668        if (which & XkbKTLevelNamesMask) {
3669            XkbKeyTypePtr pType = xkb->map->types;
3670            int nKTLevels = 0;
3671
3672            length += XkbPaddedSize(xkb->map->num_types) / 4;
3673            for (i = 0; i < xkb->map->num_types; i++, pType++) {
3674                if (pType->level_names != NULL)
3675                    nKTLevels += pType->num_levels;
3676            }
3677            rep->nKTLevels = nKTLevels;
3678            length += nKTLevels;
3679        }
3680    }
3681    else {
3682        rep->nTypes = 0;
3683        rep->nKTLevels = 0;
3684        which &= ~(XkbKeyTypeNamesMask | XkbKTLevelNamesMask);
3685    }
3686
3687    rep->minKeyCode = xkb->min_key_code;
3688    rep->maxKeyCode = xkb->max_key_code;
3689    rep->indicators = 0;
3690    rep->virtualMods = 0;
3691    rep->groupNames = 0;
3692    if (xkb->names != NULL) {
3693        if (which & XkbIndicatorNamesMask) {
3694            int nLeds;
3695
3696            rep->indicators =
3697                _XkbCountAtoms(xkb->names->indicators, XkbNumIndicators,
3698                               &nLeds);
3699            length += nLeds;
3700            if (nLeds == 0)
3701                which &= ~XkbIndicatorNamesMask;
3702        }
3703
3704        if (which & XkbVirtualModNamesMask) {
3705            int nVMods;
3706
3707            rep->virtualMods =
3708                _XkbCountAtoms(xkb->names->vmods, XkbNumVirtualMods, &nVMods);
3709            length += nVMods;
3710            if (nVMods == 0)
3711                which &= ~XkbVirtualModNamesMask;
3712        }
3713
3714        if (which & XkbGroupNamesMask) {
3715            int nGroups;
3716
3717            rep->groupNames =
3718                _XkbCountAtoms(xkb->names->groups, XkbNumKbdGroups, &nGroups);
3719            length += nGroups;
3720            if (nGroups == 0)
3721                which &= ~XkbGroupNamesMask;
3722        }
3723
3724        if ((which & XkbKeyNamesMask) && (xkb->names->keys))
3725            length += rep->nKeys;
3726        else
3727            which &= ~XkbKeyNamesMask;
3728
3729        if ((which & XkbKeyAliasesMask) &&
3730            (xkb->names->key_aliases) && (xkb->names->num_key_aliases > 0)) {
3731            rep->nKeyAliases = xkb->names->num_key_aliases;
3732            length += rep->nKeyAliases * 2;
3733        }
3734        else {
3735            which &= ~XkbKeyAliasesMask;
3736            rep->nKeyAliases = 0;
3737        }
3738
3739        if ((which & XkbRGNamesMask) && (xkb->names->num_rg > 0))
3740            length += xkb->names->num_rg;
3741        else
3742            which &= ~XkbRGNamesMask;
3743    }
3744    else {
3745        which &= ~(XkbIndicatorNamesMask | XkbVirtualModNamesMask);
3746        which &= ~(XkbGroupNamesMask | XkbKeyNamesMask | XkbKeyAliasesMask);
3747        which &= ~XkbRGNamesMask;
3748    }
3749
3750    rep->length = length;
3751    rep->which = which;
3752    return Success;
3753}
3754
3755static int
3756XkbSendNames(ClientPtr client, XkbDescPtr xkb, xkbGetNamesReply * rep)
3757{
3758    register unsigned i, length, which;
3759    char *start;
3760    char *desc;
3761
3762    length = rep->length * 4;
3763    which = rep->which;
3764    if (client->swapped) {
3765        swaps(&rep->sequenceNumber);
3766        swapl(&rep->length);
3767        swapl(&rep->which);
3768        swaps(&rep->virtualMods);
3769        swapl(&rep->indicators);
3770    }
3771
3772    start = desc = calloc(1, length);
3773    if (!start)
3774        return BadAlloc;
3775    if (xkb->names) {
3776        if (which & XkbKeycodesNameMask) {
3777            *((CARD32 *) desc) = xkb->names->keycodes;
3778            if (client->swapped) {
3779                swapl((int *) desc);
3780            }
3781            desc += 4;
3782        }
3783        if (which & XkbGeometryNameMask) {
3784            *((CARD32 *) desc) = xkb->names->geometry;
3785            if (client->swapped) {
3786                swapl((int *) desc);
3787            }
3788            desc += 4;
3789        }
3790        if (which & XkbSymbolsNameMask) {
3791            *((CARD32 *) desc) = xkb->names->symbols;
3792            if (client->swapped) {
3793                swapl((int *) desc);
3794            }
3795            desc += 4;
3796        }
3797        if (which & XkbPhysSymbolsNameMask) {
3798            register CARD32 *atm = (CARD32 *) desc;
3799
3800            atm[0] = (CARD32) xkb->names->phys_symbols;
3801            if (client->swapped) {
3802                swapl(&atm[0]);
3803            }
3804            desc += 4;
3805        }
3806        if (which & XkbTypesNameMask) {
3807            *((CARD32 *) desc) = (CARD32) xkb->names->types;
3808            if (client->swapped) {
3809                swapl((int *) desc);
3810            }
3811            desc += 4;
3812        }
3813        if (which & XkbCompatNameMask) {
3814            *((CARD32 *) desc) = (CARD32) xkb->names->compat;
3815            if (client->swapped) {
3816                swapl((int *) desc);
3817            }
3818            desc += 4;
3819        }
3820        if (which & XkbKeyTypeNamesMask) {
3821            register CARD32 *atm = (CARD32 *) desc;
3822            register XkbKeyTypePtr type = xkb->map->types;
3823
3824            for (i = 0; i < xkb->map->num_types; i++, atm++, type++) {
3825                *atm = (CARD32) type->name;
3826                if (client->swapped) {
3827                    swapl(atm);
3828                }
3829            }
3830            desc = (char *) atm;
3831        }
3832        if (which & XkbKTLevelNamesMask && xkb->map) {
3833            XkbKeyTypePtr type = xkb->map->types;
3834            register CARD32 *atm;
3835
3836            for (i = 0; i < rep->nTypes; i++, type++) {
3837                *desc++ = type->num_levels;
3838            }
3839            desc += XkbPaddedSize(rep->nTypes) - rep->nTypes;
3840
3841            atm = (CARD32 *) desc;
3842            type = xkb->map->types;
3843            for (i = 0; i < xkb->map->num_types; i++, type++) {
3844                register unsigned l;
3845
3846                if (type->level_names) {
3847                    for (l = 0; l < type->num_levels; l++, atm++) {
3848                        *atm = type->level_names[l];
3849                        if (client->swapped) {
3850                            swapl(atm);
3851                        }
3852                    }
3853                    desc += type->num_levels * 4;
3854                }
3855            }
3856        }
3857        if (which & XkbIndicatorNamesMask) {
3858            desc =
3859                _XkbWriteAtoms(desc, xkb->names->indicators, XkbNumIndicators,
3860                               client->swapped);
3861        }
3862        if (which & XkbVirtualModNamesMask) {
3863            desc = _XkbWriteAtoms(desc, xkb->names->vmods, XkbNumVirtualMods,
3864                                  client->swapped);
3865        }
3866        if (which & XkbGroupNamesMask) {
3867            desc = _XkbWriteAtoms(desc, xkb->names->groups, XkbNumKbdGroups,
3868                                  client->swapped);
3869        }
3870        if (which & XkbKeyNamesMask) {
3871            for (i = 0; i < rep->nKeys; i++, desc += sizeof(XkbKeyNameRec)) {
3872                *((XkbKeyNamePtr) desc) = xkb->names->keys[i + rep->firstKey];
3873            }
3874        }
3875        if (which & XkbKeyAliasesMask) {
3876            XkbKeyAliasPtr pAl;
3877
3878            pAl = xkb->names->key_aliases;
3879            for (i = 0; i < rep->nKeyAliases;
3880                 i++, pAl++, desc += 2 * XkbKeyNameLength) {
3881                *((XkbKeyAliasPtr) desc) = *pAl;
3882            }
3883        }
3884        if ((which & XkbRGNamesMask) && (rep->nRadioGroups > 0)) {
3885            register CARD32 *atm = (CARD32 *) desc;
3886
3887            for (i = 0; i < rep->nRadioGroups; i++, atm++) {
3888                *atm = (CARD32) xkb->names->radio_groups[i];
3889                if (client->swapped) {
3890                    swapl(atm);
3891                }
3892            }
3893            desc += rep->nRadioGroups * 4;
3894        }
3895    }
3896
3897    if ((desc - start) != (length)) {
3898        ErrorF("[xkb] BOGUS LENGTH in write names, expected %d, got %ld\n",
3899               length, (unsigned long) (desc - start));
3900    }
3901    WriteToClient(client, SIZEOF(xkbGetNamesReply), rep);
3902    WriteToClient(client, length, start);
3903    free((char *) start);
3904    return Success;
3905}
3906
3907int
3908ProcXkbGetNames(ClientPtr client)
3909{
3910    DeviceIntPtr dev;
3911    XkbDescPtr xkb;
3912    xkbGetNamesReply rep;
3913
3914    REQUEST(xkbGetNamesReq);
3915    REQUEST_SIZE_MATCH(xkbGetNamesReq);
3916
3917    if (!(client->xkbClientFlags & _XkbClientInitialized))
3918        return BadAccess;
3919
3920    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
3921    CHK_MASK_LEGAL(0x01, stuff->which, XkbAllNamesMask);
3922
3923    xkb = dev->key->xkbInfo->desc;
3924    rep = (xkbGetNamesReply) {
3925        .type = X_Reply,
3926        .deviceID = dev->id,
3927        .sequenceNumber = client->sequence,
3928        .length = 0,
3929        .which = stuff->which,
3930        .nTypes = xkb->map->num_types,
3931        .firstKey = xkb->min_key_code,
3932        .nKeys = XkbNumKeys(xkb),
3933        .nKeyAliases = xkb->names ? xkb->names->num_key_aliases : 0,
3934        .nRadioGroups = xkb->names ? xkb->names->num_rg : 0
3935    };
3936    XkbComputeGetNamesReplySize(xkb, &rep);
3937    return XkbSendNames(client, xkb, &rep);
3938}
3939
3940/***====================================================================***/
3941
3942static CARD32 *
3943_XkbCheckAtoms(CARD32 *wire, int nAtoms, int swapped, Atom *pError)
3944{
3945    register int i;
3946
3947    for (i = 0; i < nAtoms; i++, wire++) {
3948        if (swapped) {
3949            swapl(wire);
3950        }
3951        if ((((Atom) *wire) != None) && (!ValidAtom((Atom) *wire))) {
3952            *pError = ((Atom) *wire);
3953            return NULL;
3954        }
3955    }
3956    return wire;
3957}
3958
3959static CARD32 *
3960_XkbCheckMaskedAtoms(CARD32 *wire, int nAtoms, CARD32 present, int swapped,
3961                     Atom *pError)
3962{
3963    register unsigned i, bit;
3964
3965    for (i = 0, bit = 1; (i < nAtoms) && (present); i++, bit <<= 1) {
3966        if ((present & bit) == 0)
3967            continue;
3968        if (swapped) {
3969            swapl(wire);
3970        }
3971        if ((((Atom) *wire) != None) && (!ValidAtom(((Atom) *wire)))) {
3972            *pError = (Atom) *wire;
3973            return NULL;
3974        }
3975        wire++;
3976    }
3977    return wire;
3978}
3979
3980static Atom *
3981_XkbCopyMaskedAtoms(Atom *wire, Atom *dest, int nAtoms, CARD32 present)
3982{
3983    register int i, bit;
3984
3985    for (i = 0, bit = 1; (i < nAtoms) && (present); i++, bit <<= 1) {
3986        if ((present & bit) == 0)
3987            continue;
3988        dest[i] = *wire++;
3989    }
3990    return wire;
3991}
3992
3993static Bool
3994_XkbCheckTypeName(Atom name, int typeNdx)
3995{
3996    const char *str;
3997
3998    str = NameForAtom(name);
3999    if ((strcmp(str, "ONE_LEVEL") == 0) || (strcmp(str, "TWO_LEVEL") == 0) ||
4000        (strcmp(str, "ALPHABETIC") == 0) || (strcmp(str, "KEYPAD") == 0))
4001        return FALSE;
4002    return TRUE;
4003}
4004
4005/**
4006 * Check the device-dependent data in the request against the device. Returns
4007 * Success, or the appropriate error code.
4008 */
4009static int
4010_XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
4011                  xkbSetNamesReq * stuff, CARD32 *data)
4012{
4013    XkbDescRec *xkb;
4014    CARD32 *tmp;
4015    Atom bad = None;
4016
4017    tmp = data;
4018    xkb = dev->key->xkbInfo->desc;
4019
4020    if (stuff->which & XkbKeyTypeNamesMask) {
4021        int i;
4022        CARD32 *old;
4023
4024        if (stuff->nTypes < 1) {
4025            client->errorValue = _XkbErrCode2(0x02, stuff->nTypes);
4026            return BadValue;
4027        }
4028        if ((unsigned) (stuff->firstType + stuff->nTypes - 1) >=
4029            xkb->map->num_types) {
4030            client->errorValue =
4031                _XkbErrCode4(0x03, stuff->firstType, stuff->nTypes,
4032                             xkb->map->num_types);
4033            return BadValue;
4034        }
4035        if (((unsigned) stuff->firstType) <= XkbLastRequiredType) {
4036            client->errorValue = _XkbErrCode2(0x04, stuff->firstType);
4037            return BadAccess;
4038        }
4039        old = tmp;
4040        tmp = _XkbCheckAtoms(tmp, stuff->nTypes, client->swapped, &bad);
4041        if (!tmp) {
4042            client->errorValue = bad;
4043            return BadAtom;
4044        }
4045        for (i = 0; i < stuff->nTypes; i++, old++) {
4046            if (!_XkbCheckTypeName((Atom) *old, stuff->firstType + i))
4047                client->errorValue = _XkbErrCode2(0x05, i);
4048        }
4049    }
4050    if (stuff->which & XkbKTLevelNamesMask) {
4051        unsigned i;
4052        XkbKeyTypePtr type;
4053        CARD8 *width;
4054
4055        if (stuff->nKTLevels < 1) {
4056            client->errorValue = _XkbErrCode2(0x05, stuff->nKTLevels);
4057            return BadValue;
4058        }
4059        if ((unsigned) (stuff->firstKTLevel + stuff->nKTLevels - 1) >=
4060            xkb->map->num_types) {
4061            client->errorValue = _XkbErrCode4(0x06, stuff->firstKTLevel,
4062                                              stuff->nKTLevels,
4063                                              xkb->map->num_types);
4064            return BadValue;
4065        }
4066        width = (CARD8 *) tmp;
4067        tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels));
4068        type = &xkb->map->types[stuff->firstKTLevel];
4069        for (i = 0; i < stuff->nKTLevels; i++, type++) {
4070            if (width[i] == 0)
4071                continue;
4072            else if (width[i] != type->num_levels) {
4073                client->errorValue = _XkbErrCode4(0x07, i + stuff->firstKTLevel,
4074                                                  type->num_levels, width[i]);
4075                return BadMatch;
4076            }
4077            tmp = _XkbCheckAtoms(tmp, width[i], client->swapped, &bad);
4078            if (!tmp) {
4079                client->errorValue = bad;
4080                return BadAtom;
4081            }
4082        }
4083    }
4084    if (stuff->which & XkbIndicatorNamesMask) {
4085        if (stuff->indicators == 0) {
4086            client->errorValue = 0x08;
4087            return BadMatch;
4088        }
4089        tmp = _XkbCheckMaskedAtoms(tmp, XkbNumIndicators, stuff->indicators,
4090                                   client->swapped, &bad);
4091        if (!tmp) {
4092            client->errorValue = bad;
4093            return BadAtom;
4094        }
4095    }
4096    if (stuff->which & XkbVirtualModNamesMask) {
4097        if (stuff->virtualMods == 0) {
4098            client->errorValue = 0x09;
4099            return BadMatch;
4100        }
4101        tmp = _XkbCheckMaskedAtoms(tmp, XkbNumVirtualMods,
4102                                   (CARD32) stuff->virtualMods,
4103                                   client->swapped, &bad);
4104        if (!tmp) {
4105            client->errorValue = bad;
4106            return BadAtom;
4107        }
4108    }
4109    if (stuff->which & XkbGroupNamesMask) {
4110        if (stuff->groupNames == 0) {
4111            client->errorValue = 0x0a;
4112            return BadMatch;
4113        }
4114        tmp = _XkbCheckMaskedAtoms(tmp, XkbNumKbdGroups,
4115                                   (CARD32) stuff->groupNames,
4116                                   client->swapped, &bad);
4117        if (!tmp) {
4118            client->errorValue = bad;
4119            return BadAtom;
4120        }
4121    }
4122    if (stuff->which & XkbKeyNamesMask) {
4123        if (stuff->firstKey < (unsigned) xkb->min_key_code) {
4124            client->errorValue = _XkbErrCode3(0x0b, xkb->min_key_code,
4125                                              stuff->firstKey);
4126            return BadValue;
4127        }
4128        if (((unsigned) (stuff->firstKey + stuff->nKeys - 1) >
4129             xkb->max_key_code) || (stuff->nKeys < 1)) {
4130            client->errorValue =
4131                _XkbErrCode4(0x0c, xkb->max_key_code, stuff->firstKey,
4132                             stuff->nKeys);
4133            return BadValue;
4134        }
4135        tmp += stuff->nKeys;
4136    }
4137    if ((stuff->which & XkbKeyAliasesMask) && (stuff->nKeyAliases > 0)) {
4138        tmp += stuff->nKeyAliases * 2;
4139    }
4140    if (stuff->which & XkbRGNamesMask) {
4141        if (stuff->nRadioGroups < 1) {
4142            client->errorValue = _XkbErrCode2(0x0d, stuff->nRadioGroups);
4143            return BadValue;
4144        }
4145        tmp = _XkbCheckAtoms(tmp, stuff->nRadioGroups, client->swapped, &bad);
4146        if (!tmp) {
4147            client->errorValue = bad;
4148            return BadAtom;
4149        }
4150    }
4151    if ((tmp - ((CARD32 *) stuff)) != stuff->length) {
4152        client->errorValue = stuff->length;
4153        return BadLength;
4154    }
4155
4156    return Success;
4157}
4158
4159static int
4160_XkbSetNames(ClientPtr client, DeviceIntPtr dev, xkbSetNamesReq * stuff)
4161{
4162    XkbDescRec *xkb;
4163    XkbNamesRec *names;
4164    CARD32 *tmp;
4165    xkbNamesNotify nn;
4166
4167    tmp = (CARD32 *) &stuff[1];
4168    xkb = dev->key->xkbInfo->desc;
4169    names = xkb->names;
4170
4171    if (XkbAllocNames(xkb, stuff->which, stuff->nRadioGroups,
4172                      stuff->nKeyAliases) != Success) {
4173        return BadAlloc;
4174    }
4175
4176    memset(&nn, 0, sizeof(xkbNamesNotify));
4177    nn.changed = stuff->which;
4178    tmp = (CARD32 *) &stuff[1];
4179    if (stuff->which & XkbKeycodesNameMask)
4180        names->keycodes = *tmp++;
4181    if (stuff->which & XkbGeometryNameMask)
4182        names->geometry = *tmp++;
4183    if (stuff->which & XkbSymbolsNameMask)
4184        names->symbols = *tmp++;
4185    if (stuff->which & XkbPhysSymbolsNameMask)
4186        names->phys_symbols = *tmp++;
4187    if (stuff->which & XkbTypesNameMask)
4188        names->types = *tmp++;
4189    if (stuff->which & XkbCompatNameMask)
4190        names->compat = *tmp++;
4191    if ((stuff->which & XkbKeyTypeNamesMask) && (stuff->nTypes > 0)) {
4192        register unsigned i;
4193        register XkbKeyTypePtr type;
4194
4195        type = &xkb->map->types[stuff->firstType];
4196        for (i = 0; i < stuff->nTypes; i++, type++) {
4197            type->name = *tmp++;
4198        }
4199        nn.firstType = stuff->firstType;
4200        nn.nTypes = stuff->nTypes;
4201    }
4202    if (stuff->which & XkbKTLevelNamesMask) {
4203        register XkbKeyTypePtr type;
4204        register unsigned i;
4205        CARD8 *width;
4206
4207        width = (CARD8 *) tmp;
4208        tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels));
4209        type = &xkb->map->types[stuff->firstKTLevel];
4210        for (i = 0; i < stuff->nKTLevels; i++, type++) {
4211            if (width[i] > 0) {
4212                if (type->level_names) {
4213                    register unsigned n;
4214
4215                    for (n = 0; n < width[i]; n++) {
4216                        type->level_names[n] = tmp[n];
4217                    }
4218                }
4219                tmp += width[i];
4220            }
4221        }
4222        nn.firstLevelName = 0;
4223        nn.nLevelNames = stuff->nTypes;
4224    }
4225    if (stuff->which & XkbIndicatorNamesMask) {
4226        tmp = _XkbCopyMaskedAtoms(tmp, names->indicators, XkbNumIndicators,
4227                                  stuff->indicators);
4228        nn.changedIndicators = stuff->indicators;
4229    }
4230    if (stuff->which & XkbVirtualModNamesMask) {
4231        tmp = _XkbCopyMaskedAtoms(tmp, names->vmods, XkbNumVirtualMods,
4232                                  stuff->virtualMods);
4233        nn.changedVirtualMods = stuff->virtualMods;
4234    }
4235    if (stuff->which & XkbGroupNamesMask) {
4236        tmp = _XkbCopyMaskedAtoms(tmp, names->groups, XkbNumKbdGroups,
4237                                  stuff->groupNames);
4238        nn.changedVirtualMods = stuff->groupNames;
4239    }
4240    if (stuff->which & XkbKeyNamesMask) {
4241        memcpy((char *) &names->keys[stuff->firstKey], (char *) tmp,
4242               stuff->nKeys * XkbKeyNameLength);
4243        tmp += stuff->nKeys;
4244        nn.firstKey = stuff->firstKey;
4245        nn.nKeys = stuff->nKeys;
4246    }
4247    if (stuff->which & XkbKeyAliasesMask) {
4248        if (stuff->nKeyAliases > 0) {
4249            register int na = stuff->nKeyAliases;
4250
4251            if (XkbAllocNames(xkb, XkbKeyAliasesMask, 0, na) != Success)
4252                return BadAlloc;
4253            memcpy((char *) names->key_aliases, (char *) tmp,
4254                   stuff->nKeyAliases * sizeof(XkbKeyAliasRec));
4255            tmp += stuff->nKeyAliases * 2;
4256        }
4257        else if (names->key_aliases != NULL) {
4258            free(names->key_aliases);
4259            names->key_aliases = NULL;
4260            names->num_key_aliases = 0;
4261        }
4262        nn.nAliases = names->num_key_aliases;
4263    }
4264    if (stuff->which & XkbRGNamesMask) {
4265        if (stuff->nRadioGroups > 0) {
4266            register unsigned i, nrg;
4267
4268            nrg = stuff->nRadioGroups;
4269            if (XkbAllocNames(xkb, XkbRGNamesMask, nrg, 0) != Success)
4270                return BadAlloc;
4271
4272            for (i = 0; i < stuff->nRadioGroups; i++) {
4273                names->radio_groups[i] = tmp[i];
4274            }
4275            tmp += stuff->nRadioGroups;
4276        }
4277        else if (names->radio_groups) {
4278            free(names->radio_groups);
4279            names->radio_groups = NULL;
4280            names->num_rg = 0;
4281        }
4282        nn.nRadioGroups = names->num_rg;
4283    }
4284    if (nn.changed) {
4285        Bool needExtEvent;
4286
4287        needExtEvent = (nn.changed & XkbIndicatorNamesMask) != 0;
4288        XkbSendNamesNotify(dev, &nn);
4289        if (needExtEvent) {
4290            XkbSrvLedInfoPtr sli;
4291            xkbExtensionDeviceNotify edev;
4292            register int i;
4293            register unsigned bit;
4294
4295            sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
4296                                    XkbXI_IndicatorsMask);
4297            sli->namesPresent = 0;
4298            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
4299                if (names->indicators[i] != None)
4300                    sli->namesPresent |= bit;
4301            }
4302            memset(&edev, 0, sizeof(xkbExtensionDeviceNotify));
4303            edev.reason = XkbXI_IndicatorNamesMask;
4304            edev.ledClass = KbdFeedbackClass;
4305            edev.ledID = dev->kbdfeed->ctrl.id;
4306            edev.ledsDefined = sli->namesPresent | sli->mapsPresent;
4307            edev.ledState = sli->effectiveState;
4308            edev.firstBtn = 0;
4309            edev.nBtns = 0;
4310            edev.supported = XkbXI_AllFeaturesMask;
4311            edev.unsupported = 0;
4312            XkbSendExtensionDeviceNotify(dev, client, &edev);
4313        }
4314    }
4315    return Success;
4316}
4317
4318int
4319ProcXkbSetNames(ClientPtr client)
4320{
4321    DeviceIntPtr dev;
4322    CARD32 *tmp;
4323    Atom bad;
4324    int rc;
4325
4326    REQUEST(xkbSetNamesReq);
4327    REQUEST_AT_LEAST_SIZE(xkbSetNamesReq);
4328
4329    if (!(client->xkbClientFlags & _XkbClientInitialized))
4330        return BadAccess;
4331
4332    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
4333    CHK_MASK_LEGAL(0x01, stuff->which, XkbAllNamesMask);
4334
4335    /* check device-independent stuff */
4336    tmp = (CARD32 *) &stuff[1];
4337
4338    if (stuff->which & XkbKeycodesNameMask) {
4339        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4340        if (!tmp) {
4341            client->errorValue = bad;
4342            return BadAtom;
4343        }
4344    }
4345    if (stuff->which & XkbGeometryNameMask) {
4346        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4347        if (!tmp) {
4348            client->errorValue = bad;
4349            return BadAtom;
4350        }
4351    }
4352    if (stuff->which & XkbSymbolsNameMask) {
4353        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4354        if (!tmp) {
4355            client->errorValue = bad;
4356            return BadAtom;
4357        }
4358    }
4359    if (stuff->which & XkbPhysSymbolsNameMask) {
4360        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4361        if (!tmp) {
4362            client->errorValue = bad;
4363            return BadAtom;
4364        }
4365    }
4366    if (stuff->which & XkbTypesNameMask) {
4367        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4368        if (!tmp) {
4369            client->errorValue = bad;
4370            return BadAtom;
4371        }
4372    }
4373    if (stuff->which & XkbCompatNameMask) {
4374        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4375        if (!tmp) {
4376            client->errorValue = bad;
4377            return BadAtom;
4378        }
4379    }
4380
4381    /* start of device-dependent tests */
4382    rc = _XkbSetNamesCheck(client, dev, stuff, tmp);
4383    if (rc != Success)
4384        return rc;
4385
4386    if (stuff->deviceSpec == XkbUseCoreKbd) {
4387        DeviceIntPtr other;
4388
4389        for (other = inputInfo.devices; other; other = other->next) {
4390            if ((other != dev) && other->key && !IsMaster(other) &&
4391                GetMaster(other, MASTER_KEYBOARD) == dev) {
4392
4393                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
4394                              DixManageAccess);
4395                if (rc == Success) {
4396                    rc = _XkbSetNamesCheck(client, other, stuff, tmp);
4397                    if (rc != Success)
4398                        return rc;
4399                }
4400            }
4401        }
4402    }
4403
4404    /* everything is okay -- update names */
4405
4406    rc = _XkbSetNames(client, dev, stuff);
4407    if (rc != Success)
4408        return rc;
4409
4410    if (stuff->deviceSpec == XkbUseCoreKbd) {
4411        DeviceIntPtr other;
4412
4413        for (other = inputInfo.devices; other; other = other->next) {
4414            if ((other != dev) && other->key && !IsMaster(other) &&
4415                GetMaster(other, MASTER_KEYBOARD) == dev) {
4416
4417                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
4418                              DixManageAccess);
4419                if (rc == Success)
4420                    _XkbSetNames(client, other, stuff);
4421            }
4422        }
4423    }
4424
4425    /* everything is okay -- update names */
4426
4427    return Success;
4428}
4429
4430/***====================================================================***/
4431
4432#include "xkbgeom.h"
4433
4434#define	XkbSizeCountedString(s)  ((s)?((((2+strlen(s))+3)/4)*4):4)
4435
4436/**
4437 * Write the zero-terminated string str into wire as a pascal string with a
4438 * 16-bit length field prefixed before the actual string.
4439 *
4440 * @param wire The destination array, usually the wire struct
4441 * @param str The source string as zero-terminated C string
4442 * @param swap If TRUE, the length field is swapped.
4443 *
4444 * @return The input string in the format <string length><string> with a
4445 * (swapped) 16 bit string length, non-zero terminated.
4446 */
4447static char *
4448XkbWriteCountedString(char *wire, const char *str, Bool swap)
4449{
4450    CARD16 len, *pLen, paddedLen;
4451
4452    if (!str)
4453        return wire;
4454
4455    len = strlen(str);
4456    pLen = (CARD16 *) wire;
4457    *pLen = len;
4458    if (swap) {
4459        swaps(pLen);
4460    }
4461    paddedLen = pad_to_int32(sizeof(len) + len) - sizeof(len);
4462    strncpy(&wire[sizeof(len)], str, paddedLen);
4463    wire += sizeof(len) + paddedLen;
4464    return wire;
4465}
4466
4467static int
4468XkbSizeGeomProperties(XkbGeometryPtr geom)
4469{
4470    register int i, size;
4471    XkbPropertyPtr prop;
4472
4473    for (size = i = 0, prop = geom->properties; i < geom->num_properties;
4474         i++, prop++) {
4475        size += XkbSizeCountedString(prop->name);
4476        size += XkbSizeCountedString(prop->value);
4477    }
4478    return size;
4479}
4480
4481static char *
4482XkbWriteGeomProperties(char *wire, XkbGeometryPtr geom, Bool swap)
4483{
4484    register int i;
4485    register XkbPropertyPtr prop;
4486
4487    for (i = 0, prop = geom->properties; i < geom->num_properties; i++, prop++) {
4488        wire = XkbWriteCountedString(wire, prop->name, swap);
4489        wire = XkbWriteCountedString(wire, prop->value, swap);
4490    }
4491    return wire;
4492}
4493
4494static int
4495XkbSizeGeomKeyAliases(XkbGeometryPtr geom)
4496{
4497    return geom->num_key_aliases * (2 * XkbKeyNameLength);
4498}
4499
4500static char *
4501XkbWriteGeomKeyAliases(char *wire, XkbGeometryPtr geom, Bool swap)
4502{
4503    register int sz;
4504
4505    sz = geom->num_key_aliases * (XkbKeyNameLength * 2);
4506    if (sz > 0) {
4507        memcpy(wire, (char *) geom->key_aliases, sz);
4508        wire += sz;
4509    }
4510    return wire;
4511}
4512
4513static int
4514XkbSizeGeomColors(XkbGeometryPtr geom)
4515{
4516    register int i, size;
4517    register XkbColorPtr color;
4518
4519    for (i = size = 0, color = geom->colors; i < geom->num_colors; i++, color++) {
4520        size += XkbSizeCountedString(color->spec);
4521    }
4522    return size;
4523}
4524
4525static char *
4526XkbWriteGeomColors(char *wire, XkbGeometryPtr geom, Bool swap)
4527{
4528    register int i;
4529    register XkbColorPtr color;
4530
4531    for (i = 0, color = geom->colors; i < geom->num_colors; i++, color++) {
4532        wire = XkbWriteCountedString(wire, color->spec, swap);
4533    }
4534    return wire;
4535}
4536
4537static int
4538XkbSizeGeomShapes(XkbGeometryPtr geom)
4539{
4540    register int i, size;
4541    register XkbShapePtr shape;
4542
4543    for (i = size = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) {
4544        register int n;
4545        register XkbOutlinePtr ol;
4546
4547        size += SIZEOF(xkbShapeWireDesc);
4548        for (n = 0, ol = shape->outlines; n < shape->num_outlines; n++, ol++) {
4549            size += SIZEOF(xkbOutlineWireDesc);
4550            size += ol->num_points * SIZEOF(xkbPointWireDesc);
4551        }
4552    }
4553    return size;
4554}
4555
4556static char *
4557XkbWriteGeomShapes(char *wire, XkbGeometryPtr geom, Bool swap)
4558{
4559    int i;
4560    XkbShapePtr shape;
4561    xkbShapeWireDesc *shapeWire;
4562
4563    for (i = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) {
4564        register int o;
4565        XkbOutlinePtr ol;
4566        xkbOutlineWireDesc *olWire;
4567
4568        shapeWire = (xkbShapeWireDesc *) wire;
4569        shapeWire->name = shape->name;
4570        shapeWire->nOutlines = shape->num_outlines;
4571        if (shape->primary != NULL)
4572            shapeWire->primaryNdx = XkbOutlineIndex(shape, shape->primary);
4573        else
4574            shapeWire->primaryNdx = XkbNoShape;
4575        if (shape->approx != NULL)
4576            shapeWire->approxNdx = XkbOutlineIndex(shape, shape->approx);
4577        else
4578            shapeWire->approxNdx = XkbNoShape;
4579        shapeWire->pad = 0;
4580        if (swap) {
4581            swapl(&shapeWire->name);
4582        }
4583        wire = (char *) &shapeWire[1];
4584        for (o = 0, ol = shape->outlines; o < shape->num_outlines; o++, ol++) {
4585            register int p;
4586            XkbPointPtr pt;
4587            xkbPointWireDesc *ptWire;
4588
4589            olWire = (xkbOutlineWireDesc *) wire;
4590            olWire->nPoints = ol->num_points;
4591            olWire->cornerRadius = ol->corner_radius;
4592            olWire->pad = 0;
4593            wire = (char *) &olWire[1];
4594            ptWire = (xkbPointWireDesc *) wire;
4595            for (p = 0, pt = ol->points; p < ol->num_points; p++, pt++) {
4596                ptWire[p].x = pt->x;
4597                ptWire[p].y = pt->y;
4598                if (swap) {
4599                    swaps(&ptWire[p].x);
4600                    swaps(&ptWire[p].y);
4601                }
4602            }
4603            wire = (char *) &ptWire[ol->num_points];
4604        }
4605    }
4606    return wire;
4607}
4608
4609static int
4610XkbSizeGeomDoodads(int num_doodads, XkbDoodadPtr doodad)
4611{
4612    register int i, size;
4613
4614    for (i = size = 0; i < num_doodads; i++, doodad++) {
4615        size += SIZEOF(xkbAnyDoodadWireDesc);
4616        if (doodad->any.type == XkbTextDoodad) {
4617            size += XkbSizeCountedString(doodad->text.text);
4618            size += XkbSizeCountedString(doodad->text.font);
4619        }
4620        else if (doodad->any.type == XkbLogoDoodad) {
4621            size += XkbSizeCountedString(doodad->logo.logo_name);
4622        }
4623    }
4624    return size;
4625}
4626
4627static char *
4628XkbWriteGeomDoodads(char *wire, int num_doodads, XkbDoodadPtr doodad, Bool swap)
4629{
4630    register int i;
4631    xkbDoodadWireDesc *doodadWire;
4632
4633    for (i = 0; i < num_doodads; i++, doodad++) {
4634        doodadWire = (xkbDoodadWireDesc *) wire;
4635        wire = (char *) &doodadWire[1];
4636        memset(doodadWire, 0, SIZEOF(xkbDoodadWireDesc));
4637        doodadWire->any.name = doodad->any.name;
4638        doodadWire->any.type = doodad->any.type;
4639        doodadWire->any.priority = doodad->any.priority;
4640        doodadWire->any.top = doodad->any.top;
4641        doodadWire->any.left = doodad->any.left;
4642        if (swap) {
4643            swapl(&doodadWire->any.name);
4644            swaps(&doodadWire->any.top);
4645            swaps(&doodadWire->any.left);
4646        }
4647        switch (doodad->any.type) {
4648        case XkbOutlineDoodad:
4649        case XkbSolidDoodad:
4650            doodadWire->shape.angle = doodad->shape.angle;
4651            doodadWire->shape.colorNdx = doodad->shape.color_ndx;
4652            doodadWire->shape.shapeNdx = doodad->shape.shape_ndx;
4653            if (swap) {
4654                swaps(&doodadWire->shape.angle);
4655            }
4656            break;
4657        case XkbTextDoodad:
4658            doodadWire->text.angle = doodad->text.angle;
4659            doodadWire->text.width = doodad->text.width;
4660            doodadWire->text.height = doodad->text.height;
4661            doodadWire->text.colorNdx = doodad->text.color_ndx;
4662            if (swap) {
4663                swaps(&doodadWire->text.angle);
4664                swaps(&doodadWire->text.width);
4665                swaps(&doodadWire->text.height);
4666            }
4667            wire = XkbWriteCountedString(wire, doodad->text.text, swap);
4668            wire = XkbWriteCountedString(wire, doodad->text.font, swap);
4669            break;
4670        case XkbIndicatorDoodad:
4671            doodadWire->indicator.shapeNdx = doodad->indicator.shape_ndx;
4672            doodadWire->indicator.onColorNdx = doodad->indicator.on_color_ndx;
4673            doodadWire->indicator.offColorNdx = doodad->indicator.off_color_ndx;
4674            break;
4675        case XkbLogoDoodad:
4676            doodadWire->logo.angle = doodad->logo.angle;
4677            doodadWire->logo.colorNdx = doodad->logo.color_ndx;
4678            doodadWire->logo.shapeNdx = doodad->logo.shape_ndx;
4679            wire = XkbWriteCountedString(wire, doodad->logo.logo_name, swap);
4680            break;
4681        default:
4682            ErrorF("[xkb] Unknown doodad type %d in XkbWriteGeomDoodads\n",
4683                   doodad->any.type);
4684            ErrorF("[xkb] Ignored\n");
4685            break;
4686        }
4687    }
4688    return wire;
4689}
4690
4691static char *
4692XkbWriteGeomOverlay(char *wire, XkbOverlayPtr ol, Bool swap)
4693{
4694    register int r;
4695    XkbOverlayRowPtr row;
4696    xkbOverlayWireDesc *olWire;
4697
4698    olWire = (xkbOverlayWireDesc *) wire;
4699    olWire->name = ol->name;
4700    olWire->nRows = ol->num_rows;
4701    olWire->pad1 = 0;
4702    olWire->pad2 = 0;
4703    if (swap) {
4704        swapl(&olWire->name);
4705    }
4706    wire = (char *) &olWire[1];
4707    for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) {
4708        unsigned int k;
4709        XkbOverlayKeyPtr key;
4710        xkbOverlayRowWireDesc *rowWire;
4711
4712        rowWire = (xkbOverlayRowWireDesc *) wire;
4713        rowWire->rowUnder = row->row_under;
4714        rowWire->nKeys = row->num_keys;
4715        rowWire->pad1 = 0;
4716        wire = (char *) &rowWire[1];
4717        for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
4718            xkbOverlayKeyWireDesc *keyWire;
4719
4720            keyWire = (xkbOverlayKeyWireDesc *) wire;
4721            memcpy(keyWire->over, key->over.name, XkbKeyNameLength);
4722            memcpy(keyWire->under, key->under.name, XkbKeyNameLength);
4723            wire = (char *) &keyWire[1];
4724        }
4725    }
4726    return wire;
4727}
4728
4729static int
4730XkbSizeGeomSections(XkbGeometryPtr geom)
4731{
4732    register int i, size;
4733    XkbSectionPtr section;
4734
4735    for (i = size = 0, section = geom->sections; i < geom->num_sections;
4736         i++, section++) {
4737        size += SIZEOF(xkbSectionWireDesc);
4738        if (section->rows) {
4739            int r;
4740            XkbRowPtr row;
4741
4742            for (r = 0, row = section->rows; r < section->num_rows; row++, r++) {
4743                size += SIZEOF(xkbRowWireDesc);
4744                size += row->num_keys * SIZEOF(xkbKeyWireDesc);
4745            }
4746        }
4747        if (section->doodads)
4748            size += XkbSizeGeomDoodads(section->num_doodads, section->doodads);
4749        if (section->overlays) {
4750            int o;
4751            XkbOverlayPtr ol;
4752
4753            for (o = 0, ol = section->overlays; o < section->num_overlays;
4754                 o++, ol++) {
4755                int r;
4756                XkbOverlayRowPtr row;
4757
4758                size += SIZEOF(xkbOverlayWireDesc);
4759                for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) {
4760                    size += SIZEOF(xkbOverlayRowWireDesc);
4761                    size += row->num_keys * SIZEOF(xkbOverlayKeyWireDesc);
4762                }
4763            }
4764        }
4765    }
4766    return size;
4767}
4768
4769static char *
4770XkbWriteGeomSections(char *wire, XkbGeometryPtr geom, Bool swap)
4771{
4772    register int i;
4773    XkbSectionPtr section;
4774    xkbSectionWireDesc *sectionWire;
4775
4776    for (i = 0, section = geom->sections; i < geom->num_sections;
4777         i++, section++) {
4778        sectionWire = (xkbSectionWireDesc *) wire;
4779        sectionWire->name = section->name;
4780        sectionWire->top = section->top;
4781        sectionWire->left = section->left;
4782        sectionWire->width = section->width;
4783        sectionWire->height = section->height;
4784        sectionWire->angle = section->angle;
4785        sectionWire->priority = section->priority;
4786        sectionWire->nRows = section->num_rows;
4787        sectionWire->nDoodads = section->num_doodads;
4788        sectionWire->nOverlays = section->num_overlays;
4789        sectionWire->pad = 0;
4790        if (swap) {
4791            swapl(&sectionWire->name);
4792            swaps(&sectionWire->top);
4793            swaps(&sectionWire->left);
4794            swaps(&sectionWire->width);
4795            swaps(&sectionWire->height);
4796            swaps(&sectionWire->angle);
4797        }
4798        wire = (char *) &sectionWire[1];
4799        if (section->rows) {
4800            int r;
4801            XkbRowPtr row;
4802            xkbRowWireDesc *rowWire;
4803
4804            for (r = 0, row = section->rows; r < section->num_rows; r++, row++) {
4805                rowWire = (xkbRowWireDesc *) wire;
4806                rowWire->top = row->top;
4807                rowWire->left = row->left;
4808                rowWire->nKeys = row->num_keys;
4809                rowWire->vertical = row->vertical;
4810                rowWire->pad = 0;
4811                if (swap) {
4812                    swaps(&rowWire->top);
4813                    swaps(&rowWire->left);
4814                }
4815                wire = (char *) &rowWire[1];
4816                if (row->keys) {
4817                    int k;
4818                    XkbKeyPtr key;
4819                    xkbKeyWireDesc *keyWire;
4820
4821                    keyWire = (xkbKeyWireDesc *) wire;
4822                    for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
4823                        memcpy(keyWire[k].name, key->name.name,
4824                               XkbKeyNameLength);
4825                        keyWire[k].gap = key->gap;
4826                        keyWire[k].shapeNdx = key->shape_ndx;
4827                        keyWire[k].colorNdx = key->color_ndx;
4828                        if (swap) {
4829                            swaps(&keyWire[k].gap);
4830                        }
4831                    }
4832                    wire = (char *) &keyWire[row->num_keys];
4833                }
4834            }
4835        }
4836        if (section->doodads) {
4837            wire = XkbWriteGeomDoodads(wire,
4838                                       section->num_doodads, section->doodads,
4839                                       swap);
4840        }
4841        if (section->overlays) {
4842            register int o;
4843
4844            for (o = 0; o < section->num_overlays; o++) {
4845                wire = XkbWriteGeomOverlay(wire, &section->overlays[o], swap);
4846            }
4847        }
4848    }
4849    return wire;
4850}
4851
4852static Status
4853XkbComputeGetGeometryReplySize(XkbGeometryPtr geom,
4854                               xkbGetGeometryReply * rep, Atom name)
4855{
4856    int len;
4857
4858    if (geom != NULL) {
4859        len = XkbSizeCountedString(geom->label_font);
4860        len += XkbSizeGeomProperties(geom);
4861        len += XkbSizeGeomColors(geom);
4862        len += XkbSizeGeomShapes(geom);
4863        len += XkbSizeGeomSections(geom);
4864        len += XkbSizeGeomDoodads(geom->num_doodads, geom->doodads);
4865        len += XkbSizeGeomKeyAliases(geom);
4866        rep->length = len / 4;
4867        rep->found = TRUE;
4868        rep->name = geom->name;
4869        rep->widthMM = geom->width_mm;
4870        rep->heightMM = geom->height_mm;
4871        rep->nProperties = geom->num_properties;
4872        rep->nColors = geom->num_colors;
4873        rep->nShapes = geom->num_shapes;
4874        rep->nSections = geom->num_sections;
4875        rep->nDoodads = geom->num_doodads;
4876        rep->nKeyAliases = geom->num_key_aliases;
4877        rep->baseColorNdx = XkbGeomColorIndex(geom, geom->base_color);
4878        rep->labelColorNdx = XkbGeomColorIndex(geom, geom->label_color);
4879    }
4880    else {
4881        rep->length = 0;
4882        rep->found = FALSE;
4883        rep->name = name;
4884        rep->widthMM = rep->heightMM = 0;
4885        rep->nProperties = rep->nColors = rep->nShapes = 0;
4886        rep->nSections = rep->nDoodads = 0;
4887        rep->nKeyAliases = 0;
4888        rep->labelColorNdx = rep->baseColorNdx = 0;
4889    }
4890    return Success;
4891}
4892static int
4893XkbSendGeometry(ClientPtr client,
4894                XkbGeometryPtr geom, xkbGetGeometryReply * rep, Bool freeGeom)
4895{
4896    char *desc, *start;
4897    int len;
4898
4899    if (geom != NULL) {
4900        start = desc = xallocarray(rep->length, 4);
4901        if (!start)
4902            return BadAlloc;
4903        len = rep->length * 4;
4904        desc = XkbWriteCountedString(desc, geom->label_font, client->swapped);
4905        if (rep->nProperties > 0)
4906            desc = XkbWriteGeomProperties(desc, geom, client->swapped);
4907        if (rep->nColors > 0)
4908            desc = XkbWriteGeomColors(desc, geom, client->swapped);
4909        if (rep->nShapes > 0)
4910            desc = XkbWriteGeomShapes(desc, geom, client->swapped);
4911        if (rep->nSections > 0)
4912            desc = XkbWriteGeomSections(desc, geom, client->swapped);
4913        if (rep->nDoodads > 0)
4914            desc = XkbWriteGeomDoodads(desc, geom->num_doodads, geom->doodads,
4915                                       client->swapped);
4916        if (rep->nKeyAliases > 0)
4917            desc = XkbWriteGeomKeyAliases(desc, geom, client->swapped);
4918        if ((desc - start) != (len)) {
4919            ErrorF
4920                ("[xkb] BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n",
4921                 len, (unsigned long) (desc - start));
4922        }
4923    }
4924    else {
4925        len = 0;
4926        start = NULL;
4927    }
4928    if (client->swapped) {
4929        swaps(&rep->sequenceNumber);
4930        swapl(&rep->length);
4931        swapl(&rep->name);
4932        swaps(&rep->widthMM);
4933        swaps(&rep->heightMM);
4934        swaps(&rep->nProperties);
4935        swaps(&rep->nColors);
4936        swaps(&rep->nShapes);
4937        swaps(&rep->nSections);
4938        swaps(&rep->nDoodads);
4939        swaps(&rep->nKeyAliases);
4940    }
4941    WriteToClient(client, SIZEOF(xkbGetGeometryReply), rep);
4942    if (len > 0)
4943        WriteToClient(client, len, start);
4944    if (start != NULL)
4945        free((char *) start);
4946    if (freeGeom)
4947        XkbFreeGeometry(geom, XkbGeomAllMask, TRUE);
4948    return Success;
4949}
4950
4951int
4952ProcXkbGetGeometry(ClientPtr client)
4953{
4954    DeviceIntPtr dev;
4955    xkbGetGeometryReply rep;
4956    XkbGeometryPtr geom;
4957    Bool shouldFree;
4958    Status status;
4959
4960    REQUEST(xkbGetGeometryReq);
4961    REQUEST_SIZE_MATCH(xkbGetGeometryReq);
4962
4963    if (!(client->xkbClientFlags & _XkbClientInitialized))
4964        return BadAccess;
4965
4966    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
4967    CHK_ATOM_OR_NONE(stuff->name);
4968
4969    geom = XkbLookupNamedGeometry(dev, stuff->name, &shouldFree);
4970    rep = (xkbGetGeometryReply) {
4971        .type = X_Reply,
4972        .deviceID = dev->id,
4973        .sequenceNumber = client->sequence,
4974        .length = 0
4975    };
4976    status = XkbComputeGetGeometryReplySize(geom, &rep, stuff->name);
4977    if (status != Success)
4978        return status;
4979    else
4980        return XkbSendGeometry(client, geom, &rep, shouldFree);
4981}
4982
4983/***====================================================================***/
4984
4985static Status
4986_GetCountedString(char **wire_inout, ClientPtr client, char **str)
4987{
4988    char *wire, *next;
4989    CARD16 len;
4990
4991    wire = *wire_inout;
4992    len = *(CARD16 *) wire;
4993    if (client->swapped) {
4994        swaps(&len);
4995    }
4996    next = wire + XkbPaddedSize(len + 2);
4997    /* Check we're still within the size of the request */
4998    if (client->req_len <
4999        bytes_to_int32(next - (char *) client->requestBuffer))
5000        return BadValue;
5001    *str = malloc(len + 1);
5002    if (!*str)
5003        return BadAlloc;
5004    memcpy(*str, &wire[2], len);
5005    *(*str + len) = '\0';
5006    *wire_inout = next;
5007    return Success;
5008}
5009
5010static Status
5011_CheckSetDoodad(char **wire_inout,
5012                XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client)
5013{
5014    char *wire;
5015    xkbDoodadWireDesc *dWire;
5016    xkbAnyDoodadWireDesc any;
5017    xkbTextDoodadWireDesc text;
5018    XkbDoodadPtr doodad;
5019    Status status;
5020
5021    dWire = (xkbDoodadWireDesc *) (*wire_inout);
5022    any = dWire->any;
5023    wire = (char *) &dWire[1];
5024    if (client->swapped) {
5025        swapl(&any.name);
5026        swaps(&any.top);
5027        swaps(&any.left);
5028        swaps(&any.angle);
5029    }
5030    CHK_ATOM_ONLY(dWire->any.name);
5031    doodad = XkbAddGeomDoodad(geom, section, any.name);
5032    if (!doodad)
5033        return BadAlloc;
5034    doodad->any.type = dWire->any.type;
5035    doodad->any.priority = dWire->any.priority;
5036    doodad->any.top = any.top;
5037    doodad->any.left = any.left;
5038    doodad->any.angle = any.angle;
5039    switch (doodad->any.type) {
5040    case XkbOutlineDoodad:
5041    case XkbSolidDoodad:
5042        if (dWire->shape.colorNdx >= geom->num_colors) {
5043            client->errorValue = _XkbErrCode3(0x40, geom->num_colors,
5044                                              dWire->shape.colorNdx);
5045            return BadMatch;
5046        }
5047        if (dWire->shape.shapeNdx >= geom->num_shapes) {
5048            client->errorValue = _XkbErrCode3(0x41, geom->num_shapes,
5049                                              dWire->shape.shapeNdx);
5050            return BadMatch;
5051        }
5052        doodad->shape.color_ndx = dWire->shape.colorNdx;
5053        doodad->shape.shape_ndx = dWire->shape.shapeNdx;
5054        break;
5055    case XkbTextDoodad:
5056        if (dWire->text.colorNdx >= geom->num_colors) {
5057            client->errorValue = _XkbErrCode3(0x42, geom->num_colors,
5058                                              dWire->text.colorNdx);
5059            return BadMatch;
5060        }
5061        text = dWire->text;
5062        if (client->swapped) {
5063            swaps(&text.width);
5064            swaps(&text.height);
5065        }
5066        doodad->text.width = text.width;
5067        doodad->text.height = text.height;
5068        doodad->text.color_ndx = dWire->text.colorNdx;
5069        status = _GetCountedString(&wire, client, &doodad->text.text);
5070        if (status != Success)
5071            return status;
5072        status = _GetCountedString(&wire, client, &doodad->text.font);
5073        if (status != Success) {
5074            free (doodad->text.text);
5075            return status;
5076        }
5077        break;
5078    case XkbIndicatorDoodad:
5079        if (dWire->indicator.onColorNdx >= geom->num_colors) {
5080            client->errorValue = _XkbErrCode3(0x43, geom->num_colors,
5081                                              dWire->indicator.onColorNdx);
5082            return BadMatch;
5083        }
5084        if (dWire->indicator.offColorNdx >= geom->num_colors) {
5085            client->errorValue = _XkbErrCode3(0x44, geom->num_colors,
5086                                              dWire->indicator.offColorNdx);
5087            return BadMatch;
5088        }
5089        if (dWire->indicator.shapeNdx >= geom->num_shapes) {
5090            client->errorValue = _XkbErrCode3(0x45, geom->num_shapes,
5091                                              dWire->indicator.shapeNdx);
5092            return BadMatch;
5093        }
5094        doodad->indicator.shape_ndx = dWire->indicator.shapeNdx;
5095        doodad->indicator.on_color_ndx = dWire->indicator.onColorNdx;
5096        doodad->indicator.off_color_ndx = dWire->indicator.offColorNdx;
5097        break;
5098    case XkbLogoDoodad:
5099        if (dWire->logo.colorNdx >= geom->num_colors) {
5100            client->errorValue = _XkbErrCode3(0x46, geom->num_colors,
5101                                              dWire->logo.colorNdx);
5102            return BadMatch;
5103        }
5104        if (dWire->logo.shapeNdx >= geom->num_shapes) {
5105            client->errorValue = _XkbErrCode3(0x47, geom->num_shapes,
5106                                              dWire->logo.shapeNdx);
5107            return BadMatch;
5108        }
5109        doodad->logo.color_ndx = dWire->logo.colorNdx;
5110        doodad->logo.shape_ndx = dWire->logo.shapeNdx;
5111        status = _GetCountedString(&wire, client, &doodad->logo.logo_name);
5112        if (status != Success)
5113            return status;
5114        break;
5115    default:
5116        client->errorValue = _XkbErrCode2(0x4F, dWire->any.type);
5117        return BadValue;
5118    }
5119    *wire_inout = wire;
5120    return Success;
5121}
5122
5123static Status
5124_CheckSetOverlay(char **wire_inout,
5125                 XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client)
5126{
5127    register int r;
5128    char *wire;
5129    XkbOverlayPtr ol;
5130    xkbOverlayWireDesc *olWire;
5131    xkbOverlayRowWireDesc *rWire;
5132
5133    wire = *wire_inout;
5134    olWire = (xkbOverlayWireDesc *) wire;
5135    if (client->swapped) {
5136        swapl(&olWire->name);
5137    }
5138    CHK_ATOM_ONLY(olWire->name);
5139    ol = XkbAddGeomOverlay(section, olWire->name, olWire->nRows);
5140    rWire = (xkbOverlayRowWireDesc *) &olWire[1];
5141    for (r = 0; r < olWire->nRows; r++) {
5142        register int k;
5143        xkbOverlayKeyWireDesc *kWire;
5144        XkbOverlayRowPtr row;
5145
5146        if (rWire->rowUnder > section->num_rows) {
5147            client->errorValue = _XkbErrCode4(0x20, r, section->num_rows,
5148                                              rWire->rowUnder);
5149            return BadMatch;
5150        }
5151        row = XkbAddGeomOverlayRow(ol, rWire->rowUnder, rWire->nKeys);
5152        kWire = (xkbOverlayKeyWireDesc *) &rWire[1];
5153        for (k = 0; k < rWire->nKeys; k++, kWire++) {
5154            if (XkbAddGeomOverlayKey(ol, row,
5155                                     (char *) kWire->over,
5156                                     (char *) kWire->under) == NULL) {
5157                client->errorValue = _XkbErrCode3(0x21, r, k);
5158                return BadMatch;
5159            }
5160        }
5161        rWire = (xkbOverlayRowWireDesc *) kWire;
5162    }
5163    olWire = (xkbOverlayWireDesc *) rWire;
5164    wire = (char *) olWire;
5165    *wire_inout = wire;
5166    return Success;
5167}
5168
5169static Status
5170_CheckSetSections(XkbGeometryPtr geom,
5171                  xkbSetGeometryReq * req, char **wire_inout, ClientPtr client)
5172{
5173    Status status;
5174    register int s;
5175    char *wire;
5176    xkbSectionWireDesc *sWire;
5177    XkbSectionPtr section;
5178
5179    wire = *wire_inout;
5180    if (req->nSections < 1)
5181        return Success;
5182    sWire = (xkbSectionWireDesc *) wire;
5183    for (s = 0; s < req->nSections; s++) {
5184        register int r;
5185        xkbRowWireDesc *rWire;
5186
5187        if (client->swapped) {
5188            swapl(&sWire->name);
5189            swaps(&sWire->top);
5190            swaps(&sWire->left);
5191            swaps(&sWire->width);
5192            swaps(&sWire->height);
5193            swaps(&sWire->angle);
5194        }
5195        CHK_ATOM_ONLY(sWire->name);
5196        section = XkbAddGeomSection(geom, sWire->name, sWire->nRows,
5197                                    sWire->nDoodads, sWire->nOverlays);
5198        if (!section)
5199            return BadAlloc;
5200        section->priority = sWire->priority;
5201        section->top = sWire->top;
5202        section->left = sWire->left;
5203        section->width = sWire->width;
5204        section->height = sWire->height;
5205        section->angle = sWire->angle;
5206        rWire = (xkbRowWireDesc *) &sWire[1];
5207        for (r = 0; r < sWire->nRows; r++) {
5208            register int k;
5209            XkbRowPtr row;
5210            xkbKeyWireDesc *kWire;
5211
5212            if (client->swapped) {
5213                swaps(&rWire->top);
5214                swaps(&rWire->left);
5215            }
5216            row = XkbAddGeomRow(section, rWire->nKeys);
5217            if (!row)
5218                return BadAlloc;
5219            row->top = rWire->top;
5220            row->left = rWire->left;
5221            row->vertical = rWire->vertical;
5222            kWire = (xkbKeyWireDesc *) &rWire[1];
5223            for (k = 0; k < rWire->nKeys; k++) {
5224                XkbKeyPtr key;
5225
5226                key = XkbAddGeomKey(row);
5227                if (!key)
5228                    return BadAlloc;
5229                memcpy(key->name.name, kWire[k].name, XkbKeyNameLength);
5230                key->gap = kWire[k].gap;
5231                key->shape_ndx = kWire[k].shapeNdx;
5232                key->color_ndx = kWire[k].colorNdx;
5233                if (key->shape_ndx >= geom->num_shapes) {
5234                    client->errorValue = _XkbErrCode3(0x10, key->shape_ndx,
5235                                                      geom->num_shapes);
5236                    return BadMatch;
5237                }
5238                if (key->color_ndx >= geom->num_colors) {
5239                    client->errorValue = _XkbErrCode3(0x11, key->color_ndx,
5240                                                      geom->num_colors);
5241                    return BadMatch;
5242                }
5243            }
5244            rWire = (xkbRowWireDesc *) &kWire[rWire->nKeys];
5245        }
5246        wire = (char *) rWire;
5247        if (sWire->nDoodads > 0) {
5248            register int d;
5249
5250            for (d = 0; d < sWire->nDoodads; d++) {
5251                status = _CheckSetDoodad(&wire, geom, section, client);
5252                if (status != Success)
5253                    return status;
5254            }
5255        }
5256        if (sWire->nOverlays > 0) {
5257            register int o;
5258
5259            for (o = 0; o < sWire->nOverlays; o++) {
5260                status = _CheckSetOverlay(&wire, geom, section, client);
5261                if (status != Success)
5262                    return status;
5263            }
5264        }
5265        sWire = (xkbSectionWireDesc *) wire;
5266    }
5267    wire = (char *) sWire;
5268    *wire_inout = wire;
5269    return Success;
5270}
5271
5272static Status
5273_CheckSetShapes(XkbGeometryPtr geom,
5274                xkbSetGeometryReq * req, char **wire_inout, ClientPtr client)
5275{
5276    register int i;
5277    char *wire;
5278
5279    wire = *wire_inout;
5280    if (req->nShapes < 1) {
5281        client->errorValue = _XkbErrCode2(0x06, req->nShapes);
5282        return BadValue;
5283    }
5284    else {
5285        xkbShapeWireDesc *shapeWire;
5286        XkbShapePtr shape;
5287        register int o;
5288
5289        shapeWire = (xkbShapeWireDesc *) wire;
5290        for (i = 0; i < req->nShapes; i++) {
5291            xkbOutlineWireDesc *olWire;
5292            XkbOutlinePtr ol;
5293
5294            shape =
5295                XkbAddGeomShape(geom, shapeWire->name, shapeWire->nOutlines);
5296            if (!shape)
5297                return BadAlloc;
5298            olWire = (xkbOutlineWireDesc *) (&shapeWire[1]);
5299            for (o = 0; o < shapeWire->nOutlines; o++) {
5300                register int p;
5301                XkbPointPtr pt;
5302                xkbPointWireDesc *ptWire;
5303
5304                ol = XkbAddGeomOutline(shape, olWire->nPoints);
5305                if (!ol)
5306                    return BadAlloc;
5307                ol->corner_radius = olWire->cornerRadius;
5308                ptWire = (xkbPointWireDesc *) &olWire[1];
5309                for (p = 0, pt = ol->points; p < olWire->nPoints; p++, pt++) {
5310                    pt->x = ptWire[p].x;
5311                    pt->y = ptWire[p].y;
5312                    if (client->swapped) {
5313                        swaps(&pt->x);
5314                        swaps(&pt->y);
5315                    }
5316                }
5317                ol->num_points = olWire->nPoints;
5318                olWire = (xkbOutlineWireDesc *) (&ptWire[olWire->nPoints]);
5319            }
5320            if (shapeWire->primaryNdx != XkbNoShape)
5321                shape->primary = &shape->outlines[shapeWire->primaryNdx];
5322            if (shapeWire->approxNdx != XkbNoShape)
5323                shape->approx = &shape->outlines[shapeWire->approxNdx];
5324            shapeWire = (xkbShapeWireDesc *) olWire;
5325        }
5326        wire = (char *) shapeWire;
5327    }
5328    if (geom->num_shapes != req->nShapes) {
5329        client->errorValue = _XkbErrCode3(0x07, geom->num_shapes, req->nShapes);
5330        return BadMatch;
5331    }
5332
5333    *wire_inout = wire;
5334    return Success;
5335}
5336
5337static Status
5338_CheckSetGeom(XkbGeometryPtr geom, xkbSetGeometryReq * req, ClientPtr client)
5339{
5340    register int i;
5341    Status status;
5342    char *wire;
5343
5344    wire = (char *) &req[1];
5345    status = _GetCountedString(&wire, client, &geom->label_font);
5346    if (status != Success)
5347        return status;
5348
5349    for (i = 0; i < req->nProperties; i++) {
5350        char *name, *val;
5351
5352        status = _GetCountedString(&wire, client, &name);
5353        if (status != Success)
5354            return status;
5355        status = _GetCountedString(&wire, client, &val);
5356        if (status != Success) {
5357            free(name);
5358            return status;
5359        }
5360        if (XkbAddGeomProperty(geom, name, val) == NULL) {
5361            free(name);
5362            free(val);
5363            return BadAlloc;
5364        }
5365        free(name);
5366        free(val);
5367    }
5368
5369    if (req->nColors < 2) {
5370        client->errorValue = _XkbErrCode3(0x01, 2, req->nColors);
5371        return BadValue;
5372    }
5373    if (req->baseColorNdx > req->nColors) {
5374        client->errorValue =
5375            _XkbErrCode3(0x03, req->nColors, req->baseColorNdx);
5376        return BadMatch;
5377    }
5378    if (req->labelColorNdx > req->nColors) {
5379        client->errorValue =
5380            _XkbErrCode3(0x03, req->nColors, req->labelColorNdx);
5381        return BadMatch;
5382    }
5383    if (req->labelColorNdx == req->baseColorNdx) {
5384        client->errorValue = _XkbErrCode3(0x04, req->baseColorNdx,
5385                                          req->labelColorNdx);
5386        return BadMatch;
5387    }
5388
5389    for (i = 0; i < req->nColors; i++) {
5390        char *name;
5391
5392        status = _GetCountedString(&wire, client, &name);
5393        if (status != Success)
5394            return status;
5395        if (!XkbAddGeomColor(geom, name, geom->num_colors)) {
5396            free(name);
5397            return BadAlloc;
5398        }
5399        free(name);
5400    }
5401    if (req->nColors != geom->num_colors) {
5402        client->errorValue = _XkbErrCode3(0x05, req->nColors, geom->num_colors);
5403        return BadMatch;
5404    }
5405    geom->label_color = &geom->colors[req->labelColorNdx];
5406    geom->base_color = &geom->colors[req->baseColorNdx];
5407
5408    if ((status = _CheckSetShapes(geom, req, &wire, client)) != Success)
5409        return status;
5410
5411    if ((status = _CheckSetSections(geom, req, &wire, client)) != Success)
5412        return status;
5413
5414    for (i = 0; i < req->nDoodads; i++) {
5415        status = _CheckSetDoodad(&wire, geom, NULL, client);
5416        if (status != Success)
5417            return status;
5418    }
5419
5420    for (i = 0; i < req->nKeyAliases; i++) {
5421        if (XkbAddGeomKeyAlias(geom, &wire[XkbKeyNameLength], wire) == NULL)
5422            return BadAlloc;
5423        wire += 2 * XkbKeyNameLength;
5424    }
5425    return Success;
5426}
5427
5428static int
5429_XkbSetGeometry(ClientPtr client, DeviceIntPtr dev, xkbSetGeometryReq * stuff)
5430{
5431    XkbDescPtr xkb;
5432    Bool new_name;
5433    xkbNewKeyboardNotify nkn;
5434    XkbGeometryPtr geom, old;
5435    XkbGeometrySizesRec sizes;
5436    Status status;
5437
5438    xkb = dev->key->xkbInfo->desc;
5439    old = xkb->geom;
5440    xkb->geom = NULL;
5441
5442    sizes.which = XkbGeomAllMask;
5443    sizes.num_properties = stuff->nProperties;
5444    sizes.num_colors = stuff->nColors;
5445    sizes.num_shapes = stuff->nShapes;
5446    sizes.num_sections = stuff->nSections;
5447    sizes.num_doodads = stuff->nDoodads;
5448    sizes.num_key_aliases = stuff->nKeyAliases;
5449    if ((status = XkbAllocGeometry(xkb, &sizes)) != Success) {
5450        xkb->geom = old;
5451        return status;
5452    }
5453    geom = xkb->geom;
5454    geom->name = stuff->name;
5455    geom->width_mm = stuff->widthMM;
5456    geom->height_mm = stuff->heightMM;
5457    if ((status = _CheckSetGeom(geom, stuff, client)) != Success) {
5458        XkbFreeGeometry(geom, XkbGeomAllMask, TRUE);
5459        xkb->geom = old;
5460        return status;
5461    }
5462    new_name = (xkb->names->geometry != geom->name);
5463    xkb->names->geometry = geom->name;
5464    if (old)
5465        XkbFreeGeometry(old, XkbGeomAllMask, TRUE);
5466    if (new_name) {
5467        xkbNamesNotify nn;
5468
5469        memset(&nn, 0, sizeof(xkbNamesNotify));
5470        nn.changed = XkbGeometryNameMask;
5471        XkbSendNamesNotify(dev, &nn);
5472    }
5473    nkn.deviceID = nkn.oldDeviceID = dev->id;
5474    nkn.minKeyCode = nkn.oldMinKeyCode = xkb->min_key_code;
5475    nkn.maxKeyCode = nkn.oldMaxKeyCode = xkb->max_key_code;
5476    nkn.requestMajor = XkbReqCode;
5477    nkn.requestMinor = X_kbSetGeometry;
5478    nkn.changed = XkbNKN_GeometryMask;
5479    XkbSendNewKeyboardNotify(dev, &nkn);
5480    return Success;
5481}
5482
5483int
5484ProcXkbSetGeometry(ClientPtr client)
5485{
5486    DeviceIntPtr dev;
5487    int rc;
5488
5489    REQUEST(xkbSetGeometryReq);
5490    REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq);
5491
5492    if (!(client->xkbClientFlags & _XkbClientInitialized))
5493        return BadAccess;
5494
5495    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
5496    CHK_ATOM_OR_NONE(stuff->name);
5497
5498    rc = _XkbSetGeometry(client, dev, stuff);
5499    if (rc != Success)
5500        return rc;
5501
5502    if (stuff->deviceSpec == XkbUseCoreKbd) {
5503        DeviceIntPtr other;
5504
5505        for (other = inputInfo.devices; other; other = other->next) {
5506            if ((other != dev) && other->key && !IsMaster(other) &&
5507                GetMaster(other, MASTER_KEYBOARD) == dev) {
5508                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
5509                              DixManageAccess);
5510                if (rc == Success)
5511                    _XkbSetGeometry(client, other, stuff);
5512            }
5513        }
5514    }
5515
5516    return Success;
5517}
5518
5519/***====================================================================***/
5520
5521int
5522ProcXkbPerClientFlags(ClientPtr client)
5523{
5524    DeviceIntPtr dev;
5525    xkbPerClientFlagsReply rep;
5526    XkbInterestPtr interest;
5527    Mask access_mode = DixGetAttrAccess | DixSetAttrAccess;
5528
5529    REQUEST(xkbPerClientFlagsReq);
5530    REQUEST_SIZE_MATCH(xkbPerClientFlagsReq);
5531
5532    if (!(client->xkbClientFlags & _XkbClientInitialized))
5533        return BadAccess;
5534
5535    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
5536    CHK_MASK_LEGAL(0x01, stuff->change, XkbPCF_AllFlagsMask);
5537    CHK_MASK_MATCH(0x02, stuff->change, stuff->value);
5538
5539    interest = XkbFindClientResource((DevicePtr) dev, client);
5540    if (stuff->change) {
5541        client->xkbClientFlags &= ~stuff->change;
5542        client->xkbClientFlags |= stuff->value;
5543    }
5544    if (stuff->change & XkbPCF_AutoResetControlsMask) {
5545        Bool want;
5546
5547        want = stuff->value & XkbPCF_AutoResetControlsMask;
5548        if (interest && !want) {
5549            interest->autoCtrls = interest->autoCtrlValues = 0;
5550        }
5551        else if (want && (!interest)) {
5552            XID id = FakeClientID(client->index);
5553
5554            if (!AddResource(id, RT_XKBCLIENT, dev))
5555                return BadAlloc;
5556            interest = XkbAddClientResource((DevicePtr) dev, client, id);
5557            if (!interest)
5558                return BadAlloc;
5559        }
5560        if (interest && want) {
5561            register unsigned affect;
5562
5563            affect = stuff->ctrlsToChange;
5564
5565            CHK_MASK_LEGAL(0x03, affect, XkbAllBooleanCtrlsMask);
5566            CHK_MASK_MATCH(0x04, affect, stuff->autoCtrls);
5567            CHK_MASK_MATCH(0x05, stuff->autoCtrls, stuff->autoCtrlValues);
5568
5569            interest->autoCtrls &= ~affect;
5570            interest->autoCtrlValues &= ~affect;
5571            interest->autoCtrls |= stuff->autoCtrls & affect;
5572            interest->autoCtrlValues |= stuff->autoCtrlValues & affect;
5573        }
5574    }
5575
5576    rep = (xkbPerClientFlagsReply) {
5577        .type = X_Reply,
5578        .sequenceNumber = client->sequence,
5579        .length = 0,
5580        .supported = XkbPCF_AllFlagsMask,
5581        .value = client->xkbClientFlags & XkbPCF_AllFlagsMask,
5582        .autoCtrls = interest ? interest->autoCtrls : 0,
5583        .autoCtrlValues =  interest ? interest->autoCtrlValues : 0,
5584    };
5585    if (client->swapped) {
5586        swaps(&rep.sequenceNumber);
5587        swapl(&rep.supported);
5588        swapl(&rep.value);
5589        swapl(&rep.autoCtrls);
5590        swapl(&rep.autoCtrlValues);
5591    }
5592    WriteToClient(client, SIZEOF(xkbPerClientFlagsReply), &rep);
5593    return Success;
5594}
5595
5596/***====================================================================***/
5597
5598/* all latin-1 alphanumerics, plus parens, minus, underscore, slash */
5599/* and wildcards */
5600static unsigned char componentSpecLegal[] = {
5601    0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x87,
5602    0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07,
5603    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5604    0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
5605};
5606
5607/* same as above but accepts percent, plus and bar too */
5608static unsigned char componentExprLegal[] = {
5609    0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0xff, 0x87,
5610    0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x17,
5611    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5612    0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
5613};
5614
5615static char *
5616GetComponentSpec(unsigned char **pWire, Bool allowExpr, int *errRtrn)
5617{
5618    int len;
5619    register int i;
5620    unsigned char *wire, *str, *tmp, *legal;
5621
5622    if (allowExpr)
5623        legal = &componentExprLegal[0];
5624    else
5625        legal = &componentSpecLegal[0];
5626
5627    wire = *pWire;
5628    len = (*(unsigned char *) wire++);
5629    if (len > 0) {
5630        str = calloc(1, len + 1);
5631        if (str) {
5632            tmp = str;
5633            for (i = 0; i < len; i++) {
5634                if (legal[(*wire) / 8] & (1 << ((*wire) % 8)))
5635                    *tmp++ = *wire++;
5636                else
5637                    wire++;
5638            }
5639            if (tmp != str)
5640                *tmp++ = '\0';
5641            else {
5642                free(str);
5643                str = NULL;
5644            }
5645        }
5646        else {
5647            *errRtrn = BadAlloc;
5648        }
5649    }
5650    else {
5651        str = NULL;
5652    }
5653    *pWire = wire;
5654    return (char *) str;
5655}
5656
5657/***====================================================================***/
5658
5659int
5660ProcXkbListComponents(ClientPtr client)
5661{
5662    DeviceIntPtr dev;
5663    xkbListComponentsReply rep;
5664    unsigned len;
5665    unsigned char *str;
5666    uint8_t size;
5667    int i;
5668
5669    REQUEST(xkbListComponentsReq);
5670    REQUEST_AT_LEAST_SIZE(xkbListComponentsReq);
5671
5672    if (!(client->xkbClientFlags & _XkbClientInitialized))
5673        return BadAccess;
5674
5675    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
5676
5677    /* The request is followed by six Pascal strings (i.e. size in characters
5678     * followed by a string pattern) describing what the client wants us to
5679     * list.  We don't care, but might as well check they haven't got the
5680     * length wrong. */
5681    str = (unsigned char *) &stuff[1];
5682    for (i = 0; i < 6; i++) {
5683        size = *((uint8_t *)str);
5684        len = (str + size + 1) - ((unsigned char *) stuff);
5685        if ((XkbPaddedSize(len) / 4) > stuff->length)
5686            return BadLength;
5687        str += (size + 1);
5688    }
5689    if ((XkbPaddedSize(len) / 4) != stuff->length)
5690        return BadLength;
5691    rep = (xkbListComponentsReply) {
5692        .type = X_Reply,
5693        .deviceID = dev->id,
5694        .sequenceNumber = client->sequence,
5695        .length = 0,
5696        .nKeymaps = 0,
5697        .nKeycodes = 0,
5698        .nTypes = 0,
5699        .nCompatMaps = 0,
5700        .nSymbols = 0,
5701        .nGeometries = 0,
5702        .extra = 0
5703    };
5704    if (client->swapped) {
5705        swaps(&rep.sequenceNumber);
5706        swapl(&rep.length);
5707        swaps(&rep.nKeymaps);
5708        swaps(&rep.nKeycodes);
5709        swaps(&rep.nTypes);
5710        swaps(&rep.nCompatMaps);
5711        swaps(&rep.nSymbols);
5712        swaps(&rep.nGeometries);
5713        swaps(&rep.extra);
5714    }
5715    WriteToClient(client, SIZEOF(xkbListComponentsReply), &rep);
5716    return Success;
5717}
5718
5719/***====================================================================***/
5720int
5721ProcXkbGetKbdByName(ClientPtr client)
5722{
5723    DeviceIntPtr dev;
5724    DeviceIntPtr tmpd;
5725    DeviceIntPtr master;
5726    xkbGetKbdByNameReply rep = { 0 };
5727    xkbGetMapReply mrep = { 0 };
5728    xkbGetCompatMapReply crep = { 0 };
5729    xkbGetIndicatorMapReply irep = { 0 };
5730    xkbGetNamesReply nrep = { 0 };
5731    xkbGetGeometryReply grep = { 0 };
5732    XkbComponentNamesRec names = { 0 };
5733    XkbDescPtr xkb, new;
5734    XkbEventCauseRec cause;
5735    unsigned char *str;
5736    char mapFile[PATH_MAX];
5737    unsigned len;
5738    unsigned fwant, fneed, reported;
5739    int status;
5740    Bool geom_changed;
5741    XkbSrvLedInfoPtr old_sli;
5742    XkbSrvLedInfoPtr sli;
5743    Mask access_mode = DixGetAttrAccess | DixManageAccess;
5744
5745    REQUEST(xkbGetKbdByNameReq);
5746    REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq);
5747
5748    if (!(client->xkbClientFlags & _XkbClientInitialized))
5749        return BadAccess;
5750
5751    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
5752    master = GetMaster(dev, MASTER_KEYBOARD);
5753
5754    xkb = dev->key->xkbInfo->desc;
5755    status = Success;
5756    str = (unsigned char *) &stuff[1];
5757    if (GetComponentSpec(&str, TRUE, &status))  /* keymap, unsupported */
5758        return BadMatch;
5759    names.keycodes = GetComponentSpec(&str, TRUE, &status);
5760    names.types = GetComponentSpec(&str, TRUE, &status);
5761    names.compat = GetComponentSpec(&str, TRUE, &status);
5762    names.symbols = GetComponentSpec(&str, TRUE, &status);
5763    names.geometry = GetComponentSpec(&str, TRUE, &status);
5764    if (status != Success)
5765        return status;
5766    len = str - ((unsigned char *) stuff);
5767    if ((XkbPaddedSize(len) / 4) != stuff->length)
5768        return BadLength;
5769
5770    CHK_MASK_LEGAL(0x01, stuff->want, XkbGBN_AllComponentsMask);
5771    CHK_MASK_LEGAL(0x02, stuff->need, XkbGBN_AllComponentsMask);
5772
5773    if (stuff->load)
5774        fwant = XkbGBN_AllComponentsMask;
5775    else
5776        fwant = stuff->want | stuff->need;
5777    if ((!names.compat) &&
5778        (fwant & (XkbGBN_CompatMapMask | XkbGBN_IndicatorMapMask))) {
5779        names.compat = Xstrdup("%");
5780    }
5781    if ((!names.types) && (fwant & (XkbGBN_TypesMask))) {
5782        names.types = Xstrdup("%");
5783    }
5784    if ((!names.symbols) && (fwant & XkbGBN_SymbolsMask)) {
5785        names.symbols = Xstrdup("%");
5786    }
5787    geom_changed = ((names.geometry != NULL) &&
5788                    (strcmp(names.geometry, "%") != 0));
5789    if ((!names.geometry) && (fwant & XkbGBN_GeometryMask)) {
5790        names.geometry = Xstrdup("%");
5791        geom_changed = FALSE;
5792    }
5793
5794    memset(mapFile, 0, PATH_MAX);
5795    rep.type = X_Reply;
5796    rep.deviceID = dev->id;
5797    rep.sequenceNumber = client->sequence;
5798    rep.length = 0;
5799    rep.minKeyCode = xkb->min_key_code;
5800    rep.maxKeyCode = xkb->max_key_code;
5801    rep.loaded = FALSE;
5802    fwant =
5803        XkbConvertGetByNameComponents(TRUE, stuff->want) | XkmVirtualModsMask;
5804    fneed = XkbConvertGetByNameComponents(TRUE, stuff->need);
5805    rep.reported = XkbConvertGetByNameComponents(FALSE, fwant | fneed);
5806    if (stuff->load) {
5807        fneed |= XkmKeymapRequired;
5808        fwant |= XkmKeymapLegal;
5809    }
5810    if ((fwant | fneed) & XkmSymbolsMask) {
5811        fneed |= XkmKeyNamesIndex | XkmTypesIndex;
5812        fwant |= XkmIndicatorsIndex;
5813    }
5814
5815    /* We pass dev in here so we can get the old names out if needed. */
5816    rep.found = XkbDDXLoadKeymapByNames(dev, &names, fwant, fneed, &new,
5817                                        mapFile, PATH_MAX);
5818    rep.newKeyboard = FALSE;
5819    rep.pad1 = rep.pad2 = rep.pad3 = rep.pad4 = 0;
5820
5821    stuff->want |= stuff->need;
5822    if (new == NULL)
5823        rep.reported = 0;
5824    else {
5825        if (stuff->load)
5826            rep.loaded = TRUE;
5827        if (stuff->load ||
5828            ((rep.reported & XkbGBN_SymbolsMask) && (new->compat))) {
5829            XkbChangesRec changes;
5830
5831            memset(&changes, 0, sizeof(changes));
5832            XkbUpdateDescActions(new,
5833                                 new->min_key_code, XkbNumKeys(new), &changes);
5834        }
5835
5836        if (new->map == NULL)
5837            rep.reported &= ~(XkbGBN_SymbolsMask | XkbGBN_TypesMask);
5838        else if (rep.reported & (XkbGBN_SymbolsMask | XkbGBN_TypesMask)) {
5839            mrep.type = X_Reply;
5840            mrep.deviceID = dev->id;
5841            mrep.sequenceNumber = client->sequence;
5842            mrep.length =
5843                ((SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply)) >> 2);
5844            mrep.minKeyCode = new->min_key_code;
5845            mrep.maxKeyCode = new->max_key_code;
5846            mrep.present = 0;
5847            mrep.totalSyms = mrep.totalActs =
5848                mrep.totalKeyBehaviors = mrep.totalKeyExplicit =
5849                mrep.totalModMapKeys = mrep.totalVModMapKeys = 0;
5850            if (rep.reported & (XkbGBN_TypesMask | XkbGBN_ClientSymbolsMask)) {
5851                mrep.present |= XkbKeyTypesMask;
5852                mrep.firstType = 0;
5853                mrep.nTypes = mrep.totalTypes = new->map->num_types;
5854            }
5855            else {
5856                mrep.firstType = mrep.nTypes = 0;
5857                mrep.totalTypes = 0;
5858            }
5859            if (rep.reported & XkbGBN_ClientSymbolsMask) {
5860                mrep.present |= (XkbKeySymsMask | XkbModifierMapMask);
5861                mrep.firstKeySym = mrep.firstModMapKey = new->min_key_code;
5862                mrep.nKeySyms = mrep.nModMapKeys = XkbNumKeys(new);
5863            }
5864            else {
5865                mrep.firstKeySym = mrep.firstModMapKey = 0;
5866                mrep.nKeySyms = mrep.nModMapKeys = 0;
5867            }
5868            if (rep.reported & XkbGBN_ServerSymbolsMask) {
5869                mrep.present |= XkbAllServerInfoMask;
5870                mrep.virtualMods = ~0;
5871                mrep.firstKeyAct = mrep.firstKeyBehavior =
5872                    mrep.firstKeyExplicit = new->min_key_code;
5873                mrep.nKeyActs = mrep.nKeyBehaviors =
5874                    mrep.nKeyExplicit = XkbNumKeys(new);
5875                mrep.firstVModMapKey = new->min_key_code;
5876                mrep.nVModMapKeys = XkbNumKeys(new);
5877            }
5878            else {
5879                mrep.virtualMods = 0;
5880                mrep.firstKeyAct = mrep.firstKeyBehavior =
5881                    mrep.firstKeyExplicit = 0;
5882                mrep.nKeyActs = mrep.nKeyBehaviors = mrep.nKeyExplicit = 0;
5883            }
5884            XkbComputeGetMapReplySize(new, &mrep);
5885            rep.length += SIZEOF(xGenericReply) / 4 + mrep.length;
5886        }
5887        if (new->compat == NULL)
5888            rep.reported &= ~XkbGBN_CompatMapMask;
5889        else if (rep.reported & XkbGBN_CompatMapMask) {
5890            crep.type = X_Reply;
5891            crep.deviceID = dev->id;
5892            crep.sequenceNumber = client->sequence;
5893            crep.length = 0;
5894            crep.groups = XkbAllGroupsMask;
5895            crep.firstSI = 0;
5896            crep.nSI = crep.nTotalSI = new->compat->num_si;
5897            XkbComputeGetCompatMapReplySize(new->compat, &crep);
5898            rep.length += SIZEOF(xGenericReply) / 4 + crep.length;
5899        }
5900        if (new->indicators == NULL)
5901            rep.reported &= ~XkbGBN_IndicatorMapMask;
5902        else if (rep.reported & XkbGBN_IndicatorMapMask) {
5903            irep.type = X_Reply;
5904            irep.deviceID = dev->id;
5905            irep.sequenceNumber = client->sequence;
5906            irep.length = 0;
5907            irep.which = XkbAllIndicatorsMask;
5908            XkbComputeGetIndicatorMapReplySize(new->indicators, &irep);
5909            rep.length += SIZEOF(xGenericReply) / 4 + irep.length;
5910        }
5911        if (new->names == NULL)
5912            rep.reported &= ~(XkbGBN_OtherNamesMask | XkbGBN_KeyNamesMask);
5913        else if (rep.reported & (XkbGBN_OtherNamesMask | XkbGBN_KeyNamesMask)) {
5914            nrep.type = X_Reply;
5915            nrep.deviceID = dev->id;
5916            nrep.sequenceNumber = client->sequence;
5917            nrep.length = 0;
5918            nrep.minKeyCode = new->min_key_code;
5919            nrep.maxKeyCode = new->max_key_code;
5920            if (rep.reported & XkbGBN_OtherNamesMask) {
5921                nrep.which = XkbAllNamesMask;
5922                if (new->map != NULL)
5923                    nrep.nTypes = new->map->num_types;
5924                else
5925                    nrep.nTypes = 0;
5926                nrep.nKTLevels = 0;
5927                nrep.groupNames = XkbAllGroupsMask;
5928                nrep.virtualMods = XkbAllVirtualModsMask;
5929                nrep.indicators = XkbAllIndicatorsMask;
5930                nrep.nRadioGroups = new->names->num_rg;
5931            }
5932            else {
5933                nrep.which = 0;
5934                nrep.nTypes = 0;
5935                nrep.nKTLevels = 0;
5936                nrep.groupNames = 0;
5937                nrep.virtualMods = 0;
5938                nrep.indicators = 0;
5939                nrep.nRadioGroups = 0;
5940            }
5941            if (rep.reported & XkbGBN_KeyNamesMask) {
5942                nrep.which |= XkbKeyNamesMask;
5943                nrep.firstKey = new->min_key_code;
5944                nrep.nKeys = XkbNumKeys(new);
5945                nrep.nKeyAliases = new->names->num_key_aliases;
5946                if (nrep.nKeyAliases)
5947                    nrep.which |= XkbKeyAliasesMask;
5948            }
5949            else {
5950                nrep.which &= ~(XkbKeyNamesMask | XkbKeyAliasesMask);
5951                nrep.firstKey = nrep.nKeys = 0;
5952                nrep.nKeyAliases = 0;
5953            }
5954            XkbComputeGetNamesReplySize(new, &nrep);
5955            rep.length += SIZEOF(xGenericReply) / 4 + nrep.length;
5956        }
5957        if (new->geom == NULL)
5958            rep.reported &= ~XkbGBN_GeometryMask;
5959        else if (rep.reported & XkbGBN_GeometryMask) {
5960            grep.type = X_Reply;
5961            grep.deviceID = dev->id;
5962            grep.sequenceNumber = client->sequence;
5963            grep.length = 0;
5964            grep.found = TRUE;
5965            grep.pad = 0;
5966            grep.widthMM = grep.heightMM = 0;
5967            grep.nProperties = grep.nColors = grep.nShapes = 0;
5968            grep.nSections = grep.nDoodads = 0;
5969            grep.baseColorNdx = grep.labelColorNdx = 0;
5970            XkbComputeGetGeometryReplySize(new->geom, &grep, None);
5971            rep.length += SIZEOF(xGenericReply) / 4 + grep.length;
5972        }
5973    }
5974
5975    reported = rep.reported;
5976    if (client->swapped) {
5977        swaps(&rep.sequenceNumber);
5978        swapl(&rep.length);
5979        swaps(&rep.found);
5980        swaps(&rep.reported);
5981    }
5982    WriteToClient(client, SIZEOF(xkbGetKbdByNameReply), &rep);
5983    if (reported & (XkbGBN_SymbolsMask | XkbGBN_TypesMask))
5984        XkbSendMap(client, new, &mrep);
5985    if (reported & XkbGBN_CompatMapMask)
5986        XkbSendCompatMap(client, new->compat, &crep);
5987    if (reported & XkbGBN_IndicatorMapMask)
5988        XkbSendIndicatorMap(client, new->indicators, &irep);
5989    if (reported & (XkbGBN_KeyNamesMask | XkbGBN_OtherNamesMask))
5990        XkbSendNames(client, new, &nrep);
5991    if (reported & XkbGBN_GeometryMask)
5992        XkbSendGeometry(client, new->geom, &grep, FALSE);
5993    if (rep.loaded) {
5994        XkbDescPtr old_xkb;
5995        xkbNewKeyboardNotify nkn;
5996
5997        old_xkb = xkb;
5998        xkb = new;
5999        dev->key->xkbInfo->desc = xkb;
6000        new = old_xkb;          /* so it'll get freed automatically */
6001
6002        XkbCopyControls(xkb, old_xkb);
6003
6004        nkn.deviceID = nkn.oldDeviceID = dev->id;
6005        nkn.minKeyCode = new->min_key_code;
6006        nkn.maxKeyCode = new->max_key_code;
6007        nkn.oldMinKeyCode = xkb->min_key_code;
6008        nkn.oldMaxKeyCode = xkb->max_key_code;
6009        nkn.requestMajor = XkbReqCode;
6010        nkn.requestMinor = X_kbGetKbdByName;
6011        nkn.changed = XkbNKN_KeycodesMask;
6012        if (geom_changed)
6013            nkn.changed |= XkbNKN_GeometryMask;
6014        XkbSendNewKeyboardNotify(dev, &nkn);
6015
6016        /* Update the map and LED info on the device itself, as well as
6017         * any slaves if it's an MD, or its MD if it's an SD and was the
6018         * last device used on that MD. */
6019        for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
6020            if (tmpd != dev && GetMaster(tmpd, MASTER_KEYBOARD) != dev &&
6021                (tmpd != master || dev != master->lastSlave))
6022                continue;
6023
6024            if (tmpd != dev)
6025                XkbDeviceApplyKeymap(tmpd, xkb);
6026
6027            if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) {
6028                old_sli = tmpd->kbdfeed->xkb_sli;
6029                tmpd->kbdfeed->xkb_sli = NULL;
6030                sli = XkbAllocSrvLedInfo(tmpd, tmpd->kbdfeed, NULL, 0);
6031                if (sli) {
6032                    sli->explicitState = old_sli->explicitState;
6033                    sli->effectiveState = old_sli->effectiveState;
6034                }
6035                tmpd->kbdfeed->xkb_sli = sli;
6036                XkbFreeSrvLedInfo(old_sli);
6037            }
6038        }
6039    }
6040    if ((new != NULL) && (new != xkb)) {
6041        XkbFreeKeyboard(new, XkbAllComponentsMask, TRUE);
6042        new = NULL;
6043    }
6044    XkbFreeComponentNames(&names, FALSE);
6045    XkbSetCauseXkbReq(&cause, X_kbGetKbdByName, client);
6046    XkbUpdateAllDeviceIndicators(NULL, &cause);
6047
6048    return Success;
6049}
6050
6051/***====================================================================***/
6052
6053static int
6054ComputeDeviceLedInfoSize(DeviceIntPtr dev,
6055                         unsigned int what, XkbSrvLedInfoPtr sli)
6056{
6057    int nNames, nMaps;
6058    register unsigned n, bit;
6059
6060    if (sli == NULL)
6061        return 0;
6062    nNames = nMaps = 0;
6063    if ((what & XkbXI_IndicatorNamesMask) == 0)
6064        sli->namesPresent = 0;
6065    if ((what & XkbXI_IndicatorMapsMask) == 0)
6066        sli->mapsPresent = 0;
6067
6068    for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6069        if (sli->names && sli->names[n] != None) {
6070            sli->namesPresent |= bit;
6071            nNames++;
6072        }
6073        if (sli->maps && XkbIM_InUse(&sli->maps[n])) {
6074            sli->mapsPresent |= bit;
6075            nMaps++;
6076        }
6077    }
6078    return (nNames * 4) + (nMaps * SIZEOF(xkbIndicatorMapWireDesc));
6079}
6080
6081static int
6082CheckDeviceLedFBs(DeviceIntPtr dev,
6083                  int class,
6084                  int id, xkbGetDeviceInfoReply * rep, ClientPtr client)
6085{
6086    int nFBs = 0;
6087    int length = 0;
6088    Bool classOk;
6089
6090    if (class == XkbDfltXIClass) {
6091        if (dev->kbdfeed)
6092            class = KbdFeedbackClass;
6093        else if (dev->leds)
6094            class = LedFeedbackClass;
6095        else {
6096            client->errorValue = _XkbErrCode2(XkbErr_BadClass, class);
6097            return XkbKeyboardErrorCode;
6098        }
6099    }
6100    classOk = FALSE;
6101    if ((dev->kbdfeed) &&
6102        ((class == KbdFeedbackClass) || (class == XkbAllXIClasses))) {
6103        KbdFeedbackPtr kf;
6104
6105        classOk = TRUE;
6106        for (kf = dev->kbdfeed; (kf); kf = kf->next) {
6107            if ((id != XkbAllXIIds) && (id != XkbDfltXIId) &&
6108                (id != kf->ctrl.id))
6109                continue;
6110            nFBs++;
6111            length += SIZEOF(xkbDeviceLedsWireDesc);
6112            if (!kf->xkb_sli)
6113                kf->xkb_sli = XkbAllocSrvLedInfo(dev, kf, NULL, 0);
6114            length += ComputeDeviceLedInfoSize(dev, rep->present, kf->xkb_sli);
6115            if (id != XkbAllXIIds)
6116                break;
6117        }
6118    }
6119    if ((dev->leds) &&
6120        ((class == LedFeedbackClass) || (class == XkbAllXIClasses))) {
6121        LedFeedbackPtr lf;
6122
6123        classOk = TRUE;
6124        for (lf = dev->leds; (lf); lf = lf->next) {
6125            if ((id != XkbAllXIIds) && (id != XkbDfltXIId) &&
6126                (id != lf->ctrl.id))
6127                continue;
6128            nFBs++;
6129            length += SIZEOF(xkbDeviceLedsWireDesc);
6130            if (!lf->xkb_sli)
6131                lf->xkb_sli = XkbAllocSrvLedInfo(dev, NULL, lf, 0);
6132            length += ComputeDeviceLedInfoSize(dev, rep->present, lf->xkb_sli);
6133            if (id != XkbAllXIIds)
6134                break;
6135        }
6136    }
6137    if (nFBs > 0) {
6138        rep->nDeviceLedFBs = nFBs;
6139        rep->length += (length / 4);
6140        return Success;
6141    }
6142    if (classOk)
6143        client->errorValue = _XkbErrCode2(XkbErr_BadId, id);
6144    else
6145        client->errorValue = _XkbErrCode2(XkbErr_BadClass, class);
6146    return XkbKeyboardErrorCode;
6147}
6148
6149static int
6150SendDeviceLedInfo(XkbSrvLedInfoPtr sli, ClientPtr client)
6151{
6152    xkbDeviceLedsWireDesc wire;
6153    int length;
6154
6155    length = 0;
6156    wire.ledClass = sli->class;
6157    wire.ledID = sli->id;
6158    wire.namesPresent = sli->namesPresent;
6159    wire.mapsPresent = sli->mapsPresent;
6160    wire.physIndicators = sli->physIndicators;
6161    wire.state = sli->effectiveState;
6162    if (client->swapped) {
6163        swaps(&wire.ledClass);
6164        swaps(&wire.ledID);
6165        swapl(&wire.namesPresent);
6166        swapl(&wire.mapsPresent);
6167        swapl(&wire.physIndicators);
6168        swapl(&wire.state);
6169    }
6170    WriteToClient(client, SIZEOF(xkbDeviceLedsWireDesc), &wire);
6171    length += SIZEOF(xkbDeviceLedsWireDesc);
6172    if (sli->namesPresent | sli->mapsPresent) {
6173        register unsigned i, bit;
6174
6175        if (sli->namesPresent) {
6176            CARD32 awire;
6177
6178            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
6179                if (sli->namesPresent & bit) {
6180                    awire = (CARD32) sli->names[i];
6181                    if (client->swapped) {
6182                        swapl(&awire);
6183                    }
6184                    WriteToClient(client, 4, &awire);
6185                    length += 4;
6186                }
6187            }
6188        }
6189        if (sli->mapsPresent) {
6190            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
6191                xkbIndicatorMapWireDesc iwire;
6192
6193                if (sli->mapsPresent & bit) {
6194                    iwire.flags = sli->maps[i].flags;
6195                    iwire.whichGroups = sli->maps[i].which_groups;
6196                    iwire.groups = sli->maps[i].groups;
6197                    iwire.whichMods = sli->maps[i].which_mods;
6198                    iwire.mods = sli->maps[i].mods.mask;
6199                    iwire.realMods = sli->maps[i].mods.real_mods;
6200                    iwire.virtualMods = sli->maps[i].mods.vmods;
6201                    iwire.ctrls = sli->maps[i].ctrls;
6202                    if (client->swapped) {
6203                        swaps(&iwire.virtualMods);
6204                        swapl(&iwire.ctrls);
6205                    }
6206                    WriteToClient(client, SIZEOF(xkbIndicatorMapWireDesc),
6207                                  &iwire);
6208                    length += SIZEOF(xkbIndicatorMapWireDesc);
6209                }
6210            }
6211        }
6212    }
6213    return length;
6214}
6215
6216static int
6217SendDeviceLedFBs(DeviceIntPtr dev,
6218                 int class, int id, unsigned wantLength, ClientPtr client)
6219{
6220    int length = 0;
6221
6222    if (class == XkbDfltXIClass) {
6223        if (dev->kbdfeed)
6224            class = KbdFeedbackClass;
6225        else if (dev->leds)
6226            class = LedFeedbackClass;
6227    }
6228    if ((dev->kbdfeed) &&
6229        ((class == KbdFeedbackClass) || (class == XkbAllXIClasses))) {
6230        KbdFeedbackPtr kf;
6231
6232        for (kf = dev->kbdfeed; (kf); kf = kf->next) {
6233            if ((id == XkbAllXIIds) || (id == XkbDfltXIId) ||
6234                (id == kf->ctrl.id)) {
6235                length += SendDeviceLedInfo(kf->xkb_sli, client);
6236                if (id != XkbAllXIIds)
6237                    break;
6238            }
6239        }
6240    }
6241    if ((dev->leds) &&
6242        ((class == LedFeedbackClass) || (class == XkbAllXIClasses))) {
6243        LedFeedbackPtr lf;
6244
6245        for (lf = dev->leds; (lf); lf = lf->next) {
6246            if ((id == XkbAllXIIds) || (id == XkbDfltXIId) ||
6247                (id == lf->ctrl.id)) {
6248                length += SendDeviceLedInfo(lf->xkb_sli, client);
6249                if (id != XkbAllXIIds)
6250                    break;
6251            }
6252        }
6253    }
6254    if (length == wantLength)
6255        return Success;
6256    else
6257        return BadLength;
6258}
6259
6260int
6261ProcXkbGetDeviceInfo(ClientPtr client)
6262{
6263    DeviceIntPtr dev;
6264    xkbGetDeviceInfoReply rep;
6265    int status, nDeviceLedFBs;
6266    unsigned length, nameLen;
6267    CARD16 ledClass, ledID;
6268    unsigned wanted;
6269    char *str;
6270
6271    REQUEST(xkbGetDeviceInfoReq);
6272    REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq);
6273
6274    if (!(client->xkbClientFlags & _XkbClientInitialized))
6275        return BadAccess;
6276
6277    wanted = stuff->wanted;
6278
6279    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
6280    CHK_MASK_LEGAL(0x01, wanted, XkbXI_AllDeviceFeaturesMask);
6281
6282    if ((!dev->button) || ((stuff->nBtns < 1) && (!stuff->allBtns)))
6283        wanted &= ~XkbXI_ButtonActionsMask;
6284    if ((!dev->kbdfeed) && (!dev->leds))
6285        wanted &= ~XkbXI_IndicatorsMask;
6286
6287    nameLen = XkbSizeCountedString(dev->name);
6288    rep = (xkbGetDeviceInfoReply) {
6289        .type = X_Reply,
6290        .deviceID = dev->id,
6291        .sequenceNumber = client->sequence,
6292        .length = nameLen / 4,
6293        .present = wanted,
6294        .supported = XkbXI_AllDeviceFeaturesMask,
6295        .unsupported = 0,
6296        .nDeviceLedFBs = 0,
6297        .firstBtnWanted = 0,
6298        .nBtnsWanted = 0,
6299        .firstBtnRtrn = 0,
6300        .nBtnsRtrn = 0,
6301        .totalBtns = dev->button ? dev->button->numButtons : 0,
6302        .hasOwnState = (dev->key && dev->key->xkbInfo),
6303        .dfltKbdFB = dev->kbdfeed ? dev->kbdfeed->ctrl.id : XkbXINone,
6304        .dfltLedFB = dev->leds ? dev->leds->ctrl.id : XkbXINone,
6305        .devType = dev->xinput_type
6306    };
6307
6308    ledClass = stuff->ledClass;
6309    ledID = stuff->ledID;
6310
6311    if (wanted & XkbXI_ButtonActionsMask) {
6312        if (stuff->allBtns) {
6313            stuff->firstBtn = 0;
6314            stuff->nBtns = dev->button->numButtons;
6315        }
6316
6317        if ((stuff->firstBtn + stuff->nBtns) > dev->button->numButtons) {
6318            client->errorValue = _XkbErrCode4(0x02, dev->button->numButtons,
6319                                              stuff->firstBtn, stuff->nBtns);
6320            return BadValue;
6321        }
6322        else {
6323            rep.firstBtnWanted = stuff->firstBtn;
6324            rep.nBtnsWanted = stuff->nBtns;
6325            if (dev->button->xkb_acts != NULL) {
6326                XkbAction *act;
6327                register int i;
6328
6329                rep.firstBtnRtrn = stuff->firstBtn;
6330                rep.nBtnsRtrn = stuff->nBtns;
6331                act = &dev->button->xkb_acts[rep.firstBtnWanted];
6332                for (i = 0; i < rep.nBtnsRtrn; i++, act++) {
6333                    if (act->type != XkbSA_NoAction)
6334                        break;
6335                }
6336                rep.firstBtnRtrn += i;
6337                rep.nBtnsRtrn -= i;
6338                act =
6339                    &dev->button->xkb_acts[rep.firstBtnRtrn + rep.nBtnsRtrn -
6340                                           1];
6341                for (i = 0; i < rep.nBtnsRtrn; i++, act--) {
6342                    if (act->type != XkbSA_NoAction)
6343                        break;
6344                }
6345                rep.nBtnsRtrn -= i;
6346            }
6347            rep.length += (rep.nBtnsRtrn * SIZEOF(xkbActionWireDesc)) / 4;
6348        }
6349    }
6350
6351    if (wanted & XkbXI_IndicatorsMask) {
6352        status = CheckDeviceLedFBs(dev, ledClass, ledID, &rep, client);
6353        if (status != Success)
6354            return status;
6355    }
6356    length = rep.length * 4;
6357    nDeviceLedFBs = rep.nDeviceLedFBs;
6358    if (client->swapped) {
6359        swaps(&rep.sequenceNumber);
6360        swapl(&rep.length);
6361        swaps(&rep.present);
6362        swaps(&rep.supported);
6363        swaps(&rep.unsupported);
6364        swaps(&rep.nDeviceLedFBs);
6365        swaps(&rep.dfltKbdFB);
6366        swaps(&rep.dfltLedFB);
6367        swapl(&rep.devType);
6368    }
6369    WriteToClient(client, SIZEOF(xkbGetDeviceInfoReply), &rep);
6370
6371    str = malloc(nameLen);
6372    if (!str)
6373        return BadAlloc;
6374    XkbWriteCountedString(str, dev->name, client->swapped);
6375    WriteToClient(client, nameLen, str);
6376    free(str);
6377    length -= nameLen;
6378
6379    if (rep.nBtnsRtrn > 0) {
6380        int sz;
6381        xkbActionWireDesc *awire;
6382
6383        sz = rep.nBtnsRtrn * SIZEOF(xkbActionWireDesc);
6384        awire = (xkbActionWireDesc *) &dev->button->xkb_acts[rep.firstBtnRtrn];
6385        WriteToClient(client, sz, awire);
6386        length -= sz;
6387    }
6388    if (nDeviceLedFBs > 0) {
6389        status = SendDeviceLedFBs(dev, ledClass, ledID, length, client);
6390        if (status != Success)
6391            return status;
6392    }
6393    else if (length != 0) {
6394        ErrorF("[xkb] Internal Error!  BadLength in ProcXkbGetDeviceInfo\n");
6395        ErrorF("[xkb]                  Wrote %d fewer bytes than expected\n",
6396               length);
6397        return BadLength;
6398    }
6399    return Success;
6400}
6401
6402static char *
6403CheckSetDeviceIndicators(char *wire,
6404                         DeviceIntPtr dev,
6405                         int num, int *status_rtrn, ClientPtr client)
6406{
6407    xkbDeviceLedsWireDesc *ledWire;
6408    int i;
6409    XkbSrvLedInfoPtr sli;
6410
6411    ledWire = (xkbDeviceLedsWireDesc *) wire;
6412    for (i = 0; i < num; i++) {
6413        if (client->swapped) {
6414            swaps(&ledWire->ledClass);
6415            swaps(&ledWire->ledID);
6416            swapl(&ledWire->namesPresent);
6417            swapl(&ledWire->mapsPresent);
6418            swapl(&ledWire->physIndicators);
6419        }
6420
6421        sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID,
6422                                XkbXI_IndicatorsMask);
6423        if (sli != NULL) {
6424            register int n;
6425            register unsigned bit;
6426            int nMaps, nNames;
6427            CARD32 *atomWire;
6428            xkbIndicatorMapWireDesc *mapWire;
6429
6430            nMaps = nNames = 0;
6431            for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6432                if (ledWire->namesPresent & bit)
6433                    nNames++;
6434                if (ledWire->mapsPresent & bit)
6435                    nMaps++;
6436            }
6437            atomWire = (CARD32 *) &ledWire[1];
6438            if (nNames > 0) {
6439                for (n = 0; n < nNames; n++) {
6440                    if (client->swapped) {
6441                        swapl(atomWire);
6442                    }
6443                    CHK_ATOM_OR_NONE3(((Atom) (*atomWire)), client->errorValue,
6444                                      *status_rtrn, NULL);
6445                    atomWire++;
6446                }
6447            }
6448            mapWire = (xkbIndicatorMapWireDesc *) atomWire;
6449            if (nMaps > 0) {
6450                for (n = 0; n < nMaps; n++) {
6451                    if (client->swapped) {
6452                        swaps(&mapWire->virtualMods);
6453                        swapl(&mapWire->ctrls);
6454                    }
6455                    CHK_MASK_LEGAL3(0x21, mapWire->whichGroups,
6456                                    XkbIM_UseAnyGroup,
6457                                    client->errorValue, *status_rtrn, NULL);
6458                    CHK_MASK_LEGAL3(0x22, mapWire->whichMods, XkbIM_UseAnyMods,
6459                                    client->errorValue, *status_rtrn, NULL);
6460                    mapWire++;
6461                }
6462            }
6463            ledWire = (xkbDeviceLedsWireDesc *) mapWire;
6464        }
6465        else {
6466            /* SHOULD NEVER HAPPEN */
6467            return (char *) ledWire;
6468        }
6469    }
6470    return (char *) ledWire;
6471}
6472
6473static char *
6474SetDeviceIndicators(char *wire,
6475                    DeviceIntPtr dev,
6476                    unsigned changed,
6477                    int num,
6478                    int *status_rtrn,
6479                    ClientPtr client, xkbExtensionDeviceNotify * ev)
6480{
6481    xkbDeviceLedsWireDesc *ledWire;
6482    int i;
6483    XkbEventCauseRec cause;
6484    unsigned namec, mapc, statec;
6485    xkbExtensionDeviceNotify ed;
6486    XkbChangesRec changes;
6487    DeviceIntPtr kbd;
6488
6489    memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify));
6490    memset((char *) &changes, 0, sizeof(XkbChangesRec));
6491    XkbSetCauseXkbReq(&cause, X_kbSetDeviceInfo, client);
6492    ledWire = (xkbDeviceLedsWireDesc *) wire;
6493    for (i = 0; i < num; i++) {
6494        register int n;
6495        register unsigned bit;
6496        CARD32 *atomWire;
6497        xkbIndicatorMapWireDesc *mapWire;
6498        XkbSrvLedInfoPtr sli;
6499
6500        namec = mapc = statec = 0;
6501        sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID,
6502                                XkbXI_IndicatorMapsMask);
6503        if (!sli) {
6504            /* SHOULD NEVER HAPPEN!! */
6505            return (char *) ledWire;
6506        }
6507
6508        atomWire = (CARD32 *) &ledWire[1];
6509        if (changed & XkbXI_IndicatorNamesMask) {
6510            namec = sli->namesPresent | ledWire->namesPresent;
6511            memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom));
6512        }
6513        if (ledWire->namesPresent) {
6514            sli->namesPresent = ledWire->namesPresent;
6515            memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom));
6516            for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6517                if (ledWire->namesPresent & bit) {
6518                    sli->names[n] = (Atom) *atomWire;
6519                    if (sli->names[n] == None)
6520                        ledWire->namesPresent &= ~bit;
6521                    atomWire++;
6522                }
6523            }
6524        }
6525        mapWire = (xkbIndicatorMapWireDesc *) atomWire;
6526        if (changed & XkbXI_IndicatorMapsMask) {
6527            mapc = sli->mapsPresent | ledWire->mapsPresent;
6528            sli->mapsPresent = ledWire->mapsPresent;
6529            memset((char *) sli->maps, 0,
6530                   XkbNumIndicators * sizeof(XkbIndicatorMapRec));
6531        }
6532        if (ledWire->mapsPresent) {
6533            for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6534                if (ledWire->mapsPresent & bit) {
6535                    sli->maps[n].flags = mapWire->flags;
6536                    sli->maps[n].which_groups = mapWire->whichGroups;
6537                    sli->maps[n].groups = mapWire->groups;
6538                    sli->maps[n].which_mods = mapWire->whichMods;
6539                    sli->maps[n].mods.mask = mapWire->mods;
6540                    sli->maps[n].mods.real_mods = mapWire->realMods;
6541                    sli->maps[n].mods.vmods = mapWire->virtualMods;
6542                    sli->maps[n].ctrls = mapWire->ctrls;
6543                    mapWire++;
6544                }
6545            }
6546        }
6547        if (changed & XkbXI_IndicatorStateMask) {
6548            statec = sli->effectiveState ^ ledWire->state;
6549            sli->explicitState &= ~statec;
6550            sli->explicitState |= (ledWire->state & statec);
6551        }
6552        if (namec)
6553            XkbApplyLedNameChanges(dev, sli, namec, &ed, &changes, &cause);
6554        if (mapc)
6555            XkbApplyLedMapChanges(dev, sli, mapc, &ed, &changes, &cause);
6556        if (statec)
6557            XkbApplyLedStateChanges(dev, sli, statec, &ed, &changes, &cause);
6558
6559        kbd = dev;
6560        if ((sli->flags & XkbSLI_HasOwnState) == 0)
6561            kbd = inputInfo.keyboard;
6562
6563        XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause);
6564        ledWire = (xkbDeviceLedsWireDesc *) mapWire;
6565    }
6566    return (char *) ledWire;
6567}
6568
6569static int
6570_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev,
6571                  xkbSetDeviceInfoReq * stuff)
6572{
6573    char *wire;
6574
6575    wire = (char *) &stuff[1];
6576    if (stuff->change & XkbXI_ButtonActionsMask) {
6577        if (!dev->button) {
6578            client->errorValue = _XkbErrCode2(XkbErr_BadClass, ButtonClass);
6579            return XkbKeyboardErrorCode;
6580        }
6581        if ((stuff->firstBtn + stuff->nBtns) > dev->button->numButtons) {
6582            client->errorValue =
6583                _XkbErrCode4(0x02, stuff->firstBtn, stuff->nBtns,
6584                             dev->button->numButtons);
6585            return BadMatch;
6586        }
6587        wire += (stuff->nBtns * SIZEOF(xkbActionWireDesc));
6588    }
6589    if (stuff->change & XkbXI_IndicatorsMask) {
6590        int status = Success;
6591
6592        wire = CheckSetDeviceIndicators(wire, dev, stuff->nDeviceLedFBs,
6593                                        &status, client);
6594        if (status != Success)
6595            return status;
6596    }
6597    if (((wire - ((char *) stuff)) / 4) != stuff->length)
6598        return BadLength;
6599
6600    return Success;
6601}
6602
6603static int
6604_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev,
6605                       xkbSetDeviceInfoReq * stuff)
6606{
6607    char *wire;
6608    xkbExtensionDeviceNotify ed;
6609
6610    memset((char *) &ed, 0, SIZEOF(xkbExtensionDeviceNotify));
6611    ed.deviceID = dev->id;
6612    wire = (char *) &stuff[1];
6613    if (stuff->change & XkbXI_ButtonActionsMask) {
6614        int nBtns, sz, i;
6615        XkbAction *acts;
6616        DeviceIntPtr kbd;
6617
6618        nBtns = dev->button->numButtons;
6619        acts = dev->button->xkb_acts;
6620        if (acts == NULL) {
6621            acts = calloc(nBtns, sizeof(XkbAction));
6622            if (!acts)
6623                return BadAlloc;
6624            dev->button->xkb_acts = acts;
6625        }
6626        sz = stuff->nBtns * SIZEOF(xkbActionWireDesc);
6627        memcpy((char *) &acts[stuff->firstBtn], (char *) wire, sz);
6628        wire += sz;
6629        ed.reason |= XkbXI_ButtonActionsMask;
6630        ed.firstBtn = stuff->firstBtn;
6631        ed.nBtns = stuff->nBtns;
6632
6633        if (dev->key)
6634            kbd = dev;
6635        else
6636            kbd = inputInfo.keyboard;
6637        acts = &dev->button->xkb_acts[stuff->firstBtn];
6638        for (i = 0; i < stuff->nBtns; i++, acts++) {
6639            if (acts->type != XkbSA_NoAction)
6640                XkbSetActionKeyMods(kbd->key->xkbInfo->desc, acts, 0);
6641        }
6642    }
6643    if (stuff->change & XkbXI_IndicatorsMask) {
6644        int status = Success;
6645
6646        wire = SetDeviceIndicators(wire, dev, stuff->change,
6647                                   stuff->nDeviceLedFBs, &status, client, &ed);
6648        if (status != Success)
6649            return status;
6650    }
6651    if ((stuff->change) && (ed.reason))
6652        XkbSendExtensionDeviceNotify(dev, client, &ed);
6653    return Success;
6654}
6655
6656int
6657ProcXkbSetDeviceInfo(ClientPtr client)
6658{
6659    DeviceIntPtr dev;
6660    int rc;
6661
6662    REQUEST(xkbSetDeviceInfoReq);
6663    REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq);
6664
6665    if (!(client->xkbClientFlags & _XkbClientInitialized))
6666        return BadAccess;
6667
6668    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
6669    CHK_MASK_LEGAL(0x01, stuff->change, XkbXI_AllFeaturesMask);
6670
6671    rc = _XkbSetDeviceInfoCheck(client, dev, stuff);
6672
6673    if (rc != Success)
6674        return rc;
6675
6676    if (stuff->deviceSpec == XkbUseCoreKbd ||
6677        stuff->deviceSpec == XkbUseCorePtr) {
6678        DeviceIntPtr other;
6679
6680        for (other = inputInfo.devices; other; other = other->next) {
6681            if (((other != dev) && !IsMaster(other) &&
6682                 GetMaster(other, MASTER_KEYBOARD) == dev) &&
6683                ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
6684                 (stuff->deviceSpec == XkbUseCorePtr && other->button))) {
6685                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
6686                              DixManageAccess);
6687                if (rc == Success) {
6688                    rc = _XkbSetDeviceInfoCheck(client, other, stuff);
6689                    if (rc != Success)
6690                        return rc;
6691                }
6692            }
6693        }
6694    }
6695
6696    /* checks done, apply */
6697    rc = _XkbSetDeviceInfo(client, dev, stuff);
6698    if (rc != Success)
6699        return rc;
6700
6701    if (stuff->deviceSpec == XkbUseCoreKbd ||
6702        stuff->deviceSpec == XkbUseCorePtr) {
6703        DeviceIntPtr other;
6704
6705        for (other = inputInfo.devices; other; other = other->next) {
6706            if (((other != dev) && !IsMaster(other) &&
6707                 GetMaster(other, MASTER_KEYBOARD) == dev) &&
6708                ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
6709                 (stuff->deviceSpec == XkbUseCorePtr && other->button))) {
6710                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
6711                              DixManageAccess);
6712                if (rc == Success) {
6713                    rc = _XkbSetDeviceInfo(client, other, stuff);
6714                    if (rc != Success)
6715                        return rc;
6716                }
6717            }
6718        }
6719    }
6720
6721    return Success;
6722}
6723
6724/***====================================================================***/
6725
6726int
6727ProcXkbSetDebuggingFlags(ClientPtr client)
6728{
6729    CARD32 newFlags, newCtrls, extraLength;
6730    xkbSetDebuggingFlagsReply rep;
6731    int rc;
6732
6733    REQUEST(xkbSetDebuggingFlagsReq);
6734    REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq);
6735
6736    rc = XaceHook(XACE_SERVER_ACCESS, client, DixDebugAccess);
6737    if (rc != Success)
6738        return rc;
6739
6740    newFlags = xkbDebugFlags & (~stuff->affectFlags);
6741    newFlags |= (stuff->flags & stuff->affectFlags);
6742    newCtrls = xkbDebugCtrls & (~stuff->affectCtrls);
6743    newCtrls |= (stuff->ctrls & stuff->affectCtrls);
6744    if (xkbDebugFlags || newFlags || stuff->msgLength) {
6745        ErrorF("[xkb] XkbDebug: Setting debug flags to 0x%lx\n",
6746               (long) newFlags);
6747        if (newCtrls != xkbDebugCtrls)
6748            ErrorF("[xkb] XkbDebug: Setting debug controls to 0x%lx\n",
6749                   (long) newCtrls);
6750    }
6751    extraLength = (stuff->length << 2) - sz_xkbSetDebuggingFlagsReq;
6752    if (stuff->msgLength > 0) {
6753        char *msg;
6754
6755        if (extraLength < XkbPaddedSize(stuff->msgLength)) {
6756            ErrorF
6757                ("[xkb] XkbDebug: msgLength= %d, length= %ld (should be %d)\n",
6758                 stuff->msgLength, (long) extraLength,
6759                 XkbPaddedSize(stuff->msgLength));
6760            return BadLength;
6761        }
6762        msg = (char *) &stuff[1];
6763        if (msg[stuff->msgLength - 1] != '\0') {
6764            ErrorF("[xkb] XkbDebug: message not null-terminated\n");
6765            return BadValue;
6766        }
6767        ErrorF("[xkb] XkbDebug: %s\n", msg);
6768    }
6769    xkbDebugFlags = newFlags;
6770    xkbDebugCtrls = newCtrls;
6771
6772    rep = (xkbSetDebuggingFlagsReply) {
6773        .type = X_Reply,
6774        .sequenceNumber = client->sequence,
6775        .length = 0,
6776        .currentFlags = newFlags,
6777        .currentCtrls = newCtrls,
6778        .supportedFlags = ~0,
6779        .supportedCtrls = ~0
6780    };
6781    if (client->swapped) {
6782        swaps(&rep.sequenceNumber);
6783        swapl(&rep.currentFlags);
6784        swapl(&rep.currentCtrls);
6785        swapl(&rep.supportedFlags);
6786        swapl(&rep.supportedCtrls);
6787    }
6788    WriteToClient(client, SIZEOF(xkbSetDebuggingFlagsReply), &rep);
6789    return Success;
6790}
6791
6792/***====================================================================***/
6793
6794static int
6795ProcXkbDispatch(ClientPtr client)
6796{
6797    REQUEST(xReq);
6798    switch (stuff->data) {
6799    case X_kbUseExtension:
6800        return ProcXkbUseExtension(client);
6801    case X_kbSelectEvents:
6802        return ProcXkbSelectEvents(client);
6803    case X_kbBell:
6804        return ProcXkbBell(client);
6805    case X_kbGetState:
6806        return ProcXkbGetState(client);
6807    case X_kbLatchLockState:
6808        return ProcXkbLatchLockState(client);
6809    case X_kbGetControls:
6810        return ProcXkbGetControls(client);
6811    case X_kbSetControls:
6812        return ProcXkbSetControls(client);
6813    case X_kbGetMap:
6814        return ProcXkbGetMap(client);
6815    case X_kbSetMap:
6816        return ProcXkbSetMap(client);
6817    case X_kbGetCompatMap:
6818        return ProcXkbGetCompatMap(client);
6819    case X_kbSetCompatMap:
6820        return ProcXkbSetCompatMap(client);
6821    case X_kbGetIndicatorState:
6822        return ProcXkbGetIndicatorState(client);
6823    case X_kbGetIndicatorMap:
6824        return ProcXkbGetIndicatorMap(client);
6825    case X_kbSetIndicatorMap:
6826        return ProcXkbSetIndicatorMap(client);
6827    case X_kbGetNamedIndicator:
6828        return ProcXkbGetNamedIndicator(client);
6829    case X_kbSetNamedIndicator:
6830        return ProcXkbSetNamedIndicator(client);
6831    case X_kbGetNames:
6832        return ProcXkbGetNames(client);
6833    case X_kbSetNames:
6834        return ProcXkbSetNames(client);
6835    case X_kbGetGeometry:
6836        return ProcXkbGetGeometry(client);
6837    case X_kbSetGeometry:
6838        return ProcXkbSetGeometry(client);
6839    case X_kbPerClientFlags:
6840        return ProcXkbPerClientFlags(client);
6841    case X_kbListComponents:
6842        return ProcXkbListComponents(client);
6843    case X_kbGetKbdByName:
6844        return ProcXkbGetKbdByName(client);
6845    case X_kbGetDeviceInfo:
6846        return ProcXkbGetDeviceInfo(client);
6847    case X_kbSetDeviceInfo:
6848        return ProcXkbSetDeviceInfo(client);
6849    case X_kbSetDebuggingFlags:
6850        return ProcXkbSetDebuggingFlags(client);
6851    default:
6852        return BadRequest;
6853    }
6854}
6855
6856static int
6857XkbClientGone(void *data, XID id)
6858{
6859    DevicePtr pXDev = (DevicePtr) data;
6860
6861    if (!XkbRemoveResourceClient(pXDev, id)) {
6862        ErrorF
6863            ("[xkb] Internal Error! bad RemoveResourceClient in XkbClientGone\n");
6864    }
6865    return 1;
6866}
6867
6868void
6869XkbExtensionInit(void)
6870{
6871    ExtensionEntry *extEntry;
6872
6873    RT_XKBCLIENT = CreateNewResourceType(XkbClientGone, "XkbClient");
6874    if (!RT_XKBCLIENT)
6875        return;
6876
6877    if (!XkbInitPrivates())
6878        return;
6879
6880    if ((extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors,
6881                                 ProcXkbDispatch, SProcXkbDispatch,
6882                                 NULL, StandardMinorOpcode))) {
6883        XkbReqCode = (unsigned char) extEntry->base;
6884        XkbEventBase = (unsigned char) extEntry->eventBase;
6885        XkbErrorBase = (unsigned char) extEntry->errorBase;
6886        XkbKeyboardErrorCode = XkbErrorBase + XkbKeyboard;
6887    }
6888    return;
6889}
6890