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