xkb.c revision f7df2e56
105b261ecSmrg/************************************************************
205b261ecSmrgCopyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
305b261ecSmrg
405b261ecSmrgPermission to use, copy, modify, and distribute this
505b261ecSmrgsoftware and its documentation for any purpose and without
605b261ecSmrgfee is hereby granted, provided that the above copyright
705b261ecSmrgnotice appear in all copies and that both that copyright
805b261ecSmrgnotice and this permission notice appear in supporting
9f7df2e56Smrgdocumentation, and that the name of Silicon Graphics not be
10f7df2e56Smrgused in advertising or publicity pertaining to distribution
1105b261ecSmrgof the software without specific prior written permission.
12f7df2e56SmrgSilicon Graphics makes no representation about the suitability
1305b261ecSmrgof this software for any purpose. It is provided "as is"
1405b261ecSmrgwithout any express or implied warranty.
1505b261ecSmrg
16f7df2e56SmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17f7df2e56SmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1805b261ecSmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19f7df2e56SmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20f7df2e56SmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21f7df2e56SmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
2205b261ecSmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
2305b261ecSmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE.
2405b261ecSmrg
2505b261ecSmrg********************************************************/
2605b261ecSmrg
2705b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
2805b261ecSmrg#include <dix-config.h>
2905b261ecSmrg#endif
3005b261ecSmrg
3105b261ecSmrg#include <stdio.h>
3205b261ecSmrg#include <X11/X.h>
3305b261ecSmrg#include <X11/Xproto.h>
3405b261ecSmrg#include "misc.h"
3505b261ecSmrg#include "inputstr.h"
3605b261ecSmrg#define	XKBSRV_NEED_FILE_FUNCS
3705b261ecSmrg#include <xkbsrv.h>
3805b261ecSmrg#include "extnsionst.h"
39f7df2e56Smrg#include "extinit.h"
404642e01fSmrg#include "xace.h"
4105b261ecSmrg#include "xkb.h"
426747b715Smrg#include "protocol-versions.h"
4305b261ecSmrg
4405b261ecSmrg#include <X11/extensions/XI.h>
456747b715Smrg#include <X11/extensions/XKMformat.h>
4605b261ecSmrg
47f7df2e56Smrgint XkbEventBase;
48f7df2e56Smrgstatic int XkbErrorBase;
49f7df2e56Smrgint XkbReqCode;
50f7df2e56Smrgint XkbKeyboardErrorCode;
51f7df2e56SmrgCARD32 xkbDebugFlags = 0;
52f7df2e56Smrgstatic CARD32 xkbDebugCtrls = 0;
5305b261ecSmrg
54f7df2e56Smrgstatic RESTYPE RT_XKBCLIENT;
5505b261ecSmrg
5605b261ecSmrg/***====================================================================***/
5705b261ecSmrg
584642e01fSmrg#define	CHK_DEVICE(dev, id, client, access_mode, lf) {\
5905b261ecSmrg    int why;\
60f7df2e56Smrg    int tmprc = lf(&(dev), id, client, access_mode, &why);\
61f7df2e56Smrg    if (tmprc != Success) {\
624642e01fSmrg	client->errorValue = _XkbErrCode2(why, id);\
63f7df2e56Smrg	return tmprc;\
6405b261ecSmrg    }\
6505b261ecSmrg}
6605b261ecSmrg
674642e01fSmrg#define	CHK_KBD_DEVICE(dev, id, client, mode) \
684642e01fSmrg    CHK_DEVICE(dev, id, client, mode, _XkbLookupKeyboard)
694642e01fSmrg#define	CHK_LED_DEVICE(dev, id, client, mode) \
704642e01fSmrg    CHK_DEVICE(dev, id, client, mode, _XkbLookupLedDevice)
714642e01fSmrg#define	CHK_BELL_DEVICE(dev, id, client, mode) \
724642e01fSmrg    CHK_DEVICE(dev, id, client, mode, _XkbLookupBellDevice)
734642e01fSmrg#define	CHK_ANY_DEVICE(dev, id, client, mode) \
744642e01fSmrg    CHK_DEVICE(dev, id, client, mode, _XkbLookupAnyDevice)
7505b261ecSmrg
7605b261ecSmrg#define	CHK_ATOM_ONLY2(a,ev,er) {\
7705b261ecSmrg	if (((a)==None)||(!ValidAtom((a)))) {\
7805b261ecSmrg	    (ev)= (XID)(a);\
7905b261ecSmrg	    return er;\
8005b261ecSmrg	}\
8105b261ecSmrg}
8205b261ecSmrg#define	CHK_ATOM_ONLY(a) \
8305b261ecSmrg	CHK_ATOM_ONLY2(a,client->errorValue,BadAtom)
8405b261ecSmrg
8505b261ecSmrg#define	CHK_ATOM_OR_NONE3(a,ev,er,ret) {\
8605b261ecSmrg	if (((a)!=None)&&(!ValidAtom((a)))) {\
8705b261ecSmrg	    (ev)= (XID)(a);\
8805b261ecSmrg	    (er)= BadAtom;\
8905b261ecSmrg	    return ret;\
9005b261ecSmrg	}\
9105b261ecSmrg}
9205b261ecSmrg#define	CHK_ATOM_OR_NONE2(a,ev,er) {\
9305b261ecSmrg	if (((a)!=None)&&(!ValidAtom((a)))) {\
9405b261ecSmrg	    (ev)= (XID)(a);\
9505b261ecSmrg	    return er;\
9605b261ecSmrg	}\
9705b261ecSmrg}
9805b261ecSmrg#define	CHK_ATOM_OR_NONE(a) \
9905b261ecSmrg	CHK_ATOM_OR_NONE2(a,client->errorValue,BadAtom)
10005b261ecSmrg
10105b261ecSmrg#define	CHK_MASK_LEGAL3(err,mask,legal,ev,er,ret)	{\
10205b261ecSmrg	if ((mask)&(~(legal))) { \
10305b261ecSmrg	    (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\
10405b261ecSmrg	    (er)= BadValue;\
10505b261ecSmrg	    return ret;\
10605b261ecSmrg	}\
10705b261ecSmrg}
10805b261ecSmrg#define	CHK_MASK_LEGAL2(err,mask,legal,ev,er)	{\
10905b261ecSmrg	if ((mask)&(~(legal))) { \
11005b261ecSmrg	    (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\
11105b261ecSmrg	    return er;\
11205b261ecSmrg	}\
11305b261ecSmrg}
11405b261ecSmrg#define	CHK_MASK_LEGAL(err,mask,legal) \
11505b261ecSmrg	CHK_MASK_LEGAL2(err,mask,legal,client->errorValue,BadValue)
11605b261ecSmrg
11705b261ecSmrg#define	CHK_MASK_MATCH(err,affect,value) {\
11805b261ecSmrg	if ((value)&(~(affect))) { \
11905b261ecSmrg	    client->errorValue= _XkbErrCode2((err),((value)&(~(affect))));\
12005b261ecSmrg	    return BadMatch;\
12105b261ecSmrg	}\
12205b261ecSmrg}
12305b261ecSmrg#define	CHK_MASK_OVERLAP(err,m1,m2) {\
12405b261ecSmrg	if ((m1)&(m2)) { \
12505b261ecSmrg	    client->errorValue= _XkbErrCode2((err),((m1)&(m2)));\
12605b261ecSmrg	    return BadMatch;\
12705b261ecSmrg	}\
12805b261ecSmrg}
12905b261ecSmrg#define	CHK_KEY_RANGE2(err,first,num,x,ev,er) {\
13005b261ecSmrg	if (((unsigned)(first)+(num)-1)>(x)->max_key_code) {\
13105b261ecSmrg	    (ev)=_XkbErrCode4(err,(first),(num),(x)->max_key_code);\
13205b261ecSmrg	    return er;\
13305b261ecSmrg	}\
13405b261ecSmrg	else if ( (first)<(x)->min_key_code ) {\
13505b261ecSmrg	    (ev)=_XkbErrCode3(err+1,(first),xkb->min_key_code);\
13605b261ecSmrg	    return er;\
13705b261ecSmrg	}\
13805b261ecSmrg}
13905b261ecSmrg#define	CHK_KEY_RANGE(err,first,num,x)  \
14005b261ecSmrg	CHK_KEY_RANGE2(err,first,num,x,client->errorValue,BadValue)
14105b261ecSmrg
14205b261ecSmrg#define	CHK_REQ_KEY_RANGE2(err,first,num,r,ev,er) {\
14305b261ecSmrg	if (((unsigned)(first)+(num)-1)>(r)->maxKeyCode) {\
14405b261ecSmrg	    (ev)=_XkbErrCode4(err,(first),(num),(r)->maxKeyCode);\
14505b261ecSmrg	    return er;\
14605b261ecSmrg	}\
14705b261ecSmrg	else if ( (first)<(r)->minKeyCode ) {\
14805b261ecSmrg	    (ev)=_XkbErrCode3(err+1,(first),(r)->minKeyCode);\
14905b261ecSmrg	    return er;\
15005b261ecSmrg	}\
15105b261ecSmrg}
15205b261ecSmrg#define	CHK_REQ_KEY_RANGE(err,first,num,r)  \
15305b261ecSmrg	CHK_REQ_KEY_RANGE2(err,first,num,r,client->errorValue,BadValue)
15405b261ecSmrg
15505b261ecSmrg/***====================================================================***/
15605b261ecSmrg
15705b261ecSmrgint
15805b261ecSmrgProcXkbUseExtension(ClientPtr client)
15905b261ecSmrg{
16005b261ecSmrg    REQUEST(xkbUseExtensionReq);
161f7df2e56Smrg    xkbUseExtensionReply rep;
162f7df2e56Smrg    int supported;
16305b261ecSmrg
16405b261ecSmrg    REQUEST_SIZE_MATCH(xkbUseExtensionReq);
1656747b715Smrg    if (stuff->wantedMajor != SERVER_XKB_MAJOR_VERSION) {
166f7df2e56Smrg        /* pre-release version 0.65 is compatible with 1.00 */
167f7df2e56Smrg        supported = ((SERVER_XKB_MAJOR_VERSION == 1) &&
168f7df2e56Smrg                     (stuff->wantedMajor == 0) && (stuff->wantedMinor == 65));
169f7df2e56Smrg    }
170f7df2e56Smrg    else
171f7df2e56Smrg        supported = 1;
172f7df2e56Smrg
173f7df2e56Smrg    if ((supported) && (!(client->xkbClientFlags & _XkbClientInitialized))) {
174f7df2e56Smrg        client->xkbClientFlags = _XkbClientInitialized;
175f7df2e56Smrg        client->vMajor = stuff->wantedMajor;
176f7df2e56Smrg        client->vMinor = stuff->wantedMinor;
177f7df2e56Smrg    }
178f7df2e56Smrg    else if (xkbDebugFlags & 0x1) {
179f7df2e56Smrg        ErrorF
180f7df2e56Smrg            ("[xkb] Rejecting client %d (0x%lx) (wants %d.%02d, have %d.%02d)\n",
181f7df2e56Smrg             client->index, (long) client->clientAsMask, stuff->wantedMajor,
182f7df2e56Smrg             stuff->wantedMinor, SERVER_XKB_MAJOR_VERSION,
183f7df2e56Smrg             SERVER_XKB_MINOR_VERSION);
184f7df2e56Smrg    }
185f7df2e56Smrg    rep = (xkbUseExtensionReply) {
186f7df2e56Smrg        .type = X_Reply,
187f7df2e56Smrg        .supported = supported,
188f7df2e56Smrg        .sequenceNumber = client->sequence,
189f7df2e56Smrg        .length = 0,
190f7df2e56Smrg        .serverMajor = SERVER_XKB_MAJOR_VERSION,
191f7df2e56Smrg        .serverMinor = SERVER_XKB_MINOR_VERSION
192f7df2e56Smrg    };
193f7df2e56Smrg    if (client->swapped) {
194f7df2e56Smrg        swaps(&rep.sequenceNumber);
195f7df2e56Smrg        swaps(&rep.serverMajor);
196f7df2e56Smrg        swaps(&rep.serverMinor);
19705b261ecSmrg    }
198f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbUseExtensionReply), &rep);
1996747b715Smrg    return Success;
20005b261ecSmrg}
20105b261ecSmrg
20205b261ecSmrg/***====================================================================***/
20305b261ecSmrg
20405b261ecSmrgint
20505b261ecSmrgProcXkbSelectEvents(ClientPtr client)
20605b261ecSmrg{
207f7df2e56Smrg    unsigned legal;
208f7df2e56Smrg    DeviceIntPtr dev;
209f7df2e56Smrg    XkbInterestPtr masks;
210f7df2e56Smrg
21105b261ecSmrg    REQUEST(xkbSelectEventsReq);
21205b261ecSmrg
21305b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSelectEventsReq);
21405b261ecSmrg
215f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
216f7df2e56Smrg        return BadAccess;
21705b261ecSmrg
2184642e01fSmrg    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixUseAccess);
21905b261ecSmrg
220f7df2e56Smrg    if (((stuff->affectWhich & XkbMapNotifyMask) != 0) && (stuff->affectMap)) {
221f7df2e56Smrg        client->mapNotifyMask &= ~stuff->affectMap;
222f7df2e56Smrg        client->mapNotifyMask |= (stuff->affectMap & stuff->map);
22305b261ecSmrg    }
224f7df2e56Smrg    if ((stuff->affectWhich & (~XkbMapNotifyMask)) == 0)
225f7df2e56Smrg        return Success;
226f7df2e56Smrg
227f7df2e56Smrg    masks = XkbFindClientResource((DevicePtr) dev, client);
228f7df2e56Smrg    if (!masks) {
229f7df2e56Smrg        XID id = FakeClientID(client->index);
23005b261ecSmrg
231f7df2e56Smrg        if (!AddResource(id, RT_XKBCLIENT, dev))
232f7df2e56Smrg            return BadAlloc;
233f7df2e56Smrg        masks = XkbAddClientResource((DevicePtr) dev, client, id);
23405b261ecSmrg    }
23505b261ecSmrg    if (masks) {
236f7df2e56Smrg        union {
237f7df2e56Smrg            CARD8 *c8;
238f7df2e56Smrg            CARD16 *c16;
239f7df2e56Smrg            CARD32 *c32;
240f7df2e56Smrg        } from, to;
241f7df2e56Smrg        register unsigned bit, ndx, maskLeft, dataLeft, size;
242f7df2e56Smrg
243f7df2e56Smrg        from.c8 = (CARD8 *) &stuff[1];
244f7df2e56Smrg        dataLeft = (stuff->length * 4) - SIZEOF(xkbSelectEventsReq);
245f7df2e56Smrg        maskLeft = (stuff->affectWhich & (~XkbMapNotifyMask));
246f7df2e56Smrg        for (ndx = 0, bit = 1; (maskLeft != 0); ndx++, bit <<= 1) {
247f7df2e56Smrg            if ((bit & maskLeft) == 0)
248f7df2e56Smrg                continue;
249f7df2e56Smrg            maskLeft &= ~bit;
250f7df2e56Smrg            switch (ndx) {
251f7df2e56Smrg            case XkbNewKeyboardNotify:
252f7df2e56Smrg                to.c16 = &client->newKeyboardNotifyMask;
253f7df2e56Smrg                legal = XkbAllNewKeyboardEventsMask;
254f7df2e56Smrg                size = 2;
255f7df2e56Smrg                break;
256f7df2e56Smrg            case XkbStateNotify:
257f7df2e56Smrg                to.c16 = &masks->stateNotifyMask;
258f7df2e56Smrg                legal = XkbAllStateEventsMask;
259f7df2e56Smrg                size = 2;
260f7df2e56Smrg                break;
261f7df2e56Smrg            case XkbControlsNotify:
262f7df2e56Smrg                to.c32 = &masks->ctrlsNotifyMask;
263f7df2e56Smrg                legal = XkbAllControlEventsMask;
264f7df2e56Smrg                size = 4;
265f7df2e56Smrg                break;
266f7df2e56Smrg            case XkbIndicatorStateNotify:
267f7df2e56Smrg                to.c32 = &masks->iStateNotifyMask;
268f7df2e56Smrg                legal = XkbAllIndicatorEventsMask;
269f7df2e56Smrg                size = 4;
270f7df2e56Smrg                break;
271f7df2e56Smrg            case XkbIndicatorMapNotify:
272f7df2e56Smrg                to.c32 = &masks->iMapNotifyMask;
273f7df2e56Smrg                legal = XkbAllIndicatorEventsMask;
274f7df2e56Smrg                size = 4;
275f7df2e56Smrg                break;
276f7df2e56Smrg            case XkbNamesNotify:
277f7df2e56Smrg                to.c16 = &masks->namesNotifyMask;
278f7df2e56Smrg                legal = XkbAllNameEventsMask;
279f7df2e56Smrg                size = 2;
280f7df2e56Smrg                break;
281f7df2e56Smrg            case XkbCompatMapNotify:
282f7df2e56Smrg                to.c8 = &masks->compatNotifyMask;
283f7df2e56Smrg                legal = XkbAllCompatMapEventsMask;
284f7df2e56Smrg                size = 1;
285f7df2e56Smrg                break;
286f7df2e56Smrg            case XkbBellNotify:
287f7df2e56Smrg                to.c8 = &masks->bellNotifyMask;
288f7df2e56Smrg                legal = XkbAllBellEventsMask;
289f7df2e56Smrg                size = 1;
290f7df2e56Smrg                break;
291f7df2e56Smrg            case XkbActionMessage:
292f7df2e56Smrg                to.c8 = &masks->actionMessageMask;
293f7df2e56Smrg                legal = XkbAllActionMessagesMask;
294f7df2e56Smrg                size = 1;
295f7df2e56Smrg                break;
296f7df2e56Smrg            case XkbAccessXNotify:
297f7df2e56Smrg                to.c16 = &masks->accessXNotifyMask;
298f7df2e56Smrg                legal = XkbAllAccessXEventsMask;
299f7df2e56Smrg                size = 2;
300f7df2e56Smrg                break;
301f7df2e56Smrg            case XkbExtensionDeviceNotify:
302f7df2e56Smrg                to.c16 = &masks->extDevNotifyMask;
303f7df2e56Smrg                legal = XkbAllExtensionDeviceEventsMask;
304f7df2e56Smrg                size = 2;
305f7df2e56Smrg                break;
306f7df2e56Smrg            default:
307f7df2e56Smrg                client->errorValue = _XkbErrCode2(33, bit);
308f7df2e56Smrg                return BadValue;
309f7df2e56Smrg            }
310f7df2e56Smrg
311f7df2e56Smrg            if (stuff->clear & bit) {
312f7df2e56Smrg                if (size == 2)
313f7df2e56Smrg                    to.c16[0] = 0;
314f7df2e56Smrg                else if (size == 4)
315f7df2e56Smrg                    to.c32[0] = 0;
316f7df2e56Smrg                else
317f7df2e56Smrg                    to.c8[0] = 0;
318f7df2e56Smrg            }
319f7df2e56Smrg            else if (stuff->selectAll & bit) {
320f7df2e56Smrg                if (size == 2)
321f7df2e56Smrg                    to.c16[0] = ~0;
322f7df2e56Smrg                else if (size == 4)
323f7df2e56Smrg                    to.c32[0] = ~0;
324f7df2e56Smrg                else
325f7df2e56Smrg                    to.c8[0] = ~0;
326f7df2e56Smrg            }
327f7df2e56Smrg            else {
328f7df2e56Smrg                if (dataLeft < (size * 2))
329f7df2e56Smrg                    return BadLength;
330f7df2e56Smrg                if (size == 2) {
331f7df2e56Smrg                    CHK_MASK_MATCH(ndx, from.c16[0], from.c16[1]);
332f7df2e56Smrg                    CHK_MASK_LEGAL(ndx, from.c16[0], legal);
333f7df2e56Smrg                    to.c16[0] &= ~from.c16[0];
334f7df2e56Smrg                    to.c16[0] |= (from.c16[0] & from.c16[1]);
335f7df2e56Smrg                }
336f7df2e56Smrg                else if (size == 4) {
337f7df2e56Smrg                    CHK_MASK_MATCH(ndx, from.c32[0], from.c32[1]);
338f7df2e56Smrg                    CHK_MASK_LEGAL(ndx, from.c32[0], legal);
339f7df2e56Smrg                    to.c32[0] &= ~from.c32[0];
340f7df2e56Smrg                    to.c32[0] |= (from.c32[0] & from.c32[1]);
341f7df2e56Smrg                }
342f7df2e56Smrg                else {
343f7df2e56Smrg                    CHK_MASK_MATCH(ndx, from.c8[0], from.c8[1]);
344f7df2e56Smrg                    CHK_MASK_LEGAL(ndx, from.c8[0], legal);
345f7df2e56Smrg                    to.c8[0] &= ~from.c8[0];
346f7df2e56Smrg                    to.c8[0] |= (from.c8[0] & from.c8[1]);
347f7df2e56Smrg                    size = 2;
348f7df2e56Smrg                }
349f7df2e56Smrg                from.c8 += (size * 2);
350f7df2e56Smrg                dataLeft -= (size * 2);
351f7df2e56Smrg            }
352f7df2e56Smrg        }
353f7df2e56Smrg        if (dataLeft > 2) {
354f7df2e56Smrg            ErrorF("[xkb] Extra data (%d bytes) after SelectEvents\n",
355f7df2e56Smrg                   dataLeft);
356f7df2e56Smrg            return BadLength;
357f7df2e56Smrg        }
358f7df2e56Smrg        return Success;
35905b261ecSmrg    }
36005b261ecSmrg    return BadAlloc;
36105b261ecSmrg}
36205b261ecSmrg
36305b261ecSmrg/***====================================================================***/
3644642e01fSmrg/**
3654642e01fSmrg * Ring a bell on the given device for the given client.
3664642e01fSmrg */
3674642e01fSmrgstatic int
3684642e01fSmrg_XkbBell(ClientPtr client, DeviceIntPtr dev, WindowPtr pWin,
3694642e01fSmrg         int bellClass, int bellID, int pitch, int duration,
3704642e01fSmrg         int percent, int forceSound, int eventOnly, Atom name)
3714642e01fSmrg{
372f7df2e56Smrg    int base;
373f7df2e56Smrg    void *ctrl;
374f7df2e56Smrg    int oldPitch, oldDuration;
375f7df2e56Smrg    int newPercent;
3764642e01fSmrg
3774642e01fSmrg    if (bellClass == KbdFeedbackClass) {
378f7df2e56Smrg        KbdFeedbackPtr k;
379f7df2e56Smrg
380f7df2e56Smrg        if (bellID == XkbDfltXIId)
381f7df2e56Smrg            k = dev->kbdfeed;
3824642e01fSmrg        else {
383f7df2e56Smrg            for (k = dev->kbdfeed; k; k = k->next) {
3844642e01fSmrg                if (k->ctrl.id == bellID)
3854642e01fSmrg                    break;
3864642e01fSmrg            }
3874642e01fSmrg        }
3884642e01fSmrg        if (!k) {
389f7df2e56Smrg            client->errorValue = _XkbErrCode2(0x5, bellID);
3904642e01fSmrg            return BadValue;
3914642e01fSmrg        }
3924642e01fSmrg        base = k->ctrl.bell;
393f7df2e56Smrg        ctrl = (void *) &(k->ctrl);
394f7df2e56Smrg        oldPitch = k->ctrl.bell_pitch;
395f7df2e56Smrg        oldDuration = k->ctrl.bell_duration;
396f7df2e56Smrg        if (pitch != 0) {
397f7df2e56Smrg            if (pitch == -1)
398f7df2e56Smrg                k->ctrl.bell_pitch = defaultKeyboardControl.bell_pitch;
399f7df2e56Smrg            else
400f7df2e56Smrg                k->ctrl.bell_pitch = pitch;
4014642e01fSmrg        }
402f7df2e56Smrg        if (duration != 0) {
403f7df2e56Smrg            if (duration == -1)
404f7df2e56Smrg                k->ctrl.bell_duration = defaultKeyboardControl.bell_duration;
405f7df2e56Smrg            else
406f7df2e56Smrg                k->ctrl.bell_duration = duration;
4074642e01fSmrg        }
4084642e01fSmrg    }
4094642e01fSmrg    else if (bellClass == BellFeedbackClass) {
410f7df2e56Smrg        BellFeedbackPtr b;
411f7df2e56Smrg
412f7df2e56Smrg        if (bellID == XkbDfltXIId)
413f7df2e56Smrg            b = dev->bell;
4144642e01fSmrg        else {
415f7df2e56Smrg            for (b = dev->bell; b; b = b->next) {
4164642e01fSmrg                if (b->ctrl.id == bellID)
4174642e01fSmrg                    break;
4184642e01fSmrg            }
4194642e01fSmrg        }
4204642e01fSmrg        if (!b) {
421f7df2e56Smrg            client->errorValue = _XkbErrCode2(0x6, bellID);
4224642e01fSmrg            return BadValue;
4234642e01fSmrg        }
4244642e01fSmrg        base = b->ctrl.percent;
425f7df2e56Smrg        ctrl = (void *) &(b->ctrl);
426f7df2e56Smrg        oldPitch = b->ctrl.pitch;
427f7df2e56Smrg        oldDuration = b->ctrl.duration;
428f7df2e56Smrg        if (pitch != 0) {
429f7df2e56Smrg            if (pitch == -1)
430f7df2e56Smrg                b->ctrl.pitch = defaultKeyboardControl.bell_pitch;
431f7df2e56Smrg            else
432f7df2e56Smrg                b->ctrl.pitch = pitch;
4334642e01fSmrg        }
434f7df2e56Smrg        if (duration != 0) {
435f7df2e56Smrg            if (duration == -1)
436f7df2e56Smrg                b->ctrl.duration = defaultKeyboardControl.bell_duration;
437f7df2e56Smrg            else
438f7df2e56Smrg                b->ctrl.duration = duration;
4394642e01fSmrg        }
4404642e01fSmrg    }
4414642e01fSmrg    else {
4424642e01fSmrg        client->errorValue = _XkbErrCode2(0x7, bellClass);
4434642e01fSmrg        return BadValue;
4444642e01fSmrg    }
4454642e01fSmrg
446f7df2e56Smrg    newPercent = (base * percent) / 100;
4474642e01fSmrg    if (percent < 0)
448f7df2e56Smrg        newPercent = base + newPercent;
449f7df2e56Smrg    else
450f7df2e56Smrg        newPercent = base - newPercent + percent;
4514642e01fSmrg
4524642e01fSmrg    XkbHandleBell(forceSound, eventOnly,
453f7df2e56Smrg                  dev, newPercent, ctrl, bellClass, name, pWin, client);
454f7df2e56Smrg    if ((pitch != 0) || (duration != 0)) {
4554642e01fSmrg        if (bellClass == KbdFeedbackClass) {
456f7df2e56Smrg            KbdFeedbackPtr k;
457f7df2e56Smrg
458f7df2e56Smrg            k = (KbdFeedbackPtr) ctrl;
459f7df2e56Smrg            if (pitch != 0)
460f7df2e56Smrg                k->ctrl.bell_pitch = oldPitch;
461f7df2e56Smrg            if (duration != 0)
462f7df2e56Smrg                k->ctrl.bell_duration = oldDuration;
4634642e01fSmrg        }
4644642e01fSmrg        else {
465f7df2e56Smrg            BellFeedbackPtr b;
466f7df2e56Smrg
467f7df2e56Smrg            b = (BellFeedbackPtr) ctrl;
468f7df2e56Smrg            if (pitch != 0)
469f7df2e56Smrg                b->ctrl.pitch = oldPitch;
470f7df2e56Smrg            if (duration != 0)
471f7df2e56Smrg                b->ctrl.duration = oldDuration;
4724642e01fSmrg        }
4734642e01fSmrg    }
4744642e01fSmrg
4754642e01fSmrg    return Success;
4764642e01fSmrg}
47705b261ecSmrg
47805b261ecSmrgint
47905b261ecSmrgProcXkbBell(ClientPtr client)
48005b261ecSmrg{
48105b261ecSmrg    REQUEST(xkbBellReq);
48205b261ecSmrg    DeviceIntPtr dev;
483f7df2e56Smrg    WindowPtr pWin;
4844642e01fSmrg    int rc;
48505b261ecSmrg
48605b261ecSmrg    REQUEST_SIZE_MATCH(xkbBellReq);
48705b261ecSmrg
488f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
489f7df2e56Smrg        return BadAccess;
49005b261ecSmrg
4914642e01fSmrg    CHK_BELL_DEVICE(dev, stuff->deviceSpec, client, DixBellAccess);
49205b261ecSmrg    CHK_ATOM_OR_NONE(stuff->name);
49305b261ecSmrg
4944642e01fSmrg    /* device-independent checks request for sane values */
495f7df2e56Smrg    if ((stuff->forceSound) && (stuff->eventOnly)) {
496f7df2e56Smrg        client->errorValue =
497f7df2e56Smrg            _XkbErrCode3(0x1, stuff->forceSound, stuff->eventOnly);
498f7df2e56Smrg        return BadMatch;
49905b261ecSmrg    }
50005b261ecSmrg    if (stuff->percent < -100 || stuff->percent > 100) {
501f7df2e56Smrg        client->errorValue = _XkbErrCode2(0x2, stuff->percent);
502f7df2e56Smrg        return BadValue;
50305b261ecSmrg    }
504f7df2e56Smrg    if (stuff->duration < -1) {
505f7df2e56Smrg        client->errorValue = _XkbErrCode2(0x3, stuff->duration);
506f7df2e56Smrg        return BadValue;
50705b261ecSmrg    }
508f7df2e56Smrg    if (stuff->pitch < -1) {
509f7df2e56Smrg        client->errorValue = _XkbErrCode2(0x4, stuff->pitch);
510f7df2e56Smrg        return BadValue;
51105b261ecSmrg    }
51205b261ecSmrg
51305b261ecSmrg    if (stuff->bellClass == XkbDfltXIClass) {
514f7df2e56Smrg        if (dev->kbdfeed != NULL)
515f7df2e56Smrg            stuff->bellClass = KbdFeedbackClass;
516f7df2e56Smrg        else
517f7df2e56Smrg            stuff->bellClass = BellFeedbackClass;
51805b261ecSmrg    }
5194642e01fSmrg
520f7df2e56Smrg    if (stuff->window != None) {
521f7df2e56Smrg        rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
522f7df2e56Smrg        if (rc != Success) {
523f7df2e56Smrg            client->errorValue = stuff->window;
524f7df2e56Smrg            return rc;
525f7df2e56Smrg        }
52605b261ecSmrg    }
527f7df2e56Smrg    else
528f7df2e56Smrg        pWin = NULL;
52905b261ecSmrg
5304642e01fSmrg    /* Client wants to ring a bell on the core keyboard?
5314642e01fSmrg       Ring the bell on the core keyboard (which does nothing, but if that
5324642e01fSmrg       fails the client is screwed anyway), and then on all extension devices.
5334642e01fSmrg       Fail if the core keyboard fails but not the extension devices.  this
5344642e01fSmrg       may cause some keyboards to ding and others to stay silent. Fix
5354642e01fSmrg       your client to use explicit keyboards to avoid this.
5364642e01fSmrg
5374642e01fSmrg       dev is the device the client requested.
5384642e01fSmrg     */
5394642e01fSmrg    rc = _XkbBell(client, dev, pWin, stuff->bellClass, stuff->bellID,
5404642e01fSmrg                  stuff->pitch, stuff->duration, stuff->percent,
5414642e01fSmrg                  stuff->forceSound, stuff->eventOnly, stuff->name);
5424642e01fSmrg
5434642e01fSmrg    if ((rc == Success) && ((stuff->deviceSpec == XkbUseCoreKbd) ||
544f7df2e56Smrg                            (stuff->deviceSpec == XkbUseCorePtr))) {
5454642e01fSmrg        DeviceIntPtr other;
546f7df2e56Smrg
547f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
548f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
549f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
5504642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixBellAccess);
5514642e01fSmrg                if (rc == Success)
5524642e01fSmrg                    _XkbBell(client, other, pWin, stuff->bellClass,
5534642e01fSmrg                             stuff->bellID, stuff->pitch, stuff->duration,
5544642e01fSmrg                             stuff->percent, stuff->forceSound,
5554642e01fSmrg                             stuff->eventOnly, stuff->name);
5564642e01fSmrg            }
5574642e01fSmrg        }
558f7df2e56Smrg        rc = Success;           /* reset to success, that's what we got for the VCK */
55905b261ecSmrg    }
5604642e01fSmrg
5614642e01fSmrg    return rc;
56205b261ecSmrg}
56305b261ecSmrg
56405b261ecSmrg/***====================================================================***/
56505b261ecSmrg
56605b261ecSmrgint
56705b261ecSmrgProcXkbGetState(ClientPtr client)
56805b261ecSmrg{
56905b261ecSmrg    REQUEST(xkbGetStateReq);
570f7df2e56Smrg    DeviceIntPtr dev;
571f7df2e56Smrg    xkbGetStateReply rep;
572f7df2e56Smrg    XkbStateRec *xkb;
57305b261ecSmrg
57405b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetStateReq);
57505b261ecSmrg
576f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
577f7df2e56Smrg        return BadAccess;
57805b261ecSmrg
5796747b715Smrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
58005b261ecSmrg
581f7df2e56Smrg    xkb = &dev->key->xkbInfo->state;
582f7df2e56Smrg    rep = (xkbGetStateReply) {
583f7df2e56Smrg        .type = X_Reply,
584f7df2e56Smrg        .deviceID = dev->id,
585f7df2e56Smrg        .sequenceNumber = client->sequence,
586f7df2e56Smrg        .length = 0,
587f7df2e56Smrg        .mods = XkbStateFieldFromRec(xkb) & 0xff,
588f7df2e56Smrg        .baseMods = xkb->base_mods,
589f7df2e56Smrg        .latchedMods = xkb->latched_mods,
590f7df2e56Smrg        .lockedMods = xkb->locked_mods,
591f7df2e56Smrg        .group = xkb->group,
592f7df2e56Smrg        .lockedGroup = xkb->locked_group,
593f7df2e56Smrg        .baseGroup = xkb->base_group,
594f7df2e56Smrg        .latchedGroup = xkb->latched_group,
595f7df2e56Smrg        .compatState = xkb->compat_state,
596f7df2e56Smrg        .ptrBtnState = xkb->ptr_buttons
597f7df2e56Smrg    };
59805b261ecSmrg    if (client->swapped) {
599f7df2e56Smrg        swaps(&rep.sequenceNumber);
600f7df2e56Smrg        swaps(&rep.ptrBtnState);
60105b261ecSmrg    }
602f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetStateReply), &rep);
6036747b715Smrg    return Success;
60405b261ecSmrg}
60505b261ecSmrg
60605b261ecSmrg/***====================================================================***/
60705b261ecSmrg
60805b261ecSmrgint
60905b261ecSmrgProcXkbLatchLockState(ClientPtr client)
61005b261ecSmrg{
61105b261ecSmrg    int status;
61205b261ecSmrg    DeviceIntPtr dev, tmpd;
613f7df2e56Smrg    XkbStateRec oldState, *newState;
61405b261ecSmrg    CARD16 changed;
61505b261ecSmrg    xkbStateNotify sn;
61605b261ecSmrg    XkbEventCauseRec cause;
61705b261ecSmrg
61805b261ecSmrg    REQUEST(xkbLatchLockStateReq);
61905b261ecSmrg    REQUEST_SIZE_MATCH(xkbLatchLockStateReq);
62005b261ecSmrg
62105b261ecSmrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
622f7df2e56Smrg        return BadAccess;
62305b261ecSmrg
6244642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
62505b261ecSmrg    CHK_MASK_MATCH(0x01, stuff->affectModLocks, stuff->modLocks);
62605b261ecSmrg    CHK_MASK_MATCH(0x01, stuff->affectModLatches, stuff->modLatches);
62705b261ecSmrg
62805b261ecSmrg    status = Success;
62905b261ecSmrg
63005b261ecSmrg    for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
631f7df2e56Smrg        if ((tmpd == dev) ||
632f7df2e56Smrg            (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) {
6336747b715Smrg            if (!tmpd->key || !tmpd->key->xkbInfo)
63405b261ecSmrg                continue;
63505b261ecSmrg
63605b261ecSmrg            oldState = tmpd->key->xkbInfo->state;
63705b261ecSmrg            newState = &tmpd->key->xkbInfo->state;
63805b261ecSmrg            if (stuff->affectModLocks) {
63905b261ecSmrg                newState->locked_mods &= ~stuff->affectModLocks;
640f7df2e56Smrg                newState->locked_mods |=
641f7df2e56Smrg                    (stuff->affectModLocks & stuff->modLocks);
64205b261ecSmrg            }
64305b261ecSmrg            if (status == Success && stuff->lockGroup)
64405b261ecSmrg                newState->locked_group = stuff->groupLock;
64505b261ecSmrg            if (status == Success && stuff->affectModLatches)
64605b261ecSmrg                status = XkbLatchModifiers(tmpd, stuff->affectModLatches,
64705b261ecSmrg                                           stuff->modLatches);
64805b261ecSmrg            if (status == Success && stuff->latchGroup)
64905b261ecSmrg                status = XkbLatchGroup(tmpd, stuff->groupLatch);
65005b261ecSmrg
65105b261ecSmrg            if (status != Success)
65205b261ecSmrg                return status;
65305b261ecSmrg
65405b261ecSmrg            XkbComputeDerivedState(tmpd->key->xkbInfo);
65505b261ecSmrg
65605b261ecSmrg            changed = XkbStateChangedFlags(&oldState, newState);
65705b261ecSmrg            if (changed) {
65805b261ecSmrg                sn.keycode = 0;
65905b261ecSmrg                sn.eventType = 0;
66005b261ecSmrg                sn.requestMajor = XkbReqCode;
66105b261ecSmrg                sn.requestMinor = X_kbLatchLockState;
66205b261ecSmrg                sn.changed = changed;
66305b261ecSmrg                XkbSendStateNotify(tmpd, &sn);
6646747b715Smrg                changed = XkbIndicatorsToUpdate(tmpd, changed, FALSE);
66505b261ecSmrg                if (changed) {
66605b261ecSmrg                    XkbSetCauseXkbReq(&cause, X_kbLatchLockState, client);
6676747b715Smrg                    XkbUpdateIndicators(tmpd, changed, TRUE, NULL, &cause);
668f7df2e56Smrg                }
66905b261ecSmrg            }
67005b261ecSmrg        }
67105b261ecSmrg    }
67205b261ecSmrg
6736747b715Smrg    return Success;
67405b261ecSmrg}
67505b261ecSmrg
67605b261ecSmrg/***====================================================================***/
67705b261ecSmrg
67805b261ecSmrgint
67905b261ecSmrgProcXkbGetControls(ClientPtr client)
68005b261ecSmrg{
68105b261ecSmrg    xkbGetControlsReply rep;
682f7df2e56Smrg    XkbControlsPtr xkb;
683f7df2e56Smrg    DeviceIntPtr dev;
68405b261ecSmrg
68505b261ecSmrg    REQUEST(xkbGetControlsReq);
68605b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetControlsReq);
68705b261ecSmrg
688f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
689f7df2e56Smrg        return BadAccess;
69005b261ecSmrg
6914642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
692f7df2e56Smrg
69305b261ecSmrg    xkb = dev->key->xkbInfo->desc->ctrls;
694f7df2e56Smrg    rep = (xkbGetControlsReply) {
695f7df2e56Smrg        .type = X_Reply,
696f7df2e56Smrg        .deviceID = ((DeviceIntPtr) dev)->id,
697f7df2e56Smrg        .sequenceNumber = client->sequence,
698f7df2e56Smrg        .length = bytes_to_int32(SIZEOF(xkbGetControlsReply) -
699f7df2e56Smrg                                 SIZEOF(xGenericReply)),
700f7df2e56Smrg        .mkDfltBtn = xkb->mk_dflt_btn,
701f7df2e56Smrg        .numGroups = xkb->num_groups,
702f7df2e56Smrg        .groupsWrap = xkb->groups_wrap,
703f7df2e56Smrg        .internalMods = xkb->internal.mask,
704f7df2e56Smrg        .ignoreLockMods = xkb->ignore_lock.mask,
705f7df2e56Smrg        .internalRealMods = xkb->internal.real_mods,
706f7df2e56Smrg        .ignoreLockRealMods = xkb->ignore_lock.real_mods,
707f7df2e56Smrg        .internalVMods = xkb->internal.vmods,
708f7df2e56Smrg        .ignoreLockVMods = xkb->ignore_lock.vmods,
709f7df2e56Smrg        .repeatDelay = xkb->repeat_delay,
710f7df2e56Smrg        .repeatInterval = xkb->repeat_interval,
711f7df2e56Smrg        .slowKeysDelay = xkb->slow_keys_delay,
712f7df2e56Smrg        .debounceDelay = xkb->debounce_delay,
713f7df2e56Smrg        .mkDelay = xkb->mk_delay,
714f7df2e56Smrg        .mkInterval = xkb->mk_interval,
715f7df2e56Smrg        .mkTimeToMax = xkb->mk_time_to_max,
716f7df2e56Smrg        .mkMaxSpeed = xkb->mk_max_speed,
717f7df2e56Smrg        .mkCurve = xkb->mk_curve,
718f7df2e56Smrg        .axOptions = xkb->ax_options,
719f7df2e56Smrg        .axTimeout = xkb->ax_timeout,
720f7df2e56Smrg        .axtOptsMask = xkb->axt_opts_mask,
721f7df2e56Smrg        .axtOptsValues = xkb->axt_opts_values,
722f7df2e56Smrg        .axtCtrlsMask = xkb->axt_ctrls_mask,
723f7df2e56Smrg        .axtCtrlsValues = xkb->axt_ctrls_values,
724f7df2e56Smrg        .enabledCtrls = xkb->enabled_ctrls,
725f7df2e56Smrg    };
726f7df2e56Smrg    memcpy(rep.perKeyRepeat, xkb->per_key_repeat, XkbPerKeyBitArraySize);
72705b261ecSmrg    if (client->swapped) {
728f7df2e56Smrg        swaps(&rep.sequenceNumber);
729f7df2e56Smrg        swapl(&rep.length);
730f7df2e56Smrg        swaps(&rep.internalVMods);
731f7df2e56Smrg        swaps(&rep.ignoreLockVMods);
732f7df2e56Smrg        swapl(&rep.enabledCtrls);
733f7df2e56Smrg        swaps(&rep.repeatDelay);
734f7df2e56Smrg        swaps(&rep.repeatInterval);
735f7df2e56Smrg        swaps(&rep.slowKeysDelay);
736f7df2e56Smrg        swaps(&rep.debounceDelay);
737f7df2e56Smrg        swaps(&rep.mkDelay);
738f7df2e56Smrg        swaps(&rep.mkInterval);
739f7df2e56Smrg        swaps(&rep.mkTimeToMax);
740f7df2e56Smrg        swaps(&rep.mkMaxSpeed);
741f7df2e56Smrg        swaps(&rep.mkCurve);
742f7df2e56Smrg        swaps(&rep.axTimeout);
743f7df2e56Smrg        swapl(&rep.axtCtrlsMask);
744f7df2e56Smrg        swapl(&rep.axtCtrlsValues);
745f7df2e56Smrg        swaps(&rep.axtOptsMask);
746f7df2e56Smrg        swaps(&rep.axtOptsValues);
747f7df2e56Smrg        swaps(&rep.axOptions);
748f7df2e56Smrg    }
749f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetControlsReply), &rep);
7506747b715Smrg    return Success;
75105b261ecSmrg}
75205b261ecSmrg
75305b261ecSmrgint
75405b261ecSmrgProcXkbSetControls(ClientPtr client)
75505b261ecSmrg{
756f7df2e56Smrg    DeviceIntPtr dev, tmpd;
757f7df2e56Smrg    XkbSrvInfoPtr xkbi;
758f7df2e56Smrg    XkbControlsPtr ctrl;
759f7df2e56Smrg    XkbControlsRec new, old;
760f7df2e56Smrg    xkbControlsNotify cn;
761f7df2e56Smrg    XkbEventCauseRec cause;
762f7df2e56Smrg    XkbSrvLedInfoPtr sli;
76305b261ecSmrg
76405b261ecSmrg    REQUEST(xkbSetControlsReq);
76505b261ecSmrg    REQUEST_SIZE_MATCH(xkbSetControlsReq);
76605b261ecSmrg
76705b261ecSmrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
768f7df2e56Smrg        return BadAccess;
76905b261ecSmrg
7704642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
77105b261ecSmrg    CHK_MASK_LEGAL(0x01, stuff->changeCtrls, XkbAllControlsMask);
77205b261ecSmrg
7736747b715Smrg    for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
7746747b715Smrg        if (!tmpd->key || !tmpd->key->xkbInfo)
7756747b715Smrg            continue;
776f7df2e56Smrg        if ((tmpd == dev) ||
777f7df2e56Smrg            (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) {
77805b261ecSmrg            xkbi = tmpd->key->xkbInfo;
77905b261ecSmrg            ctrl = xkbi->desc->ctrls;
78005b261ecSmrg            new = *ctrl;
78105b261ecSmrg            XkbSetCauseXkbReq(&cause, X_kbSetControls, client);
78205b261ecSmrg
78305b261ecSmrg            if (stuff->changeCtrls & XkbInternalModsMask) {
78405b261ecSmrg                CHK_MASK_MATCH(0x02, stuff->affectInternalMods,
78505b261ecSmrg                               stuff->internalMods);
78605b261ecSmrg                CHK_MASK_MATCH(0x03, stuff->affectInternalVMods,
78705b261ecSmrg                               stuff->internalVMods);
78805b261ecSmrg
78905b261ecSmrg                new.internal.real_mods &= ~(stuff->affectInternalMods);
79005b261ecSmrg                new.internal.real_mods |= (stuff->affectInternalMods &
79105b261ecSmrg                                           stuff->internalMods);
79205b261ecSmrg                new.internal.vmods &= ~(stuff->affectInternalVMods);
79305b261ecSmrg                new.internal.vmods |= (stuff->affectInternalVMods &
79405b261ecSmrg                                       stuff->internalVMods);
79505b261ecSmrg                new.internal.mask = new.internal.real_mods |
796f7df2e56Smrg                    XkbMaskForVMask(xkbi->desc, new.internal.vmods);
79705b261ecSmrg            }
79805b261ecSmrg
79905b261ecSmrg            if (stuff->changeCtrls & XkbIgnoreLockModsMask) {
80005b261ecSmrg                CHK_MASK_MATCH(0x4, stuff->affectIgnoreLockMods,
80105b261ecSmrg                               stuff->ignoreLockMods);
80205b261ecSmrg                CHK_MASK_MATCH(0x5, stuff->affectIgnoreLockVMods,
80305b261ecSmrg                               stuff->ignoreLockVMods);
80405b261ecSmrg
80505b261ecSmrg                new.ignore_lock.real_mods &= ~(stuff->affectIgnoreLockMods);
80605b261ecSmrg                new.ignore_lock.real_mods |= (stuff->affectIgnoreLockMods &
80705b261ecSmrg                                              stuff->ignoreLockMods);
80805b261ecSmrg                new.ignore_lock.vmods &= ~(stuff->affectIgnoreLockVMods);
80905b261ecSmrg                new.ignore_lock.vmods |= (stuff->affectIgnoreLockVMods &
81005b261ecSmrg                                          stuff->ignoreLockVMods);
81105b261ecSmrg                new.ignore_lock.mask = new.ignore_lock.real_mods |
812f7df2e56Smrg                    XkbMaskForVMask(xkbi->desc, new.ignore_lock.vmods);
81305b261ecSmrg            }
81405b261ecSmrg
81505b261ecSmrg            CHK_MASK_MATCH(0x06, stuff->affectEnabledCtrls,
81605b261ecSmrg                           stuff->enabledCtrls);
81705b261ecSmrg            if (stuff->affectEnabledCtrls) {
81805b261ecSmrg                CHK_MASK_LEGAL(0x07, stuff->affectEnabledCtrls,
81905b261ecSmrg                               XkbAllBooleanCtrlsMask);
82005b261ecSmrg
82105b261ecSmrg                new.enabled_ctrls &= ~(stuff->affectEnabledCtrls);
82205b261ecSmrg                new.enabled_ctrls |= (stuff->affectEnabledCtrls &
82305b261ecSmrg                                      stuff->enabledCtrls);
82405b261ecSmrg            }
82505b261ecSmrg
82605b261ecSmrg            if (stuff->changeCtrls & XkbRepeatKeysMask) {
82705b261ecSmrg                if (stuff->repeatDelay < 1 || stuff->repeatInterval < 1) {
82805b261ecSmrg                    client->errorValue = _XkbErrCode3(0x08, stuff->repeatDelay,
82905b261ecSmrg                                                      stuff->repeatInterval);
83005b261ecSmrg                    return BadValue;
83105b261ecSmrg                }
83205b261ecSmrg
83305b261ecSmrg                new.repeat_delay = stuff->repeatDelay;
83405b261ecSmrg                new.repeat_interval = stuff->repeatInterval;
83505b261ecSmrg            }
83605b261ecSmrg
83705b261ecSmrg            if (stuff->changeCtrls & XkbSlowKeysMask) {
83805b261ecSmrg                if (stuff->slowKeysDelay < 1) {
83905b261ecSmrg                    client->errorValue = _XkbErrCode2(0x09,
84005b261ecSmrg                                                      stuff->slowKeysDelay);
84105b261ecSmrg                    return BadValue;
84205b261ecSmrg                }
84305b261ecSmrg
84405b261ecSmrg                new.slow_keys_delay = stuff->slowKeysDelay;
84505b261ecSmrg            }
84605b261ecSmrg
84705b261ecSmrg            if (stuff->changeCtrls & XkbBounceKeysMask) {
84805b261ecSmrg                if (stuff->debounceDelay < 1) {
84905b261ecSmrg                    client->errorValue = _XkbErrCode2(0x0A,
85005b261ecSmrg                                                      stuff->debounceDelay);
85105b261ecSmrg                    return BadValue;
85205b261ecSmrg                }
85305b261ecSmrg
85405b261ecSmrg                new.debounce_delay = stuff->debounceDelay;
85505b261ecSmrg            }
85605b261ecSmrg
85705b261ecSmrg            if (stuff->changeCtrls & XkbMouseKeysMask) {
85805b261ecSmrg                if (stuff->mkDfltBtn > XkbMaxMouseKeysBtn) {
85905b261ecSmrg                    client->errorValue = _XkbErrCode2(0x0B, stuff->mkDfltBtn);
86005b261ecSmrg                    return BadValue;
86105b261ecSmrg                }
86205b261ecSmrg
86305b261ecSmrg                new.mk_dflt_btn = stuff->mkDfltBtn;
86405b261ecSmrg            }
86505b261ecSmrg
86605b261ecSmrg            if (stuff->changeCtrls & XkbMouseKeysAccelMask) {
86705b261ecSmrg                if (stuff->mkDelay < 1 || stuff->mkInterval < 1 ||
86805b261ecSmrg                    stuff->mkTimeToMax < 1 || stuff->mkMaxSpeed < 1 ||
86905b261ecSmrg                    stuff->mkCurve < -1000) {
870f7df2e56Smrg                    client->errorValue = _XkbErrCode2(0x0C, 0);
87105b261ecSmrg                    return BadValue;
87205b261ecSmrg                }
87305b261ecSmrg
87405b261ecSmrg                new.mk_delay = stuff->mkDelay;
87505b261ecSmrg                new.mk_interval = stuff->mkInterval;
87605b261ecSmrg                new.mk_time_to_max = stuff->mkTimeToMax;
87705b261ecSmrg                new.mk_max_speed = stuff->mkMaxSpeed;
87805b261ecSmrg                new.mk_curve = stuff->mkCurve;
87905b261ecSmrg                AccessXComputeCurveFactor(xkbi, &new);
88005b261ecSmrg            }
88105b261ecSmrg
88205b261ecSmrg            if (stuff->changeCtrls & XkbGroupsWrapMask) {
88305b261ecSmrg                unsigned act, num;
88405b261ecSmrg
88505b261ecSmrg                act = XkbOutOfRangeGroupAction(stuff->groupsWrap);
88605b261ecSmrg                switch (act) {
88705b261ecSmrg                case XkbRedirectIntoRange:
88805b261ecSmrg                    num = XkbOutOfRangeGroupNumber(stuff->groupsWrap);
88905b261ecSmrg                    if (num >= new.num_groups) {
89005b261ecSmrg                        client->errorValue = _XkbErrCode3(0x0D, new.num_groups,
89105b261ecSmrg                                                          num);
89205b261ecSmrg                        return BadValue;
89305b261ecSmrg                    }
89405b261ecSmrg                case XkbWrapIntoRange:
89505b261ecSmrg                case XkbClampIntoRange:
89605b261ecSmrg                    break;
89705b261ecSmrg                default:
89805b261ecSmrg                    client->errorValue = _XkbErrCode2(0x0E, act);
89905b261ecSmrg                    return BadValue;
90005b261ecSmrg                }
90105b261ecSmrg
902f7df2e56Smrg                new.groups_wrap = stuff->groupsWrap;
90305b261ecSmrg            }
90405b261ecSmrg
90505b261ecSmrg            CHK_MASK_LEGAL(0x0F, stuff->axOptions, XkbAX_AllOptionsMask);
90605b261ecSmrg            if (stuff->changeCtrls & XkbAccessXKeysMask) {
90705b261ecSmrg                new.ax_options = stuff->axOptions & XkbAX_AllOptionsMask;
90805b261ecSmrg            }
90905b261ecSmrg            else {
91005b261ecSmrg                if (stuff->changeCtrls & XkbStickyKeysMask) {
91105b261ecSmrg                    new.ax_options &= ~(XkbAX_SKOptionsMask);
91205b261ecSmrg                    new.ax_options |= (stuff->axOptions & XkbAX_SKOptionsMask);
91305b261ecSmrg                }
914f7df2e56Smrg
91505b261ecSmrg                if (stuff->changeCtrls & XkbAccessXFeedbackMask) {
91605b261ecSmrg                    new.ax_options &= ~(XkbAX_FBOptionsMask);
91705b261ecSmrg                    new.ax_options |= (stuff->axOptions & XkbAX_FBOptionsMask);
91805b261ecSmrg                }
91905b261ecSmrg            }
92005b261ecSmrg
92105b261ecSmrg            if (stuff->changeCtrls & XkbAccessXTimeoutMask) {
92205b261ecSmrg                if (stuff->axTimeout < 1) {
92305b261ecSmrg                    client->errorValue = _XkbErrCode2(0x10, stuff->axTimeout);
92405b261ecSmrg                    return BadValue;
92505b261ecSmrg                }
92605b261ecSmrg                CHK_MASK_MATCH(0x11, stuff->axtCtrlsMask,
92705b261ecSmrg                               stuff->axtCtrlsValues);
92805b261ecSmrg                CHK_MASK_LEGAL(0x12, stuff->axtCtrlsMask,
92905b261ecSmrg                               XkbAllBooleanCtrlsMask);
93005b261ecSmrg                CHK_MASK_MATCH(0x13, stuff->axtOptsMask, stuff->axtOptsValues);
93105b261ecSmrg                CHK_MASK_LEGAL(0x14, stuff->axtOptsMask, XkbAX_AllOptionsMask);
93205b261ecSmrg                new.ax_timeout = stuff->axTimeout;
93305b261ecSmrg                new.axt_ctrls_mask = stuff->axtCtrlsMask;
93405b261ecSmrg                new.axt_ctrls_values = (stuff->axtCtrlsValues &
93505b261ecSmrg                                        stuff->axtCtrlsMask);
93605b261ecSmrg                new.axt_opts_mask = stuff->axtOptsMask;
93705b261ecSmrg                new.axt_opts_values = (stuff->axtOptsValues &
93805b261ecSmrg                                       stuff->axtOptsMask);
93905b261ecSmrg            }
94005b261ecSmrg
9419ace9065Smrg            if (stuff->changeCtrls & XkbPerKeyRepeatMask) {
94205b261ecSmrg                memcpy(new.per_key_repeat, stuff->perKeyRepeat,
94305b261ecSmrg                       XkbPerKeyBitArraySize);
9449ace9065Smrg                if (xkbi->repeatKey &&
9459ace9065Smrg                    !BitIsOn(new.per_key_repeat, xkbi->repeatKey)) {
9469ace9065Smrg                    AccessXCancelRepeatKey(xkbi, xkbi->repeatKey);
9479ace9065Smrg                }
9489ace9065Smrg            }
94905b261ecSmrg
950f7df2e56Smrg            old = *ctrl;
951f7df2e56Smrg            *ctrl = new;
95205b261ecSmrg            XkbDDXChangeControls(tmpd, &old, ctrl);
95305b261ecSmrg
9546747b715Smrg            if (XkbComputeControlsNotify(tmpd, &old, ctrl, &cn, FALSE)) {
95505b261ecSmrg                cn.keycode = 0;
95605b261ecSmrg                cn.eventType = 0;
95705b261ecSmrg                cn.requestMajor = XkbReqCode;
95805b261ecSmrg                cn.requestMinor = X_kbSetControls;
95905b261ecSmrg                XkbSendControlsNotify(tmpd, &cn);
96005b261ecSmrg            }
96105b261ecSmrg
96205b261ecSmrg            sli = XkbFindSrvLedInfo(tmpd, XkbDfltXIClass, XkbDfltXIId, 0);
96305b261ecSmrg            if (sli)
9646747b715Smrg                XkbUpdateIndicators(tmpd, sli->usesControls, TRUE, NULL,
96505b261ecSmrg                                    &cause);
96605b261ecSmrg
96705b261ecSmrg            /* If sticky keys were disabled, clear all locks and latches */
96805b261ecSmrg            if ((old.enabled_ctrls & XkbStickyKeysMask) &&
96905b261ecSmrg                !(ctrl->enabled_ctrls & XkbStickyKeysMask))
9706747b715Smrg                XkbClearAllLatchesAndLocks(tmpd, xkbi, TRUE, &cause);
97105b261ecSmrg        }
97205b261ecSmrg    }
97305b261ecSmrg
9746747b715Smrg    return Success;
97505b261ecSmrg}
97605b261ecSmrg
97705b261ecSmrg/***====================================================================***/
97805b261ecSmrg
97905b261ecSmrgstatic int
980f7df2e56SmrgXkbSizeKeyTypes(XkbDescPtr xkb, xkbGetMapReply * rep)
98105b261ecSmrg{
982f7df2e56Smrg    XkbKeyTypeRec *type;
983f7df2e56Smrg    unsigned i, len;
984f7df2e56Smrg
985f7df2e56Smrg    len = 0;
986f7df2e56Smrg    if (((rep->present & XkbKeyTypesMask) == 0) || (rep->nTypes < 1) ||
987f7df2e56Smrg        (!xkb) || (!xkb->map) || (!xkb->map->types)) {
988f7df2e56Smrg        rep->present &= ~XkbKeyTypesMask;
989f7df2e56Smrg        rep->firstType = rep->nTypes = 0;
990f7df2e56Smrg        return 0;
991f7df2e56Smrg    }
992f7df2e56Smrg    type = &xkb->map->types[rep->firstType];
993f7df2e56Smrg    for (i = 0; i < rep->nTypes; i++, type++) {
994f7df2e56Smrg        len += SIZEOF(xkbKeyTypeWireDesc);
995f7df2e56Smrg        if (type->map_count > 0) {
996f7df2e56Smrg            len += (type->map_count * SIZEOF(xkbKTMapEntryWireDesc));
997f7df2e56Smrg            if (type->preserve)
998f7df2e56Smrg                len += (type->map_count * SIZEOF(xkbModsWireDesc));
999f7df2e56Smrg        }
100005b261ecSmrg    }
100105b261ecSmrg    return len;
100205b261ecSmrg}
100305b261ecSmrg
100405b261ecSmrgstatic char *
1005f7df2e56SmrgXkbWriteKeyTypes(XkbDescPtr xkb,
1006f7df2e56Smrg                 xkbGetMapReply * rep, char *buf, ClientPtr client)
100705b261ecSmrg{
1008f7df2e56Smrg    XkbKeyTypePtr type;
1009f7df2e56Smrg    unsigned i;
101005b261ecSmrg    xkbKeyTypeWireDesc *wire;
101105b261ecSmrg
1012f7df2e56Smrg    type = &xkb->map->types[rep->firstType];
1013f7df2e56Smrg    for (i = 0; i < rep->nTypes; i++, type++) {
1014f7df2e56Smrg        register unsigned n;
1015f7df2e56Smrg
1016f7df2e56Smrg        wire = (xkbKeyTypeWireDesc *) buf;
1017f7df2e56Smrg        wire->mask = type->mods.mask;
1018f7df2e56Smrg        wire->realMods = type->mods.real_mods;
1019f7df2e56Smrg        wire->virtualMods = type->mods.vmods;
1020f7df2e56Smrg        wire->numLevels = type->num_levels;
1021f7df2e56Smrg        wire->nMapEntries = type->map_count;
1022f7df2e56Smrg        wire->preserve = (type->preserve != NULL);
1023f7df2e56Smrg        if (client->swapped) {
1024f7df2e56Smrg            swaps(&wire->virtualMods);
1025f7df2e56Smrg        }
1026f7df2e56Smrg
1027f7df2e56Smrg        buf = (char *) &wire[1];
1028f7df2e56Smrg        if (wire->nMapEntries > 0) {
1029f7df2e56Smrg            xkbKTMapEntryWireDesc *ewire;
1030f7df2e56Smrg            XkbKTMapEntryPtr entry;
1031f7df2e56Smrg
1032f7df2e56Smrg            ewire = (xkbKTMapEntryWireDesc *) buf;
1033f7df2e56Smrg            entry = type->map;
1034f7df2e56Smrg            for (n = 0; n < type->map_count; n++, ewire++, entry++) {
1035f7df2e56Smrg                ewire->active = entry->active;
1036f7df2e56Smrg                ewire->mask = entry->mods.mask;
1037f7df2e56Smrg                ewire->level = entry->level;
1038f7df2e56Smrg                ewire->realMods = entry->mods.real_mods;
1039f7df2e56Smrg                ewire->virtualMods = entry->mods.vmods;
1040f7df2e56Smrg                if (client->swapped) {
1041f7df2e56Smrg                    swaps(&ewire->virtualMods);
1042f7df2e56Smrg                }
1043f7df2e56Smrg            }
1044f7df2e56Smrg            buf = (char *) ewire;
1045f7df2e56Smrg            if (type->preserve != NULL) {
1046f7df2e56Smrg                xkbModsWireDesc *pwire;
1047f7df2e56Smrg                XkbModsPtr preserve;
1048f7df2e56Smrg
1049f7df2e56Smrg                pwire = (xkbModsWireDesc *) buf;
1050f7df2e56Smrg                preserve = type->preserve;
1051f7df2e56Smrg                for (n = 0; n < type->map_count; n++, pwire++, preserve++) {
1052f7df2e56Smrg                    pwire->mask = preserve->mask;
1053f7df2e56Smrg                    pwire->realMods = preserve->real_mods;
1054f7df2e56Smrg                    pwire->virtualMods = preserve->vmods;
1055f7df2e56Smrg                    if (client->swapped) {
1056f7df2e56Smrg                        swaps(&pwire->virtualMods);
1057f7df2e56Smrg                    }
1058f7df2e56Smrg                }
1059f7df2e56Smrg                buf = (char *) pwire;
1060f7df2e56Smrg            }
1061f7df2e56Smrg        }
106205b261ecSmrg    }
106305b261ecSmrg    return buf;
106405b261ecSmrg}
106505b261ecSmrg
106605b261ecSmrgstatic int
1067f7df2e56SmrgXkbSizeKeySyms(XkbDescPtr xkb, xkbGetMapReply * rep)
106805b261ecSmrg{
1069f7df2e56Smrg    XkbSymMapPtr symMap;
1070f7df2e56Smrg    unsigned i, len;
1071f7df2e56Smrg    unsigned nSyms, nSymsThisKey;
1072f7df2e56Smrg
1073f7df2e56Smrg    if (((rep->present & XkbKeySymsMask) == 0) || (rep->nKeySyms < 1) ||
1074f7df2e56Smrg        (!xkb) || (!xkb->map) || (!xkb->map->key_sym_map)) {
1075f7df2e56Smrg        rep->present &= ~XkbKeySymsMask;
1076f7df2e56Smrg        rep->firstKeySym = rep->nKeySyms = 0;
1077f7df2e56Smrg        rep->totalSyms = 0;
1078f7df2e56Smrg        return 0;
1079f7df2e56Smrg    }
1080f7df2e56Smrg    len = rep->nKeySyms * SIZEOF(xkbSymMapWireDesc);
108105b261ecSmrg    symMap = &xkb->map->key_sym_map[rep->firstKeySym];
1082f7df2e56Smrg    for (i = nSyms = 0; i < rep->nKeySyms; i++, symMap++) {
1083f7df2e56Smrg        if (symMap->offset != 0) {
1084f7df2e56Smrg            nSymsThisKey = XkbNumGroups(symMap->group_info) * symMap->width;
1085f7df2e56Smrg            nSyms += nSymsThisKey;
1086f7df2e56Smrg        }
1087f7df2e56Smrg    }
1088f7df2e56Smrg    len += nSyms * 4;
1089f7df2e56Smrg    rep->totalSyms = nSyms;
109005b261ecSmrg    return len;
109105b261ecSmrg}
109205b261ecSmrg
109305b261ecSmrgstatic int
1094f7df2e56SmrgXkbSizeVirtualMods(XkbDescPtr xkb, xkbGetMapReply * rep)
109505b261ecSmrg{
1096f7df2e56Smrg    register unsigned i, nMods, bit;
109705b261ecSmrg
1098f7df2e56Smrg    if (((rep->present & XkbVirtualModsMask) == 0) || (rep->virtualMods == 0) ||
1099f7df2e56Smrg        (!xkb) || (!xkb->server)) {
1100f7df2e56Smrg        rep->present &= ~XkbVirtualModsMask;
1101f7df2e56Smrg        rep->virtualMods = 0;
1102f7df2e56Smrg        return 0;
110305b261ecSmrg    }
1104f7df2e56Smrg    for (i = nMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
1105f7df2e56Smrg        if (rep->virtualMods & bit)
1106f7df2e56Smrg            nMods++;
110705b261ecSmrg    }
110805b261ecSmrg    return XkbPaddedSize(nMods);
110905b261ecSmrg}
111005b261ecSmrg
111105b261ecSmrgstatic char *
1112f7df2e56SmrgXkbWriteKeySyms(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1113f7df2e56Smrg                ClientPtr client)
111405b261ecSmrg{
1115f7df2e56Smrg    register KeySym *pSym;
1116f7df2e56Smrg    XkbSymMapPtr symMap;
1117f7df2e56Smrg    xkbSymMapWireDesc *outMap;
1118f7df2e56Smrg    register unsigned i;
111905b261ecSmrg
112005b261ecSmrg    symMap = &xkb->map->key_sym_map[rep->firstKeySym];
1121f7df2e56Smrg    for (i = 0; i < rep->nKeySyms; i++, symMap++) {
1122f7df2e56Smrg        outMap = (xkbSymMapWireDesc *) buf;
1123f7df2e56Smrg        outMap->ktIndex[0] = symMap->kt_index[0];
1124f7df2e56Smrg        outMap->ktIndex[1] = symMap->kt_index[1];
1125f7df2e56Smrg        outMap->ktIndex[2] = symMap->kt_index[2];
1126f7df2e56Smrg        outMap->ktIndex[3] = symMap->kt_index[3];
1127f7df2e56Smrg        outMap->groupInfo = symMap->group_info;
1128f7df2e56Smrg        outMap->width = symMap->width;
1129f7df2e56Smrg        outMap->nSyms = symMap->width * XkbNumGroups(symMap->group_info);
1130f7df2e56Smrg        buf = (char *) &outMap[1];
1131f7df2e56Smrg        if (outMap->nSyms == 0)
1132f7df2e56Smrg            continue;
1133f7df2e56Smrg
1134f7df2e56Smrg        pSym = &xkb->map->syms[symMap->offset];
1135f7df2e56Smrg        memcpy((char *) buf, (char *) pSym, outMap->nSyms * 4);
1136f7df2e56Smrg        if (client->swapped) {
1137f7df2e56Smrg            register int nSyms = outMap->nSyms;
1138f7df2e56Smrg
1139f7df2e56Smrg            swaps(&outMap->nSyms);
1140f7df2e56Smrg            while (nSyms-- > 0) {
1141f7df2e56Smrg                swapl((int *) buf);
1142f7df2e56Smrg                buf += 4;
1143f7df2e56Smrg            }
1144f7df2e56Smrg        }
1145f7df2e56Smrg        else
1146f7df2e56Smrg            buf += outMap->nSyms * 4;
114705b261ecSmrg    }
114805b261ecSmrg    return buf;
114905b261ecSmrg}
115005b261ecSmrg
115105b261ecSmrgstatic int
1152f7df2e56SmrgXkbSizeKeyActions(XkbDescPtr xkb, xkbGetMapReply * rep)
115305b261ecSmrg{
1154f7df2e56Smrg    unsigned i, len, nActs;
1155f7df2e56Smrg    register KeyCode firstKey;
1156f7df2e56Smrg
1157f7df2e56Smrg    if (((rep->present & XkbKeyActionsMask) == 0) || (rep->nKeyActs < 1) ||
1158f7df2e56Smrg        (!xkb) || (!xkb->server) || (!xkb->server->key_acts)) {
1159f7df2e56Smrg        rep->present &= ~XkbKeyActionsMask;
1160f7df2e56Smrg        rep->firstKeyAct = rep->nKeyActs = 0;
1161f7df2e56Smrg        rep->totalActs = 0;
1162f7df2e56Smrg        return 0;
1163f7df2e56Smrg    }
1164f7df2e56Smrg    firstKey = rep->firstKeyAct;
1165f7df2e56Smrg    for (nActs = i = 0; i < rep->nKeyActs; i++) {
1166f7df2e56Smrg        if (xkb->server->key_acts[i + firstKey] != 0)
1167f7df2e56Smrg            nActs += XkbKeyNumActions(xkb, i + firstKey);
1168f7df2e56Smrg    }
1169f7df2e56Smrg    len = XkbPaddedSize(rep->nKeyActs) + (nActs * SIZEOF(xkbActionWireDesc));
1170f7df2e56Smrg    rep->totalActs = nActs;
117105b261ecSmrg    return len;
117205b261ecSmrg}
117305b261ecSmrg
117405b261ecSmrgstatic char *
1175f7df2e56SmrgXkbWriteKeyActions(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1176f7df2e56Smrg                   ClientPtr client)
117705b261ecSmrg{
1178f7df2e56Smrg    unsigned i;
1179f7df2e56Smrg    CARD8 *numDesc;
1180f7df2e56Smrg    XkbAnyAction *actDesc;
1181f7df2e56Smrg
1182f7df2e56Smrg    numDesc = (CARD8 *) buf;
1183f7df2e56Smrg    for (i = 0; i < rep->nKeyActs; i++) {
1184f7df2e56Smrg        if (xkb->server->key_acts[i + rep->firstKeyAct] == 0)
1185f7df2e56Smrg            numDesc[i] = 0;
1186f7df2e56Smrg        else
1187f7df2e56Smrg            numDesc[i] = XkbKeyNumActions(xkb, (i + rep->firstKeyAct));
1188f7df2e56Smrg    }
1189f7df2e56Smrg    buf += XkbPaddedSize(rep->nKeyActs);
1190f7df2e56Smrg
1191f7df2e56Smrg    actDesc = (XkbAnyAction *) buf;
1192f7df2e56Smrg    for (i = 0; i < rep->nKeyActs; i++) {
1193f7df2e56Smrg        if (xkb->server->key_acts[i + rep->firstKeyAct] != 0) {
1194f7df2e56Smrg            unsigned int num;
1195f7df2e56Smrg
1196f7df2e56Smrg            num = XkbKeyNumActions(xkb, (i + rep->firstKeyAct));
1197f7df2e56Smrg            memcpy((char *) actDesc,
1198f7df2e56Smrg                   (char *) XkbKeyActionsPtr(xkb, (i + rep->firstKeyAct)),
1199f7df2e56Smrg                   num * SIZEOF(xkbActionWireDesc));
1200f7df2e56Smrg            actDesc += num;
1201f7df2e56Smrg        }
1202f7df2e56Smrg    }
1203f7df2e56Smrg    buf = (char *) actDesc;
120405b261ecSmrg    return buf;
120505b261ecSmrg}
120605b261ecSmrg
120705b261ecSmrgstatic int
1208f7df2e56SmrgXkbSizeKeyBehaviors(XkbDescPtr xkb, xkbGetMapReply * rep)
120905b261ecSmrg{
1210f7df2e56Smrg    unsigned i, len, nBhvr;
1211f7df2e56Smrg    XkbBehavior *bhv;
1212f7df2e56Smrg
1213f7df2e56Smrg    if (((rep->present & XkbKeyBehaviorsMask) == 0) || (rep->nKeyBehaviors < 1)
1214f7df2e56Smrg        || (!xkb) || (!xkb->server) || (!xkb->server->behaviors)) {
1215f7df2e56Smrg        rep->present &= ~XkbKeyBehaviorsMask;
1216f7df2e56Smrg        rep->firstKeyBehavior = rep->nKeyBehaviors = 0;
1217f7df2e56Smrg        rep->totalKeyBehaviors = 0;
1218f7df2e56Smrg        return 0;
1219f7df2e56Smrg    }
1220f7df2e56Smrg    bhv = &xkb->server->behaviors[rep->firstKeyBehavior];
1221f7df2e56Smrg    for (nBhvr = i = 0; i < rep->nKeyBehaviors; i++, bhv++) {
1222f7df2e56Smrg        if (bhv->type != XkbKB_Default)
1223f7df2e56Smrg            nBhvr++;
1224f7df2e56Smrg    }
1225f7df2e56Smrg    len = nBhvr * SIZEOF(xkbBehaviorWireDesc);
1226f7df2e56Smrg    rep->totalKeyBehaviors = nBhvr;
122705b261ecSmrg    return len;
122805b261ecSmrg}
122905b261ecSmrg
123005b261ecSmrgstatic char *
1231f7df2e56SmrgXkbWriteKeyBehaviors(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1232f7df2e56Smrg                     ClientPtr client)
123305b261ecSmrg{
1234f7df2e56Smrg    unsigned i;
1235f7df2e56Smrg    xkbBehaviorWireDesc *wire;
1236f7df2e56Smrg    XkbBehavior *pBhvr;
1237f7df2e56Smrg
1238f7df2e56Smrg    wire = (xkbBehaviorWireDesc *) buf;
1239f7df2e56Smrg    pBhvr = &xkb->server->behaviors[rep->firstKeyBehavior];
1240f7df2e56Smrg    for (i = 0; i < rep->nKeyBehaviors; i++, pBhvr++) {
1241f7df2e56Smrg        if (pBhvr->type != XkbKB_Default) {
1242f7df2e56Smrg            wire->key = i + rep->firstKeyBehavior;
1243f7df2e56Smrg            wire->type = pBhvr->type;
1244f7df2e56Smrg            wire->data = pBhvr->data;
1245f7df2e56Smrg            wire++;
1246f7df2e56Smrg        }
1247f7df2e56Smrg    }
1248f7df2e56Smrg    buf = (char *) wire;
124905b261ecSmrg    return buf;
125005b261ecSmrg}
125105b261ecSmrg
125205b261ecSmrgstatic int
1253f7df2e56SmrgXkbSizeExplicit(XkbDescPtr xkb, xkbGetMapReply * rep)
125405b261ecSmrg{
1255f7df2e56Smrg    unsigned i, len, nRtrn;
1256f7df2e56Smrg
1257f7df2e56Smrg    if (((rep->present & XkbExplicitComponentsMask) == 0) ||
1258f7df2e56Smrg        (rep->nKeyExplicit < 1) || (!xkb) || (!xkb->server) ||
1259f7df2e56Smrg        (!xkb->server->explicit)) {
1260f7df2e56Smrg        rep->present &= ~XkbExplicitComponentsMask;
1261f7df2e56Smrg        rep->firstKeyExplicit = rep->nKeyExplicit = 0;
1262f7df2e56Smrg        rep->totalKeyExplicit = 0;
1263f7df2e56Smrg        return 0;
1264f7df2e56Smrg    }
1265f7df2e56Smrg    for (nRtrn = i = 0; i < rep->nKeyExplicit; i++) {
1266f7df2e56Smrg        if (xkb->server->explicit[i + rep->firstKeyExplicit] != 0)
1267f7df2e56Smrg            nRtrn++;
1268f7df2e56Smrg    }
1269f7df2e56Smrg    rep->totalKeyExplicit = nRtrn;
1270f7df2e56Smrg    len = XkbPaddedSize(nRtrn * 2);     /* two bytes per non-zero explicit component */
127105b261ecSmrg    return len;
127205b261ecSmrg}
127305b261ecSmrg
127405b261ecSmrgstatic char *
1275f7df2e56SmrgXkbWriteExplicit(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1276f7df2e56Smrg                 ClientPtr client)
127705b261ecSmrg{
1278f7df2e56Smrg    unsigned i;
1279f7df2e56Smrg    char *start;
1280f7df2e56Smrg    unsigned char *pExp;
1281f7df2e56Smrg
1282f7df2e56Smrg    start = buf;
1283f7df2e56Smrg    pExp = &xkb->server->explicit[rep->firstKeyExplicit];
1284f7df2e56Smrg    for (i = 0; i < rep->nKeyExplicit; i++, pExp++) {
1285f7df2e56Smrg        if (*pExp != 0) {
1286f7df2e56Smrg            *buf++ = i + rep->firstKeyExplicit;
1287f7df2e56Smrg            *buf++ = *pExp;
1288f7df2e56Smrg        }
1289f7df2e56Smrg    }
1290f7df2e56Smrg    i = XkbPaddedSize(buf - start) - (buf - start);     /* pad to word boundary */
1291f7df2e56Smrg    return buf + i;
129205b261ecSmrg}
129305b261ecSmrg
129405b261ecSmrgstatic int
1295f7df2e56SmrgXkbSizeModifierMap(XkbDescPtr xkb, xkbGetMapReply * rep)
129605b261ecSmrg{
1297f7df2e56Smrg    unsigned i, len, nRtrn;
129805b261ecSmrg
1299f7df2e56Smrg    if (((rep->present & XkbModifierMapMask) == 0) || (rep->nModMapKeys < 1) ||
1300f7df2e56Smrg        (!xkb) || (!xkb->map) || (!xkb->map->modmap)) {
1301f7df2e56Smrg        rep->present &= ~XkbModifierMapMask;
1302f7df2e56Smrg        rep->firstModMapKey = rep->nModMapKeys = 0;
1303f7df2e56Smrg        rep->totalModMapKeys = 0;
1304f7df2e56Smrg        return 0;
130505b261ecSmrg    }
1306f7df2e56Smrg    for (nRtrn = i = 0; i < rep->nModMapKeys; i++) {
1307f7df2e56Smrg        if (xkb->map->modmap[i + rep->firstModMapKey] != 0)
1308f7df2e56Smrg            nRtrn++;
130905b261ecSmrg    }
1310f7df2e56Smrg    rep->totalModMapKeys = nRtrn;
1311f7df2e56Smrg    len = XkbPaddedSize(nRtrn * 2);     /* two bytes per non-zero modmap component */
131205b261ecSmrg    return len;
131305b261ecSmrg}
131405b261ecSmrg
131505b261ecSmrgstatic char *
1316f7df2e56SmrgXkbWriteModifierMap(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1317f7df2e56Smrg                    ClientPtr client)
131805b261ecSmrg{
1319f7df2e56Smrg    unsigned i;
1320f7df2e56Smrg    char *start;
1321f7df2e56Smrg    unsigned char *pMap;
1322f7df2e56Smrg
1323f7df2e56Smrg    start = buf;
1324f7df2e56Smrg    pMap = &xkb->map->modmap[rep->firstModMapKey];
1325f7df2e56Smrg    for (i = 0; i < rep->nModMapKeys; i++, pMap++) {
1326f7df2e56Smrg        if (*pMap != 0) {
1327f7df2e56Smrg            *buf++ = i + rep->firstModMapKey;
1328f7df2e56Smrg            *buf++ = *pMap;
1329f7df2e56Smrg        }
1330f7df2e56Smrg    }
1331f7df2e56Smrg    i = XkbPaddedSize(buf - start) - (buf - start);     /* pad to word boundary */
1332f7df2e56Smrg    return buf + i;
133305b261ecSmrg}
133405b261ecSmrg
133505b261ecSmrgstatic int
1336f7df2e56SmrgXkbSizeVirtualModMap(XkbDescPtr xkb, xkbGetMapReply * rep)
133705b261ecSmrg{
1338f7df2e56Smrg    unsigned i, len, nRtrn;
133905b261ecSmrg
1340f7df2e56Smrg    if (((rep->present & XkbVirtualModMapMask) == 0) || (rep->nVModMapKeys < 1)
1341f7df2e56Smrg        || (!xkb) || (!xkb->server) || (!xkb->server->vmodmap)) {
1342f7df2e56Smrg        rep->present &= ~XkbVirtualModMapMask;
1343f7df2e56Smrg        rep->firstVModMapKey = rep->nVModMapKeys = 0;
1344f7df2e56Smrg        rep->totalVModMapKeys = 0;
1345f7df2e56Smrg        return 0;
134605b261ecSmrg    }
1347f7df2e56Smrg    for (nRtrn = i = 0; i < rep->nVModMapKeys; i++) {
1348f7df2e56Smrg        if (xkb->server->vmodmap[i + rep->firstVModMapKey] != 0)
1349f7df2e56Smrg            nRtrn++;
135005b261ecSmrg    }
1351f7df2e56Smrg    rep->totalVModMapKeys = nRtrn;
1352f7df2e56Smrg    len = nRtrn * SIZEOF(xkbVModMapWireDesc);
135305b261ecSmrg    return len;
135405b261ecSmrg}
135505b261ecSmrg
135605b261ecSmrgstatic char *
1357f7df2e56SmrgXkbWriteVirtualModMap(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1358f7df2e56Smrg                      ClientPtr client)
135905b261ecSmrg{
1360f7df2e56Smrg    unsigned i;
1361f7df2e56Smrg    xkbVModMapWireDesc *wire;
1362f7df2e56Smrg    unsigned short *pMap;
1363f7df2e56Smrg
1364f7df2e56Smrg    wire = (xkbVModMapWireDesc *) buf;
1365f7df2e56Smrg    pMap = &xkb->server->vmodmap[rep->firstVModMapKey];
1366f7df2e56Smrg    for (i = 0; i < rep->nVModMapKeys; i++, pMap++) {
1367f7df2e56Smrg        if (*pMap != 0) {
1368f7df2e56Smrg            wire->key = i + rep->firstVModMapKey;
1369f7df2e56Smrg            wire->vmods = *pMap;
1370f7df2e56Smrg            wire++;
1371f7df2e56Smrg        }
1372f7df2e56Smrg    }
1373f7df2e56Smrg    return (char *) wire;
137405b261ecSmrg}
137505b261ecSmrg
137605b261ecSmrgstatic Status
1377f7df2e56SmrgXkbComputeGetMapReplySize(XkbDescPtr xkb, xkbGetMapReply * rep)
137805b261ecSmrg{
1379f7df2e56Smrg    int len;
1380f7df2e56Smrg
1381f7df2e56Smrg    rep->minKeyCode = xkb->min_key_code;
1382f7df2e56Smrg    rep->maxKeyCode = xkb->max_key_code;
1383f7df2e56Smrg    len = XkbSizeKeyTypes(xkb, rep);
1384f7df2e56Smrg    len += XkbSizeKeySyms(xkb, rep);
1385f7df2e56Smrg    len += XkbSizeKeyActions(xkb, rep);
1386f7df2e56Smrg    len += XkbSizeKeyBehaviors(xkb, rep);
1387f7df2e56Smrg    len += XkbSizeVirtualMods(xkb, rep);
1388f7df2e56Smrg    len += XkbSizeExplicit(xkb, rep);
1389f7df2e56Smrg    len += XkbSizeModifierMap(xkb, rep);
1390f7df2e56Smrg    len += XkbSizeVirtualModMap(xkb, rep);
1391f7df2e56Smrg    rep->length += (len / 4);
139205b261ecSmrg    return Success;
139305b261ecSmrg}
139405b261ecSmrg
139505b261ecSmrgstatic int
1396f7df2e56SmrgXkbSendMap(ClientPtr client, XkbDescPtr xkb, xkbGetMapReply * rep)
139705b261ecSmrg{
1398f7df2e56Smrg    unsigned i, len;
1399f7df2e56Smrg    char *desc, *start;
140005b261ecSmrg
1401f7df2e56Smrg    len = (rep->length * 4) - (SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply));
1402f7df2e56Smrg    start = desc = calloc(1, len);
140305b261ecSmrg    if (!start)
1404f7df2e56Smrg        return BadAlloc;
1405f7df2e56Smrg    if (rep->nTypes > 0)
1406f7df2e56Smrg        desc = XkbWriteKeyTypes(xkb, rep, desc, client);
1407f7df2e56Smrg    if (rep->nKeySyms > 0)
1408f7df2e56Smrg        desc = XkbWriteKeySyms(xkb, rep, desc, client);
1409f7df2e56Smrg    if (rep->nKeyActs > 0)
1410f7df2e56Smrg        desc = XkbWriteKeyActions(xkb, rep, desc, client);
1411f7df2e56Smrg    if (rep->totalKeyBehaviors > 0)
1412f7df2e56Smrg        desc = XkbWriteKeyBehaviors(xkb, rep, desc, client);
1413f7df2e56Smrg    if (rep->virtualMods) {
1414f7df2e56Smrg        register int sz, bit;
1415f7df2e56Smrg
1416f7df2e56Smrg        for (i = sz = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
1417f7df2e56Smrg            if (rep->virtualMods & bit) {
1418f7df2e56Smrg                desc[sz++] = xkb->server->vmods[i];
1419f7df2e56Smrg            }
1420f7df2e56Smrg        }
1421f7df2e56Smrg        desc += XkbPaddedSize(sz);
1422f7df2e56Smrg    }
1423f7df2e56Smrg    if (rep->totalKeyExplicit > 0)
1424f7df2e56Smrg        desc = XkbWriteExplicit(xkb, rep, desc, client);
1425f7df2e56Smrg    if (rep->totalModMapKeys > 0)
1426f7df2e56Smrg        desc = XkbWriteModifierMap(xkb, rep, desc, client);
1427f7df2e56Smrg    if (rep->totalVModMapKeys > 0)
1428f7df2e56Smrg        desc = XkbWriteVirtualModMap(xkb, rep, desc, client);
1429f7df2e56Smrg    if ((desc - start) != (len)) {
1430f7df2e56Smrg        ErrorF
1431f7df2e56Smrg            ("[xkb] BOGUS LENGTH in write keyboard desc, expected %d, got %ld\n",
1432f7df2e56Smrg             len, (unsigned long) (desc - start));
143305b261ecSmrg    }
143405b261ecSmrg    if (client->swapped) {
1435f7df2e56Smrg        swaps(&rep->sequenceNumber);
1436f7df2e56Smrg        swapl(&rep->length);
1437f7df2e56Smrg        swaps(&rep->present);
1438f7df2e56Smrg        swaps(&rep->totalSyms);
1439f7df2e56Smrg        swaps(&rep->totalActs);
1440f7df2e56Smrg    }
1441f7df2e56Smrg    WriteToClient(client, (i = SIZEOF(xkbGetMapReply)), rep);
144205b261ecSmrg    WriteToClient(client, len, start);
1443f7df2e56Smrg    free((char *) start);
14446747b715Smrg    return Success;
144505b261ecSmrg}
144605b261ecSmrg
144705b261ecSmrgint
144805b261ecSmrgProcXkbGetMap(ClientPtr client)
144905b261ecSmrg{
1450f7df2e56Smrg    DeviceIntPtr dev;
1451f7df2e56Smrg    xkbGetMapReply rep;
1452f7df2e56Smrg    XkbDescRec *xkb;
1453f7df2e56Smrg    int n, status;
145405b261ecSmrg
145505b261ecSmrg    REQUEST(xkbGetMapReq);
145605b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetMapReq);
1457f7df2e56Smrg
1458f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
1459f7df2e56Smrg        return BadAccess;
146005b261ecSmrg
14614642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
1462f7df2e56Smrg    CHK_MASK_OVERLAP(0x01, stuff->full, stuff->partial);
1463f7df2e56Smrg    CHK_MASK_LEGAL(0x02, stuff->full, XkbAllMapComponentsMask);
1464f7df2e56Smrg    CHK_MASK_LEGAL(0x03, stuff->partial, XkbAllMapComponentsMask);
1465f7df2e56Smrg
1466f7df2e56Smrg    xkb = dev->key->xkbInfo->desc;
1467f7df2e56Smrg    rep = (xkbGetMapReply) {
1468f7df2e56Smrg        .type = X_Reply,
1469f7df2e56Smrg        .deviceID = dev->id,
1470f7df2e56Smrg        .sequenceNumber = client->sequence,
1471f7df2e56Smrg        .length = (SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply)) >> 2,
1472f7df2e56Smrg        .present = stuff->partial | stuff->full,
1473f7df2e56Smrg        .minKeyCode = xkb->min_key_code,
1474f7df2e56Smrg        .maxKeyCode = xkb->max_key_code
1475f7df2e56Smrg    };
1476f7df2e56Smrg
1477f7df2e56Smrg    if (stuff->full & XkbKeyTypesMask) {
1478f7df2e56Smrg        rep.firstType = 0;
1479f7df2e56Smrg        rep.nTypes = xkb->map->num_types;
1480f7df2e56Smrg    }
1481f7df2e56Smrg    else if (stuff->partial & XkbKeyTypesMask) {
1482f7df2e56Smrg        if (((unsigned) stuff->firstType + stuff->nTypes) > xkb->map->num_types) {
1483f7df2e56Smrg            client->errorValue = _XkbErrCode4(0x04, xkb->map->num_types,
1484f7df2e56Smrg                                              stuff->firstType, stuff->nTypes);
1485f7df2e56Smrg            return BadValue;
1486f7df2e56Smrg        }
1487f7df2e56Smrg        rep.firstType = stuff->firstType;
1488f7df2e56Smrg        rep.nTypes = stuff->nTypes;
1489f7df2e56Smrg    }
1490f7df2e56Smrg    else
1491f7df2e56Smrg        rep.nTypes = 0;
149205b261ecSmrg    rep.totalTypes = xkb->map->num_types;
149305b261ecSmrg
1494f7df2e56Smrg    n = XkbNumKeys(xkb);
1495f7df2e56Smrg    if (stuff->full & XkbKeySymsMask) {
1496f7df2e56Smrg        rep.firstKeySym = xkb->min_key_code;
1497f7df2e56Smrg        rep.nKeySyms = n;
1498f7df2e56Smrg    }
1499f7df2e56Smrg    else if (stuff->partial & XkbKeySymsMask) {
1500f7df2e56Smrg        CHK_KEY_RANGE(0x05, stuff->firstKeySym, stuff->nKeySyms, xkb);
1501f7df2e56Smrg        rep.firstKeySym = stuff->firstKeySym;
1502f7df2e56Smrg        rep.nKeySyms = stuff->nKeySyms;
1503f7df2e56Smrg    }
1504f7df2e56Smrg    else
1505f7df2e56Smrg        rep.nKeySyms = 0;
1506f7df2e56Smrg    rep.totalSyms = 0;
1507f7df2e56Smrg
1508f7df2e56Smrg    if (stuff->full & XkbKeyActionsMask) {
1509f7df2e56Smrg        rep.firstKeyAct = xkb->min_key_code;
1510f7df2e56Smrg        rep.nKeyActs = n;
1511f7df2e56Smrg    }
1512f7df2e56Smrg    else if (stuff->partial & XkbKeyActionsMask) {
1513f7df2e56Smrg        CHK_KEY_RANGE(0x07, stuff->firstKeyAct, stuff->nKeyActs, xkb);
1514f7df2e56Smrg        rep.firstKeyAct = stuff->firstKeyAct;
1515f7df2e56Smrg        rep.nKeyActs = stuff->nKeyActs;
1516f7df2e56Smrg    }
1517f7df2e56Smrg    else
1518f7df2e56Smrg        rep.nKeyActs = 0;
1519f7df2e56Smrg    rep.totalActs = 0;
1520f7df2e56Smrg
1521f7df2e56Smrg    if (stuff->full & XkbKeyBehaviorsMask) {
1522f7df2e56Smrg        rep.firstKeyBehavior = xkb->min_key_code;
1523f7df2e56Smrg        rep.nKeyBehaviors = n;
1524f7df2e56Smrg    }
1525f7df2e56Smrg    else if (stuff->partial & XkbKeyBehaviorsMask) {
1526f7df2e56Smrg        CHK_KEY_RANGE(0x09, stuff->firstKeyBehavior, stuff->nKeyBehaviors, xkb);
1527f7df2e56Smrg        rep.firstKeyBehavior = stuff->firstKeyBehavior;
1528f7df2e56Smrg        rep.nKeyBehaviors = stuff->nKeyBehaviors;
1529f7df2e56Smrg    }
1530f7df2e56Smrg    else
1531f7df2e56Smrg        rep.nKeyBehaviors = 0;
1532f7df2e56Smrg    rep.totalKeyBehaviors = 0;
1533f7df2e56Smrg
1534f7df2e56Smrg    if (stuff->full & XkbVirtualModsMask)
1535f7df2e56Smrg        rep.virtualMods = ~0;
1536f7df2e56Smrg    else if (stuff->partial & XkbVirtualModsMask)
1537f7df2e56Smrg        rep.virtualMods = stuff->virtualMods;
1538f7df2e56Smrg
1539f7df2e56Smrg    if (stuff->full & XkbExplicitComponentsMask) {
1540f7df2e56Smrg        rep.firstKeyExplicit = xkb->min_key_code;
1541f7df2e56Smrg        rep.nKeyExplicit = n;
1542f7df2e56Smrg    }
1543f7df2e56Smrg    else if (stuff->partial & XkbExplicitComponentsMask) {
1544f7df2e56Smrg        CHK_KEY_RANGE(0x0B, stuff->firstKeyExplicit, stuff->nKeyExplicit, xkb);
1545f7df2e56Smrg        rep.firstKeyExplicit = stuff->firstKeyExplicit;
1546f7df2e56Smrg        rep.nKeyExplicit = stuff->nKeyExplicit;
1547f7df2e56Smrg    }
1548f7df2e56Smrg    else
1549f7df2e56Smrg        rep.nKeyExplicit = 0;
1550f7df2e56Smrg    rep.totalKeyExplicit = 0;
1551f7df2e56Smrg
1552f7df2e56Smrg    if (stuff->full & XkbModifierMapMask) {
1553f7df2e56Smrg        rep.firstModMapKey = xkb->min_key_code;
1554f7df2e56Smrg        rep.nModMapKeys = n;
1555f7df2e56Smrg    }
1556f7df2e56Smrg    else if (stuff->partial & XkbModifierMapMask) {
1557f7df2e56Smrg        CHK_KEY_RANGE(0x0D, stuff->firstModMapKey, stuff->nModMapKeys, xkb);
1558f7df2e56Smrg        rep.firstModMapKey = stuff->firstModMapKey;
1559f7df2e56Smrg        rep.nModMapKeys = stuff->nModMapKeys;
1560f7df2e56Smrg    }
1561f7df2e56Smrg    else
1562f7df2e56Smrg        rep.nModMapKeys = 0;
1563f7df2e56Smrg    rep.totalModMapKeys = 0;
1564f7df2e56Smrg
1565f7df2e56Smrg    if (stuff->full & XkbVirtualModMapMask) {
1566f7df2e56Smrg        rep.firstVModMapKey = xkb->min_key_code;
1567f7df2e56Smrg        rep.nVModMapKeys = n;
1568f7df2e56Smrg    }
1569f7df2e56Smrg    else if (stuff->partial & XkbVirtualModMapMask) {
1570f7df2e56Smrg        CHK_KEY_RANGE(0x0F, stuff->firstVModMapKey, stuff->nVModMapKeys, xkb);
1571f7df2e56Smrg        rep.firstVModMapKey = stuff->firstVModMapKey;
1572f7df2e56Smrg        rep.nVModMapKeys = stuff->nVModMapKeys;
1573f7df2e56Smrg    }
1574f7df2e56Smrg    else
1575f7df2e56Smrg        rep.nVModMapKeys = 0;
1576f7df2e56Smrg    rep.totalVModMapKeys = 0;
1577f7df2e56Smrg
1578f7df2e56Smrg    if ((status = XkbComputeGetMapReplySize(xkb, &rep)) != Success)
1579f7df2e56Smrg        return status;
1580f7df2e56Smrg    return XkbSendMap(client, xkb, &rep);
158105b261ecSmrg}
158205b261ecSmrg
158305b261ecSmrg/***====================================================================***/
158405b261ecSmrg
158505b261ecSmrgstatic int
1586f7df2e56SmrgCheckKeyTypes(ClientPtr client,
1587f7df2e56Smrg              XkbDescPtr xkb,
1588f7df2e56Smrg              xkbSetMapReq * req,
1589f7df2e56Smrg              xkbKeyTypeWireDesc ** wireRtrn,
1590f7df2e56Smrg              int *nMapsRtrn, CARD8 *mapWidthRtrn)
159105b261ecSmrg{
1592f7df2e56Smrg    unsigned nMaps;
1593f7df2e56Smrg    register unsigned i, n;
1594f7df2e56Smrg    register CARD8 *map;
1595f7df2e56Smrg    register xkbKeyTypeWireDesc *wire = *wireRtrn;
1596f7df2e56Smrg
1597f7df2e56Smrg    if (req->firstType > ((unsigned) xkb->map->num_types)) {
1598f7df2e56Smrg        *nMapsRtrn = _XkbErrCode3(0x01, req->firstType, xkb->map->num_types);
1599f7df2e56Smrg        return 0;
1600f7df2e56Smrg    }
1601f7df2e56Smrg    if (req->flags & XkbSetMapResizeTypes) {
1602f7df2e56Smrg        nMaps = req->firstType + req->nTypes;
1603f7df2e56Smrg        if (nMaps < XkbNumRequiredTypes) {      /* canonical types must be there */
1604f7df2e56Smrg            *nMapsRtrn = _XkbErrCode4(0x02, req->firstType, req->nTypes, 4);
1605f7df2e56Smrg            return 0;
1606f7df2e56Smrg        }
1607f7df2e56Smrg    }
1608f7df2e56Smrg    else if (req->present & XkbKeyTypesMask) {
1609f7df2e56Smrg        nMaps = xkb->map->num_types;
1610f7df2e56Smrg        if ((req->firstType + req->nTypes) > nMaps) {
1611f7df2e56Smrg            *nMapsRtrn = req->firstType + req->nTypes;
1612f7df2e56Smrg            return 0;
1613f7df2e56Smrg        }
161405b261ecSmrg    }
161505b261ecSmrg    else {
1616f7df2e56Smrg        *nMapsRtrn = xkb->map->num_types;
1617f7df2e56Smrg        for (i = 0; i < xkb->map->num_types; i++) {
1618f7df2e56Smrg            mapWidthRtrn[i] = xkb->map->types[i].num_levels;
1619f7df2e56Smrg        }
1620f7df2e56Smrg        return 1;
1621f7df2e56Smrg    }
1622f7df2e56Smrg
1623f7df2e56Smrg    for (i = 0; i < req->firstType; i++) {
1624f7df2e56Smrg        mapWidthRtrn[i] = xkb->map->types[i].num_levels;
1625f7df2e56Smrg    }
1626f7df2e56Smrg    for (i = 0; i < req->nTypes; i++) {
1627f7df2e56Smrg        unsigned width;
1628f7df2e56Smrg
1629f7df2e56Smrg        if (client->swapped) {
1630f7df2e56Smrg            swaps(&wire->virtualMods);
1631f7df2e56Smrg        }
1632f7df2e56Smrg        n = i + req->firstType;
1633f7df2e56Smrg        width = wire->numLevels;
1634f7df2e56Smrg        if (width < 1) {
1635f7df2e56Smrg            *nMapsRtrn = _XkbErrCode3(0x04, n, width);
1636f7df2e56Smrg            return 0;
1637f7df2e56Smrg        }
1638f7df2e56Smrg        else if ((n == XkbOneLevelIndex) && (width != 1)) {     /* must be width 1 */
1639f7df2e56Smrg            *nMapsRtrn = _XkbErrCode3(0x05, n, width);
1640f7df2e56Smrg            return 0;
1641f7df2e56Smrg        }
1642f7df2e56Smrg        else if ((width != 2) &&
1643f7df2e56Smrg                 ((n == XkbTwoLevelIndex) || (n == XkbKeypadIndex) ||
1644f7df2e56Smrg                  (n == XkbAlphabeticIndex))) {
1645f7df2e56Smrg            /* TWO_LEVEL, ALPHABETIC and KEYPAD must be width 2 */
1646f7df2e56Smrg            *nMapsRtrn = _XkbErrCode3(0x05, n, width);
1647f7df2e56Smrg            return 0;
1648f7df2e56Smrg        }
1649f7df2e56Smrg        if (wire->nMapEntries > 0) {
1650f7df2e56Smrg            xkbKTSetMapEntryWireDesc *mapWire;
1651f7df2e56Smrg            xkbModsWireDesc *preWire;
1652f7df2e56Smrg
1653f7df2e56Smrg            mapWire = (xkbKTSetMapEntryWireDesc *) &wire[1];
1654f7df2e56Smrg            preWire = (xkbModsWireDesc *) &mapWire[wire->nMapEntries];
1655f7df2e56Smrg            for (n = 0; n < wire->nMapEntries; n++) {
1656f7df2e56Smrg                if (client->swapped) {
1657f7df2e56Smrg                    swaps(&mapWire[n].virtualMods);
1658f7df2e56Smrg                }
1659f7df2e56Smrg                if (mapWire[n].realMods & (~wire->realMods)) {
1660f7df2e56Smrg                    *nMapsRtrn = _XkbErrCode4(0x06, n, mapWire[n].realMods,
1661f7df2e56Smrg                                              wire->realMods);
1662f7df2e56Smrg                    return 0;
1663f7df2e56Smrg                }
1664f7df2e56Smrg                if (mapWire[n].virtualMods & (~wire->virtualMods)) {
1665f7df2e56Smrg                    *nMapsRtrn = _XkbErrCode3(0x07, n, mapWire[n].virtualMods);
1666f7df2e56Smrg                    return 0;
1667f7df2e56Smrg                }
1668f7df2e56Smrg                if (mapWire[n].level >= wire->numLevels) {
1669f7df2e56Smrg                    *nMapsRtrn = _XkbErrCode4(0x08, n, wire->numLevels,
1670f7df2e56Smrg                                              mapWire[n].level);
1671f7df2e56Smrg                    return 0;
1672f7df2e56Smrg                }
1673f7df2e56Smrg                if (wire->preserve) {
1674f7df2e56Smrg                    if (client->swapped) {
1675f7df2e56Smrg                        swaps(&preWire[n].virtualMods);
1676f7df2e56Smrg                    }
1677f7df2e56Smrg                    if (preWire[n].realMods & (~mapWire[n].realMods)) {
1678f7df2e56Smrg                        *nMapsRtrn = _XkbErrCode4(0x09, n, preWire[n].realMods,
1679f7df2e56Smrg                                                  mapWire[n].realMods);
1680f7df2e56Smrg                        return 0;
1681f7df2e56Smrg                    }
1682f7df2e56Smrg                    if (preWire[n].virtualMods & (~mapWire[n].virtualMods)) {
1683f7df2e56Smrg                        *nMapsRtrn =
1684f7df2e56Smrg                            _XkbErrCode3(0x0a, n, preWire[n].virtualMods);
1685f7df2e56Smrg                        return 0;
1686f7df2e56Smrg                    }
1687f7df2e56Smrg                }
1688f7df2e56Smrg            }
1689f7df2e56Smrg            if (wire->preserve)
1690f7df2e56Smrg                map = (CARD8 *) &preWire[wire->nMapEntries];
1691f7df2e56Smrg            else
1692f7df2e56Smrg                map = (CARD8 *) &mapWire[wire->nMapEntries];
1693f7df2e56Smrg        }
1694f7df2e56Smrg        else
1695f7df2e56Smrg            map = (CARD8 *) &wire[1];
1696f7df2e56Smrg        mapWidthRtrn[i + req->firstType] = wire->numLevels;
1697f7df2e56Smrg        wire = (xkbKeyTypeWireDesc *) map;
1698f7df2e56Smrg    }
1699f7df2e56Smrg    for (i = req->firstType + req->nTypes; i < nMaps; i++) {
1700f7df2e56Smrg        mapWidthRtrn[i] = xkb->map->types[i].num_levels;
170105b261ecSmrg    }
170205b261ecSmrg    *nMapsRtrn = nMaps;
170305b261ecSmrg    *wireRtrn = wire;
170405b261ecSmrg    return 1;
170505b261ecSmrg}
170605b261ecSmrg
170705b261ecSmrgstatic int
1708f7df2e56SmrgCheckKeySyms(ClientPtr client,
1709f7df2e56Smrg             XkbDescPtr xkb,
1710f7df2e56Smrg             xkbSetMapReq * req,
1711f7df2e56Smrg             int nTypes,
1712f7df2e56Smrg             CARD8 *mapWidths,
1713f7df2e56Smrg             CARD16 *symsPerKey, xkbSymMapWireDesc ** wireRtrn, int *errorRtrn)
171405b261ecSmrg{
1715f7df2e56Smrg    register unsigned i;
1716f7df2e56Smrg    XkbSymMapPtr map;
1717f7df2e56Smrg    xkbSymMapWireDesc *wire = *wireRtrn;
1718f7df2e56Smrg
1719f7df2e56Smrg    if (!(XkbKeySymsMask & req->present))
1720f7df2e56Smrg        return 1;
1721f7df2e56Smrg    CHK_REQ_KEY_RANGE2(0x11, req->firstKeySym, req->nKeySyms, req, (*errorRtrn),
1722f7df2e56Smrg                       0);
1723f7df2e56Smrg    for (i = 0; i < req->nKeySyms; i++) {
1724f7df2e56Smrg        KeySym *pSyms;
1725f7df2e56Smrg        register unsigned nG;
1726f7df2e56Smrg
1727f7df2e56Smrg        if (client->swapped) {
1728f7df2e56Smrg            swaps(&wire->nSyms);
1729f7df2e56Smrg        }
1730f7df2e56Smrg        nG = XkbNumGroups(wire->groupInfo);
1731f7df2e56Smrg        if (nG > XkbNumKbdGroups) {
1732f7df2e56Smrg            *errorRtrn = _XkbErrCode3(0x14, i + req->firstKeySym, nG);
1733f7df2e56Smrg            return 0;
1734f7df2e56Smrg        }
1735f7df2e56Smrg        if (nG > 0) {
1736f7df2e56Smrg            register int g, w;
1737f7df2e56Smrg
1738f7df2e56Smrg            for (g = w = 0; g < nG; g++) {
1739f7df2e56Smrg                if (wire->ktIndex[g] >= (unsigned) nTypes) {
1740f7df2e56Smrg                    *errorRtrn = _XkbErrCode4(0x15, i + req->firstKeySym, g,
1741f7df2e56Smrg                                              wire->ktIndex[g]);
1742f7df2e56Smrg                    return 0;
1743f7df2e56Smrg                }
1744f7df2e56Smrg                if (mapWidths[wire->ktIndex[g]] > w)
1745f7df2e56Smrg                    w = mapWidths[wire->ktIndex[g]];
1746f7df2e56Smrg            }
1747f7df2e56Smrg            if (wire->width != w) {
1748f7df2e56Smrg                *errorRtrn =
1749f7df2e56Smrg                    _XkbErrCode3(0x16, i + req->firstKeySym, wire->width);
1750f7df2e56Smrg                return 0;
1751f7df2e56Smrg            }
1752f7df2e56Smrg            w *= nG;
1753f7df2e56Smrg            symsPerKey[i + req->firstKeySym] = w;
1754f7df2e56Smrg            if (w != wire->nSyms) {
1755f7df2e56Smrg                *errorRtrn =
1756f7df2e56Smrg                    _XkbErrCode4(0x16, i + req->firstKeySym, wire->nSyms, w);
1757f7df2e56Smrg                return 0;
1758f7df2e56Smrg            }
1759f7df2e56Smrg        }
1760f7df2e56Smrg        else if (wire->nSyms != 0) {
1761f7df2e56Smrg            *errorRtrn = _XkbErrCode3(0x17, i + req->firstKeySym, wire->nSyms);
1762f7df2e56Smrg            return 0;
1763f7df2e56Smrg        }
1764f7df2e56Smrg        pSyms = (KeySym *) &wire[1];
1765f7df2e56Smrg        wire = (xkbSymMapWireDesc *) &pSyms[wire->nSyms];
176605b261ecSmrg    }
176705b261ecSmrg
176805b261ecSmrg    map = &xkb->map->key_sym_map[i];
1769f7df2e56Smrg    for (; i <= (unsigned) xkb->max_key_code; i++, map++) {
1770f7df2e56Smrg        register int g, nG, w;
1771f7df2e56Smrg
1772f7df2e56Smrg        nG = XkbKeyNumGroups(xkb, i);
1773f7df2e56Smrg        for (w = g = 0; g < nG; g++) {
1774f7df2e56Smrg            if (map->kt_index[g] >= (unsigned) nTypes) {
1775f7df2e56Smrg                *errorRtrn = _XkbErrCode4(0x18, i, g, map->kt_index[g]);
1776f7df2e56Smrg                return 0;
1777f7df2e56Smrg            }
1778f7df2e56Smrg            if (mapWidths[map->kt_index[g]] > w)
1779f7df2e56Smrg                w = mapWidths[map->kt_index[g]];
1780f7df2e56Smrg        }
1781f7df2e56Smrg        symsPerKey[i] = w * nG;
178205b261ecSmrg    }
178305b261ecSmrg    *wireRtrn = wire;
178405b261ecSmrg    return 1;
178505b261ecSmrg}
178605b261ecSmrg
178705b261ecSmrgstatic int
1788f7df2e56SmrgCheckKeyActions(XkbDescPtr xkb,
1789f7df2e56Smrg                xkbSetMapReq * req,
1790f7df2e56Smrg                int nTypes,
1791f7df2e56Smrg                CARD8 *mapWidths,
1792f7df2e56Smrg                CARD16 *symsPerKey, CARD8 **wireRtrn, int *nActsRtrn)
179305b261ecSmrg{
1794f7df2e56Smrg    int nActs;
1795f7df2e56Smrg    CARD8 *wire = *wireRtrn;
1796f7df2e56Smrg    register unsigned i;
1797f7df2e56Smrg
1798f7df2e56Smrg    if (!(XkbKeyActionsMask & req->present))
1799f7df2e56Smrg        return 1;
1800f7df2e56Smrg    CHK_REQ_KEY_RANGE2(0x21, req->firstKeyAct, req->nKeyActs, req, (*nActsRtrn),
1801f7df2e56Smrg                       0);
1802f7df2e56Smrg    for (nActs = i = 0; i < req->nKeyActs; i++) {
1803f7df2e56Smrg        if (wire[0] != 0) {
1804f7df2e56Smrg            if (wire[0] == symsPerKey[i + req->firstKeyAct])
1805f7df2e56Smrg                nActs += wire[0];
1806f7df2e56Smrg            else {
1807f7df2e56Smrg                *nActsRtrn = _XkbErrCode3(0x23, i + req->firstKeyAct, wire[0]);
1808f7df2e56Smrg                return 0;
1809f7df2e56Smrg            }
1810f7df2e56Smrg        }
1811f7df2e56Smrg        wire++;
1812f7df2e56Smrg    }
1813f7df2e56Smrg    if (req->nKeyActs % 4)
1814f7df2e56Smrg        wire += 4 - (req->nKeyActs % 4);
1815f7df2e56Smrg    *wireRtrn = (CARD8 *) (((XkbAnyAction *) wire) + nActs);
181605b261ecSmrg    *nActsRtrn = nActs;
181705b261ecSmrg    return 1;
181805b261ecSmrg}
181905b261ecSmrg
182005b261ecSmrgstatic int
1821f7df2e56SmrgCheckKeyBehaviors(XkbDescPtr xkb,
1822f7df2e56Smrg                  xkbSetMapReq * req,
1823f7df2e56Smrg                  xkbBehaviorWireDesc ** wireRtrn, int *errorRtrn)
182405b261ecSmrg{
1825f7df2e56Smrg    register xkbBehaviorWireDesc *wire = *wireRtrn;
1826f7df2e56Smrg    register XkbServerMapPtr server = xkb->server;
1827f7df2e56Smrg    register unsigned i;
1828f7df2e56Smrg    unsigned first, last;
1829f7df2e56Smrg
1830f7df2e56Smrg    if (((req->present & XkbKeyBehaviorsMask) == 0) || (req->nKeyBehaviors < 1)) {
1831f7df2e56Smrg        req->present &= ~XkbKeyBehaviorsMask;
1832f7df2e56Smrg        req->nKeyBehaviors = 0;
1833f7df2e56Smrg        return 1;
1834f7df2e56Smrg    }
1835f7df2e56Smrg    first = req->firstKeyBehavior;
1836f7df2e56Smrg    last = req->firstKeyBehavior + req->nKeyBehaviors - 1;
1837f7df2e56Smrg    if (first < req->minKeyCode) {
1838f7df2e56Smrg        *errorRtrn = _XkbErrCode3(0x31, first, req->minKeyCode);
1839f7df2e56Smrg        return 0;
1840f7df2e56Smrg    }
1841f7df2e56Smrg    if (last > req->maxKeyCode) {
1842f7df2e56Smrg        *errorRtrn = _XkbErrCode3(0x32, last, req->maxKeyCode);
1843f7df2e56Smrg        return 0;
1844f7df2e56Smrg    }
1845f7df2e56Smrg
1846f7df2e56Smrg    for (i = 0; i < req->totalKeyBehaviors; i++, wire++) {
1847f7df2e56Smrg        if ((wire->key < first) || (wire->key > last)) {
1848f7df2e56Smrg            *errorRtrn = _XkbErrCode4(0x33, first, last, wire->key);
1849f7df2e56Smrg            return 0;
1850f7df2e56Smrg        }
1851f7df2e56Smrg        if ((wire->type & XkbKB_Permanent) &&
1852f7df2e56Smrg            ((server->behaviors[wire->key].type != wire->type) ||
1853f7df2e56Smrg             (server->behaviors[wire->key].data != wire->data))) {
1854f7df2e56Smrg            *errorRtrn = _XkbErrCode3(0x33, wire->key, wire->type);
1855f7df2e56Smrg            return 0;
1856f7df2e56Smrg        }
1857f7df2e56Smrg        if ((wire->type == XkbKB_RadioGroup) &&
1858f7df2e56Smrg            ((wire->data & (~XkbKB_RGAllowNone)) > XkbMaxRadioGroups)) {
1859f7df2e56Smrg            *errorRtrn = _XkbErrCode4(0x34, wire->key, wire->data,
1860f7df2e56Smrg                                      XkbMaxRadioGroups);
1861f7df2e56Smrg            return 0;
1862f7df2e56Smrg        }
1863f7df2e56Smrg        if ((wire->type == XkbKB_Overlay1) || (wire->type == XkbKB_Overlay2)) {
1864f7df2e56Smrg            CHK_KEY_RANGE2(0x35, wire->key, 1, xkb, *errorRtrn, 0);
1865f7df2e56Smrg        }
186605b261ecSmrg    }
186705b261ecSmrg    *wireRtrn = wire;
186805b261ecSmrg    return 1;
186905b261ecSmrg}
187005b261ecSmrg
187105b261ecSmrgstatic int
1872f7df2e56SmrgCheckVirtualMods(XkbDescRec * xkb,
1873f7df2e56Smrg                 xkbSetMapReq * req, CARD8 **wireRtrn, int *errorRtrn)
187405b261ecSmrg{
1875f7df2e56Smrg    register CARD8 *wire = *wireRtrn;
1876f7df2e56Smrg    register unsigned i, nMods, bit;
187705b261ecSmrg
1878f7df2e56Smrg    if (((req->present & XkbVirtualModsMask) == 0) || (req->virtualMods == 0))
1879f7df2e56Smrg        return 1;
1880f7df2e56Smrg    for (i = nMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
1881f7df2e56Smrg        if (req->virtualMods & bit)
1882f7df2e56Smrg            nMods++;
188305b261ecSmrg    }
1884f7df2e56Smrg    *wireRtrn = (wire + XkbPaddedSize(nMods));
188505b261ecSmrg    return 1;
188605b261ecSmrg}
188705b261ecSmrg
188805b261ecSmrgstatic int
1889f7df2e56SmrgCheckKeyExplicit(XkbDescPtr xkb,
1890f7df2e56Smrg                 xkbSetMapReq * req, CARD8 **wireRtrn, int *errorRtrn)
189105b261ecSmrg{
1892f7df2e56Smrg    register CARD8 *wire = *wireRtrn;
1893f7df2e56Smrg    CARD8 *start;
1894f7df2e56Smrg    register unsigned i;
1895f7df2e56Smrg    int first, last;
1896f7df2e56Smrg
1897f7df2e56Smrg    if (((req->present & XkbExplicitComponentsMask) == 0) ||
1898f7df2e56Smrg        (req->nKeyExplicit < 1)) {
1899f7df2e56Smrg        req->present &= ~XkbExplicitComponentsMask;
1900f7df2e56Smrg        req->nKeyExplicit = 0;
1901f7df2e56Smrg        return 1;
1902f7df2e56Smrg    }
1903f7df2e56Smrg    first = req->firstKeyExplicit;
1904f7df2e56Smrg    last = first + req->nKeyExplicit - 1;
1905f7df2e56Smrg    if (first < req->minKeyCode) {
1906f7df2e56Smrg        *errorRtrn = _XkbErrCode3(0x51, first, req->minKeyCode);
1907f7df2e56Smrg        return 0;
1908f7df2e56Smrg    }
1909f7df2e56Smrg    if (last > req->maxKeyCode) {
1910f7df2e56Smrg        *errorRtrn = _XkbErrCode3(0x52, last, req->maxKeyCode);
1911f7df2e56Smrg        return 0;
1912f7df2e56Smrg    }
1913f7df2e56Smrg    start = wire;
1914f7df2e56Smrg    for (i = 0; i < req->totalKeyExplicit; i++, wire += 2) {
1915f7df2e56Smrg        if ((wire[0] < first) || (wire[0] > last)) {
1916f7df2e56Smrg            *errorRtrn = _XkbErrCode4(0x53, first, last, wire[0]);
1917f7df2e56Smrg            return 0;
1918f7df2e56Smrg        }
1919f7df2e56Smrg        if (wire[1] & (~XkbAllExplicitMask)) {
1920f7df2e56Smrg            *errorRtrn = _XkbErrCode3(0x52, ~XkbAllExplicitMask, wire[1]);
1921f7df2e56Smrg            return 0;
1922f7df2e56Smrg        }
1923f7df2e56Smrg    }
1924f7df2e56Smrg    wire += XkbPaddedSize(wire - start) - (wire - start);
1925f7df2e56Smrg    *wireRtrn = wire;
192605b261ecSmrg    return 1;
192705b261ecSmrg}
192805b261ecSmrg
192905b261ecSmrgstatic int
1930f7df2e56SmrgCheckModifierMap(XkbDescPtr xkb, xkbSetMapReq * req, CARD8 **wireRtrn,
1931f7df2e56Smrg                 int *errRtrn)
193205b261ecSmrg{
1933f7df2e56Smrg    register CARD8 *wire = *wireRtrn;
1934f7df2e56Smrg    CARD8 *start;
1935f7df2e56Smrg    register unsigned i;
1936f7df2e56Smrg    int first, last;
1937f7df2e56Smrg
1938f7df2e56Smrg    if (((req->present & XkbModifierMapMask) == 0) || (req->nModMapKeys < 1)) {
1939f7df2e56Smrg        req->present &= ~XkbModifierMapMask;
1940f7df2e56Smrg        req->nModMapKeys = 0;
1941f7df2e56Smrg        return 1;
1942f7df2e56Smrg    }
1943f7df2e56Smrg    first = req->firstModMapKey;
1944f7df2e56Smrg    last = first + req->nModMapKeys - 1;
1945f7df2e56Smrg    if (first < req->minKeyCode) {
1946f7df2e56Smrg        *errRtrn = _XkbErrCode3(0x61, first, req->minKeyCode);
1947f7df2e56Smrg        return 0;
1948f7df2e56Smrg    }
1949f7df2e56Smrg    if (last > req->maxKeyCode) {
1950f7df2e56Smrg        *errRtrn = _XkbErrCode3(0x62, last, req->maxKeyCode);
1951f7df2e56Smrg        return 0;
1952f7df2e56Smrg    }
1953f7df2e56Smrg    start = wire;
1954f7df2e56Smrg    for (i = 0; i < req->totalModMapKeys; i++, wire += 2) {
1955f7df2e56Smrg        if ((wire[0] < first) || (wire[0] > last)) {
1956f7df2e56Smrg            *errRtrn = _XkbErrCode4(0x63, first, last, wire[0]);
1957f7df2e56Smrg            return 0;
1958f7df2e56Smrg        }
1959f7df2e56Smrg    }
1960f7df2e56Smrg    wire += XkbPaddedSize(wire - start) - (wire - start);
1961f7df2e56Smrg    *wireRtrn = wire;
196205b261ecSmrg    return 1;
196305b261ecSmrg}
196405b261ecSmrg
196505b261ecSmrgstatic int
1966f7df2e56SmrgCheckVirtualModMap(XkbDescPtr xkb,
1967f7df2e56Smrg                   xkbSetMapReq * req,
1968f7df2e56Smrg                   xkbVModMapWireDesc ** wireRtrn, int *errRtrn)
196905b261ecSmrg{
1970f7df2e56Smrg    register xkbVModMapWireDesc *wire = *wireRtrn;
1971f7df2e56Smrg    register unsigned i;
1972f7df2e56Smrg    int first, last;
1973f7df2e56Smrg
1974f7df2e56Smrg    if (((req->present & XkbVirtualModMapMask) == 0) || (req->nVModMapKeys < 1)) {
1975f7df2e56Smrg        req->present &= ~XkbVirtualModMapMask;
1976f7df2e56Smrg        req->nVModMapKeys = 0;
1977f7df2e56Smrg        return 1;
1978f7df2e56Smrg    }
1979f7df2e56Smrg    first = req->firstVModMapKey;
1980f7df2e56Smrg    last = first + req->nVModMapKeys - 1;
1981f7df2e56Smrg    if (first < req->minKeyCode) {
1982f7df2e56Smrg        *errRtrn = _XkbErrCode3(0x71, first, req->minKeyCode);
1983f7df2e56Smrg        return 0;
1984f7df2e56Smrg    }
1985f7df2e56Smrg    if (last > req->maxKeyCode) {
1986f7df2e56Smrg        *errRtrn = _XkbErrCode3(0x72, last, req->maxKeyCode);
1987f7df2e56Smrg        return 0;
1988f7df2e56Smrg    }
1989f7df2e56Smrg    for (i = 0; i < req->totalVModMapKeys; i++, wire++) {
1990f7df2e56Smrg        if ((wire->key < first) || (wire->key > last)) {
1991f7df2e56Smrg            *errRtrn = _XkbErrCode4(0x73, first, last, wire->key);
1992f7df2e56Smrg            return 0;
1993f7df2e56Smrg        }
1994f7df2e56Smrg    }
1995f7df2e56Smrg    *wireRtrn = wire;
199605b261ecSmrg    return 1;
199705b261ecSmrg}
199805b261ecSmrg
199905b261ecSmrgstatic char *
2000f7df2e56SmrgSetKeyTypes(XkbDescPtr xkb,
2001f7df2e56Smrg            xkbSetMapReq * req,
2002f7df2e56Smrg            xkbKeyTypeWireDesc * wire, XkbChangesPtr changes)
200305b261ecSmrg{
2004f7df2e56Smrg    register unsigned i;
2005f7df2e56Smrg    unsigned first, last;
2006f7df2e56Smrg    CARD8 *map;
2007f7df2e56Smrg
2008f7df2e56Smrg    if ((unsigned) (req->firstType + req->nTypes) > xkb->map->size_types) {
2009f7df2e56Smrg        i = req->firstType + req->nTypes;
2010f7df2e56Smrg        if (XkbAllocClientMap(xkb, XkbKeyTypesMask, i) != Success) {
2011f7df2e56Smrg            return NULL;
2012f7df2e56Smrg        }
2013f7df2e56Smrg    }
2014f7df2e56Smrg    if ((unsigned) (req->firstType + req->nTypes) > xkb->map->num_types)
2015f7df2e56Smrg        xkb->map->num_types = req->firstType + req->nTypes;
2016f7df2e56Smrg
2017f7df2e56Smrg    for (i = 0; i < req->nTypes; i++) {
2018f7df2e56Smrg        XkbKeyTypePtr pOld;
2019f7df2e56Smrg        register unsigned n;
2020f7df2e56Smrg
2021f7df2e56Smrg        if (XkbResizeKeyType(xkb, i + req->firstType, wire->nMapEntries,
2022f7df2e56Smrg                             wire->preserve, wire->numLevels) != Success) {
2023f7df2e56Smrg            return NULL;
2024f7df2e56Smrg        }
2025f7df2e56Smrg        pOld = &xkb->map->types[i + req->firstType];
2026f7df2e56Smrg        map = (CARD8 *) &wire[1];
2027f7df2e56Smrg
2028f7df2e56Smrg        pOld->mods.real_mods = wire->realMods;
2029f7df2e56Smrg        pOld->mods.vmods = wire->virtualMods;
2030f7df2e56Smrg        pOld->num_levels = wire->numLevels;
2031f7df2e56Smrg        pOld->map_count = wire->nMapEntries;
2032f7df2e56Smrg
2033f7df2e56Smrg        pOld->mods.mask = pOld->mods.real_mods |
2034f7df2e56Smrg            XkbMaskForVMask(xkb, pOld->mods.vmods);
2035f7df2e56Smrg
2036f7df2e56Smrg        if (wire->nMapEntries) {
2037f7df2e56Smrg            xkbKTSetMapEntryWireDesc *mapWire;
2038f7df2e56Smrg            xkbModsWireDesc *preWire;
2039f7df2e56Smrg            unsigned tmp;
2040f7df2e56Smrg
2041f7df2e56Smrg            mapWire = (xkbKTSetMapEntryWireDesc *) map;
2042f7df2e56Smrg            preWire = (xkbModsWireDesc *) &mapWire[wire->nMapEntries];
2043f7df2e56Smrg            for (n = 0; n < wire->nMapEntries; n++) {
2044f7df2e56Smrg                pOld->map[n].active = 1;
2045f7df2e56Smrg                pOld->map[n].mods.mask = mapWire[n].realMods;
2046f7df2e56Smrg                pOld->map[n].mods.real_mods = mapWire[n].realMods;
2047f7df2e56Smrg                pOld->map[n].mods.vmods = mapWire[n].virtualMods;
2048f7df2e56Smrg                pOld->map[n].level = mapWire[n].level;
2049f7df2e56Smrg                if (mapWire[n].virtualMods != 0) {
2050f7df2e56Smrg                    tmp = XkbMaskForVMask(xkb, mapWire[n].virtualMods);
2051f7df2e56Smrg                    pOld->map[n].active = (tmp != 0);
2052f7df2e56Smrg                    pOld->map[n].mods.mask |= tmp;
2053f7df2e56Smrg                }
2054f7df2e56Smrg                if (wire->preserve) {
2055f7df2e56Smrg                    pOld->preserve[n].real_mods = preWire[n].realMods;
2056f7df2e56Smrg                    pOld->preserve[n].vmods = preWire[n].virtualMods;
2057f7df2e56Smrg                    tmp = XkbMaskForVMask(xkb, preWire[n].virtualMods);
2058f7df2e56Smrg                    pOld->preserve[n].mask = preWire[n].realMods | tmp;
2059f7df2e56Smrg                }
2060f7df2e56Smrg            }
2061f7df2e56Smrg            if (wire->preserve)
2062f7df2e56Smrg                map = (CARD8 *) &preWire[wire->nMapEntries];
2063f7df2e56Smrg            else
2064f7df2e56Smrg                map = (CARD8 *) &mapWire[wire->nMapEntries];
2065f7df2e56Smrg        }
2066f7df2e56Smrg        else
2067f7df2e56Smrg            map = (CARD8 *) &wire[1];
2068f7df2e56Smrg        wire = (xkbKeyTypeWireDesc *) map;
2069f7df2e56Smrg    }
2070f7df2e56Smrg    first = req->firstType;
2071f7df2e56Smrg    last = first + req->nTypes - 1;     /* last changed type */
2072f7df2e56Smrg    if (changes->map.changed & XkbKeyTypesMask) {
2073f7df2e56Smrg        int oldLast;
2074f7df2e56Smrg
2075f7df2e56Smrg        oldLast = changes->map.first_type + changes->map.num_types - 1;
2076f7df2e56Smrg        if (changes->map.first_type < first)
2077f7df2e56Smrg            first = changes->map.first_type;
2078f7df2e56Smrg        if (oldLast > last)
2079f7df2e56Smrg            last = oldLast;
2080f7df2e56Smrg    }
2081f7df2e56Smrg    changes->map.changed |= XkbKeyTypesMask;
208205b261ecSmrg    changes->map.first_type = first;
2083f7df2e56Smrg    changes->map.num_types = (last - first) + 1;
2084f7df2e56Smrg    return (char *) wire;
208505b261ecSmrg}
208605b261ecSmrg
208705b261ecSmrgstatic char *
2088f7df2e56SmrgSetKeySyms(ClientPtr client,
2089f7df2e56Smrg           XkbDescPtr xkb,
2090f7df2e56Smrg           xkbSetMapReq * req,
2091f7df2e56Smrg           xkbSymMapWireDesc * wire, XkbChangesPtr changes, DeviceIntPtr dev)
209205b261ecSmrg{
2093f7df2e56Smrg    register unsigned i, s;
2094f7df2e56Smrg    XkbSymMapPtr oldMap;
2095f7df2e56Smrg    KeySym *newSyms;
2096f7df2e56Smrg    KeySym *pSyms;
2097f7df2e56Smrg    unsigned first, last;
209805b261ecSmrg
209905b261ecSmrg    oldMap = &xkb->map->key_sym_map[req->firstKeySym];
2100f7df2e56Smrg    for (i = 0; i < req->nKeySyms; i++, oldMap++) {
2101f7df2e56Smrg        pSyms = (KeySym *) &wire[1];
2102f7df2e56Smrg        if (wire->nSyms > 0) {
2103f7df2e56Smrg            newSyms = XkbResizeKeySyms(xkb, i + req->firstKeySym, wire->nSyms);
2104f7df2e56Smrg            for (s = 0; s < wire->nSyms; s++) {
2105f7df2e56Smrg                newSyms[s] = pSyms[s];
2106f7df2e56Smrg            }
2107f7df2e56Smrg            if (client->swapped) {
2108f7df2e56Smrg                for (s = 0; s < wire->nSyms; s++) {
2109f7df2e56Smrg                    swapl(&newSyms[s]);
2110f7df2e56Smrg                }
2111f7df2e56Smrg            }
2112f7df2e56Smrg        }
2113f7df2e56Smrg        oldMap->kt_index[0] = wire->ktIndex[0];
2114f7df2e56Smrg        oldMap->kt_index[1] = wire->ktIndex[1];
2115f7df2e56Smrg        oldMap->kt_index[2] = wire->ktIndex[2];
2116f7df2e56Smrg        oldMap->kt_index[3] = wire->ktIndex[3];
2117f7df2e56Smrg        oldMap->group_info = wire->groupInfo;
2118f7df2e56Smrg        oldMap->width = wire->width;
2119f7df2e56Smrg        wire = (xkbSymMapWireDesc *) &pSyms[wire->nSyms];
2120f7df2e56Smrg    }
2121f7df2e56Smrg    first = req->firstKeySym;
2122f7df2e56Smrg    last = first + req->nKeySyms - 1;
2123f7df2e56Smrg    if (changes->map.changed & XkbKeySymsMask) {
2124f7df2e56Smrg        int oldLast =
2125f7df2e56Smrg            (changes->map.first_key_sym + changes->map.num_key_syms - 1);
2126f7df2e56Smrg        if (changes->map.first_key_sym < first)
2127f7df2e56Smrg            first = changes->map.first_key_sym;
2128f7df2e56Smrg        if (oldLast > last)
2129f7df2e56Smrg            last = oldLast;
2130f7df2e56Smrg    }
2131f7df2e56Smrg    changes->map.changed |= XkbKeySymsMask;
213205b261ecSmrg    changes->map.first_key_sym = first;
2133f7df2e56Smrg    changes->map.num_key_syms = (last - first + 1);
2134f7df2e56Smrg
2135f7df2e56Smrg    s = 0;
2136f7df2e56Smrg    for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
2137f7df2e56Smrg        if (XkbKeyNumGroups(xkb, i) > s)
2138f7df2e56Smrg            s = XkbKeyNumGroups(xkb, i);
2139f7df2e56Smrg    }
2140f7df2e56Smrg    if (s != xkb->ctrls->num_groups) {
2141f7df2e56Smrg        xkbControlsNotify cn;
2142f7df2e56Smrg        XkbControlsRec old;
2143f7df2e56Smrg
2144f7df2e56Smrg        cn.keycode = 0;
2145f7df2e56Smrg        cn.eventType = 0;
2146f7df2e56Smrg        cn.requestMajor = XkbReqCode;
2147f7df2e56Smrg        cn.requestMinor = X_kbSetMap;
2148f7df2e56Smrg        old = *xkb->ctrls;
2149f7df2e56Smrg        xkb->ctrls->num_groups = s;
2150f7df2e56Smrg        if (XkbComputeControlsNotify(dev, &old, xkb->ctrls, &cn, FALSE))
2151f7df2e56Smrg            XkbSendControlsNotify(dev, &cn);
2152f7df2e56Smrg    }
2153f7df2e56Smrg    return (char *) wire;
215405b261ecSmrg}
215505b261ecSmrg
215605b261ecSmrgstatic char *
2157f7df2e56SmrgSetKeyActions(XkbDescPtr xkb,
2158f7df2e56Smrg              xkbSetMapReq * req, CARD8 *wire, XkbChangesPtr changes)
215905b261ecSmrg{
2160f7df2e56Smrg    register unsigned i, first, last;
2161f7df2e56Smrg    CARD8 *nActs = wire;
2162f7df2e56Smrg    XkbAction *newActs;
2163f7df2e56Smrg
2164f7df2e56Smrg    wire += XkbPaddedSize(req->nKeyActs);
2165f7df2e56Smrg    for (i = 0; i < req->nKeyActs; i++) {
2166f7df2e56Smrg        if (nActs[i] == 0)
2167f7df2e56Smrg            xkb->server->key_acts[i + req->firstKeyAct] = 0;
2168f7df2e56Smrg        else {
2169f7df2e56Smrg            newActs = XkbResizeKeyActions(xkb, i + req->firstKeyAct, nActs[i]);
2170f7df2e56Smrg            memcpy((char *) newActs, (char *) wire,
2171f7df2e56Smrg                   nActs[i] * SIZEOF(xkbActionWireDesc));
2172f7df2e56Smrg            wire += nActs[i] * SIZEOF(xkbActionWireDesc);
2173f7df2e56Smrg        }
2174f7df2e56Smrg    }
2175f7df2e56Smrg    first = req->firstKeyAct;
2176f7df2e56Smrg    last = (first + req->nKeyActs - 1);
2177f7df2e56Smrg    if (changes->map.changed & XkbKeyActionsMask) {
2178f7df2e56Smrg        int oldLast;
2179f7df2e56Smrg
2180f7df2e56Smrg        oldLast = changes->map.first_key_act + changes->map.num_key_acts - 1;
2181f7df2e56Smrg        if (changes->map.first_key_act < first)
2182f7df2e56Smrg            first = changes->map.first_key_act;
2183f7df2e56Smrg        if (oldLast > last)
2184f7df2e56Smrg            last = oldLast;
2185f7df2e56Smrg    }
2186f7df2e56Smrg    changes->map.changed |= XkbKeyActionsMask;
2187f7df2e56Smrg    changes->map.first_key_act = first;
2188f7df2e56Smrg    changes->map.num_key_acts = (last - first + 1);
2189f7df2e56Smrg    return (char *) wire;
219005b261ecSmrg}
219105b261ecSmrg
219205b261ecSmrgstatic char *
2193f7df2e56SmrgSetKeyBehaviors(XkbSrvInfoPtr xkbi,
2194f7df2e56Smrg                xkbSetMapReq * req,
2195f7df2e56Smrg                xkbBehaviorWireDesc * wire, XkbChangesPtr changes)
219605b261ecSmrg{
2197f7df2e56Smrg    register unsigned i;
2198f7df2e56Smrg    int maxRG = -1;
2199f7df2e56Smrg    XkbDescPtr xkb = xkbi->desc;
2200f7df2e56Smrg    XkbServerMapPtr server = xkb->server;
2201f7df2e56Smrg    unsigned first, last;
2202f7df2e56Smrg
2203f7df2e56Smrg    first = req->firstKeyBehavior;
2204f7df2e56Smrg    last = req->firstKeyBehavior + req->nKeyBehaviors - 1;
2205f7df2e56Smrg    memset(&server->behaviors[first], 0,
2206f7df2e56Smrg           req->nKeyBehaviors * sizeof(XkbBehavior));
2207f7df2e56Smrg    for (i = 0; i < req->totalKeyBehaviors; i++) {
2208f7df2e56Smrg        if ((server->behaviors[wire->key].type & XkbKB_Permanent) == 0) {
2209f7df2e56Smrg            server->behaviors[wire->key].type = wire->type;
2210f7df2e56Smrg            server->behaviors[wire->key].data = wire->data;
2211f7df2e56Smrg            if ((wire->type == XkbKB_RadioGroup) &&
2212f7df2e56Smrg                (((int) wire->data) > maxRG))
2213f7df2e56Smrg                maxRG = wire->data + 1;
2214f7df2e56Smrg        }
2215f7df2e56Smrg        wire++;
2216f7df2e56Smrg    }
2217f7df2e56Smrg
2218f7df2e56Smrg    if (maxRG > (int) xkbi->nRadioGroups) {
221905b261ecSmrg        if (xkbi->radioGroups)
2220f7df2e56Smrg            xkbi->radioGroups = reallocarray(xkbi->radioGroups, maxRG,
2221f7df2e56Smrg                                             sizeof(XkbRadioGroupRec));
2222f7df2e56Smrg        else
2223f7df2e56Smrg            xkbi->radioGroups = calloc(maxRG, sizeof(XkbRadioGroupRec));
222405b261ecSmrg        if (xkbi->radioGroups) {
2225f7df2e56Smrg            if (xkbi->nRadioGroups)
2226f7df2e56Smrg                memset(&xkbi->radioGroups[xkbi->nRadioGroups], 0,
2227f7df2e56Smrg                       (maxRG - xkbi->nRadioGroups) * sizeof(XkbRadioGroupRec));
2228f7df2e56Smrg            xkbi->nRadioGroups = maxRG;
222905b261ecSmrg        }
2230f7df2e56Smrg        else
2231f7df2e56Smrg            xkbi->nRadioGroups = 0;
223205b261ecSmrg        /* should compute members here */
223305b261ecSmrg    }
2234f7df2e56Smrg    if (changes->map.changed & XkbKeyBehaviorsMask) {
2235f7df2e56Smrg        unsigned oldLast;
2236f7df2e56Smrg
2237f7df2e56Smrg        oldLast = changes->map.first_key_behavior +
2238f7df2e56Smrg            changes->map.num_key_behaviors - 1;
2239f7df2e56Smrg        if (changes->map.first_key_behavior < req->firstKeyBehavior)
2240f7df2e56Smrg            first = changes->map.first_key_behavior;
2241f7df2e56Smrg        if (oldLast > last)
2242f7df2e56Smrg            last = oldLast;
224305b261ecSmrg    }
2244f7df2e56Smrg    changes->map.changed |= XkbKeyBehaviorsMask;
224505b261ecSmrg    changes->map.first_key_behavior = first;
2246f7df2e56Smrg    changes->map.num_key_behaviors = (last - first + 1);
2247f7df2e56Smrg    return (char *) wire;
224805b261ecSmrg}
224905b261ecSmrg
225005b261ecSmrgstatic char *
2251f7df2e56SmrgSetVirtualMods(XkbSrvInfoPtr xkbi, xkbSetMapReq * req, CARD8 *wire,
2252f7df2e56Smrg               XkbChangesPtr changes)
225305b261ecSmrg{
2254f7df2e56Smrg    register int i, bit, nMods;
2255f7df2e56Smrg    XkbServerMapPtr srv = xkbi->desc->server;
2256f7df2e56Smrg
2257f7df2e56Smrg    if (((req->present & XkbVirtualModsMask) == 0) || (req->virtualMods == 0))
2258f7df2e56Smrg        return (char *) wire;
2259f7df2e56Smrg    for (i = nMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
2260f7df2e56Smrg        if (req->virtualMods & bit) {
2261f7df2e56Smrg            if (srv->vmods[i] != wire[nMods]) {
2262f7df2e56Smrg                changes->map.changed |= XkbVirtualModsMask;
2263f7df2e56Smrg                changes->map.vmods |= bit;
2264f7df2e56Smrg                srv->vmods[i] = wire[nMods];
2265f7df2e56Smrg            }
2266f7df2e56Smrg            nMods++;
2267f7df2e56Smrg        }
2268f7df2e56Smrg    }
2269f7df2e56Smrg    return (char *) (wire + XkbPaddedSize(nMods));
227005b261ecSmrg}
227105b261ecSmrg
227205b261ecSmrgstatic char *
2273f7df2e56SmrgSetKeyExplicit(XkbSrvInfoPtr xkbi, xkbSetMapReq * req, CARD8 *wire,
2274f7df2e56Smrg               XkbChangesPtr changes)
227505b261ecSmrg{
2276f7df2e56Smrg    register unsigned i, first, last;
2277f7df2e56Smrg    XkbServerMapPtr xkb = xkbi->desc->server;
2278f7df2e56Smrg    CARD8 *start;
227905b261ecSmrg
2280f7df2e56Smrg    start = wire;
2281f7df2e56Smrg    first = req->firstKeyExplicit;
2282f7df2e56Smrg    last = req->firstKeyExplicit + req->nKeyExplicit - 1;
22836747b715Smrg    memset(&xkb->explicit[first], 0, req->nKeyExplicit);
2284f7df2e56Smrg    for (i = 0; i < req->totalKeyExplicit; i++, wire += 2) {
2285f7df2e56Smrg        xkb->explicit[wire[0]] = wire[1];
2286f7df2e56Smrg    }
2287f7df2e56Smrg    if (first > 0) {
2288f7df2e56Smrg        if (changes->map.changed & XkbExplicitComponentsMask) {
2289f7df2e56Smrg            int oldLast;
2290f7df2e56Smrg
2291f7df2e56Smrg            oldLast = changes->map.first_key_explicit +
2292f7df2e56Smrg                changes->map.num_key_explicit - 1;
2293f7df2e56Smrg            if (changes->map.first_key_explicit < first)
2294f7df2e56Smrg                first = changes->map.first_key_explicit;
2295f7df2e56Smrg            if (oldLast > last)
2296f7df2e56Smrg                last = oldLast;
2297f7df2e56Smrg        }
2298f7df2e56Smrg        changes->map.first_key_explicit = first;
2299f7df2e56Smrg        changes->map.num_key_explicit = (last - first) + 1;
2300f7df2e56Smrg    }
2301f7df2e56Smrg    wire += XkbPaddedSize(wire - start) - (wire - start);
2302f7df2e56Smrg    return (char *) wire;
230305b261ecSmrg}
230405b261ecSmrg
230505b261ecSmrgstatic char *
2306f7df2e56SmrgSetModifierMap(XkbSrvInfoPtr xkbi,
2307f7df2e56Smrg               xkbSetMapReq * req, CARD8 *wire, XkbChangesPtr changes)
230805b261ecSmrg{
2309f7df2e56Smrg    register unsigned i, first, last;
2310f7df2e56Smrg    XkbClientMapPtr xkb = xkbi->desc->map;
2311f7df2e56Smrg    CARD8 *start;
231205b261ecSmrg
2313f7df2e56Smrg    start = wire;
2314f7df2e56Smrg    first = req->firstModMapKey;
2315f7df2e56Smrg    last = req->firstModMapKey + req->nModMapKeys - 1;
23166747b715Smrg    memset(&xkb->modmap[first], 0, req->nModMapKeys);
2317f7df2e56Smrg    for (i = 0; i < req->totalModMapKeys; i++, wire += 2) {
2318f7df2e56Smrg        xkb->modmap[wire[0]] = wire[1];
2319f7df2e56Smrg    }
2320f7df2e56Smrg    if (first > 0) {
2321f7df2e56Smrg        if (changes->map.changed & XkbModifierMapMask) {
2322f7df2e56Smrg            int oldLast;
2323f7df2e56Smrg
2324f7df2e56Smrg            oldLast = changes->map.first_modmap_key +
2325f7df2e56Smrg                changes->map.num_modmap_keys - 1;
2326f7df2e56Smrg            if (changes->map.first_modmap_key < first)
2327f7df2e56Smrg                first = changes->map.first_modmap_key;
2328f7df2e56Smrg            if (oldLast > last)
2329f7df2e56Smrg                last = oldLast;
2330f7df2e56Smrg        }
2331f7df2e56Smrg        changes->map.first_modmap_key = first;
2332f7df2e56Smrg        changes->map.num_modmap_keys = (last - first) + 1;
2333f7df2e56Smrg    }
2334f7df2e56Smrg    wire += XkbPaddedSize(wire - start) - (wire - start);
2335f7df2e56Smrg    return (char *) wire;
233605b261ecSmrg}
233705b261ecSmrg
233805b261ecSmrgstatic char *
2339f7df2e56SmrgSetVirtualModMap(XkbSrvInfoPtr xkbi,
2340f7df2e56Smrg                 xkbSetMapReq * req,
2341f7df2e56Smrg                 xkbVModMapWireDesc * wire, XkbChangesPtr changes)
234205b261ecSmrg{
2343f7df2e56Smrg    register unsigned i, first, last;
2344f7df2e56Smrg    XkbServerMapPtr srv = xkbi->desc->server;
2345f7df2e56Smrg
2346f7df2e56Smrg    first = req->firstVModMapKey;
2347f7df2e56Smrg    last = req->firstVModMapKey + req->nVModMapKeys - 1;
2348f7df2e56Smrg    memset(&srv->vmodmap[first], 0, req->nVModMapKeys * sizeof(unsigned short));
2349f7df2e56Smrg    for (i = 0; i < req->totalVModMapKeys; i++, wire++) {
2350f7df2e56Smrg        srv->vmodmap[wire->key] = wire->vmods;
2351f7df2e56Smrg    }
2352f7df2e56Smrg    if (first > 0) {
2353f7df2e56Smrg        if (changes->map.changed & XkbVirtualModMapMask) {
2354f7df2e56Smrg            int oldLast;
2355f7df2e56Smrg
2356f7df2e56Smrg            oldLast = changes->map.first_vmodmap_key +
2357f7df2e56Smrg                changes->map.num_vmodmap_keys - 1;
2358f7df2e56Smrg            if (changes->map.first_vmodmap_key < first)
2359f7df2e56Smrg                first = changes->map.first_vmodmap_key;
2360f7df2e56Smrg            if (oldLast > last)
2361f7df2e56Smrg                last = oldLast;
2362f7df2e56Smrg        }
2363f7df2e56Smrg        changes->map.first_vmodmap_key = first;
2364f7df2e56Smrg        changes->map.num_vmodmap_keys = (last - first) + 1;
2365f7df2e56Smrg    }
2366f7df2e56Smrg    return (char *) wire;
236705b261ecSmrg}
236805b261ecSmrg
23694642e01fSmrg/**
23704642e01fSmrg * Check if the given request can be applied to the given device but don't
23714642e01fSmrg * actually do anything..
23724642e01fSmrg */
23734642e01fSmrgstatic int
2374f7df2e56Smrg_XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq * req,
2375f7df2e56Smrg                 char *values)
237605b261ecSmrg{
2377f7df2e56Smrg    XkbSrvInfoPtr xkbi;
2378f7df2e56Smrg    XkbDescPtr xkb;
2379f7df2e56Smrg    int error;
2380f7df2e56Smrg    int nTypes = 0, nActions;
2381f7df2e56Smrg    CARD8 mapWidths[XkbMaxLegalKeyCode + 1] = { 0 };
2382f7df2e56Smrg    CARD16 symsPerKey[XkbMaxLegalKeyCode + 1] = { 0 };
2383f7df2e56Smrg    XkbSymMapPtr map;
2384f7df2e56Smrg    int i;
2385f7df2e56Smrg
2386f7df2e56Smrg    xkbi = dev->key->xkbInfo;
238705b261ecSmrg    xkb = xkbi->desc;
238805b261ecSmrg
2389f7df2e56Smrg    if ((xkb->min_key_code != req->minKeyCode) ||
23904642e01fSmrg        (xkb->max_key_code != req->maxKeyCode)) {
2391f7df2e56Smrg        if (client->vMajor != 1) {      /* pre 1.0 versions of Xlib have a bug */
2392f7df2e56Smrg            req->minKeyCode = xkb->min_key_code;
2393f7df2e56Smrg            req->maxKeyCode = xkb->max_key_code;
2394f7df2e56Smrg        }
2395f7df2e56Smrg        else {
2396f7df2e56Smrg            if (!XkbIsLegalKeycode(req->minKeyCode)) {
2397f7df2e56Smrg                client->errorValue =
2398f7df2e56Smrg                    _XkbErrCode3(2, req->minKeyCode, req->maxKeyCode);
2399f7df2e56Smrg                return BadValue;
2400f7df2e56Smrg            }
2401f7df2e56Smrg            if (req->minKeyCode > req->maxKeyCode) {
2402f7df2e56Smrg                client->errorValue =
2403f7df2e56Smrg                    _XkbErrCode3(3, req->minKeyCode, req->maxKeyCode);
2404f7df2e56Smrg                return BadMatch;
2405f7df2e56Smrg            }
2406f7df2e56Smrg        }
240705b261ecSmrg    }
240805b261ecSmrg
24094642e01fSmrg    if ((req->present & XkbKeyTypesMask) &&
2410f7df2e56Smrg        (!CheckKeyTypes(client, xkb, req, (xkbKeyTypeWireDesc **) &values,
2411f7df2e56Smrg                        &nTypes, mapWidths))) {
2412f7df2e56Smrg        client->errorValue = nTypes;
2413f7df2e56Smrg        return BadValue;
241405b261ecSmrg    }
24159ace9065Smrg
24169ace9065Smrg    /* symsPerKey/mapWidths must be filled regardless of client-side flags */
24179ace9065Smrg    map = &xkb->map->key_sym_map[xkb->min_key_code];
2418f7df2e56Smrg    for (i = xkb->min_key_code; i < xkb->max_key_code; i++, map++) {
2419f7df2e56Smrg        register int g, ng, w;
2420f7df2e56Smrg
2421f7df2e56Smrg        ng = XkbNumGroups(map->group_info);
2422f7df2e56Smrg        for (w = g = 0; g < ng; g++) {
2423f7df2e56Smrg            if (map->kt_index[g] >= (unsigned) nTypes) {
2424f7df2e56Smrg                client->errorValue = _XkbErrCode4(0x13, i, g, map->kt_index[g]);
2425f7df2e56Smrg                return 0;
2426f7df2e56Smrg            }
2427f7df2e56Smrg            if (mapWidths[map->kt_index[g]] > w)
2428f7df2e56Smrg                w = mapWidths[map->kt_index[g]];
2429f7df2e56Smrg        }
2430f7df2e56Smrg        symsPerKey[i] = w * ng;
24319ace9065Smrg    }
24329ace9065Smrg
24334642e01fSmrg    if ((req->present & XkbKeySymsMask) &&
2434f7df2e56Smrg        (!CheckKeySyms(client, xkb, req, nTypes, mapWidths, symsPerKey,
2435f7df2e56Smrg                       (xkbSymMapWireDesc **) &values, &error))) {
2436f7df2e56Smrg        client->errorValue = error;
2437f7df2e56Smrg        return BadValue;
243805b261ecSmrg    }
243905b261ecSmrg
24404642e01fSmrg    if ((req->present & XkbKeyActionsMask) &&
2441f7df2e56Smrg        (!CheckKeyActions(xkb, req, nTypes, mapWidths, symsPerKey,
2442f7df2e56Smrg                          (CARD8 **) &values, &nActions))) {
2443f7df2e56Smrg        client->errorValue = nActions;
2444f7df2e56Smrg        return BadValue;
244505b261ecSmrg    }
244605b261ecSmrg
24474642e01fSmrg    if ((req->present & XkbKeyBehaviorsMask) &&
2448f7df2e56Smrg        (!CheckKeyBehaviors
2449f7df2e56Smrg         (xkb, req, (xkbBehaviorWireDesc **) &values, &error))) {
2450f7df2e56Smrg        client->errorValue = error;
2451f7df2e56Smrg        return BadValue;
245205b261ecSmrg    }
245305b261ecSmrg
24544642e01fSmrg    if ((req->present & XkbVirtualModsMask) &&
2455f7df2e56Smrg        (!CheckVirtualMods(xkb, req, (CARD8 **) &values, &error))) {
2456f7df2e56Smrg        client->errorValue = error;
2457f7df2e56Smrg        return BadValue;
245805b261ecSmrg    }
2459f7df2e56Smrg    if ((req->present & XkbExplicitComponentsMask) &&
2460f7df2e56Smrg        (!CheckKeyExplicit(xkb, req, (CARD8 **) &values, &error))) {
2461f7df2e56Smrg        client->errorValue = error;
2462f7df2e56Smrg        return BadValue;
246305b261ecSmrg    }
2464f7df2e56Smrg    if ((req->present & XkbModifierMapMask) &&
2465f7df2e56Smrg        (!CheckModifierMap(xkb, req, (CARD8 **) &values, &error))) {
2466f7df2e56Smrg        client->errorValue = error;
2467f7df2e56Smrg        return BadValue;
246805b261ecSmrg    }
2469f7df2e56Smrg    if ((req->present & XkbVirtualModMapMask) &&
2470f7df2e56Smrg        (!CheckVirtualModMap
2471f7df2e56Smrg         (xkb, req, (xkbVModMapWireDesc **) &values, &error))) {
2472f7df2e56Smrg        client->errorValue = error;
2473f7df2e56Smrg        return BadValue;
247405b261ecSmrg    }
24754642e01fSmrg
2476f7df2e56Smrg    if (((values - ((char *) req)) / 4) != req->length) {
2477f7df2e56Smrg        ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after check)\n");
2478f7df2e56Smrg        client->errorValue = values - ((char *) &req[1]);
2479f7df2e56Smrg        return BadLength;
248005b261ecSmrg    }
24814642e01fSmrg
24824642e01fSmrg    return Success;
24834642e01fSmrg}
24844642e01fSmrg
24854642e01fSmrg/**
24864642e01fSmrg * Apply the given request on the given device.
24874642e01fSmrg */
24884642e01fSmrgstatic int
2489f7df2e56Smrg_XkbSetMap(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq * req, char *values)
24904642e01fSmrg{
2491f7df2e56Smrg    XkbEventCauseRec cause;
2492f7df2e56Smrg    XkbChangesRec change;
2493f7df2e56Smrg    Bool sentNKN;
2494f7df2e56Smrg    XkbSrvInfoPtr xkbi;
2495f7df2e56Smrg    XkbDescPtr xkb;
24964642e01fSmrg
2497f7df2e56Smrg    xkbi = dev->key->xkbInfo;
24984642e01fSmrg    xkb = xkbi->desc;
24994642e01fSmrg
2500f7df2e56Smrg    XkbSetCauseXkbReq(&cause, X_kbSetMap, client);
25016747b715Smrg    memset(&change, 0, sizeof(change));
25026747b715Smrg    sentNKN = FALSE;
2503f7df2e56Smrg    if ((xkb->min_key_code != req->minKeyCode) ||
2504f7df2e56Smrg        (xkb->max_key_code != req->maxKeyCode)) {
2505f7df2e56Smrg        Status status;
2506f7df2e56Smrg        xkbNewKeyboardNotify nkn;
2507f7df2e56Smrg
2508f7df2e56Smrg        nkn.deviceID = nkn.oldDeviceID = dev->id;
2509f7df2e56Smrg        nkn.oldMinKeyCode = xkb->min_key_code;
2510f7df2e56Smrg        nkn.oldMaxKeyCode = xkb->max_key_code;
2511f7df2e56Smrg        status = XkbChangeKeycodeRange(xkb, req->minKeyCode,
2512f7df2e56Smrg                                       req->maxKeyCode, &change);
2513f7df2e56Smrg        if (status != Success)
2514f7df2e56Smrg            return status;      /* oh-oh. what about the other keyboards? */
2515f7df2e56Smrg        nkn.minKeyCode = xkb->min_key_code;
2516f7df2e56Smrg        nkn.maxKeyCode = xkb->max_key_code;
2517f7df2e56Smrg        nkn.requestMajor = XkbReqCode;
2518f7df2e56Smrg        nkn.requestMinor = X_kbSetMap;
2519f7df2e56Smrg        nkn.changed = XkbNKN_KeycodesMask;
2520f7df2e56Smrg        XkbSendNewKeyboardNotify(dev, &nkn);
2521f7df2e56Smrg        sentNKN = TRUE;
2522f7df2e56Smrg    }
2523f7df2e56Smrg
2524f7df2e56Smrg    if (req->present & XkbKeyTypesMask) {
2525f7df2e56Smrg        values = SetKeyTypes(xkb, req, (xkbKeyTypeWireDesc *) values, &change);
2526f7df2e56Smrg        if (!values)
2527f7df2e56Smrg            goto allocFailure;
2528f7df2e56Smrg    }
2529f7df2e56Smrg    if (req->present & XkbKeySymsMask) {
2530f7df2e56Smrg        values =
2531f7df2e56Smrg            SetKeySyms(client, xkb, req, (xkbSymMapWireDesc *) values, &change,
2532f7df2e56Smrg                       dev);
2533f7df2e56Smrg        if (!values)
2534f7df2e56Smrg            goto allocFailure;
2535f7df2e56Smrg    }
2536f7df2e56Smrg    if (req->present & XkbKeyActionsMask) {
2537f7df2e56Smrg        values = SetKeyActions(xkb, req, (CARD8 *) values, &change);
2538f7df2e56Smrg        if (!values)
2539f7df2e56Smrg            goto allocFailure;
2540f7df2e56Smrg    }
2541f7df2e56Smrg    if (req->present & XkbKeyBehaviorsMask) {
2542f7df2e56Smrg        values =
2543f7df2e56Smrg            SetKeyBehaviors(xkbi, req, (xkbBehaviorWireDesc *) values, &change);
2544f7df2e56Smrg        if (!values)
2545f7df2e56Smrg            goto allocFailure;
2546f7df2e56Smrg    }
2547f7df2e56Smrg    if (req->present & XkbVirtualModsMask)
2548f7df2e56Smrg        values = SetVirtualMods(xkbi, req, (CARD8 *) values, &change);
2549f7df2e56Smrg    if (req->present & XkbExplicitComponentsMask)
2550f7df2e56Smrg        values = SetKeyExplicit(xkbi, req, (CARD8 *) values, &change);
2551f7df2e56Smrg    if (req->present & XkbModifierMapMask)
2552f7df2e56Smrg        values = SetModifierMap(xkbi, req, (CARD8 *) values, &change);
2553f7df2e56Smrg    if (req->present & XkbVirtualModMapMask)
2554f7df2e56Smrg        values =
2555f7df2e56Smrg            SetVirtualModMap(xkbi, req, (xkbVModMapWireDesc *) values, &change);
2556f7df2e56Smrg    if (((values - ((char *) req)) / 4) != req->length) {
2557f7df2e56Smrg        ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after set)\n");
2558f7df2e56Smrg        client->errorValue = values - ((char *) &req[1]);
2559f7df2e56Smrg        return BadLength;
2560f7df2e56Smrg    }
2561f7df2e56Smrg    if (req->flags & XkbSetMapRecomputeActions) {
2562f7df2e56Smrg        KeyCode first, last, firstMM, lastMM;
2563f7df2e56Smrg
2564f7df2e56Smrg        if (change.map.num_key_syms > 0) {
2565f7df2e56Smrg            first = change.map.first_key_sym;
2566f7df2e56Smrg            last = first + change.map.num_key_syms - 1;
2567f7df2e56Smrg        }
2568f7df2e56Smrg        else
2569f7df2e56Smrg            first = last = 0;
2570f7df2e56Smrg        if (change.map.num_modmap_keys > 0) {
2571f7df2e56Smrg            firstMM = change.map.first_modmap_key;
2572f7df2e56Smrg            lastMM = first + change.map.num_modmap_keys - 1;
2573f7df2e56Smrg        }
2574f7df2e56Smrg        else
2575f7df2e56Smrg            firstMM = lastMM = 0;
2576f7df2e56Smrg        if ((last > 0) && (lastMM > 0)) {
2577f7df2e56Smrg            if (firstMM < first)
2578f7df2e56Smrg                first = firstMM;
2579f7df2e56Smrg            if (lastMM > last)
2580f7df2e56Smrg                last = lastMM;
2581f7df2e56Smrg        }
2582f7df2e56Smrg        else if (lastMM > 0) {
2583f7df2e56Smrg            first = firstMM;
2584f7df2e56Smrg            last = lastMM;
2585f7df2e56Smrg        }
2586f7df2e56Smrg        if (last > 0) {
2587f7df2e56Smrg            unsigned check = 0;
2588f7df2e56Smrg
2589f7df2e56Smrg            XkbUpdateActions(dev, first, (last - first + 1), &change, &check,
2590f7df2e56Smrg                             &cause);
2591f7df2e56Smrg            if (check)
2592f7df2e56Smrg                XkbCheckSecondaryEffects(xkbi, check, &change, &cause);
2593f7df2e56Smrg        }
259405b261ecSmrg    }
259505b261ecSmrg    if (!sentNKN)
2596f7df2e56Smrg        XkbSendNotification(dev, &change, &cause);
259705b261ecSmrg
25984642e01fSmrg    return Success;
2599f7df2e56Smrg allocFailure:
260005b261ecSmrg    return BadAlloc;
260105b261ecSmrg}
260205b261ecSmrg
26034642e01fSmrgint
26044642e01fSmrgProcXkbSetMap(ClientPtr client)
26054642e01fSmrg{
2606f7df2e56Smrg    DeviceIntPtr dev;
2607f7df2e56Smrg    char *tmp;
2608f7df2e56Smrg    int rc;
26094642e01fSmrg
26104642e01fSmrg    REQUEST(xkbSetMapReq);
26114642e01fSmrg    REQUEST_AT_LEAST_SIZE(xkbSetMapReq);
26124642e01fSmrg
2613f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
2614f7df2e56Smrg        return BadAccess;
26154642e01fSmrg
26164642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
2617f7df2e56Smrg    CHK_MASK_LEGAL(0x01, stuff->present, XkbAllMapComponentsMask);
26184642e01fSmrg
2619f7df2e56Smrg    tmp = (char *) &stuff[1];
26204642e01fSmrg
26214642e01fSmrg    /* Check if we can to the SetMap on the requested device. If this
26224642e01fSmrg       succeeds, do the same thing for all extension devices (if needed).
26234642e01fSmrg       If any of them fails, fail.  */
26244642e01fSmrg    rc = _XkbSetMapChecks(client, dev, stuff, tmp);
26254642e01fSmrg
26264642e01fSmrg    if (rc != Success)
26274642e01fSmrg        return rc;
26284642e01fSmrg
2629f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
26304642e01fSmrg        DeviceIntPtr other;
2631f7df2e56Smrg
2632f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
2633f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
2634f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
2635f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
2636f7df2e56Smrg                              DixManageAccess);
2637f7df2e56Smrg                if (rc == Success) {
26384642e01fSmrg                    rc = _XkbSetMapChecks(client, other, stuff, tmp);
26394642e01fSmrg                    if (rc != Success)
26404642e01fSmrg                        return rc;
26414642e01fSmrg                }
26424642e01fSmrg            }
26434642e01fSmrg        }
26444642e01fSmrg    }
26454642e01fSmrg
26464642e01fSmrg    /* We know now that we will succed with the SetMap. In theory anyway. */
26474642e01fSmrg    rc = _XkbSetMap(client, dev, stuff, tmp);
26484642e01fSmrg    if (rc != Success)
26494642e01fSmrg        return rc;
26504642e01fSmrg
2651f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
26524642e01fSmrg        DeviceIntPtr other;
2653f7df2e56Smrg
2654f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
2655f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
2656f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
2657f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
2658f7df2e56Smrg                              DixManageAccess);
26594642e01fSmrg                if (rc == Success)
26604642e01fSmrg                    _XkbSetMap(client, other, stuff, tmp);
26614642e01fSmrg                /* ignore rc. if the SetMap failed although the check above
26624642e01fSmrg                   reported true there isn't much we can do. we still need to
26634642e01fSmrg                   set all other devices, hoping that at least they stay in
26644642e01fSmrg                   sync. */
26654642e01fSmrg            }
26664642e01fSmrg        }
26674642e01fSmrg    }
26684642e01fSmrg
26696747b715Smrg    return Success;
26704642e01fSmrg}
26714642e01fSmrg
267205b261ecSmrg/***====================================================================***/
267305b261ecSmrg
267405b261ecSmrgstatic Status
2675f7df2e56SmrgXkbComputeGetCompatMapReplySize(XkbCompatMapPtr compat,
2676f7df2e56Smrg                                xkbGetCompatMapReply * rep)
267705b261ecSmrg{
2678f7df2e56Smrg    unsigned size, nGroups;
2679f7df2e56Smrg
2680f7df2e56Smrg    nGroups = 0;
2681f7df2e56Smrg    if (rep->groups != 0) {
2682f7df2e56Smrg        register int i, bit;
2683f7df2e56Smrg
2684f7df2e56Smrg        for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2685f7df2e56Smrg            if (rep->groups & bit)
2686f7df2e56Smrg                nGroups++;
2687f7df2e56Smrg        }
2688f7df2e56Smrg    }
2689f7df2e56Smrg    size = nGroups * SIZEOF(xkbModsWireDesc);
2690f7df2e56Smrg    size += (rep->nSI * SIZEOF(xkbSymInterpretWireDesc));
2691f7df2e56Smrg    rep->length = size / 4;
269205b261ecSmrg    return Success;
269305b261ecSmrg}
269405b261ecSmrg
269505b261ecSmrgstatic int
2696f7df2e56SmrgXkbSendCompatMap(ClientPtr client,
2697f7df2e56Smrg                 XkbCompatMapPtr compat, xkbGetCompatMapReply * rep)
269805b261ecSmrg{
2699f7df2e56Smrg    char *data;
2700f7df2e56Smrg    int size;
2701f7df2e56Smrg
2702f7df2e56Smrg    if (rep->length > 0) {
2703f7df2e56Smrg        data = xallocarray(rep->length, 4);
2704f7df2e56Smrg        if (data) {
2705f7df2e56Smrg            register unsigned i, bit;
2706f7df2e56Smrg            xkbModsWireDesc *grp;
2707f7df2e56Smrg            XkbSymInterpretPtr sym = &compat->sym_interpret[rep->firstSI];
2708f7df2e56Smrg            xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *) data;
2709f7df2e56Smrg
2710f7df2e56Smrg            size = rep->length * 4;
2711f7df2e56Smrg
2712f7df2e56Smrg            for (i = 0; i < rep->nSI; i++, sym++, wire++) {
2713f7df2e56Smrg                wire->sym = sym->sym;
2714f7df2e56Smrg                wire->mods = sym->mods;
2715f7df2e56Smrg                wire->match = sym->match;
2716f7df2e56Smrg                wire->virtualMod = sym->virtual_mod;
2717f7df2e56Smrg                wire->flags = sym->flags;
2718f7df2e56Smrg                memcpy((char *) &wire->act, (char *) &sym->act,
2719f7df2e56Smrg                       sz_xkbActionWireDesc);
2720f7df2e56Smrg                if (client->swapped) {
2721f7df2e56Smrg                    swapl(&wire->sym);
2722f7df2e56Smrg                }
2723f7df2e56Smrg            }
2724f7df2e56Smrg            if (rep->groups) {
2725f7df2e56Smrg                grp = (xkbModsWireDesc *) wire;
2726f7df2e56Smrg                for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2727f7df2e56Smrg                    if (rep->groups & bit) {
2728f7df2e56Smrg                        grp->mask = compat->groups[i].mask;
2729f7df2e56Smrg                        grp->realMods = compat->groups[i].real_mods;
2730f7df2e56Smrg                        grp->virtualMods = compat->groups[i].vmods;
2731f7df2e56Smrg                        if (client->swapped) {
2732f7df2e56Smrg                            swaps(&grp->virtualMods);
2733f7df2e56Smrg                        }
2734f7df2e56Smrg                        grp++;
2735f7df2e56Smrg                    }
2736f7df2e56Smrg                }
2737f7df2e56Smrg                wire = (xkbSymInterpretWireDesc *) grp;
2738f7df2e56Smrg            }
2739f7df2e56Smrg        }
2740f7df2e56Smrg        else
2741f7df2e56Smrg            return BadAlloc;
2742f7df2e56Smrg    }
2743f7df2e56Smrg    else
2744f7df2e56Smrg        data = NULL;
274505b261ecSmrg
274605b261ecSmrg    if (client->swapped) {
2747f7df2e56Smrg        swaps(&rep->sequenceNumber);
2748f7df2e56Smrg        swapl(&rep->length);
2749f7df2e56Smrg        swaps(&rep->firstSI);
2750f7df2e56Smrg        swaps(&rep->nSI);
2751f7df2e56Smrg        swaps(&rep->nTotalSI);
275205b261ecSmrg    }
275305b261ecSmrg
2754f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetCompatMapReply), rep);
275505b261ecSmrg    if (data) {
2756f7df2e56Smrg        WriteToClient(client, size, data);
2757f7df2e56Smrg        free((char *) data);
275805b261ecSmrg    }
27596747b715Smrg    return Success;
276005b261ecSmrg}
276105b261ecSmrg
276205b261ecSmrgint
276305b261ecSmrgProcXkbGetCompatMap(ClientPtr client)
276405b261ecSmrg{
2765f7df2e56Smrg    xkbGetCompatMapReply rep;
2766f7df2e56Smrg    DeviceIntPtr dev;
2767f7df2e56Smrg    XkbDescPtr xkb;
2768f7df2e56Smrg    XkbCompatMapPtr compat;
276905b261ecSmrg
277005b261ecSmrg    REQUEST(xkbGetCompatMapReq);
277105b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetCompatMapReq);
277205b261ecSmrg
2773f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
2774f7df2e56Smrg        return BadAccess;
277505b261ecSmrg
27764642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
277705b261ecSmrg
277805b261ecSmrg    xkb = dev->key->xkbInfo->desc;
2779f7df2e56Smrg    compat = xkb->compat;
278005b261ecSmrg
2781f7df2e56Smrg    rep = (xkbGetCompatMapReply) {
2782f7df2e56Smrg        .type = X_Reply,
2783f7df2e56Smrg        .sequenceNumber = client->sequence,
2784f7df2e56Smrg        .length = 0,
2785f7df2e56Smrg        .deviceID = dev->id,
2786f7df2e56Smrg        .firstSI = stuff->firstSI,
2787f7df2e56Smrg        .nSI = stuff->nSI
2788f7df2e56Smrg    };
278905b261ecSmrg    if (stuff->getAllSI) {
2790f7df2e56Smrg        rep.firstSI = 0;
2791f7df2e56Smrg        rep.nSI = compat->num_si;
279205b261ecSmrg    }
2793f7df2e56Smrg    else if ((((unsigned) stuff->nSI) > 0) &&
2794f7df2e56Smrg             ((unsigned) (stuff->firstSI + stuff->nSI - 1) >= compat->num_si)) {
2795f7df2e56Smrg        client->errorValue = _XkbErrCode2(0x05, compat->num_si);
2796f7df2e56Smrg        return BadValue;
279705b261ecSmrg    }
279805b261ecSmrg    rep.nTotalSI = compat->num_si;
2799f7df2e56Smrg    rep.groups = stuff->groups;
2800f7df2e56Smrg    XkbComputeGetCompatMapReplySize(compat, &rep);
2801f7df2e56Smrg    return XkbSendCompatMap(client, compat, &rep);
280205b261ecSmrg}
280305b261ecSmrg
28044642e01fSmrg/**
28054642e01fSmrg * Apply the given request on the given device.
28066747b715Smrg * If dryRun is TRUE, then value checks are performed, but the device isn't
28074642e01fSmrg * modified.
28084642e01fSmrg */
28094642e01fSmrgstatic int
28104642e01fSmrg_XkbSetCompatMap(ClientPtr client, DeviceIntPtr dev,
2811f7df2e56Smrg                 xkbSetCompatMapReq * req, char *data, BOOL dryRun)
281205b261ecSmrg{
2813f7df2e56Smrg    XkbSrvInfoPtr xkbi;
2814f7df2e56Smrg    XkbDescPtr xkb;
2815f7df2e56Smrg    XkbCompatMapPtr compat;
2816f7df2e56Smrg    int nGroups;
2817f7df2e56Smrg    unsigned i, bit;
281805b261ecSmrg
281905b261ecSmrg    xkbi = dev->key->xkbInfo;
28204642e01fSmrg    xkb = xkbi->desc;
28214642e01fSmrg    compat = xkb->compat;
28224642e01fSmrg
2823f7df2e56Smrg    if ((req->nSI > 0) || (req->truncateSI)) {
2824f7df2e56Smrg        xkbSymInterpretWireDesc *wire;
2825f7df2e56Smrg
2826f7df2e56Smrg        if (req->firstSI > compat->num_si) {
2827f7df2e56Smrg            client->errorValue = _XkbErrCode2(0x02, compat->num_si);
2828f7df2e56Smrg            return BadValue;
2829f7df2e56Smrg        }
2830f7df2e56Smrg        wire = (xkbSymInterpretWireDesc *) data;
2831f7df2e56Smrg        wire += req->nSI;
2832f7df2e56Smrg        data = (char *) wire;
283305b261ecSmrg    }
28344642e01fSmrg
2835f7df2e56Smrg    nGroups = 0;
2836f7df2e56Smrg    if (req->groups != 0) {
2837f7df2e56Smrg        for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2838f7df2e56Smrg            if (req->groups & bit)
2839f7df2e56Smrg                nGroups++;
2840f7df2e56Smrg        }
284105b261ecSmrg    }
2842f7df2e56Smrg    data += nGroups * SIZEOF(xkbModsWireDesc);
2843f7df2e56Smrg    if (((data - ((char *) req)) / 4) != req->length) {
2844f7df2e56Smrg        return BadLength;
284505b261ecSmrg    }
28464642e01fSmrg
28474642e01fSmrg    /* Done all the checks we can do */
28484642e01fSmrg    if (dryRun)
28494642e01fSmrg        return Success;
28504642e01fSmrg
2851f7df2e56Smrg    data = (char *) &req[1];
2852f7df2e56Smrg    if (req->nSI > 0) {
2853f7df2e56Smrg        xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *) data;
2854f7df2e56Smrg        XkbSymInterpretPtr sym;
2855f7df2e56Smrg        unsigned int skipped = 0;
2856f7df2e56Smrg
2857f7df2e56Smrg        if ((unsigned) (req->firstSI + req->nSI) > compat->num_si) {
2858f7df2e56Smrg            compat->num_si = req->firstSI + req->nSI;
2859f7df2e56Smrg            compat->sym_interpret = reallocarray(compat->sym_interpret,
2860f7df2e56Smrg                                                 compat->num_si,
2861f7df2e56Smrg                                                 sizeof(XkbSymInterpretRec));
2862f7df2e56Smrg            if (!compat->sym_interpret) {
2863f7df2e56Smrg                compat->num_si = 0;
2864f7df2e56Smrg                return BadAlloc;
2865f7df2e56Smrg            }
2866f7df2e56Smrg        }
2867f7df2e56Smrg        else if (req->truncateSI) {
2868f7df2e56Smrg            compat->num_si = req->firstSI + req->nSI;
2869f7df2e56Smrg        }
2870f7df2e56Smrg        sym = &compat->sym_interpret[req->firstSI];
2871f7df2e56Smrg        for (i = 0; i < req->nSI; i++, wire++) {
2872f7df2e56Smrg            if (client->swapped) {
2873f7df2e56Smrg                swapl(&wire->sym);
2874f7df2e56Smrg            }
2875f7df2e56Smrg            if (wire->sym == NoSymbol && wire->match == XkbSI_AnyOfOrNone &&
2876f7df2e56Smrg                (wire->mods & 0xff) == 0xff &&
2877f7df2e56Smrg                wire->act.type == XkbSA_XFree86Private) {
2878f7df2e56Smrg                ErrorF("XKB: Skipping broken Any+AnyOfOrNone(All) -> Private "
2879f7df2e56Smrg                       "action from client\n");
2880f7df2e56Smrg                skipped++;
2881f7df2e56Smrg                continue;
2882f7df2e56Smrg            }
2883f7df2e56Smrg            sym->sym = wire->sym;
2884f7df2e56Smrg            sym->mods = wire->mods;
2885f7df2e56Smrg            sym->match = wire->match;
2886f7df2e56Smrg            sym->flags = wire->flags;
2887f7df2e56Smrg            sym->virtual_mod = wire->virtualMod;
2888f7df2e56Smrg            memcpy((char *) &sym->act, (char *) &wire->act,
2889f7df2e56Smrg                   SIZEOF(xkbActionWireDesc));
2890f7df2e56Smrg            sym++;
2891f7df2e56Smrg        }
2892f7df2e56Smrg        if (skipped) {
2893f7df2e56Smrg            if (req->firstSI + req->nSI < compat->num_si)
2894f7df2e56Smrg                memmove(sym, sym + skipped,
2895f7df2e56Smrg                        (compat->num_si - req->firstSI - req->nSI) *
2896f7df2e56Smrg                        sizeof(*sym));
2897f7df2e56Smrg            compat->num_si -= skipped;
2898f7df2e56Smrg        }
2899f7df2e56Smrg        data = (char *) wire;
290005b261ecSmrg    }
29014642e01fSmrg    else if (req->truncateSI) {
2902f7df2e56Smrg        compat->num_si = req->firstSI;
2903f7df2e56Smrg    }
2904f7df2e56Smrg
2905f7df2e56Smrg    if (req->groups != 0) {
2906f7df2e56Smrg        xkbModsWireDesc *wire = (xkbModsWireDesc *) data;
2907f7df2e56Smrg
2908f7df2e56Smrg        for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2909f7df2e56Smrg            if (req->groups & bit) {
2910f7df2e56Smrg                if (client->swapped) {
2911f7df2e56Smrg                    swaps(&wire->virtualMods);
2912f7df2e56Smrg                }
2913f7df2e56Smrg                compat->groups[i].mask = wire->realMods;
2914f7df2e56Smrg                compat->groups[i].real_mods = wire->realMods;
2915f7df2e56Smrg                compat->groups[i].vmods = wire->virtualMods;
2916f7df2e56Smrg                if (wire->virtualMods != 0) {
2917f7df2e56Smrg                    unsigned tmp;
2918f7df2e56Smrg
2919f7df2e56Smrg                    tmp = XkbMaskForVMask(xkb, wire->virtualMods);
2920f7df2e56Smrg                    compat->groups[i].mask |= tmp;
2921f7df2e56Smrg                }
2922f7df2e56Smrg                data += SIZEOF(xkbModsWireDesc);
2923f7df2e56Smrg                wire = (xkbModsWireDesc *) data;
2924f7df2e56Smrg            }
2925f7df2e56Smrg        }
2926f7df2e56Smrg    }
2927f7df2e56Smrg    i = XkbPaddedSize((data - ((char *) req)));
2928f7df2e56Smrg    if ((i / 4) != req->length) {
2929f7df2e56Smrg        ErrorF("[xkb] Internal length error on read in _XkbSetCompatMap\n");
2930f7df2e56Smrg        return BadLength;
293105b261ecSmrg    }
29324642e01fSmrg
293305b261ecSmrg    if (dev->xkb_interest) {
2934f7df2e56Smrg        xkbCompatMapNotify ev;
2935f7df2e56Smrg
2936f7df2e56Smrg        ev.deviceID = dev->id;
2937f7df2e56Smrg        ev.changedGroups = req->groups;
2938f7df2e56Smrg        ev.firstSI = req->firstSI;
2939f7df2e56Smrg        ev.nSI = req->nSI;
2940f7df2e56Smrg        ev.nTotalSI = compat->num_si;
2941f7df2e56Smrg        XkbSendCompatMapNotify(dev, &ev);
294205b261ecSmrg    }
294305b261ecSmrg
29444642e01fSmrg    if (req->recomputeActions) {
2945f7df2e56Smrg        XkbChangesRec change;
2946f7df2e56Smrg        unsigned check;
2947f7df2e56Smrg        XkbEventCauseRec cause;
2948f7df2e56Smrg
2949f7df2e56Smrg        XkbSetCauseXkbReq(&cause, X_kbSetCompatMap, client);
2950f7df2e56Smrg        memset(&change, 0, sizeof(XkbChangesRec));
2951f7df2e56Smrg        XkbUpdateActions(dev, xkb->min_key_code, XkbNumKeys(xkb), &change,
2952f7df2e56Smrg                         &check, &cause);
2953f7df2e56Smrg        if (check)
2954f7df2e56Smrg            XkbCheckSecondaryEffects(xkbi, check, &change, &cause);
2955f7df2e56Smrg        XkbSendNotification(dev, &change, &cause);
295605b261ecSmrg    }
29574642e01fSmrg    return Success;
29584642e01fSmrg}
29594642e01fSmrg
29604642e01fSmrgint
29614642e01fSmrgProcXkbSetCompatMap(ClientPtr client)
29624642e01fSmrg{
2963f7df2e56Smrg    DeviceIntPtr dev;
2964f7df2e56Smrg    char *data;
2965f7df2e56Smrg    int rc;
29664642e01fSmrg
29674642e01fSmrg    REQUEST(xkbSetCompatMapReq);
29684642e01fSmrg    REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq);
29694642e01fSmrg
2970f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
2971f7df2e56Smrg        return BadAccess;
29724642e01fSmrg
29734642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
29744642e01fSmrg
2975f7df2e56Smrg    data = (char *) &stuff[1];
29764642e01fSmrg
29774642e01fSmrg    /* check first using a dry-run */
29784642e01fSmrg    rc = _XkbSetCompatMap(client, dev, stuff, data, TRUE);
29794642e01fSmrg    if (rc != Success)
29804642e01fSmrg        return rc;
2981f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
29824642e01fSmrg        DeviceIntPtr other;
2983f7df2e56Smrg
2984f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
2985f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
2986f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
2987f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
2988f7df2e56Smrg                              DixManageAccess);
2989f7df2e56Smrg                if (rc == Success) {
29904642e01fSmrg                    /* dry-run */
29914642e01fSmrg                    rc = _XkbSetCompatMap(client, other, stuff, data, TRUE);
29924642e01fSmrg                    if (rc != Success)
29934642e01fSmrg                        return rc;
29944642e01fSmrg                }
29954642e01fSmrg            }
29964642e01fSmrg        }
29974642e01fSmrg    }
29984642e01fSmrg
29994642e01fSmrg    /* Yay, the dry-runs succeed. Let's apply */
30004642e01fSmrg    rc = _XkbSetCompatMap(client, dev, stuff, data, FALSE);
30014642e01fSmrg    if (rc != Success)
30024642e01fSmrg        return rc;
3003f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
30044642e01fSmrg        DeviceIntPtr other;
3005f7df2e56Smrg
3006f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
3007f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
3008f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
3009f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
3010f7df2e56Smrg                              DixManageAccess);
3011f7df2e56Smrg                if (rc == Success) {
30124642e01fSmrg                    rc = _XkbSetCompatMap(client, other, stuff, data, FALSE);
30134642e01fSmrg                    if (rc != Success)
30144642e01fSmrg                        return rc;
30154642e01fSmrg                }
30164642e01fSmrg            }
30174642e01fSmrg        }
30184642e01fSmrg    }
30194642e01fSmrg
30206747b715Smrg    return Success;
302105b261ecSmrg}
302205b261ecSmrg
302305b261ecSmrg/***====================================================================***/
302405b261ecSmrg
302505b261ecSmrgint
302605b261ecSmrgProcXkbGetIndicatorState(ClientPtr client)
302705b261ecSmrg{
3028f7df2e56Smrg    xkbGetIndicatorStateReply rep;
3029f7df2e56Smrg    XkbSrvLedInfoPtr sli;
3030f7df2e56Smrg    DeviceIntPtr dev;
303105b261ecSmrg
303205b261ecSmrg    REQUEST(xkbGetIndicatorStateReq);
303305b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq);
303405b261ecSmrg
3035f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
3036f7df2e56Smrg        return BadAccess;
303705b261ecSmrg
30384642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
303905b261ecSmrg
3040f7df2e56Smrg    sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
3041f7df2e56Smrg                            XkbXI_IndicatorStateMask);
304205b261ecSmrg    if (!sli)
3043f7df2e56Smrg        return BadAlloc;
304405b261ecSmrg
3045f7df2e56Smrg    rep = (xkbGetIndicatorStateReply) {
3046f7df2e56Smrg        .type = X_Reply,
3047f7df2e56Smrg        .deviceID = dev->id,
3048f7df2e56Smrg        .sequenceNumber = client->sequence,
3049f7df2e56Smrg        .length = 0,
3050f7df2e56Smrg        .state = sli->effectiveState
3051f7df2e56Smrg    };
305205b261ecSmrg
305305b261ecSmrg    if (client->swapped) {
3054f7df2e56Smrg        swaps(&rep.sequenceNumber);
3055f7df2e56Smrg        swapl(&rep.state);
305605b261ecSmrg    }
3057f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetIndicatorStateReply), &rep);
30586747b715Smrg    return Success;
305905b261ecSmrg}
306005b261ecSmrg
306105b261ecSmrg/***====================================================================***/
306205b261ecSmrg
306305b261ecSmrgstatic Status
3064f7df2e56SmrgXkbComputeGetIndicatorMapReplySize(XkbIndicatorPtr indicators,
3065f7df2e56Smrg                                   xkbGetIndicatorMapReply * rep)
306605b261ecSmrg{
3067f7df2e56Smrg    register int i, bit;
3068f7df2e56Smrg    int nIndicators;
306905b261ecSmrg
307005b261ecSmrg    rep->realIndicators = indicators->phys_indicators;
3071f7df2e56Smrg    for (i = nIndicators = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3072f7df2e56Smrg        if (rep->which & bit)
3073f7df2e56Smrg            nIndicators++;
307405b261ecSmrg    }
3075f7df2e56Smrg    rep->length = (nIndicators * SIZEOF(xkbIndicatorMapWireDesc)) / 4;
3076f7df2e56Smrg    rep->nIndicators = nIndicators;
307705b261ecSmrg    return Success;
307805b261ecSmrg}
307905b261ecSmrg
308005b261ecSmrgstatic int
3081f7df2e56SmrgXkbSendIndicatorMap(ClientPtr client,
3082f7df2e56Smrg                    XkbIndicatorPtr indicators, xkbGetIndicatorMapReply * rep)
308305b261ecSmrg{
3084f7df2e56Smrg    int length;
3085f7df2e56Smrg    CARD8 *map;
3086f7df2e56Smrg    register int i;
3087f7df2e56Smrg    register unsigned bit;
3088f7df2e56Smrg
3089f7df2e56Smrg    if (rep->length > 0) {
3090f7df2e56Smrg        CARD8 *to;
3091f7df2e56Smrg
3092f7df2e56Smrg        to = map = xallocarray(rep->length, 4);
3093f7df2e56Smrg        if (map) {
3094f7df2e56Smrg            xkbIndicatorMapWireDesc *wire = (xkbIndicatorMapWireDesc *) to;
3095f7df2e56Smrg
3096f7df2e56Smrg            length = rep->length * 4;
3097f7df2e56Smrg
3098f7df2e56Smrg            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3099f7df2e56Smrg                if (rep->which & bit) {
3100f7df2e56Smrg                    wire->flags = indicators->maps[i].flags;
3101f7df2e56Smrg                    wire->whichGroups = indicators->maps[i].which_groups;
3102f7df2e56Smrg                    wire->groups = indicators->maps[i].groups;
3103f7df2e56Smrg                    wire->whichMods = indicators->maps[i].which_mods;
3104f7df2e56Smrg                    wire->mods = indicators->maps[i].mods.mask;
3105f7df2e56Smrg                    wire->realMods = indicators->maps[i].mods.real_mods;
3106f7df2e56Smrg                    wire->virtualMods = indicators->maps[i].mods.vmods;
3107f7df2e56Smrg                    wire->ctrls = indicators->maps[i].ctrls;
3108f7df2e56Smrg                    if (client->swapped) {
3109f7df2e56Smrg                        swaps(&wire->virtualMods);
3110f7df2e56Smrg                        swapl(&wire->ctrls);
3111f7df2e56Smrg                    }
3112f7df2e56Smrg                    wire++;
3113f7df2e56Smrg                }
3114f7df2e56Smrg            }
3115f7df2e56Smrg            to = (CARD8 *) wire;
3116f7df2e56Smrg            if ((to - map) != length) {
3117f7df2e56Smrg                client->errorValue = _XkbErrCode2(0xff, length);
3118f7df2e56Smrg                free(map);
3119f7df2e56Smrg                return BadLength;
3120f7df2e56Smrg            }
3121f7df2e56Smrg        }
3122f7df2e56Smrg        else
3123f7df2e56Smrg            return BadAlloc;
3124f7df2e56Smrg    }
3125f7df2e56Smrg    else
3126f7df2e56Smrg        map = NULL;
312705b261ecSmrg    if (client->swapped) {
3128f7df2e56Smrg        swaps(&rep->sequenceNumber);
3129f7df2e56Smrg        swapl(&rep->length);
3130f7df2e56Smrg        swapl(&rep->which);
3131f7df2e56Smrg        swapl(&rep->realIndicators);
313205b261ecSmrg    }
3133f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetIndicatorMapReply), rep);
313405b261ecSmrg    if (map) {
3135f7df2e56Smrg        WriteToClient(client, length, map);
3136f7df2e56Smrg        free((char *) map);
313705b261ecSmrg    }
31386747b715Smrg    return Success;
313905b261ecSmrg}
314005b261ecSmrg
314105b261ecSmrgint
314205b261ecSmrgProcXkbGetIndicatorMap(ClientPtr client)
314305b261ecSmrg{
3144f7df2e56Smrg    xkbGetIndicatorMapReply rep;
3145f7df2e56Smrg    DeviceIntPtr dev;
3146f7df2e56Smrg    XkbDescPtr xkb;
3147f7df2e56Smrg    XkbIndicatorPtr leds;
314805b261ecSmrg
314905b261ecSmrg    REQUEST(xkbGetIndicatorMapReq);
315005b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq);
315105b261ecSmrg
3152f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
3153f7df2e56Smrg        return BadAccess;
315405b261ecSmrg
31554642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
315605b261ecSmrg
3157f7df2e56Smrg    xkb = dev->key->xkbInfo->desc;
3158f7df2e56Smrg    leds = xkb->indicators;
3159f7df2e56Smrg
3160f7df2e56Smrg    rep = (xkbGetIndicatorMapReply) {
3161f7df2e56Smrg        .type = X_Reply,
3162f7df2e56Smrg        .deviceID = dev->id,
3163f7df2e56Smrg        .sequenceNumber = client->sequence,
3164f7df2e56Smrg        .length = 0,
3165f7df2e56Smrg        .which = stuff->which
3166f7df2e56Smrg    };
3167f7df2e56Smrg    XkbComputeGetIndicatorMapReplySize(leds, &rep);
3168f7df2e56Smrg    return XkbSendIndicatorMap(client, leds, &rep);
316905b261ecSmrg}
317005b261ecSmrg
31714642e01fSmrg/**
31724642e01fSmrg * Apply the given map to the given device. Which specifies which components
31734642e01fSmrg * to apply.
31744642e01fSmrg */
31754642e01fSmrgstatic int
31764642e01fSmrg_XkbSetIndicatorMap(ClientPtr client, DeviceIntPtr dev,
3177f7df2e56Smrg                    int which, xkbIndicatorMapWireDesc * desc)
31784642e01fSmrg{
3179f7df2e56Smrg    XkbSrvInfoPtr xkbi;
3180f7df2e56Smrg    XkbSrvLedInfoPtr sli;
3181f7df2e56Smrg    XkbEventCauseRec cause;
3182f7df2e56Smrg    int i, bit;
31834642e01fSmrg
31844642e01fSmrg    xkbi = dev->key->xkbInfo;
31854642e01fSmrg
3186f7df2e56Smrg    sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
3187f7df2e56Smrg                            XkbXI_IndicatorMapsMask);
31884642e01fSmrg    if (!sli)
3189f7df2e56Smrg        return BadAlloc;
31904642e01fSmrg
31914642e01fSmrg    for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3192f7df2e56Smrg        if (which & bit) {
3193f7df2e56Smrg            sli->maps[i].flags = desc->flags;
3194f7df2e56Smrg            sli->maps[i].which_groups = desc->whichGroups;
3195f7df2e56Smrg            sli->maps[i].groups = desc->groups;
3196f7df2e56Smrg            sli->maps[i].which_mods = desc->whichMods;
3197f7df2e56Smrg            sli->maps[i].mods.mask = desc->mods;
3198f7df2e56Smrg            sli->maps[i].mods.real_mods = desc->mods;
3199f7df2e56Smrg            sli->maps[i].mods.vmods = desc->virtualMods;
3200f7df2e56Smrg            sli->maps[i].ctrls = desc->ctrls;
3201f7df2e56Smrg            if (desc->virtualMods != 0) {
3202f7df2e56Smrg                unsigned tmp;
3203f7df2e56Smrg
3204f7df2e56Smrg                tmp = XkbMaskForVMask(xkbi->desc, desc->virtualMods);
3205f7df2e56Smrg                sli->maps[i].mods.mask = desc->mods | tmp;
3206f7df2e56Smrg            }
3207f7df2e56Smrg            desc++;
3208f7df2e56Smrg        }
3209f7df2e56Smrg    }
3210f7df2e56Smrg
3211f7df2e56Smrg    XkbSetCauseXkbReq(&cause, X_kbSetIndicatorMap, client);
3212f7df2e56Smrg    XkbApplyLedMapChanges(dev, sli, which, NULL, NULL, &cause);
32134642e01fSmrg
32144642e01fSmrg    return Success;
32154642e01fSmrg}
32164642e01fSmrg
321705b261ecSmrgint
321805b261ecSmrgProcXkbSetIndicatorMap(ClientPtr client)
321905b261ecSmrg{
3220f7df2e56Smrg    int i, bit;
3221f7df2e56Smrg    int nIndicators;
3222f7df2e56Smrg    DeviceIntPtr dev;
3223f7df2e56Smrg    xkbIndicatorMapWireDesc *from;
3224f7df2e56Smrg    int rc;
322505b261ecSmrg
322605b261ecSmrg    REQUEST(xkbSetIndicatorMapReq);
322705b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq);
322805b261ecSmrg
3229f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
3230f7df2e56Smrg        return BadAccess;
323105b261ecSmrg
32324642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
323305b261ecSmrg
3234f7df2e56Smrg    if (stuff->which == 0)
3235f7df2e56Smrg        return Success;
323605b261ecSmrg
3237f7df2e56Smrg    for (nIndicators = i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3238f7df2e56Smrg        if (stuff->which & bit)
3239f7df2e56Smrg            nIndicators++;
324005b261ecSmrg    }
3241f7df2e56Smrg    if (stuff->length != ((SIZEOF(xkbSetIndicatorMapReq) +
3242f7df2e56Smrg                           (nIndicators * SIZEOF(xkbIndicatorMapWireDesc))) /
3243f7df2e56Smrg                          4)) {
3244f7df2e56Smrg        return BadLength;
324505b261ecSmrg    }
324605b261ecSmrg
3247f7df2e56Smrg    from = (xkbIndicatorMapWireDesc *) &stuff[1];
3248f7df2e56Smrg    for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3249f7df2e56Smrg        if (stuff->which & bit) {
3250f7df2e56Smrg            if (client->swapped) {
3251f7df2e56Smrg                swaps(&from->virtualMods);
3252f7df2e56Smrg                swapl(&from->ctrls);
3253f7df2e56Smrg            }
3254f7df2e56Smrg            CHK_MASK_LEGAL(i, from->whichGroups, XkbIM_UseAnyGroup);
3255f7df2e56Smrg            CHK_MASK_LEGAL(i, from->whichMods, XkbIM_UseAnyMods);
3256f7df2e56Smrg            from++;
3257f7df2e56Smrg        }
325805b261ecSmrg    }
325905b261ecSmrg
3260f7df2e56Smrg    from = (xkbIndicatorMapWireDesc *) &stuff[1];
32614642e01fSmrg    rc = _XkbSetIndicatorMap(client, dev, stuff->which, from);
32624642e01fSmrg    if (rc != Success)
32634642e01fSmrg        return rc;
32644642e01fSmrg
3265f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
32664642e01fSmrg        DeviceIntPtr other;
3267f7df2e56Smrg
3268f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
3269f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
3270f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
3271f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
3272f7df2e56Smrg                              DixSetAttrAccess);
32734642e01fSmrg                if (rc == Success)
32744642e01fSmrg                    _XkbSetIndicatorMap(client, other, stuff->which, from);
32754642e01fSmrg            }
32764642e01fSmrg        }
327705b261ecSmrg    }
327805b261ecSmrg
32794642e01fSmrg    return Success;
328005b261ecSmrg}
328105b261ecSmrg
328205b261ecSmrg/***====================================================================***/
328305b261ecSmrg
328405b261ecSmrgint
328505b261ecSmrgProcXkbGetNamedIndicator(ClientPtr client)
328605b261ecSmrg{
3287f7df2e56Smrg    DeviceIntPtr dev;
3288f7df2e56Smrg    xkbGetNamedIndicatorReply rep;
3289f7df2e56Smrg    register int i = 0;
3290f7df2e56Smrg    XkbSrvLedInfoPtr sli;
3291f7df2e56Smrg    XkbIndicatorMapPtr map = NULL;
329205b261ecSmrg
329305b261ecSmrg    REQUEST(xkbGetNamedIndicatorReq);
329405b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq);
329505b261ecSmrg
3296f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
3297f7df2e56Smrg        return BadAccess;
329805b261ecSmrg
32994642e01fSmrg    CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
330005b261ecSmrg    CHK_ATOM_ONLY(stuff->indicator);
330105b261ecSmrg
3302f7df2e56Smrg    sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID, 0);
330305b261ecSmrg    if (!sli)
3304f7df2e56Smrg        return BadAlloc;
3305f7df2e56Smrg
3306f7df2e56Smrg    i = 0;
3307f7df2e56Smrg    map = NULL;
3308f7df2e56Smrg    if ((sli->names) && (sli->maps)) {
3309f7df2e56Smrg        for (i = 0; i < XkbNumIndicators; i++) {
3310f7df2e56Smrg            if (stuff->indicator == sli->names[i]) {
3311f7df2e56Smrg                map = &sli->maps[i];
331205b261ecSmrg                break;
331305b261ecSmrg            }
331405b261ecSmrg        }
331505b261ecSmrg    }
331605b261ecSmrg
3317f7df2e56Smrg    rep = (xkbGetNamedIndicatorReply) {
3318f7df2e56Smrg        .type = X_Reply,
3319f7df2e56Smrg        .sequenceNumber = client->sequence,
3320f7df2e56Smrg        .length = 0,
3321f7df2e56Smrg        .deviceID = dev->id,
3322f7df2e56Smrg        .indicator = stuff->indicator
3323f7df2e56Smrg    };
3324f7df2e56Smrg    if (map != NULL) {
3325f7df2e56Smrg        rep.found = TRUE;
3326f7df2e56Smrg        rep.on = ((sli->effectiveState & (1 << i)) != 0);
3327f7df2e56Smrg        rep.realIndicator = ((sli->physIndicators & (1 << i)) != 0);
3328f7df2e56Smrg        rep.ndx = i;
3329f7df2e56Smrg        rep.flags = map->flags;
3330f7df2e56Smrg        rep.whichGroups = map->which_groups;
3331f7df2e56Smrg        rep.groups = map->groups;
3332f7df2e56Smrg        rep.whichMods = map->which_mods;
3333f7df2e56Smrg        rep.mods = map->mods.mask;
3334f7df2e56Smrg        rep.realMods = map->mods.real_mods;
3335f7df2e56Smrg        rep.virtualMods = map->mods.vmods;
3336f7df2e56Smrg        rep.ctrls = map->ctrls;
3337f7df2e56Smrg        rep.supported = TRUE;
3338f7df2e56Smrg    }
3339f7df2e56Smrg    else {
3340f7df2e56Smrg        rep.found = FALSE;
3341f7df2e56Smrg        rep.on = FALSE;
3342f7df2e56Smrg        rep.realIndicator = FALSE;
3343f7df2e56Smrg        rep.ndx = XkbNoIndicator;
3344f7df2e56Smrg        rep.flags = 0;
3345f7df2e56Smrg        rep.whichGroups = 0;
3346f7df2e56Smrg        rep.groups = 0;
3347f7df2e56Smrg        rep.whichMods = 0;
3348f7df2e56Smrg        rep.mods = 0;
3349f7df2e56Smrg        rep.realMods = 0;
3350f7df2e56Smrg        rep.virtualMods = 0;
3351f7df2e56Smrg        rep.ctrls = 0;
3352f7df2e56Smrg        rep.supported = TRUE;
3353f7df2e56Smrg    }
3354f7df2e56Smrg    if (client->swapped) {
3355f7df2e56Smrg        swapl(&rep.length);
3356f7df2e56Smrg        swaps(&rep.sequenceNumber);
3357f7df2e56Smrg        swapl(&rep.indicator);
3358f7df2e56Smrg        swaps(&rep.virtualMods);
3359f7df2e56Smrg        swapl(&rep.ctrls);
3360f7df2e56Smrg    }
3361f7df2e56Smrg
3362f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetNamedIndicatorReply), &rep);
33636747b715Smrg    return Success;
336405b261ecSmrg}
336505b261ecSmrg
33664642e01fSmrg/**
33674642e01fSmrg * Find the IM on the device.
33684642e01fSmrg * Returns the map, or NULL if the map doesn't exist.
33694642e01fSmrg * If the return value is NULL, led_return is undefined. Otherwise, led_return
33704642e01fSmrg * is set to the led index of the map.
33714642e01fSmrg */
33724642e01fSmrgstatic XkbIndicatorMapPtr
3373f7df2e56Smrg_XkbFindNamedIndicatorMap(XkbSrvLedInfoPtr sli, Atom indicator, int *led_return)
33744642e01fSmrg{
3375f7df2e56Smrg    XkbIndicatorMapPtr map;
337605b261ecSmrg
33774642e01fSmrg    /* search for the right indicator */
33784642e01fSmrg    map = NULL;
337905b261ecSmrg    if (sli->names && sli->maps) {
3380f7df2e56Smrg        int led;
33816747b715Smrg
3382f7df2e56Smrg        for (led = 0; (led < XkbNumIndicators) && (map == NULL); led++) {
3383f7df2e56Smrg            if (sli->names[led] == indicator) {
3384f7df2e56Smrg                map = &sli->maps[led];
3385f7df2e56Smrg                *led_return = led;
3386f7df2e56Smrg                break;
3387f7df2e56Smrg            }
3388f7df2e56Smrg        }
338905b261ecSmrg    }
339005b261ecSmrg
33914642e01fSmrg    return map;
33924642e01fSmrg}
33934642e01fSmrg
33944642e01fSmrg/**
33956747b715Smrg * Creates an indicator map on the device. If dryRun is TRUE, it only checks
33964642e01fSmrg * if creation is possible, but doesn't actually create it.
33974642e01fSmrg */
33984642e01fSmrgstatic int
33994642e01fSmrg_XkbCreateIndicatorMap(DeviceIntPtr dev, Atom indicator,
34004642e01fSmrg                       int ledClass, int ledID,
3401f7df2e56Smrg                       XkbIndicatorMapPtr * map_return, int *led_return,
34024642e01fSmrg                       Bool dryRun)
34034642e01fSmrg{
3404f7df2e56Smrg    XkbSrvLedInfoPtr sli;
3405f7df2e56Smrg    XkbIndicatorMapPtr map;
3406f7df2e56Smrg    int led;
34074642e01fSmrg
34084642e01fSmrg    sli = XkbFindSrvLedInfo(dev, ledClass, ledID, XkbXI_IndicatorsMask);
34094642e01fSmrg    if (!sli)
34104642e01fSmrg        return BadAlloc;
34114642e01fSmrg
34124642e01fSmrg    map = _XkbFindNamedIndicatorMap(sli, indicator, &led);
34134642e01fSmrg
3414f7df2e56Smrg    if (!map) {
34154642e01fSmrg        /* find first unused indicator maps and assign the name to it */
3416f7df2e56Smrg        for (led = 0, map = NULL; (led < XkbNumIndicators) && (map == NULL);
3417f7df2e56Smrg             led++) {
34184642e01fSmrg            if ((sli->names) && (sli->maps) && (sli->names[led] == None) &&
3419f7df2e56Smrg                (!XkbIM_InUse(&sli->maps[led]))) {
34204642e01fSmrg                map = &sli->maps[led];
34214642e01fSmrg                if (!dryRun)
34224642e01fSmrg                    sli->names[led] = indicator;
34234642e01fSmrg                break;
34244642e01fSmrg            }
34254642e01fSmrg        }
34264642e01fSmrg    }
34274642e01fSmrg
34284642e01fSmrg    if (!map)
34294642e01fSmrg        return BadAlloc;
34304642e01fSmrg
34314642e01fSmrg    *led_return = led;
34324642e01fSmrg    *map_return = map;
34334642e01fSmrg    return Success;
34344642e01fSmrg}
34354642e01fSmrg
34364642e01fSmrgstatic int
34374642e01fSmrg_XkbSetNamedIndicator(ClientPtr client, DeviceIntPtr dev,
3438f7df2e56Smrg                      xkbSetNamedIndicatorReq * stuff)
34394642e01fSmrg{
3440f7df2e56Smrg    unsigned int extDevReason;
3441f7df2e56Smrg    unsigned int statec, namec, mapc;
3442f7df2e56Smrg    XkbSrvLedInfoPtr sli;
3443f7df2e56Smrg    int led = 0;
3444f7df2e56Smrg    XkbIndicatorMapPtr map;
3445f7df2e56Smrg    DeviceIntPtr kbd;
3446f7df2e56Smrg    XkbEventCauseRec cause;
3447f7df2e56Smrg    xkbExtensionDeviceNotify ed;
3448f7df2e56Smrg    XkbChangesRec changes;
3449f7df2e56Smrg    int rc;
34504642e01fSmrg
34514642e01fSmrg    rc = _XkbCreateIndicatorMap(dev, stuff->indicator, stuff->ledClass,
34524642e01fSmrg                                stuff->ledID, &map, &led, FALSE);
3453f7df2e56Smrg    if (rc != Success || !map)  /* oh-oh */
34544642e01fSmrg        return rc;
34554642e01fSmrg
34564642e01fSmrg    sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID,
34574642e01fSmrg                            XkbXI_IndicatorsMask);
34584642e01fSmrg    if (!sli)
34594642e01fSmrg        return BadAlloc;
34604642e01fSmrg
34614642e01fSmrg    namec = mapc = statec = 0;
34624642e01fSmrg    extDevReason = 0;
34634642e01fSmrg
3464f7df2e56Smrg    namec |= (1 << led);
34654642e01fSmrg    sli->namesPresent |= ((stuff->indicator != None) ? (1 << led) : 0);
34664642e01fSmrg    extDevReason |= XkbXI_IndicatorNamesMask;
34674642e01fSmrg
34684642e01fSmrg    if (stuff->setMap) {
34694642e01fSmrg        map->flags = stuff->flags;
34704642e01fSmrg        map->which_groups = stuff->whichGroups;
34714642e01fSmrg        map->groups = stuff->groups;
34724642e01fSmrg        map->which_mods = stuff->whichMods;
34734642e01fSmrg        map->mods.mask = stuff->realMods;
34744642e01fSmrg        map->mods.real_mods = stuff->realMods;
3475f7df2e56Smrg        map->mods.vmods = stuff->virtualMods;
34764642e01fSmrg        map->ctrls = stuff->ctrls;
3477f7df2e56Smrg        mapc |= (1 << led);
34784642e01fSmrg    }
34794642e01fSmrg
3480f7df2e56Smrg    if ((stuff->setState) && ((map->flags & XkbIM_NoExplicit) == 0)) {
3481f7df2e56Smrg        if (stuff->on)
3482f7df2e56Smrg            sli->explicitState |= (1 << led);
3483f7df2e56Smrg        else
3484f7df2e56Smrg            sli->explicitState &= ~(1 << led);
34854642e01fSmrg        statec |= ((sli->effectiveState ^ sli->explicitState) & (1 << led));
348605b261ecSmrg    }
34874642e01fSmrg
3488f7df2e56Smrg    memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify));
3489f7df2e56Smrg    memset((char *) &changes, 0, sizeof(XkbChangesRec));
3490f7df2e56Smrg    XkbSetCauseXkbReq(&cause, X_kbSetNamedIndicator, client);
349105b261ecSmrg    if (namec)
3492f7df2e56Smrg        XkbApplyLedNameChanges(dev, sli, namec, &ed, &changes, &cause);
349305b261ecSmrg    if (mapc)
3494f7df2e56Smrg        XkbApplyLedMapChanges(dev, sli, mapc, &ed, &changes, &cause);
349505b261ecSmrg    if (statec)
3496f7df2e56Smrg        XkbApplyLedStateChanges(dev, sli, statec, &ed, &changes, &cause);
349705b261ecSmrg
34984642e01fSmrg    kbd = dev;
3499f7df2e56Smrg    if ((sli->flags & XkbSLI_HasOwnState) == 0)
35004642e01fSmrg        kbd = inputInfo.keyboard;
35014642e01fSmrg    XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause);
35024642e01fSmrg
35034642e01fSmrg    return Success;
35044642e01fSmrg}
35054642e01fSmrg
35064642e01fSmrgint
35074642e01fSmrgProcXkbSetNamedIndicator(ClientPtr client)
35084642e01fSmrg{
3509f7df2e56Smrg    int rc;
3510f7df2e56Smrg    DeviceIntPtr dev;
3511f7df2e56Smrg    int led = 0;
3512f7df2e56Smrg    XkbIndicatorMapPtr map;
35134642e01fSmrg
35144642e01fSmrg    REQUEST(xkbSetNamedIndicatorReq);
35154642e01fSmrg    REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq);
35164642e01fSmrg
3517f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
3518f7df2e56Smrg        return BadAccess;
35194642e01fSmrg
35204642e01fSmrg    CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
35214642e01fSmrg    CHK_ATOM_ONLY(stuff->indicator);
3522f7df2e56Smrg    CHK_MASK_LEGAL(0x10, stuff->whichGroups, XkbIM_UseAnyGroup);
3523f7df2e56Smrg    CHK_MASK_LEGAL(0x11, stuff->whichMods, XkbIM_UseAnyMods);
35244642e01fSmrg
35254642e01fSmrg    /* Dry-run for checks */
35264642e01fSmrg    rc = _XkbCreateIndicatorMap(dev, stuff->indicator,
35274642e01fSmrg                                stuff->ledClass, stuff->ledID,
35284642e01fSmrg                                &map, &led, TRUE);
3529f7df2e56Smrg    if (rc != Success || !map)  /* couldn't be created or didn't exist */
35304642e01fSmrg        return rc;
35314642e01fSmrg
35324642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd ||
3533f7df2e56Smrg        stuff->deviceSpec == XkbUseCorePtr) {
35344642e01fSmrg        DeviceIntPtr other;
3535f7df2e56Smrg
3536f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
3537f7df2e56Smrg            if ((other != dev) && !IsMaster(other) &&
3538f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev && (other->kbdfeed ||
3539f7df2e56Smrg                                                             other->leds) &&
3540f7df2e56Smrg                (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess)
3541f7df2e56Smrg                 == Success)) {
35424642e01fSmrg                rc = _XkbCreateIndicatorMap(other, stuff->indicator,
3543f7df2e56Smrg                                            stuff->ledClass, stuff->ledID, &map,
3544f7df2e56Smrg                                            &led, TRUE);
35454642e01fSmrg                if (rc != Success || !map)
35464642e01fSmrg                    return rc;
35474642e01fSmrg            }
35484642e01fSmrg        }
35494642e01fSmrg    }
35504642e01fSmrg
35514642e01fSmrg    /* All checks passed, let's do it */
35524642e01fSmrg    rc = _XkbSetNamedIndicator(client, dev, stuff);
35534642e01fSmrg    if (rc != Success)
35544642e01fSmrg        return rc;
35554642e01fSmrg
35564642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd ||
3557f7df2e56Smrg        stuff->deviceSpec == XkbUseCorePtr) {
35584642e01fSmrg        DeviceIntPtr other;
3559f7df2e56Smrg
3560f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
3561f7df2e56Smrg            if ((other != dev) && !IsMaster(other) &&
3562f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev && (other->kbdfeed ||
3563f7df2e56Smrg                                                             other->leds) &&
3564f7df2e56Smrg                (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess)
3565f7df2e56Smrg                 == Success)) {
35664642e01fSmrg                _XkbSetNamedIndicator(client, other, stuff);
35674642e01fSmrg            }
35684642e01fSmrg        }
35694642e01fSmrg    }
35704642e01fSmrg
35716747b715Smrg    return Success;
357205b261ecSmrg}
357305b261ecSmrg
357405b261ecSmrg/***====================================================================***/
357505b261ecSmrg
357605b261ecSmrgstatic CARD32
3577f7df2e56Smrg_XkbCountAtoms(Atom *atoms, int maxAtoms, int *count)
357805b261ecSmrg{
3579f7df2e56Smrg    register unsigned int i, bit, nAtoms;
3580f7df2e56Smrg    register CARD32 atomsPresent;
358105b261ecSmrg
3582f7df2e56Smrg    for (i = nAtoms = atomsPresent = 0, bit = 1; i < maxAtoms; i++, bit <<= 1) {
3583f7df2e56Smrg        if (atoms[i] != None) {
3584f7df2e56Smrg            atomsPresent |= bit;
3585f7df2e56Smrg            nAtoms++;
3586f7df2e56Smrg        }
358705b261ecSmrg    }
358805b261ecSmrg    if (count)
3589f7df2e56Smrg        *count = nAtoms;
359005b261ecSmrg    return atomsPresent;
359105b261ecSmrg}
359205b261ecSmrg
359305b261ecSmrgstatic char *
3594f7df2e56Smrg_XkbWriteAtoms(char *wire, Atom *atoms, int maxAtoms, int swap)
359505b261ecSmrg{
3596f7df2e56Smrg    register unsigned int i;
3597f7df2e56Smrg    Atom *atm;
3598f7df2e56Smrg
3599f7df2e56Smrg    atm = (Atom *) wire;
3600f7df2e56Smrg    for (i = 0; i < maxAtoms; i++) {
3601f7df2e56Smrg        if (atoms[i] != None) {
3602f7df2e56Smrg            *atm = atoms[i];
3603f7df2e56Smrg            if (swap) {
3604f7df2e56Smrg                swapl(atm);
3605f7df2e56Smrg            }
3606f7df2e56Smrg            atm++;
3607f7df2e56Smrg        }
3608f7df2e56Smrg    }
3609f7df2e56Smrg    return (char *) atm;
361005b261ecSmrg}
361105b261ecSmrg
361205b261ecSmrgstatic Status
3613f7df2e56SmrgXkbComputeGetNamesReplySize(XkbDescPtr xkb, xkbGetNamesReply * rep)
361405b261ecSmrg{
3615f7df2e56Smrg    register unsigned which, length;
3616f7df2e56Smrg    register int i;
3617f7df2e56Smrg
3618f7df2e56Smrg    rep->minKeyCode = xkb->min_key_code;
3619f7df2e56Smrg    rep->maxKeyCode = xkb->max_key_code;
3620f7df2e56Smrg    which = rep->which;
3621f7df2e56Smrg    length = 0;
3622f7df2e56Smrg    if (xkb->names != NULL) {
3623f7df2e56Smrg        if (which & XkbKeycodesNameMask)
3624f7df2e56Smrg            length++;
3625f7df2e56Smrg        if (which & XkbGeometryNameMask)
3626f7df2e56Smrg            length++;
3627f7df2e56Smrg        if (which & XkbSymbolsNameMask)
3628f7df2e56Smrg            length++;
3629f7df2e56Smrg        if (which & XkbPhysSymbolsNameMask)
3630f7df2e56Smrg            length++;
3631f7df2e56Smrg        if (which & XkbTypesNameMask)
3632f7df2e56Smrg            length++;
3633f7df2e56Smrg        if (which & XkbCompatNameMask)
3634f7df2e56Smrg            length++;
3635f7df2e56Smrg    }
3636f7df2e56Smrg    else
3637f7df2e56Smrg        which &= ~XkbComponentNamesMask;
3638f7df2e56Smrg
3639f7df2e56Smrg    if (xkb->map != NULL) {
3640f7df2e56Smrg        if (which & XkbKeyTypeNamesMask)
3641f7df2e56Smrg            length += xkb->map->num_types;
3642f7df2e56Smrg        rep->nTypes = xkb->map->num_types;
3643f7df2e56Smrg        if (which & XkbKTLevelNamesMask) {
3644f7df2e56Smrg            XkbKeyTypePtr pType = xkb->map->types;
3645f7df2e56Smrg            int nKTLevels = 0;
3646f7df2e56Smrg
3647f7df2e56Smrg            length += XkbPaddedSize(xkb->map->num_types) / 4;
3648f7df2e56Smrg            for (i = 0; i < xkb->map->num_types; i++, pType++) {
3649f7df2e56Smrg                if (pType->level_names != NULL)
3650f7df2e56Smrg                    nKTLevels += pType->num_levels;
3651f7df2e56Smrg            }
3652f7df2e56Smrg            rep->nKTLevels = nKTLevels;
3653f7df2e56Smrg            length += nKTLevels;
3654f7df2e56Smrg        }
365505b261ecSmrg    }
365605b261ecSmrg    else {
3657f7df2e56Smrg        rep->nTypes = 0;
3658f7df2e56Smrg        rep->nKTLevels = 0;
3659f7df2e56Smrg        which &= ~(XkbKeyTypeNamesMask | XkbKTLevelNamesMask);
3660f7df2e56Smrg    }
3661f7df2e56Smrg
3662f7df2e56Smrg    rep->minKeyCode = xkb->min_key_code;
3663f7df2e56Smrg    rep->maxKeyCode = xkb->max_key_code;
3664f7df2e56Smrg    rep->indicators = 0;
3665f7df2e56Smrg    rep->virtualMods = 0;
3666f7df2e56Smrg    rep->groupNames = 0;
3667f7df2e56Smrg    if (xkb->names != NULL) {
3668f7df2e56Smrg        if (which & XkbIndicatorNamesMask) {
3669f7df2e56Smrg            int nLeds;
3670f7df2e56Smrg
3671f7df2e56Smrg            rep->indicators =
3672f7df2e56Smrg                _XkbCountAtoms(xkb->names->indicators, XkbNumIndicators,
3673f7df2e56Smrg                               &nLeds);
3674f7df2e56Smrg            length += nLeds;
3675f7df2e56Smrg            if (nLeds == 0)
3676f7df2e56Smrg                which &= ~XkbIndicatorNamesMask;
3677f7df2e56Smrg        }
3678f7df2e56Smrg
3679f7df2e56Smrg        if (which & XkbVirtualModNamesMask) {
3680f7df2e56Smrg            int nVMods;
3681f7df2e56Smrg
3682f7df2e56Smrg            rep->virtualMods =
3683f7df2e56Smrg                _XkbCountAtoms(xkb->names->vmods, XkbNumVirtualMods, &nVMods);
3684f7df2e56Smrg            length += nVMods;
3685f7df2e56Smrg            if (nVMods == 0)
3686f7df2e56Smrg                which &= ~XkbVirtualModNamesMask;
3687f7df2e56Smrg        }
3688f7df2e56Smrg
3689f7df2e56Smrg        if (which & XkbGroupNamesMask) {
3690f7df2e56Smrg            int nGroups;
3691f7df2e56Smrg
3692f7df2e56Smrg            rep->groupNames =
3693f7df2e56Smrg                _XkbCountAtoms(xkb->names->groups, XkbNumKbdGroups, &nGroups);
3694f7df2e56Smrg            length += nGroups;
3695f7df2e56Smrg            if (nGroups == 0)
3696f7df2e56Smrg                which &= ~XkbGroupNamesMask;
3697f7df2e56Smrg        }
3698f7df2e56Smrg
3699f7df2e56Smrg        if ((which & XkbKeyNamesMask) && (xkb->names->keys))
3700f7df2e56Smrg            length += rep->nKeys;
3701f7df2e56Smrg        else
3702f7df2e56Smrg            which &= ~XkbKeyNamesMask;
3703f7df2e56Smrg
3704f7df2e56Smrg        if ((which & XkbKeyAliasesMask) &&
3705f7df2e56Smrg            (xkb->names->key_aliases) && (xkb->names->num_key_aliases > 0)) {
3706f7df2e56Smrg            rep->nKeyAliases = xkb->names->num_key_aliases;
3707f7df2e56Smrg            length += rep->nKeyAliases * 2;
3708f7df2e56Smrg        }
3709f7df2e56Smrg        else {
3710f7df2e56Smrg            which &= ~XkbKeyAliasesMask;
3711f7df2e56Smrg            rep->nKeyAliases = 0;
3712f7df2e56Smrg        }
3713f7df2e56Smrg
3714f7df2e56Smrg        if ((which & XkbRGNamesMask) && (xkb->names->num_rg > 0))
3715f7df2e56Smrg            length += xkb->names->num_rg;
3716f7df2e56Smrg        else
3717f7df2e56Smrg            which &= ~XkbRGNamesMask;
371805b261ecSmrg    }
371905b261ecSmrg    else {
3720f7df2e56Smrg        which &= ~(XkbIndicatorNamesMask | XkbVirtualModNamesMask);
3721f7df2e56Smrg        which &= ~(XkbGroupNamesMask | XkbKeyNamesMask | XkbKeyAliasesMask);
3722f7df2e56Smrg        which &= ~XkbRGNamesMask;
372305b261ecSmrg    }
372405b261ecSmrg
3725f7df2e56Smrg    rep->length = length;
3726f7df2e56Smrg    rep->which = which;
372705b261ecSmrg    return Success;
372805b261ecSmrg}
372905b261ecSmrg
373005b261ecSmrgstatic int
3731f7df2e56SmrgXkbSendNames(ClientPtr client, XkbDescPtr xkb, xkbGetNamesReply * rep)
373205b261ecSmrg{
3733f7df2e56Smrg    register unsigned i, length, which;
3734f7df2e56Smrg    char *start;
3735f7df2e56Smrg    char *desc;
373605b261ecSmrg
3737f7df2e56Smrg    length = rep->length * 4;
3738f7df2e56Smrg    which = rep->which;
373905b261ecSmrg    if (client->swapped) {
3740f7df2e56Smrg        swaps(&rep->sequenceNumber);
3741f7df2e56Smrg        swapl(&rep->length);
3742f7df2e56Smrg        swapl(&rep->which);
3743f7df2e56Smrg        swaps(&rep->virtualMods);
3744f7df2e56Smrg        swapl(&rep->indicators);
374505b261ecSmrg    }
374605b261ecSmrg
37479ace9065Smrg    start = desc = calloc(1, length);
3748f7df2e56Smrg    if (!start)
3749f7df2e56Smrg        return BadAlloc;
375005b261ecSmrg    if (xkb->names) {
3751f7df2e56Smrg        if (which & XkbKeycodesNameMask) {
3752f7df2e56Smrg            *((CARD32 *) desc) = xkb->names->keycodes;
375305b261ecSmrg            if (client->swapped) {
3754f7df2e56Smrg                swapl((int *) desc);
375505b261ecSmrg            }
3756f7df2e56Smrg            desc += 4;
375705b261ecSmrg        }
3758f7df2e56Smrg        if (which & XkbGeometryNameMask) {
3759f7df2e56Smrg            *((CARD32 *) desc) = xkb->names->geometry;
376005b261ecSmrg            if (client->swapped) {
3761f7df2e56Smrg                swapl((int *) desc);
376205b261ecSmrg            }
3763f7df2e56Smrg            desc += 4;
376405b261ecSmrg        }
3765f7df2e56Smrg        if (which & XkbSymbolsNameMask) {
3766f7df2e56Smrg            *((CARD32 *) desc) = xkb->names->symbols;
376705b261ecSmrg            if (client->swapped) {
3768f7df2e56Smrg                swapl((int *) desc);
376905b261ecSmrg            }
3770f7df2e56Smrg            desc += 4;
377105b261ecSmrg        }
3772f7df2e56Smrg        if (which & XkbPhysSymbolsNameMask) {
3773f7df2e56Smrg            register CARD32 *atm = (CARD32 *) desc;
3774f7df2e56Smrg
3775f7df2e56Smrg            atm[0] = (CARD32) xkb->names->phys_symbols;
377605b261ecSmrg            if (client->swapped) {
3777f7df2e56Smrg                swapl(&atm[0]);
377805b261ecSmrg            }
3779f7df2e56Smrg            desc += 4;
378005b261ecSmrg        }
3781f7df2e56Smrg        if (which & XkbTypesNameMask) {
3782f7df2e56Smrg            *((CARD32 *) desc) = (CARD32) xkb->names->types;
378305b261ecSmrg            if (client->swapped) {
3784f7df2e56Smrg                swapl((int *) desc);
378505b261ecSmrg            }
3786f7df2e56Smrg            desc += 4;
378705b261ecSmrg        }
3788f7df2e56Smrg        if (which & XkbCompatNameMask) {
3789f7df2e56Smrg            *((CARD32 *) desc) = (CARD32) xkb->names->compat;
379005b261ecSmrg            if (client->swapped) {
3791f7df2e56Smrg                swapl((int *) desc);
379205b261ecSmrg            }
3793f7df2e56Smrg            desc += 4;
379405b261ecSmrg        }
3795f7df2e56Smrg        if (which & XkbKeyTypeNamesMask) {
3796f7df2e56Smrg            register CARD32 *atm = (CARD32 *) desc;
3797f7df2e56Smrg            register XkbKeyTypePtr type = xkb->map->types;
379805b261ecSmrg
3799f7df2e56Smrg            for (i = 0; i < xkb->map->num_types; i++, atm++, type++) {
3800f7df2e56Smrg                *atm = (CARD32) type->name;
380105b261ecSmrg                if (client->swapped) {
3802f7df2e56Smrg                    swapl(atm);
380305b261ecSmrg                }
380405b261ecSmrg            }
3805f7df2e56Smrg            desc = (char *) atm;
380605b261ecSmrg        }
3807f7df2e56Smrg        if (which & XkbKTLevelNamesMask && xkb->map) {
380805b261ecSmrg            XkbKeyTypePtr type = xkb->map->types;
380905b261ecSmrg            register CARD32 *atm;
3810f7df2e56Smrg
3811f7df2e56Smrg            for (i = 0; i < rep->nTypes; i++, type++) {
381205b261ecSmrg                *desc++ = type->num_levels;
381305b261ecSmrg            }
3814f7df2e56Smrg            desc += XkbPaddedSize(rep->nTypes) - rep->nTypes;
381505b261ecSmrg
3816f7df2e56Smrg            atm = (CARD32 *) desc;
381705b261ecSmrg            type = xkb->map->types;
3818f7df2e56Smrg            for (i = 0; i < xkb->map->num_types; i++, type++) {
381905b261ecSmrg                register unsigned l;
3820f7df2e56Smrg
382105b261ecSmrg                if (type->level_names) {
3822f7df2e56Smrg                    for (l = 0; l < type->num_levels; l++, atm++) {
3823f7df2e56Smrg                        *atm = type->level_names[l];
382405b261ecSmrg                        if (client->swapped) {
3825f7df2e56Smrg                            swapl(atm);
382605b261ecSmrg                        }
382705b261ecSmrg                    }
3828f7df2e56Smrg                    desc += type->num_levels * 4;
382905b261ecSmrg                }
383005b261ecSmrg            }
383105b261ecSmrg        }
3832f7df2e56Smrg        if (which & XkbIndicatorNamesMask) {
3833f7df2e56Smrg            desc =
3834f7df2e56Smrg                _XkbWriteAtoms(desc, xkb->names->indicators, XkbNumIndicators,
3835f7df2e56Smrg                               client->swapped);
383605b261ecSmrg        }
3837f7df2e56Smrg        if (which & XkbVirtualModNamesMask) {
3838f7df2e56Smrg            desc = _XkbWriteAtoms(desc, xkb->names->vmods, XkbNumVirtualMods,
3839f7df2e56Smrg                                  client->swapped);
384005b261ecSmrg        }
3841f7df2e56Smrg        if (which & XkbGroupNamesMask) {
3842f7df2e56Smrg            desc = _XkbWriteAtoms(desc, xkb->names->groups, XkbNumKbdGroups,
3843f7df2e56Smrg                                  client->swapped);
384405b261ecSmrg        }
3845f7df2e56Smrg        if (which & XkbKeyNamesMask) {
3846f7df2e56Smrg            for (i = 0; i < rep->nKeys; i++, desc += sizeof(XkbKeyNameRec)) {
3847f7df2e56Smrg                *((XkbKeyNamePtr) desc) = xkb->names->keys[i + rep->firstKey];
384805b261ecSmrg            }
384905b261ecSmrg        }
3850f7df2e56Smrg        if (which & XkbKeyAliasesMask) {
3851f7df2e56Smrg            XkbKeyAliasPtr pAl;
3852f7df2e56Smrg
3853f7df2e56Smrg            pAl = xkb->names->key_aliases;
3854f7df2e56Smrg            for (i = 0; i < rep->nKeyAliases;
3855f7df2e56Smrg                 i++, pAl++, desc += 2 * XkbKeyNameLength) {
3856f7df2e56Smrg                *((XkbKeyAliasPtr) desc) = *pAl;
385705b261ecSmrg            }
385805b261ecSmrg        }
3859f7df2e56Smrg        if ((which & XkbRGNamesMask) && (rep->nRadioGroups > 0)) {
3860f7df2e56Smrg            register CARD32 *atm = (CARD32 *) desc;
3861f7df2e56Smrg
3862f7df2e56Smrg            for (i = 0; i < rep->nRadioGroups; i++, atm++) {
3863f7df2e56Smrg                *atm = (CARD32) xkb->names->radio_groups[i];
386405b261ecSmrg                if (client->swapped) {
3865f7df2e56Smrg                    swapl(atm);
386605b261ecSmrg                }
386705b261ecSmrg            }
3868f7df2e56Smrg            desc += rep->nRadioGroups * 4;
386905b261ecSmrg        }
387005b261ecSmrg    }
387105b261ecSmrg
3872f7df2e56Smrg    if ((desc - start) != (length)) {
3873f7df2e56Smrg        ErrorF("[xkb] BOGUS LENGTH in write names, expected %d, got %ld\n",
3874f7df2e56Smrg               length, (unsigned long) (desc - start));
387505b261ecSmrg    }
3876f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetNamesReply), rep);
387705b261ecSmrg    WriteToClient(client, length, start);
3878f7df2e56Smrg    free((char *) start);
38796747b715Smrg    return Success;
388005b261ecSmrg}
388105b261ecSmrg
388205b261ecSmrgint
388305b261ecSmrgProcXkbGetNames(ClientPtr client)
388405b261ecSmrg{
3885f7df2e56Smrg    DeviceIntPtr dev;
3886f7df2e56Smrg    XkbDescPtr xkb;
3887f7df2e56Smrg    xkbGetNamesReply rep;
388805b261ecSmrg
388905b261ecSmrg    REQUEST(xkbGetNamesReq);
389005b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetNamesReq);
389105b261ecSmrg
3892f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
3893f7df2e56Smrg        return BadAccess;
389405b261ecSmrg
38954642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
3896f7df2e56Smrg    CHK_MASK_LEGAL(0x01, stuff->which, XkbAllNamesMask);
389705b261ecSmrg
389805b261ecSmrg    xkb = dev->key->xkbInfo->desc;
3899f7df2e56Smrg    rep = (xkbGetNamesReply) {
3900f7df2e56Smrg        .type = X_Reply,
3901f7df2e56Smrg        .deviceID = dev->id,
3902f7df2e56Smrg        .sequenceNumber = client->sequence,
3903f7df2e56Smrg        .length = 0,
3904f7df2e56Smrg        .which = stuff->which,
3905f7df2e56Smrg        .nTypes = xkb->map->num_types,
3906f7df2e56Smrg        .firstKey = xkb->min_key_code,
3907f7df2e56Smrg        .nKeys = XkbNumKeys(xkb),
3908f7df2e56Smrg        .nKeyAliases = xkb->names ? xkb->names->num_key_aliases : 0,
3909f7df2e56Smrg        .nRadioGroups = xkb->names ? xkb->names->num_rg : 0
3910f7df2e56Smrg    };
3911f7df2e56Smrg    XkbComputeGetNamesReplySize(xkb, &rep);
3912f7df2e56Smrg    return XkbSendNames(client, xkb, &rep);
391305b261ecSmrg}
391405b261ecSmrg
391505b261ecSmrg/***====================================================================***/
391605b261ecSmrg
391705b261ecSmrgstatic CARD32 *
3918f7df2e56Smrg_XkbCheckAtoms(CARD32 *wire, int nAtoms, int swapped, Atom *pError)
391905b261ecSmrg{
3920f7df2e56Smrg    register int i;
3921f7df2e56Smrg
3922f7df2e56Smrg    for (i = 0; i < nAtoms; i++, wire++) {
3923f7df2e56Smrg        if (swapped) {
3924f7df2e56Smrg            swapl(wire);
3925f7df2e56Smrg        }
3926f7df2e56Smrg        if ((((Atom) *wire) != None) && (!ValidAtom((Atom) *wire))) {
3927f7df2e56Smrg            *pError = ((Atom) *wire);
3928f7df2e56Smrg            return NULL;
3929f7df2e56Smrg        }
393005b261ecSmrg    }
393105b261ecSmrg    return wire;
393205b261ecSmrg}
393305b261ecSmrg
393405b261ecSmrgstatic CARD32 *
3935f7df2e56Smrg_XkbCheckMaskedAtoms(CARD32 *wire, int nAtoms, CARD32 present, int swapped,
3936f7df2e56Smrg                     Atom *pError)
393705b261ecSmrg{
3938f7df2e56Smrg    register unsigned i, bit;
3939f7df2e56Smrg
3940f7df2e56Smrg    for (i = 0, bit = 1; (i < nAtoms) && (present); i++, bit <<= 1) {
3941f7df2e56Smrg        if ((present & bit) == 0)
3942f7df2e56Smrg            continue;
3943f7df2e56Smrg        if (swapped) {
3944f7df2e56Smrg            swapl(wire);
3945f7df2e56Smrg        }
3946f7df2e56Smrg        if ((((Atom) *wire) != None) && (!ValidAtom(((Atom) *wire)))) {
3947f7df2e56Smrg            *pError = (Atom) *wire;
3948f7df2e56Smrg            return NULL;
3949f7df2e56Smrg        }
3950f7df2e56Smrg        wire++;
395105b261ecSmrg    }
395205b261ecSmrg    return wire;
395305b261ecSmrg}
395405b261ecSmrg
395505b261ecSmrgstatic Atom *
3956f7df2e56Smrg_XkbCopyMaskedAtoms(Atom *wire, Atom *dest, int nAtoms, CARD32 present)
395705b261ecSmrg{
3958f7df2e56Smrg    register int i, bit;
395905b261ecSmrg
3960f7df2e56Smrg    for (i = 0, bit = 1; (i < nAtoms) && (present); i++, bit <<= 1) {
3961f7df2e56Smrg        if ((present & bit) == 0)
3962f7df2e56Smrg            continue;
3963f7df2e56Smrg        dest[i] = *wire++;
396405b261ecSmrg    }
396505b261ecSmrg    return wire;
396605b261ecSmrg}
396705b261ecSmrg
396805b261ecSmrgstatic Bool
3969f7df2e56Smrg_XkbCheckTypeName(Atom name, int typeNdx)
397005b261ecSmrg{
3971f7df2e56Smrg    const char *str;
397205b261ecSmrg
3973f7df2e56Smrg    str = NameForAtom(name);
3974f7df2e56Smrg    if ((strcmp(str, "ONE_LEVEL") == 0) || (strcmp(str, "TWO_LEVEL") == 0) ||
3975f7df2e56Smrg        (strcmp(str, "ALPHABETIC") == 0) || (strcmp(str, "KEYPAD") == 0))
3976f7df2e56Smrg        return FALSE;
39776747b715Smrg    return TRUE;
397805b261ecSmrg}
397905b261ecSmrg
39804642e01fSmrg/**
39814642e01fSmrg * Check the device-dependent data in the request against the device. Returns
39824642e01fSmrg * Success, or the appropriate error code.
39834642e01fSmrg */
39844642e01fSmrgstatic int
39854642e01fSmrg_XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
3986f7df2e56Smrg                  xkbSetNamesReq * stuff, CARD32 *data)
398705b261ecSmrg{
3988f7df2e56Smrg    XkbDescRec *xkb;
3989f7df2e56Smrg    CARD32 *tmp;
3990f7df2e56Smrg    Atom bad = None;
399105b261ecSmrg
39924642e01fSmrg    tmp = data;
39934642e01fSmrg    xkb = dev->key->xkbInfo->desc;
39944642e01fSmrg
39954642e01fSmrg    if (stuff->which & XkbKeyTypeNamesMask) {
39964642e01fSmrg        int i;
3997f7df2e56Smrg        CARD32 *old;
3998f7df2e56Smrg
3999f7df2e56Smrg        if (stuff->nTypes < 1) {
4000f7df2e56Smrg            client->errorValue = _XkbErrCode2(0x02, stuff->nTypes);
40014642e01fSmrg            return BadValue;
40024642e01fSmrg        }
4003f7df2e56Smrg        if ((unsigned) (stuff->firstType + stuff->nTypes - 1) >=
4004f7df2e56Smrg            xkb->map->num_types) {
4005f7df2e56Smrg            client->errorValue =
4006f7df2e56Smrg                _XkbErrCode4(0x03, stuff->firstType, stuff->nTypes,
4007f7df2e56Smrg                             xkb->map->num_types);
40084642e01fSmrg            return BadValue;
40094642e01fSmrg        }
4010f7df2e56Smrg        if (((unsigned) stuff->firstType) <= XkbLastRequiredType) {
4011f7df2e56Smrg            client->errorValue = _XkbErrCode2(0x04, stuff->firstType);
40124642e01fSmrg            return BadAccess;
40134642e01fSmrg        }
4014f7df2e56Smrg        old = tmp;
4015f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, stuff->nTypes, client->swapped, &bad);
40164642e01fSmrg        if (!tmp) {
4017f7df2e56Smrg            client->errorValue = bad;
40184642e01fSmrg            return BadAtom;
40194642e01fSmrg        }
4020f7df2e56Smrg        for (i = 0; i < stuff->nTypes; i++, old++) {
4021f7df2e56Smrg            if (!_XkbCheckTypeName((Atom) *old, stuff->firstType + i))
4022f7df2e56Smrg                client->errorValue = _XkbErrCode2(0x05, i);
40234642e01fSmrg        }
40244642e01fSmrg    }
4025f7df2e56Smrg    if (stuff->which & XkbKTLevelNamesMask) {
40264642e01fSmrg        unsigned i;
4027f7df2e56Smrg        XkbKeyTypePtr type;
4028f7df2e56Smrg        CARD8 *width;
4029f7df2e56Smrg
4030f7df2e56Smrg        if (stuff->nKTLevels < 1) {
4031f7df2e56Smrg            client->errorValue = _XkbErrCode2(0x05, stuff->nKTLevels);
40324642e01fSmrg            return BadValue;
40334642e01fSmrg        }
4034f7df2e56Smrg        if ((unsigned) (stuff->firstKTLevel + stuff->nKTLevels - 1) >=
4035f7df2e56Smrg            xkb->map->num_types) {
4036f7df2e56Smrg            client->errorValue = _XkbErrCode4(0x06, stuff->firstKTLevel,
4037f7df2e56Smrg                                              stuff->nKTLevels,
4038f7df2e56Smrg                                              xkb->map->num_types);
40394642e01fSmrg            return BadValue;
40404642e01fSmrg        }
4041f7df2e56Smrg        width = (CARD8 *) tmp;
4042f7df2e56Smrg        tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels));
40434642e01fSmrg        type = &xkb->map->types[stuff->firstKTLevel];
4044f7df2e56Smrg        for (i = 0; i < stuff->nKTLevels; i++, type++) {
4045f7df2e56Smrg            if (width[i] == 0)
40464642e01fSmrg                continue;
4047f7df2e56Smrg            else if (width[i] != type->num_levels) {
4048f7df2e56Smrg                client->errorValue = _XkbErrCode4(0x07, i + stuff->firstKTLevel,
4049f7df2e56Smrg                                                  type->num_levels, width[i]);
40504642e01fSmrg                return BadMatch;
40514642e01fSmrg            }
4052f7df2e56Smrg            tmp = _XkbCheckAtoms(tmp, width[i], client->swapped, &bad);
40534642e01fSmrg            if (!tmp) {
4054f7df2e56Smrg                client->errorValue = bad;
40554642e01fSmrg                return BadAtom;
40564642e01fSmrg            }
40574642e01fSmrg        }
40584642e01fSmrg    }
4059f7df2e56Smrg    if (stuff->which & XkbIndicatorNamesMask) {
4060f7df2e56Smrg        if (stuff->indicators == 0) {
4061f7df2e56Smrg            client->errorValue = 0x08;
40624642e01fSmrg            return BadMatch;
40634642e01fSmrg        }
4064f7df2e56Smrg        tmp = _XkbCheckMaskedAtoms(tmp, XkbNumIndicators, stuff->indicators,
4065f7df2e56Smrg                                   client->swapped, &bad);
40664642e01fSmrg        if (!tmp) {
4067f7df2e56Smrg            client->errorValue = bad;
40684642e01fSmrg            return BadAtom;
40694642e01fSmrg        }
40704642e01fSmrg    }
4071f7df2e56Smrg    if (stuff->which & XkbVirtualModNamesMask) {
4072f7df2e56Smrg        if (stuff->virtualMods == 0) {
4073f7df2e56Smrg            client->errorValue = 0x09;
40744642e01fSmrg            return BadMatch;
40754642e01fSmrg        }
4076f7df2e56Smrg        tmp = _XkbCheckMaskedAtoms(tmp, XkbNumVirtualMods,
4077f7df2e56Smrg                                   (CARD32) stuff->virtualMods,
4078f7df2e56Smrg                                   client->swapped, &bad);
40794642e01fSmrg        if (!tmp) {
40804642e01fSmrg            client->errorValue = bad;
40814642e01fSmrg            return BadAtom;
40824642e01fSmrg        }
40834642e01fSmrg    }
4084f7df2e56Smrg    if (stuff->which & XkbGroupNamesMask) {
4085f7df2e56Smrg        if (stuff->groupNames == 0) {
4086f7df2e56Smrg            client->errorValue = 0x0a;
40874642e01fSmrg            return BadMatch;
40884642e01fSmrg        }
4089f7df2e56Smrg        tmp = _XkbCheckMaskedAtoms(tmp, XkbNumKbdGroups,
4090f7df2e56Smrg                                   (CARD32) stuff->groupNames,
4091f7df2e56Smrg                                   client->swapped, &bad);
40924642e01fSmrg        if (!tmp) {
40934642e01fSmrg            client->errorValue = bad;
40944642e01fSmrg            return BadAtom;
40954642e01fSmrg        }
40964642e01fSmrg    }
4097f7df2e56Smrg    if (stuff->which & XkbKeyNamesMask) {
4098f7df2e56Smrg        if (stuff->firstKey < (unsigned) xkb->min_key_code) {
4099f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x0b, xkb->min_key_code,
4100f7df2e56Smrg                                              stuff->firstKey);
41014642e01fSmrg            return BadValue;
41024642e01fSmrg        }
4103f7df2e56Smrg        if (((unsigned) (stuff->firstKey + stuff->nKeys - 1) >
4104f7df2e56Smrg             xkb->max_key_code) || (stuff->nKeys < 1)) {
4105f7df2e56Smrg            client->errorValue =
4106f7df2e56Smrg                _XkbErrCode4(0x0c, xkb->max_key_code, stuff->firstKey,
4107f7df2e56Smrg                             stuff->nKeys);
41084642e01fSmrg            return BadValue;
41094642e01fSmrg        }
4110f7df2e56Smrg        tmp += stuff->nKeys;
41114642e01fSmrg    }
4112f7df2e56Smrg    if ((stuff->which & XkbKeyAliasesMask) && (stuff->nKeyAliases > 0)) {
4113f7df2e56Smrg        tmp += stuff->nKeyAliases * 2;
41144642e01fSmrg    }
4115f7df2e56Smrg    if (stuff->which & XkbRGNamesMask) {
4116f7df2e56Smrg        if (stuff->nRadioGroups < 1) {
4117f7df2e56Smrg            client->errorValue = _XkbErrCode2(0x0d, stuff->nRadioGroups);
41184642e01fSmrg            return BadValue;
41194642e01fSmrg        }
4120f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, stuff->nRadioGroups, client->swapped, &bad);
41214642e01fSmrg        if (!tmp) {
4122f7df2e56Smrg            client->errorValue = bad;
41234642e01fSmrg            return BadAtom;
41244642e01fSmrg        }
41254642e01fSmrg    }
4126f7df2e56Smrg    if ((tmp - ((CARD32 *) stuff)) != stuff->length) {
41274642e01fSmrg        client->errorValue = stuff->length;
41284642e01fSmrg        return BadLength;
41294642e01fSmrg    }
41304642e01fSmrg
41314642e01fSmrg    return Success;
41324642e01fSmrg}
41334642e01fSmrg
41344642e01fSmrgstatic int
4135f7df2e56Smrg_XkbSetNames(ClientPtr client, DeviceIntPtr dev, xkbSetNamesReq * stuff)
41364642e01fSmrg{
4137f7df2e56Smrg    XkbDescRec *xkb;
4138f7df2e56Smrg    XkbNamesRec *names;
4139f7df2e56Smrg    CARD32 *tmp;
4140f7df2e56Smrg    xkbNamesNotify nn;
41414642e01fSmrg
4142f7df2e56Smrg    tmp = (CARD32 *) &stuff[1];
41434642e01fSmrg    xkb = dev->key->xkbInfo->desc;
41444642e01fSmrg    names = xkb->names;
41454642e01fSmrg
4146f7df2e56Smrg    if (XkbAllocNames(xkb, stuff->which, stuff->nRadioGroups,
4147f7df2e56Smrg                      stuff->nKeyAliases) != Success) {
41484642e01fSmrg        return BadAlloc;
41494642e01fSmrg    }
41504642e01fSmrg
41516747b715Smrg    memset(&nn, 0, sizeof(xkbNamesNotify));
4152f7df2e56Smrg    nn.changed = stuff->which;
4153f7df2e56Smrg    tmp = (CARD32 *) &stuff[1];
4154f7df2e56Smrg    if (stuff->which & XkbKeycodesNameMask)
4155f7df2e56Smrg        names->keycodes = *tmp++;
4156f7df2e56Smrg    if (stuff->which & XkbGeometryNameMask)
4157f7df2e56Smrg        names->geometry = *tmp++;
4158f7df2e56Smrg    if (stuff->which & XkbSymbolsNameMask)
4159f7df2e56Smrg        names->symbols = *tmp++;
4160f7df2e56Smrg    if (stuff->which & XkbPhysSymbolsNameMask)
4161f7df2e56Smrg        names->phys_symbols = *tmp++;
4162f7df2e56Smrg    if (stuff->which & XkbTypesNameMask)
4163f7df2e56Smrg        names->types = *tmp++;
4164f7df2e56Smrg    if (stuff->which & XkbCompatNameMask)
4165f7df2e56Smrg        names->compat = *tmp++;
4166f7df2e56Smrg    if ((stuff->which & XkbKeyTypeNamesMask) && (stuff->nTypes > 0)) {
41674642e01fSmrg        register unsigned i;
41684642e01fSmrg        register XkbKeyTypePtr type;
41694642e01fSmrg
4170f7df2e56Smrg        type = &xkb->map->types[stuff->firstType];
4171f7df2e56Smrg        for (i = 0; i < stuff->nTypes; i++, type++) {
4172f7df2e56Smrg            type->name = *tmp++;
41734642e01fSmrg        }
4174f7df2e56Smrg        nn.firstType = stuff->firstType;
4175f7df2e56Smrg        nn.nTypes = stuff->nTypes;
41764642e01fSmrg    }
4177f7df2e56Smrg    if (stuff->which & XkbKTLevelNamesMask) {
4178f7df2e56Smrg        register XkbKeyTypePtr type;
41794642e01fSmrg        register unsigned i;
41804642e01fSmrg        CARD8 *width;
41814642e01fSmrg
4182f7df2e56Smrg        width = (CARD8 *) tmp;
4183f7df2e56Smrg        tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels));
4184f7df2e56Smrg        type = &xkb->map->types[stuff->firstKTLevel];
4185f7df2e56Smrg        for (i = 0; i < stuff->nKTLevels; i++, type++) {
4186f7df2e56Smrg            if (width[i] > 0) {
41874642e01fSmrg                if (type->level_names) {
41884642e01fSmrg                    register unsigned n;
4189f7df2e56Smrg
4190f7df2e56Smrg                    for (n = 0; n < width[i]; n++) {
4191f7df2e56Smrg                        type->level_names[n] = tmp[n];
41924642e01fSmrg                    }
41934642e01fSmrg                }
4194f7df2e56Smrg                tmp += width[i];
41954642e01fSmrg            }
41964642e01fSmrg        }
4197f7df2e56Smrg        nn.firstLevelName = 0;
4198f7df2e56Smrg        nn.nLevelNames = stuff->nTypes;
4199f7df2e56Smrg    }
4200f7df2e56Smrg    if (stuff->which & XkbIndicatorNamesMask) {
4201f7df2e56Smrg        tmp = _XkbCopyMaskedAtoms(tmp, names->indicators, XkbNumIndicators,
4202f7df2e56Smrg                                  stuff->indicators);
4203f7df2e56Smrg        nn.changedIndicators = stuff->indicators;
4204f7df2e56Smrg    }
4205f7df2e56Smrg    if (stuff->which & XkbVirtualModNamesMask) {
4206f7df2e56Smrg        tmp = _XkbCopyMaskedAtoms(tmp, names->vmods, XkbNumVirtualMods,
4207f7df2e56Smrg                                  stuff->virtualMods);
4208f7df2e56Smrg        nn.changedVirtualMods = stuff->virtualMods;
4209f7df2e56Smrg    }
4210f7df2e56Smrg    if (stuff->which & XkbGroupNamesMask) {
4211f7df2e56Smrg        tmp = _XkbCopyMaskedAtoms(tmp, names->groups, XkbNumKbdGroups,
4212f7df2e56Smrg                                  stuff->groupNames);
4213f7df2e56Smrg        nn.changedVirtualMods = stuff->groupNames;
4214f7df2e56Smrg    }
4215f7df2e56Smrg    if (stuff->which & XkbKeyNamesMask) {
4216f7df2e56Smrg        memcpy((char *) &names->keys[stuff->firstKey], (char *) tmp,
4217f7df2e56Smrg               stuff->nKeys * XkbKeyNameLength);
4218f7df2e56Smrg        tmp += stuff->nKeys;
4219f7df2e56Smrg        nn.firstKey = stuff->firstKey;
4220f7df2e56Smrg        nn.nKeys = stuff->nKeys;
4221f7df2e56Smrg    }
4222f7df2e56Smrg    if (stuff->which & XkbKeyAliasesMask) {
4223f7df2e56Smrg        if (stuff->nKeyAliases > 0) {
4224f7df2e56Smrg            register int na = stuff->nKeyAliases;
4225f7df2e56Smrg
4226f7df2e56Smrg            if (XkbAllocNames(xkb, XkbKeyAliasesMask, 0, na) != Success)
42274642e01fSmrg                return BadAlloc;
4228f7df2e56Smrg            memcpy((char *) names->key_aliases, (char *) tmp,
4229f7df2e56Smrg                   stuff->nKeyAliases * sizeof(XkbKeyAliasRec));
4230f7df2e56Smrg            tmp += stuff->nKeyAliases * 2;
42314642e01fSmrg        }
4232f7df2e56Smrg        else if (names->key_aliases != NULL) {
42336747b715Smrg            free(names->key_aliases);
4234f7df2e56Smrg            names->key_aliases = NULL;
4235f7df2e56Smrg            names->num_key_aliases = 0;
42364642e01fSmrg        }
4237f7df2e56Smrg        nn.nAliases = names->num_key_aliases;
42384642e01fSmrg    }
4239f7df2e56Smrg    if (stuff->which & XkbRGNamesMask) {
4240f7df2e56Smrg        if (stuff->nRadioGroups > 0) {
4241f7df2e56Smrg            register unsigned i, nrg;
4242f7df2e56Smrg
4243f7df2e56Smrg            nrg = stuff->nRadioGroups;
4244f7df2e56Smrg            if (XkbAllocNames(xkb, XkbRGNamesMask, nrg, 0) != Success)
42454642e01fSmrg                return BadAlloc;
42464642e01fSmrg
4247f7df2e56Smrg            for (i = 0; i < stuff->nRadioGroups; i++) {
4248f7df2e56Smrg                names->radio_groups[i] = tmp[i];
42494642e01fSmrg            }
4250f7df2e56Smrg            tmp += stuff->nRadioGroups;
42514642e01fSmrg        }
42524642e01fSmrg        else if (names->radio_groups) {
42536747b715Smrg            free(names->radio_groups);
4254f7df2e56Smrg            names->radio_groups = NULL;
4255f7df2e56Smrg            names->num_rg = 0;
42564642e01fSmrg        }
4257f7df2e56Smrg        nn.nRadioGroups = names->num_rg;
42584642e01fSmrg    }
42594642e01fSmrg    if (nn.changed) {
42604642e01fSmrg        Bool needExtEvent;
4261f7df2e56Smrg
4262f7df2e56Smrg        needExtEvent = (nn.changed & XkbIndicatorNamesMask) != 0;
4263f7df2e56Smrg        XkbSendNamesNotify(dev, &nn);
42644642e01fSmrg        if (needExtEvent) {
4265f7df2e56Smrg            XkbSrvLedInfoPtr sli;
4266f7df2e56Smrg            xkbExtensionDeviceNotify edev;
4267f7df2e56Smrg            register int i;
4268f7df2e56Smrg            register unsigned bit;
4269f7df2e56Smrg
4270f7df2e56Smrg            sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
4271f7df2e56Smrg                                    XkbXI_IndicatorsMask);
4272f7df2e56Smrg            sli->namesPresent = 0;
4273f7df2e56Smrg            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
4274f7df2e56Smrg                if (names->indicators[i] != None)
4275f7df2e56Smrg                    sli->namesPresent |= bit;
42764642e01fSmrg            }
42776747b715Smrg            memset(&edev, 0, sizeof(xkbExtensionDeviceNotify));
4278f7df2e56Smrg            edev.reason = XkbXI_IndicatorNamesMask;
4279f7df2e56Smrg            edev.ledClass = KbdFeedbackClass;
4280f7df2e56Smrg            edev.ledID = dev->kbdfeed->ctrl.id;
4281f7df2e56Smrg            edev.ledsDefined = sli->namesPresent | sli->mapsPresent;
4282f7df2e56Smrg            edev.ledState = sli->effectiveState;
4283f7df2e56Smrg            edev.firstBtn = 0;
4284f7df2e56Smrg            edev.nBtns = 0;
4285f7df2e56Smrg            edev.supported = XkbXI_AllFeaturesMask;
4286f7df2e56Smrg            edev.unsupported = 0;
4287f7df2e56Smrg            XkbSendExtensionDeviceNotify(dev, client, &edev);
42884642e01fSmrg        }
42894642e01fSmrg    }
42904642e01fSmrg    return Success;
42914642e01fSmrg}
42924642e01fSmrg
42934642e01fSmrgint
42944642e01fSmrgProcXkbSetNames(ClientPtr client)
42954642e01fSmrg{
4296f7df2e56Smrg    DeviceIntPtr dev;
4297f7df2e56Smrg    CARD32 *tmp;
4298f7df2e56Smrg    Atom bad;
4299f7df2e56Smrg    int rc;
43004642e01fSmrg
430105b261ecSmrg    REQUEST(xkbSetNamesReq);
430205b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetNamesReq);
430305b261ecSmrg
4304f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
4305f7df2e56Smrg        return BadAccess;
430605b261ecSmrg
43074642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
4308f7df2e56Smrg    CHK_MASK_LEGAL(0x01, stuff->which, XkbAllNamesMask);
430905b261ecSmrg
43104642e01fSmrg    /* check device-independent stuff */
4311f7df2e56Smrg    tmp = (CARD32 *) &stuff[1];
4312f7df2e56Smrg
4313f7df2e56Smrg    if (stuff->which & XkbKeycodesNameMask) {
4314f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4315f7df2e56Smrg        if (!tmp) {
4316f7df2e56Smrg            client->errorValue = bad;
4317f7df2e56Smrg            return BadAtom;
4318f7df2e56Smrg        }
4319f7df2e56Smrg    }
4320f7df2e56Smrg    if (stuff->which & XkbGeometryNameMask) {
4321f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4322f7df2e56Smrg        if (!tmp) {
4323f7df2e56Smrg            client->errorValue = bad;
4324f7df2e56Smrg            return BadAtom;
4325f7df2e56Smrg        }
4326f7df2e56Smrg    }
4327f7df2e56Smrg    if (stuff->which & XkbSymbolsNameMask) {
4328f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4329f7df2e56Smrg        if (!tmp) {
4330f7df2e56Smrg            client->errorValue = bad;
4331f7df2e56Smrg            return BadAtom;
4332f7df2e56Smrg        }
4333f7df2e56Smrg    }
4334f7df2e56Smrg    if (stuff->which & XkbPhysSymbolsNameMask) {
4335f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4336f7df2e56Smrg        if (!tmp) {
4337f7df2e56Smrg            client->errorValue = bad;
4338f7df2e56Smrg            return BadAtom;
4339f7df2e56Smrg        }
4340f7df2e56Smrg    }
4341f7df2e56Smrg    if (stuff->which & XkbTypesNameMask) {
4342f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4343f7df2e56Smrg        if (!tmp) {
4344f7df2e56Smrg            client->errorValue = bad;
4345f7df2e56Smrg            return BadAtom;
4346f7df2e56Smrg        }
4347f7df2e56Smrg    }
4348f7df2e56Smrg    if (stuff->which & XkbCompatNameMask) {
4349f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4350f7df2e56Smrg        if (!tmp) {
4351f7df2e56Smrg            client->errorValue = bad;
4352f7df2e56Smrg            return BadAtom;
4353f7df2e56Smrg        }
435405b261ecSmrg    }
43554642e01fSmrg
43564642e01fSmrg    /* start of device-dependent tests */
43574642e01fSmrg    rc = _XkbSetNamesCheck(client, dev, stuff, tmp);
43584642e01fSmrg    if (rc != Success)
43594642e01fSmrg        return rc;
43604642e01fSmrg
4361f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
43624642e01fSmrg        DeviceIntPtr other;
43634642e01fSmrg
4364f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
4365f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
4366f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
4367f7df2e56Smrg
4368f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
4369f7df2e56Smrg                              DixManageAccess);
4370f7df2e56Smrg                if (rc == Success) {
43714642e01fSmrg                    rc = _XkbSetNamesCheck(client, other, stuff, tmp);
43724642e01fSmrg                    if (rc != Success)
43734642e01fSmrg                        return rc;
43744642e01fSmrg                }
43754642e01fSmrg            }
43764642e01fSmrg        }
437705b261ecSmrg    }
437805b261ecSmrg
437905b261ecSmrg    /* everything is okay -- update names */
438005b261ecSmrg
43814642e01fSmrg    rc = _XkbSetNames(client, dev, stuff);
43824642e01fSmrg    if (rc != Success)
43834642e01fSmrg        return rc;
438405b261ecSmrg
4385f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
43864642e01fSmrg        DeviceIntPtr other;
43874642e01fSmrg
4388f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
4389f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
4390f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
4391f7df2e56Smrg
4392f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
4393f7df2e56Smrg                              DixManageAccess);
43944642e01fSmrg                if (rc == Success)
43954642e01fSmrg                    _XkbSetNames(client, other, stuff);
43964642e01fSmrg            }
43974642e01fSmrg        }
439805b261ecSmrg    }
43994642e01fSmrg
44004642e01fSmrg    /* everything is okay -- update names */
44014642e01fSmrg
44026747b715Smrg    return Success;
440305b261ecSmrg}
440405b261ecSmrg
440505b261ecSmrg/***====================================================================***/
440605b261ecSmrg
44074642e01fSmrg#include "xkbgeom.h"
440805b261ecSmrg
440905b261ecSmrg#define	XkbSizeCountedString(s)  ((s)?((((2+strlen(s))+3)/4)*4):4)
441005b261ecSmrg
4411f7df2e56Smrg/**
4412f7df2e56Smrg * Write the zero-terminated string str into wire as a pascal string with a
4413f7df2e56Smrg * 16-bit length field prefixed before the actual string.
4414f7df2e56Smrg *
4415f7df2e56Smrg * @param wire The destination array, usually the wire struct
4416f7df2e56Smrg * @param str The source string as zero-terminated C string
4417f7df2e56Smrg * @param swap If TRUE, the length field is swapped.
4418f7df2e56Smrg *
4419f7df2e56Smrg * @return The input string in the format <string length><string> with a
4420f7df2e56Smrg * (swapped) 16 bit string length, non-zero terminated.
4421f7df2e56Smrg */
442205b261ecSmrgstatic char *
4423f7df2e56SmrgXkbWriteCountedString(char *wire, const char *str, Bool swap)
442405b261ecSmrg{
4425f7df2e56Smrg    CARD16 len, *pLen, paddedLen;
442605b261ecSmrg
44276747b715Smrg    if (!str)
44286747b715Smrg        return wire;
44296747b715Smrg
4430f7df2e56Smrg    len = strlen(str);
4431f7df2e56Smrg    pLen = (CARD16 *) wire;
4432f7df2e56Smrg    *pLen = len;
443305b261ecSmrg    if (swap) {
4434f7df2e56Smrg        swaps(pLen);
443505b261ecSmrg    }
4436f7df2e56Smrg    paddedLen = pad_to_int32(sizeof(len) + len) - sizeof(len);
4437f7df2e56Smrg    strncpy(&wire[sizeof(len)], str, paddedLen);
4438f7df2e56Smrg    wire += sizeof(len) + paddedLen;
443905b261ecSmrg    return wire;
444005b261ecSmrg}
444105b261ecSmrg
444205b261ecSmrgstatic int
444305b261ecSmrgXkbSizeGeomProperties(XkbGeometryPtr geom)
444405b261ecSmrg{
4445f7df2e56Smrg    register int i, size;
4446f7df2e56Smrg    XkbPropertyPtr prop;
4447f7df2e56Smrg
4448f7df2e56Smrg    for (size = i = 0, prop = geom->properties; i < geom->num_properties;
4449f7df2e56Smrg         i++, prop++) {
4450f7df2e56Smrg        size += XkbSizeCountedString(prop->name);
4451f7df2e56Smrg        size += XkbSizeCountedString(prop->value);
445205b261ecSmrg    }
445305b261ecSmrg    return size;
445405b261ecSmrg}
445505b261ecSmrg
445605b261ecSmrgstatic char *
4457f7df2e56SmrgXkbWriteGeomProperties(char *wire, XkbGeometryPtr geom, Bool swap)
445805b261ecSmrg{
4459f7df2e56Smrg    register int i;
4460f7df2e56Smrg    register XkbPropertyPtr prop;
4461f7df2e56Smrg
4462f7df2e56Smrg    for (i = 0, prop = geom->properties; i < geom->num_properties; i++, prop++) {
4463f7df2e56Smrg        wire = XkbWriteCountedString(wire, prop->name, swap);
4464f7df2e56Smrg        wire = XkbWriteCountedString(wire, prop->value, swap);
446505b261ecSmrg    }
446605b261ecSmrg    return wire;
446705b261ecSmrg}
446805b261ecSmrg
446905b261ecSmrgstatic int
447005b261ecSmrgXkbSizeGeomKeyAliases(XkbGeometryPtr geom)
447105b261ecSmrg{
4472f7df2e56Smrg    return geom->num_key_aliases * (2 * XkbKeyNameLength);
447305b261ecSmrg}
447405b261ecSmrg
447505b261ecSmrgstatic char *
4476f7df2e56SmrgXkbWriteGeomKeyAliases(char *wire, XkbGeometryPtr geom, Bool swap)
447705b261ecSmrg{
4478f7df2e56Smrg    register int sz;
4479f7df2e56Smrg
4480f7df2e56Smrg    sz = geom->num_key_aliases * (XkbKeyNameLength * 2);
4481f7df2e56Smrg    if (sz > 0) {
4482f7df2e56Smrg        memcpy(wire, (char *) geom->key_aliases, sz);
4483f7df2e56Smrg        wire += sz;
448405b261ecSmrg    }
448505b261ecSmrg    return wire;
448605b261ecSmrg}
448705b261ecSmrg
448805b261ecSmrgstatic int
448905b261ecSmrgXkbSizeGeomColors(XkbGeometryPtr geom)
449005b261ecSmrg{
4491f7df2e56Smrg    register int i, size;
4492f7df2e56Smrg    register XkbColorPtr color;
449305b261ecSmrg
4494f7df2e56Smrg    for (i = size = 0, color = geom->colors; i < geom->num_colors; i++, color++) {
4495f7df2e56Smrg        size += XkbSizeCountedString(color->spec);
449605b261ecSmrg    }
449705b261ecSmrg    return size;
449805b261ecSmrg}
449905b261ecSmrg
450005b261ecSmrgstatic char *
4501f7df2e56SmrgXkbWriteGeomColors(char *wire, XkbGeometryPtr geom, Bool swap)
450205b261ecSmrg{
4503f7df2e56Smrg    register int i;
4504f7df2e56Smrg    register XkbColorPtr color;
450505b261ecSmrg
4506f7df2e56Smrg    for (i = 0, color = geom->colors; i < geom->num_colors; i++, color++) {
4507f7df2e56Smrg        wire = XkbWriteCountedString(wire, color->spec, swap);
450805b261ecSmrg    }
450905b261ecSmrg    return wire;
451005b261ecSmrg}
451105b261ecSmrg
451205b261ecSmrgstatic int
451305b261ecSmrgXkbSizeGeomShapes(XkbGeometryPtr geom)
451405b261ecSmrg{
4515f7df2e56Smrg    register int i, size;
4516f7df2e56Smrg    register XkbShapePtr shape;
4517f7df2e56Smrg
4518f7df2e56Smrg    for (i = size = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) {
4519f7df2e56Smrg        register int n;
4520f7df2e56Smrg        register XkbOutlinePtr ol;
4521f7df2e56Smrg
4522f7df2e56Smrg        size += SIZEOF(xkbShapeWireDesc);
4523f7df2e56Smrg        for (n = 0, ol = shape->outlines; n < shape->num_outlines; n++, ol++) {
4524f7df2e56Smrg            size += SIZEOF(xkbOutlineWireDesc);
4525f7df2e56Smrg            size += ol->num_points * SIZEOF(xkbPointWireDesc);
4526f7df2e56Smrg        }
452705b261ecSmrg    }
452805b261ecSmrg    return size;
452905b261ecSmrg}
453005b261ecSmrg
453105b261ecSmrgstatic char *
4532f7df2e56SmrgXkbWriteGeomShapes(char *wire, XkbGeometryPtr geom, Bool swap)
453305b261ecSmrg{
4534f7df2e56Smrg    int i;
4535f7df2e56Smrg    XkbShapePtr shape;
4536f7df2e56Smrg    xkbShapeWireDesc *shapeWire;
4537f7df2e56Smrg
4538f7df2e56Smrg    for (i = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) {
4539f7df2e56Smrg        register int o;
4540f7df2e56Smrg        XkbOutlinePtr ol;
4541f7df2e56Smrg        xkbOutlineWireDesc *olWire;
4542f7df2e56Smrg
4543f7df2e56Smrg        shapeWire = (xkbShapeWireDesc *) wire;
4544f7df2e56Smrg        shapeWire->name = shape->name;
4545f7df2e56Smrg        shapeWire->nOutlines = shape->num_outlines;
4546f7df2e56Smrg        if (shape->primary != NULL)
4547f7df2e56Smrg            shapeWire->primaryNdx = XkbOutlineIndex(shape, shape->primary);
4548f7df2e56Smrg        else
4549f7df2e56Smrg            shapeWire->primaryNdx = XkbNoShape;
4550f7df2e56Smrg        if (shape->approx != NULL)
4551f7df2e56Smrg            shapeWire->approxNdx = XkbOutlineIndex(shape, shape->approx);
4552f7df2e56Smrg        else
4553f7df2e56Smrg            shapeWire->approxNdx = XkbNoShape;
4554f7df2e56Smrg        shapeWire->pad = 0;
4555f7df2e56Smrg        if (swap) {
4556f7df2e56Smrg            swapl(&shapeWire->name);
4557f7df2e56Smrg        }
4558f7df2e56Smrg        wire = (char *) &shapeWire[1];
4559f7df2e56Smrg        for (o = 0, ol = shape->outlines; o < shape->num_outlines; o++, ol++) {
4560f7df2e56Smrg            register int p;
4561f7df2e56Smrg            XkbPointPtr pt;
4562f7df2e56Smrg            xkbPointWireDesc *ptWire;
4563f7df2e56Smrg
4564f7df2e56Smrg            olWire = (xkbOutlineWireDesc *) wire;
4565f7df2e56Smrg            olWire->nPoints = ol->num_points;
4566f7df2e56Smrg            olWire->cornerRadius = ol->corner_radius;
4567f7df2e56Smrg            olWire->pad = 0;
4568f7df2e56Smrg            wire = (char *) &olWire[1];
4569f7df2e56Smrg            ptWire = (xkbPointWireDesc *) wire;
4570f7df2e56Smrg            for (p = 0, pt = ol->points; p < ol->num_points; p++, pt++) {
4571f7df2e56Smrg                ptWire[p].x = pt->x;
4572f7df2e56Smrg                ptWire[p].y = pt->y;
4573f7df2e56Smrg                if (swap) {
4574f7df2e56Smrg                    swaps(&ptWire[p].x);
4575f7df2e56Smrg                    swaps(&ptWire[p].y);
4576f7df2e56Smrg                }
4577f7df2e56Smrg            }
4578f7df2e56Smrg            wire = (char *) &ptWire[ol->num_points];
4579f7df2e56Smrg        }
458005b261ecSmrg    }
458105b261ecSmrg    return wire;
458205b261ecSmrg}
458305b261ecSmrg
458405b261ecSmrgstatic int
4585f7df2e56SmrgXkbSizeGeomDoodads(int num_doodads, XkbDoodadPtr doodad)
458605b261ecSmrg{
4587f7df2e56Smrg    register int i, size;
4588f7df2e56Smrg
4589f7df2e56Smrg    for (i = size = 0; i < num_doodads; i++, doodad++) {
4590f7df2e56Smrg        size += SIZEOF(xkbAnyDoodadWireDesc);
4591f7df2e56Smrg        if (doodad->any.type == XkbTextDoodad) {
4592f7df2e56Smrg            size += XkbSizeCountedString(doodad->text.text);
4593f7df2e56Smrg            size += XkbSizeCountedString(doodad->text.font);
4594f7df2e56Smrg        }
4595f7df2e56Smrg        else if (doodad->any.type == XkbLogoDoodad) {
4596f7df2e56Smrg            size += XkbSizeCountedString(doodad->logo.logo_name);
4597f7df2e56Smrg        }
459805b261ecSmrg    }
459905b261ecSmrg    return size;
460005b261ecSmrg}
460105b261ecSmrg
460205b261ecSmrgstatic char *
4603f7df2e56SmrgXkbWriteGeomDoodads(char *wire, int num_doodads, XkbDoodadPtr doodad, Bool swap)
460405b261ecSmrg{
4605f7df2e56Smrg    register int i;
4606f7df2e56Smrg    xkbDoodadWireDesc *doodadWire;
4607f7df2e56Smrg
4608f7df2e56Smrg    for (i = 0; i < num_doodads; i++, doodad++) {
4609f7df2e56Smrg        doodadWire = (xkbDoodadWireDesc *) wire;
4610f7df2e56Smrg        wire = (char *) &doodadWire[1];
4611f7df2e56Smrg        memset(doodadWire, 0, SIZEOF(xkbDoodadWireDesc));
4612f7df2e56Smrg        doodadWire->any.name = doodad->any.name;
4613f7df2e56Smrg        doodadWire->any.type = doodad->any.type;
4614f7df2e56Smrg        doodadWire->any.priority = doodad->any.priority;
4615f7df2e56Smrg        doodadWire->any.top = doodad->any.top;
4616f7df2e56Smrg        doodadWire->any.left = doodad->any.left;
4617f7df2e56Smrg        if (swap) {
4618f7df2e56Smrg            swapl(&doodadWire->any.name);
4619f7df2e56Smrg            swaps(&doodadWire->any.top);
4620f7df2e56Smrg            swaps(&doodadWire->any.left);
4621f7df2e56Smrg        }
4622f7df2e56Smrg        switch (doodad->any.type) {
4623f7df2e56Smrg        case XkbOutlineDoodad:
4624f7df2e56Smrg        case XkbSolidDoodad:
4625f7df2e56Smrg            doodadWire->shape.angle = doodad->shape.angle;
4626f7df2e56Smrg            doodadWire->shape.colorNdx = doodad->shape.color_ndx;
4627f7df2e56Smrg            doodadWire->shape.shapeNdx = doodad->shape.shape_ndx;
4628f7df2e56Smrg            if (swap) {
4629f7df2e56Smrg                swaps(&doodadWire->shape.angle);
4630f7df2e56Smrg            }
4631f7df2e56Smrg            break;
4632f7df2e56Smrg        case XkbTextDoodad:
4633f7df2e56Smrg            doodadWire->text.angle = doodad->text.angle;
4634f7df2e56Smrg            doodadWire->text.width = doodad->text.width;
4635f7df2e56Smrg            doodadWire->text.height = doodad->text.height;
4636f7df2e56Smrg            doodadWire->text.colorNdx = doodad->text.color_ndx;
4637f7df2e56Smrg            if (swap) {
4638f7df2e56Smrg                swaps(&doodadWire->text.angle);
4639f7df2e56Smrg                swaps(&doodadWire->text.width);
4640f7df2e56Smrg                swaps(&doodadWire->text.height);
4641f7df2e56Smrg            }
4642f7df2e56Smrg            wire = XkbWriteCountedString(wire, doodad->text.text, swap);
4643f7df2e56Smrg            wire = XkbWriteCountedString(wire, doodad->text.font, swap);
4644f7df2e56Smrg            break;
4645f7df2e56Smrg        case XkbIndicatorDoodad:
4646f7df2e56Smrg            doodadWire->indicator.shapeNdx = doodad->indicator.shape_ndx;
4647f7df2e56Smrg            doodadWire->indicator.onColorNdx = doodad->indicator.on_color_ndx;
4648f7df2e56Smrg            doodadWire->indicator.offColorNdx = doodad->indicator.off_color_ndx;
4649f7df2e56Smrg            break;
4650f7df2e56Smrg        case XkbLogoDoodad:
4651f7df2e56Smrg            doodadWire->logo.angle = doodad->logo.angle;
4652f7df2e56Smrg            doodadWire->logo.colorNdx = doodad->logo.color_ndx;
4653f7df2e56Smrg            doodadWire->logo.shapeNdx = doodad->logo.shape_ndx;
4654f7df2e56Smrg            wire = XkbWriteCountedString(wire, doodad->logo.logo_name, swap);
4655f7df2e56Smrg            break;
4656f7df2e56Smrg        default:
4657f7df2e56Smrg            ErrorF("[xkb] Unknown doodad type %d in XkbWriteGeomDoodads\n",
4658f7df2e56Smrg                   doodad->any.type);
4659f7df2e56Smrg            ErrorF("[xkb] Ignored\n");
4660f7df2e56Smrg            break;
4661f7df2e56Smrg        }
466205b261ecSmrg    }
466305b261ecSmrg    return wire;
466405b261ecSmrg}
466505b261ecSmrg
466605b261ecSmrgstatic char *
4667f7df2e56SmrgXkbWriteGeomOverlay(char *wire, XkbOverlayPtr ol, Bool swap)
466805b261ecSmrg{
4669f7df2e56Smrg    register int r;
4670f7df2e56Smrg    XkbOverlayRowPtr row;
4671f7df2e56Smrg    xkbOverlayWireDesc *olWire;
4672f7df2e56Smrg
4673f7df2e56Smrg    olWire = (xkbOverlayWireDesc *) wire;
4674f7df2e56Smrg    olWire->name = ol->name;
4675f7df2e56Smrg    olWire->nRows = ol->num_rows;
4676f7df2e56Smrg    olWire->pad1 = 0;
4677f7df2e56Smrg    olWire->pad2 = 0;
4678f7df2e56Smrg    if (swap) {
4679f7df2e56Smrg        swapl(&olWire->name);
4680f7df2e56Smrg    }
4681f7df2e56Smrg    wire = (char *) &olWire[1];
4682f7df2e56Smrg    for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) {
4683f7df2e56Smrg        unsigned int k;
4684f7df2e56Smrg        XkbOverlayKeyPtr key;
4685f7df2e56Smrg        xkbOverlayRowWireDesc *rowWire;
4686f7df2e56Smrg
4687f7df2e56Smrg        rowWire = (xkbOverlayRowWireDesc *) wire;
4688f7df2e56Smrg        rowWire->rowUnder = row->row_under;
4689f7df2e56Smrg        rowWire->nKeys = row->num_keys;
4690f7df2e56Smrg        rowWire->pad1 = 0;
4691f7df2e56Smrg        wire = (char *) &rowWire[1];
4692f7df2e56Smrg        for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
4693f7df2e56Smrg            xkbOverlayKeyWireDesc *keyWire;
4694f7df2e56Smrg
4695f7df2e56Smrg            keyWire = (xkbOverlayKeyWireDesc *) wire;
4696f7df2e56Smrg            memcpy(keyWire->over, key->over.name, XkbKeyNameLength);
4697f7df2e56Smrg            memcpy(keyWire->under, key->under.name, XkbKeyNameLength);
4698f7df2e56Smrg            wire = (char *) &keyWire[1];
4699f7df2e56Smrg        }
4700f7df2e56Smrg    }
4701f7df2e56Smrg    return wire;
470205b261ecSmrg}
470305b261ecSmrg
470405b261ecSmrgstatic int
470505b261ecSmrgXkbSizeGeomSections(XkbGeometryPtr geom)
470605b261ecSmrg{
4707f7df2e56Smrg    register int i, size;
4708f7df2e56Smrg    XkbSectionPtr section;
4709f7df2e56Smrg
4710f7df2e56Smrg    for (i = size = 0, section = geom->sections; i < geom->num_sections;
4711f7df2e56Smrg         i++, section++) {
4712f7df2e56Smrg        size += SIZEOF(xkbSectionWireDesc);
4713f7df2e56Smrg        if (section->rows) {
4714f7df2e56Smrg            int r;
4715f7df2e56Smrg            XkbRowPtr row;
4716f7df2e56Smrg
4717f7df2e56Smrg            for (r = 0, row = section->rows; r < section->num_rows; row++, r++) {
4718f7df2e56Smrg                size += SIZEOF(xkbRowWireDesc);
4719f7df2e56Smrg                size += row->num_keys * SIZEOF(xkbKeyWireDesc);
4720f7df2e56Smrg            }
4721f7df2e56Smrg        }
4722f7df2e56Smrg        if (section->doodads)
4723f7df2e56Smrg            size += XkbSizeGeomDoodads(section->num_doodads, section->doodads);
4724f7df2e56Smrg        if (section->overlays) {
4725f7df2e56Smrg            int o;
4726f7df2e56Smrg            XkbOverlayPtr ol;
4727f7df2e56Smrg
4728f7df2e56Smrg            for (o = 0, ol = section->overlays; o < section->num_overlays;
4729f7df2e56Smrg                 o++, ol++) {
4730f7df2e56Smrg                int r;
4731f7df2e56Smrg                XkbOverlayRowPtr row;
4732f7df2e56Smrg
4733f7df2e56Smrg                size += SIZEOF(xkbOverlayWireDesc);
4734f7df2e56Smrg                for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) {
4735f7df2e56Smrg                    size += SIZEOF(xkbOverlayRowWireDesc);
4736f7df2e56Smrg                    size += row->num_keys * SIZEOF(xkbOverlayKeyWireDesc);
4737f7df2e56Smrg                }
4738f7df2e56Smrg            }
4739f7df2e56Smrg        }
474005b261ecSmrg    }
474105b261ecSmrg    return size;
474205b261ecSmrg}
474305b261ecSmrg
474405b261ecSmrgstatic char *
4745f7df2e56SmrgXkbWriteGeomSections(char *wire, XkbGeometryPtr geom, Bool swap)
474605b261ecSmrg{
4747f7df2e56Smrg    register int i;
4748f7df2e56Smrg    XkbSectionPtr section;
4749f7df2e56Smrg    xkbSectionWireDesc *sectionWire;
4750f7df2e56Smrg
4751f7df2e56Smrg    for (i = 0, section = geom->sections; i < geom->num_sections;
4752f7df2e56Smrg         i++, section++) {
4753f7df2e56Smrg        sectionWire = (xkbSectionWireDesc *) wire;
4754f7df2e56Smrg        sectionWire->name = section->name;
4755f7df2e56Smrg        sectionWire->top = section->top;
4756f7df2e56Smrg        sectionWire->left = section->left;
4757f7df2e56Smrg        sectionWire->width = section->width;
4758f7df2e56Smrg        sectionWire->height = section->height;
4759f7df2e56Smrg        sectionWire->angle = section->angle;
4760f7df2e56Smrg        sectionWire->priority = section->priority;
4761f7df2e56Smrg        sectionWire->nRows = section->num_rows;
4762f7df2e56Smrg        sectionWire->nDoodads = section->num_doodads;
4763f7df2e56Smrg        sectionWire->nOverlays = section->num_overlays;
4764f7df2e56Smrg        sectionWire->pad = 0;
4765f7df2e56Smrg        if (swap) {
4766f7df2e56Smrg            swapl(&sectionWire->name);
4767f7df2e56Smrg            swaps(&sectionWire->top);
4768f7df2e56Smrg            swaps(&sectionWire->left);
4769f7df2e56Smrg            swaps(&sectionWire->width);
4770f7df2e56Smrg            swaps(&sectionWire->height);
4771f7df2e56Smrg            swaps(&sectionWire->angle);
4772f7df2e56Smrg        }
4773f7df2e56Smrg        wire = (char *) &sectionWire[1];
4774f7df2e56Smrg        if (section->rows) {
4775f7df2e56Smrg            int r;
4776f7df2e56Smrg            XkbRowPtr row;
4777f7df2e56Smrg            xkbRowWireDesc *rowWire;
4778f7df2e56Smrg
4779f7df2e56Smrg            for (r = 0, row = section->rows; r < section->num_rows; r++, row++) {
4780f7df2e56Smrg                rowWire = (xkbRowWireDesc *) wire;
4781f7df2e56Smrg                rowWire->top = row->top;
4782f7df2e56Smrg                rowWire->left = row->left;
4783f7df2e56Smrg                rowWire->nKeys = row->num_keys;
4784f7df2e56Smrg                rowWire->vertical = row->vertical;
4785f7df2e56Smrg                rowWire->pad = 0;
4786f7df2e56Smrg                if (swap) {
4787f7df2e56Smrg                    swaps(&rowWire->top);
4788f7df2e56Smrg                    swaps(&rowWire->left);
4789f7df2e56Smrg                }
4790f7df2e56Smrg                wire = (char *) &rowWire[1];
4791f7df2e56Smrg                if (row->keys) {
4792f7df2e56Smrg                    int k;
4793f7df2e56Smrg                    XkbKeyPtr key;
4794f7df2e56Smrg                    xkbKeyWireDesc *keyWire;
4795f7df2e56Smrg
4796f7df2e56Smrg                    keyWire = (xkbKeyWireDesc *) wire;
4797f7df2e56Smrg                    for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
4798f7df2e56Smrg                        memcpy(keyWire[k].name, key->name.name,
4799f7df2e56Smrg                               XkbKeyNameLength);
4800f7df2e56Smrg                        keyWire[k].gap = key->gap;
4801f7df2e56Smrg                        keyWire[k].shapeNdx = key->shape_ndx;
4802f7df2e56Smrg                        keyWire[k].colorNdx = key->color_ndx;
4803f7df2e56Smrg                        if (swap) {
4804f7df2e56Smrg                            swaps(&keyWire[k].gap);
4805f7df2e56Smrg                        }
4806f7df2e56Smrg                    }
4807f7df2e56Smrg                    wire = (char *) &keyWire[row->num_keys];
4808f7df2e56Smrg                }
4809f7df2e56Smrg            }
4810f7df2e56Smrg        }
4811f7df2e56Smrg        if (section->doodads) {
4812f7df2e56Smrg            wire = XkbWriteGeomDoodads(wire,
4813f7df2e56Smrg                                       section->num_doodads, section->doodads,
4814f7df2e56Smrg                                       swap);
4815f7df2e56Smrg        }
4816f7df2e56Smrg        if (section->overlays) {
4817f7df2e56Smrg            register int o;
4818f7df2e56Smrg
4819f7df2e56Smrg            for (o = 0; o < section->num_overlays; o++) {
4820f7df2e56Smrg                wire = XkbWriteGeomOverlay(wire, &section->overlays[o], swap);
4821f7df2e56Smrg            }
4822f7df2e56Smrg        }
482305b261ecSmrg    }
482405b261ecSmrg    return wire;
482505b261ecSmrg}
482605b261ecSmrg
482705b261ecSmrgstatic Status
4828f7df2e56SmrgXkbComputeGetGeometryReplySize(XkbGeometryPtr geom,
4829f7df2e56Smrg                               xkbGetGeometryReply * rep, Atom name)
483005b261ecSmrg{
4831f7df2e56Smrg    int len;
4832f7df2e56Smrg
4833f7df2e56Smrg    if (geom != NULL) {
4834f7df2e56Smrg        len = XkbSizeCountedString(geom->label_font);
4835f7df2e56Smrg        len += XkbSizeGeomProperties(geom);
4836f7df2e56Smrg        len += XkbSizeGeomColors(geom);
4837f7df2e56Smrg        len += XkbSizeGeomShapes(geom);
4838f7df2e56Smrg        len += XkbSizeGeomSections(geom);
4839f7df2e56Smrg        len += XkbSizeGeomDoodads(geom->num_doodads, geom->doodads);
4840f7df2e56Smrg        len += XkbSizeGeomKeyAliases(geom);
4841f7df2e56Smrg        rep->length = len / 4;
4842f7df2e56Smrg        rep->found = TRUE;
4843f7df2e56Smrg        rep->name = geom->name;
4844f7df2e56Smrg        rep->widthMM = geom->width_mm;
4845f7df2e56Smrg        rep->heightMM = geom->height_mm;
4846f7df2e56Smrg        rep->nProperties = geom->num_properties;
4847f7df2e56Smrg        rep->nColors = geom->num_colors;
4848f7df2e56Smrg        rep->nShapes = geom->num_shapes;
4849f7df2e56Smrg        rep->nSections = geom->num_sections;
4850f7df2e56Smrg        rep->nDoodads = geom->num_doodads;
4851f7df2e56Smrg        rep->nKeyAliases = geom->num_key_aliases;
4852f7df2e56Smrg        rep->baseColorNdx = XkbGeomColorIndex(geom, geom->base_color);
4853f7df2e56Smrg        rep->labelColorNdx = XkbGeomColorIndex(geom, geom->label_color);
485405b261ecSmrg    }
485505b261ecSmrg    else {
4856f7df2e56Smrg        rep->length = 0;
4857f7df2e56Smrg        rep->found = FALSE;
4858f7df2e56Smrg        rep->name = name;
4859f7df2e56Smrg        rep->widthMM = rep->heightMM = 0;
4860f7df2e56Smrg        rep->nProperties = rep->nColors = rep->nShapes = 0;
4861f7df2e56Smrg        rep->nSections = rep->nDoodads = 0;
4862f7df2e56Smrg        rep->nKeyAliases = 0;
4863f7df2e56Smrg        rep->labelColorNdx = rep->baseColorNdx = 0;
486405b261ecSmrg    }
486505b261ecSmrg    return Success;
486605b261ecSmrg}
486705b261ecSmrgstatic int
4868f7df2e56SmrgXkbSendGeometry(ClientPtr client,
4869f7df2e56Smrg                XkbGeometryPtr geom, xkbGetGeometryReply * rep, Bool freeGeom)
487005b261ecSmrg{
4871f7df2e56Smrg    char *desc, *start;
4872f7df2e56Smrg    int len;
4873f7df2e56Smrg
4874f7df2e56Smrg    if (geom != NULL) {
4875f7df2e56Smrg        start = desc = xallocarray(rep->length, 4);
4876f7df2e56Smrg        if (!start)
4877f7df2e56Smrg            return BadAlloc;
4878f7df2e56Smrg        len = rep->length * 4;
4879f7df2e56Smrg        desc = XkbWriteCountedString(desc, geom->label_font, client->swapped);
4880f7df2e56Smrg        if (rep->nProperties > 0)
4881f7df2e56Smrg            desc = XkbWriteGeomProperties(desc, geom, client->swapped);
4882f7df2e56Smrg        if (rep->nColors > 0)
4883f7df2e56Smrg            desc = XkbWriteGeomColors(desc, geom, client->swapped);
4884f7df2e56Smrg        if (rep->nShapes > 0)
4885f7df2e56Smrg            desc = XkbWriteGeomShapes(desc, geom, client->swapped);
4886f7df2e56Smrg        if (rep->nSections > 0)
4887f7df2e56Smrg            desc = XkbWriteGeomSections(desc, geom, client->swapped);
4888f7df2e56Smrg        if (rep->nDoodads > 0)
4889f7df2e56Smrg            desc = XkbWriteGeomDoodads(desc, geom->num_doodads, geom->doodads,
4890f7df2e56Smrg                                       client->swapped);
4891f7df2e56Smrg        if (rep->nKeyAliases > 0)
4892f7df2e56Smrg            desc = XkbWriteGeomKeyAliases(desc, geom, client->swapped);
4893f7df2e56Smrg        if ((desc - start) != (len)) {
4894f7df2e56Smrg            ErrorF
4895f7df2e56Smrg                ("[xkb] BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n",
4896f7df2e56Smrg                 len, (unsigned long) (desc - start));
4897f7df2e56Smrg        }
489805b261ecSmrg    }
489905b261ecSmrg    else {
4900f7df2e56Smrg        len = 0;
4901f7df2e56Smrg        start = NULL;
490205b261ecSmrg    }
490305b261ecSmrg    if (client->swapped) {
4904f7df2e56Smrg        swaps(&rep->sequenceNumber);
4905f7df2e56Smrg        swapl(&rep->length);
4906f7df2e56Smrg        swapl(&rep->name);
4907f7df2e56Smrg        swaps(&rep->widthMM);
4908f7df2e56Smrg        swaps(&rep->heightMM);
4909f7df2e56Smrg        swaps(&rep->nProperties);
4910f7df2e56Smrg        swaps(&rep->nColors);
4911f7df2e56Smrg        swaps(&rep->nShapes);
4912f7df2e56Smrg        swaps(&rep->nSections);
4913f7df2e56Smrg        swaps(&rep->nDoodads);
4914f7df2e56Smrg        swaps(&rep->nKeyAliases);
4915f7df2e56Smrg    }
4916f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetGeometryReply), rep);
4917f7df2e56Smrg    if (len > 0)
4918f7df2e56Smrg        WriteToClient(client, len, start);
4919f7df2e56Smrg    if (start != NULL)
4920f7df2e56Smrg        free((char *) start);
492105b261ecSmrg    if (freeGeom)
4922f7df2e56Smrg        XkbFreeGeometry(geom, XkbGeomAllMask, TRUE);
49236747b715Smrg    return Success;
492405b261ecSmrg}
492505b261ecSmrg
492605b261ecSmrgint
492705b261ecSmrgProcXkbGetGeometry(ClientPtr client)
492805b261ecSmrg{
4929f7df2e56Smrg    DeviceIntPtr dev;
493005b261ecSmrg    xkbGetGeometryReply rep;
4931f7df2e56Smrg    XkbGeometryPtr geom;
4932f7df2e56Smrg    Bool shouldFree;
4933f7df2e56Smrg    Status status;
493405b261ecSmrg
493505b261ecSmrg    REQUEST(xkbGetGeometryReq);
493605b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetGeometryReq);
493705b261ecSmrg
4938f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
4939f7df2e56Smrg        return BadAccess;
494005b261ecSmrg
49414642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
494205b261ecSmrg    CHK_ATOM_OR_NONE(stuff->name);
494305b261ecSmrg
4944f7df2e56Smrg    geom = XkbLookupNamedGeometry(dev, stuff->name, &shouldFree);
4945f7df2e56Smrg    rep = (xkbGetGeometryReply) {
4946f7df2e56Smrg        .type = X_Reply,
4947f7df2e56Smrg        .deviceID = dev->id,
4948f7df2e56Smrg        .sequenceNumber = client->sequence,
4949f7df2e56Smrg        .length = 0
4950f7df2e56Smrg    };
4951f7df2e56Smrg    status = XkbComputeGetGeometryReplySize(geom, &rep, stuff->name);
4952f7df2e56Smrg    if (status != Success)
4953f7df2e56Smrg        return status;
4954f7df2e56Smrg    else
4955f7df2e56Smrg        return XkbSendGeometry(client, geom, &rep, shouldFree);
495605b261ecSmrg}
495705b261ecSmrg
495805b261ecSmrg/***====================================================================***/
495905b261ecSmrg
49601e26616aSmrgstatic Status
49611e26616aSmrg_GetCountedString(char **wire_inout, ClientPtr client, char **str)
496205b261ecSmrg{
49631e26616aSmrg    char *wire, *next;
49641e26616aSmrg    CARD16 len;
496505b261ecSmrg
49661e26616aSmrg    wire = *wire_inout;
49671e26616aSmrg    len = *(CARD16 *) wire;
49681e26616aSmrg    if (client->swapped) {
4969f7df2e56Smrg        swaps(&len);
497005b261ecSmrg    }
49711e26616aSmrg    next = wire + XkbPaddedSize(len + 2);
49721e26616aSmrg    /* Check we're still within the size of the request */
49731e26616aSmrg    if (client->req_len <
49741e26616aSmrg        bytes_to_int32(next - (char *) client->requestBuffer))
49751e26616aSmrg        return BadValue;
49761e26616aSmrg    *str = malloc(len + 1);
49771e26616aSmrg    if (!*str)
49781e26616aSmrg        return BadAlloc;
49791e26616aSmrg    memcpy(*str, &wire[2], len);
49801e26616aSmrg    *(*str + len) = '\0';
49811e26616aSmrg    *wire_inout = next;
49821e26616aSmrg    return Success;
498305b261ecSmrg}
498405b261ecSmrg
498505b261ecSmrgstatic Status
4986f7df2e56Smrg_CheckSetDoodad(char **wire_inout,
4987f7df2e56Smrg                XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client)
498805b261ecSmrg{
4989f7df2e56Smrg    char *wire;
4990f7df2e56Smrg    xkbDoodadWireDesc *dWire;
4991f7df2e56Smrg    xkbAnyDoodadWireDesc any;
4992f7df2e56Smrg    xkbTextDoodadWireDesc text;
4993f7df2e56Smrg    XkbDoodadPtr doodad;
49941e26616aSmrg    Status status;
499505b261ecSmrg
4996f7df2e56Smrg    dWire = (xkbDoodadWireDesc *) (*wire_inout);
4997f7df2e56Smrg    any = dWire->any;
4998f7df2e56Smrg    wire = (char *) &dWire[1];
499905b261ecSmrg    if (client->swapped) {
5000f7df2e56Smrg        swapl(&any.name);
5001f7df2e56Smrg        swaps(&any.top);
5002f7df2e56Smrg        swaps(&any.left);
5003f7df2e56Smrg        swaps(&any.angle);
500405b261ecSmrg    }
500505b261ecSmrg    CHK_ATOM_ONLY(dWire->any.name);
5006f7df2e56Smrg    doodad = XkbAddGeomDoodad(geom, section, any.name);
500705b261ecSmrg    if (!doodad)
5008f7df2e56Smrg        return BadAlloc;
5009f7df2e56Smrg    doodad->any.type = dWire->any.type;
5010f7df2e56Smrg    doodad->any.priority = dWire->any.priority;
5011f7df2e56Smrg    doodad->any.top = any.top;
5012f7df2e56Smrg    doodad->any.left = any.left;
5013f7df2e56Smrg    doodad->any.angle = any.angle;
501405b261ecSmrg    switch (doodad->any.type) {
5015f7df2e56Smrg    case XkbOutlineDoodad:
5016f7df2e56Smrg    case XkbSolidDoodad:
5017f7df2e56Smrg        if (dWire->shape.colorNdx >= geom->num_colors) {
5018f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x40, geom->num_colors,
5019f7df2e56Smrg                                              dWire->shape.colorNdx);
5020f7df2e56Smrg            return BadMatch;
5021f7df2e56Smrg        }
5022f7df2e56Smrg        if (dWire->shape.shapeNdx >= geom->num_shapes) {
5023f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x41, geom->num_shapes,
5024f7df2e56Smrg                                              dWire->shape.shapeNdx);
5025f7df2e56Smrg            return BadMatch;
5026f7df2e56Smrg        }
5027f7df2e56Smrg        doodad->shape.color_ndx = dWire->shape.colorNdx;
5028f7df2e56Smrg        doodad->shape.shape_ndx = dWire->shape.shapeNdx;
5029f7df2e56Smrg        break;
5030f7df2e56Smrg    case XkbTextDoodad:
5031f7df2e56Smrg        if (dWire->text.colorNdx >= geom->num_colors) {
5032f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x42, geom->num_colors,
5033f7df2e56Smrg                                              dWire->text.colorNdx);
5034f7df2e56Smrg            return BadMatch;
5035f7df2e56Smrg        }
5036f7df2e56Smrg        text = dWire->text;
5037f7df2e56Smrg        if (client->swapped) {
5038f7df2e56Smrg            swaps(&text.width);
5039f7df2e56Smrg            swaps(&text.height);
5040f7df2e56Smrg        }
5041f7df2e56Smrg        doodad->text.width = text.width;
5042f7df2e56Smrg        doodad->text.height = text.height;
5043f7df2e56Smrg        doodad->text.color_ndx = dWire->text.colorNdx;
5044f7df2e56Smrg        status = _GetCountedString(&wire, client, &doodad->text.text);
5045f7df2e56Smrg        if (status != Success)
5046f7df2e56Smrg            return status;
5047f7df2e56Smrg        status = _GetCountedString(&wire, client, &doodad->text.font);
5048f7df2e56Smrg        if (status != Success) {
5049f7df2e56Smrg            free (doodad->text.text);
5050f7df2e56Smrg            return status;
5051f7df2e56Smrg        }
5052f7df2e56Smrg        break;
5053f7df2e56Smrg    case XkbIndicatorDoodad:
5054f7df2e56Smrg        if (dWire->indicator.onColorNdx >= geom->num_colors) {
5055f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x43, geom->num_colors,
5056f7df2e56Smrg                                              dWire->indicator.onColorNdx);
5057f7df2e56Smrg            return BadMatch;
5058f7df2e56Smrg        }
5059f7df2e56Smrg        if (dWire->indicator.offColorNdx >= geom->num_colors) {
5060f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x44, geom->num_colors,
5061f7df2e56Smrg                                              dWire->indicator.offColorNdx);
5062f7df2e56Smrg            return BadMatch;
5063f7df2e56Smrg        }
5064f7df2e56Smrg        if (dWire->indicator.shapeNdx >= geom->num_shapes) {
5065f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x45, geom->num_shapes,
5066f7df2e56Smrg                                              dWire->indicator.shapeNdx);
5067f7df2e56Smrg            return BadMatch;
5068f7df2e56Smrg        }
5069f7df2e56Smrg        doodad->indicator.shape_ndx = dWire->indicator.shapeNdx;
5070f7df2e56Smrg        doodad->indicator.on_color_ndx = dWire->indicator.onColorNdx;
5071f7df2e56Smrg        doodad->indicator.off_color_ndx = dWire->indicator.offColorNdx;
5072f7df2e56Smrg        break;
5073f7df2e56Smrg    case XkbLogoDoodad:
5074f7df2e56Smrg        if (dWire->logo.colorNdx >= geom->num_colors) {
5075f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x46, geom->num_colors,
5076f7df2e56Smrg                                              dWire->logo.colorNdx);
5077f7df2e56Smrg            return BadMatch;
5078f7df2e56Smrg        }
5079f7df2e56Smrg        if (dWire->logo.shapeNdx >= geom->num_shapes) {
5080f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x47, geom->num_shapes,
5081f7df2e56Smrg                                              dWire->logo.shapeNdx);
5082f7df2e56Smrg            return BadMatch;
5083f7df2e56Smrg        }
5084f7df2e56Smrg        doodad->logo.color_ndx = dWire->logo.colorNdx;
5085f7df2e56Smrg        doodad->logo.shape_ndx = dWire->logo.shapeNdx;
5086f7df2e56Smrg        status = _GetCountedString(&wire, client, &doodad->logo.logo_name);
5087f7df2e56Smrg        if (status != Success)
5088f7df2e56Smrg            return status;
5089f7df2e56Smrg        break;
5090f7df2e56Smrg    default:
5091f7df2e56Smrg        client->errorValue = _XkbErrCode2(0x4F, dWire->any.type);
5092f7df2e56Smrg        return BadValue;
5093f7df2e56Smrg    }
5094f7df2e56Smrg    *wire_inout = wire;
5095f7df2e56Smrg    return Success;
5096f7df2e56Smrg}
5097f7df2e56Smrg
5098f7df2e56Smrgstatic Status
5099f7df2e56Smrg_CheckSetOverlay(char **wire_inout,
5100f7df2e56Smrg                 XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client)
510105b261ecSmrg{
5102f7df2e56Smrg    register int r;
5103f7df2e56Smrg    char *wire;
5104f7df2e56Smrg    XkbOverlayPtr ol;
5105f7df2e56Smrg    xkbOverlayWireDesc *olWire;
5106f7df2e56Smrg    xkbOverlayRowWireDesc *rWire;
510705b261ecSmrg
5108f7df2e56Smrg    wire = *wire_inout;
5109f7df2e56Smrg    olWire = (xkbOverlayWireDesc *) wire;
5110f7df2e56Smrg    if (client->swapped) {
5111f7df2e56Smrg        swapl(&olWire->name);
5112f7df2e56Smrg    }
5113f7df2e56Smrg    CHK_ATOM_ONLY(olWire->name);
5114f7df2e56Smrg    ol = XkbAddGeomOverlay(section, olWire->name, olWire->nRows);
5115f7df2e56Smrg    rWire = (xkbOverlayRowWireDesc *) &olWire[1];
5116f7df2e56Smrg    for (r = 0; r < olWire->nRows; r++) {
5117f7df2e56Smrg        register int k;
5118f7df2e56Smrg        xkbOverlayKeyWireDesc *kWire;
5119f7df2e56Smrg        XkbOverlayRowPtr row;
5120f7df2e56Smrg
5121f7df2e56Smrg        if (rWire->rowUnder > section->num_rows) {
5122f7df2e56Smrg            client->errorValue = _XkbErrCode4(0x20, r, section->num_rows,
5123f7df2e56Smrg                                              rWire->rowUnder);
5124f7df2e56Smrg            return BadMatch;
5125f7df2e56Smrg        }
5126f7df2e56Smrg        row = XkbAddGeomOverlayRow(ol, rWire->rowUnder, rWire->nKeys);
5127f7df2e56Smrg        kWire = (xkbOverlayKeyWireDesc *) &rWire[1];
5128f7df2e56Smrg        for (k = 0; k < rWire->nKeys; k++, kWire++) {
5129f7df2e56Smrg            if (XkbAddGeomOverlayKey(ol, row,
5130f7df2e56Smrg                                     (char *) kWire->over,
5131f7df2e56Smrg                                     (char *) kWire->under) == NULL) {
5132f7df2e56Smrg                client->errorValue = _XkbErrCode3(0x21, r, k);
5133f7df2e56Smrg                return BadMatch;
5134f7df2e56Smrg            }
5135f7df2e56Smrg        }
5136f7df2e56Smrg        rWire = (xkbOverlayRowWireDesc *) kWire;
5137f7df2e56Smrg    }
5138f7df2e56Smrg    olWire = (xkbOverlayWireDesc *) rWire;
5139f7df2e56Smrg    wire = (char *) olWire;
5140f7df2e56Smrg    *wire_inout = wire;
5141f7df2e56Smrg    return Success;
5142f7df2e56Smrg}
5143f7df2e56Smrg
5144f7df2e56Smrgstatic Status
5145f7df2e56Smrg_CheckSetSections(XkbGeometryPtr geom,
5146f7df2e56Smrg                  xkbSetGeometryReq * req, char **wire_inout, ClientPtr client)
5147f7df2e56Smrg{
5148f7df2e56Smrg    Status status;
5149f7df2e56Smrg    register int s;
5150f7df2e56Smrg    char *wire;
5151f7df2e56Smrg    xkbSectionWireDesc *sWire;
5152f7df2e56Smrg    XkbSectionPtr section;
5153f7df2e56Smrg
5154f7df2e56Smrg    wire = *wire_inout;
5155f7df2e56Smrg    if (req->nSections < 1)
5156f7df2e56Smrg        return Success;
5157f7df2e56Smrg    sWire = (xkbSectionWireDesc *) wire;
5158f7df2e56Smrg    for (s = 0; s < req->nSections; s++) {
5159f7df2e56Smrg        register int r;
5160f7df2e56Smrg        xkbRowWireDesc *rWire;
5161f7df2e56Smrg
5162f7df2e56Smrg        if (client->swapped) {
5163f7df2e56Smrg            swapl(&sWire->name);
5164f7df2e56Smrg            swaps(&sWire->top);
5165f7df2e56Smrg            swaps(&sWire->left);
5166f7df2e56Smrg            swaps(&sWire->width);
5167f7df2e56Smrg            swaps(&sWire->height);
5168f7df2e56Smrg            swaps(&sWire->angle);
5169f7df2e56Smrg        }
5170f7df2e56Smrg        CHK_ATOM_ONLY(sWire->name);
5171f7df2e56Smrg        section = XkbAddGeomSection(geom, sWire->name, sWire->nRows,
5172f7df2e56Smrg                                    sWire->nDoodads, sWire->nOverlays);
5173f7df2e56Smrg        if (!section)
5174f7df2e56Smrg            return BadAlloc;
5175f7df2e56Smrg        section->priority = sWire->priority;
5176f7df2e56Smrg        section->top = sWire->top;
5177f7df2e56Smrg        section->left = sWire->left;
5178f7df2e56Smrg        section->width = sWire->width;
5179f7df2e56Smrg        section->height = sWire->height;
5180f7df2e56Smrg        section->angle = sWire->angle;
5181f7df2e56Smrg        rWire = (xkbRowWireDesc *) &sWire[1];
5182f7df2e56Smrg        for (r = 0; r < sWire->nRows; r++) {
5183f7df2e56Smrg            register int k;
5184f7df2e56Smrg            XkbRowPtr row;
5185f7df2e56Smrg            xkbKeyWireDesc *kWire;
5186f7df2e56Smrg
5187f7df2e56Smrg            if (client->swapped) {
5188f7df2e56Smrg                swaps(&rWire->top);
5189f7df2e56Smrg                swaps(&rWire->left);
5190f7df2e56Smrg            }
5191f7df2e56Smrg            row = XkbAddGeomRow(section, rWire->nKeys);
5192f7df2e56Smrg            if (!row)
5193f7df2e56Smrg                return BadAlloc;
5194f7df2e56Smrg            row->top = rWire->top;
5195f7df2e56Smrg            row->left = rWire->left;
5196f7df2e56Smrg            row->vertical = rWire->vertical;
5197f7df2e56Smrg            kWire = (xkbKeyWireDesc *) &rWire[1];
5198f7df2e56Smrg            for (k = 0; k < rWire->nKeys; k++) {
5199f7df2e56Smrg                XkbKeyPtr key;
5200f7df2e56Smrg
5201f7df2e56Smrg                key = XkbAddGeomKey(row);
5202f7df2e56Smrg                if (!key)
5203f7df2e56Smrg                    return BadAlloc;
5204f7df2e56Smrg                memcpy(key->name.name, kWire[k].name, XkbKeyNameLength);
5205f7df2e56Smrg                key->gap = kWire[k].gap;
5206f7df2e56Smrg                key->shape_ndx = kWire[k].shapeNdx;
5207f7df2e56Smrg                key->color_ndx = kWire[k].colorNdx;
5208f7df2e56Smrg                if (key->shape_ndx >= geom->num_shapes) {
5209f7df2e56Smrg                    client->errorValue = _XkbErrCode3(0x10, key->shape_ndx,
5210f7df2e56Smrg                                                      geom->num_shapes);
5211f7df2e56Smrg                    return BadMatch;
5212f7df2e56Smrg                }
5213f7df2e56Smrg                if (key->color_ndx >= geom->num_colors) {
5214f7df2e56Smrg                    client->errorValue = _XkbErrCode3(0x11, key->color_ndx,
5215f7df2e56Smrg                                                      geom->num_colors);
5216f7df2e56Smrg                    return BadMatch;
5217f7df2e56Smrg                }
5218f7df2e56Smrg            }
5219f7df2e56Smrg            rWire = (xkbRowWireDesc *) &kWire[rWire->nKeys];
5220f7df2e56Smrg        }
5221f7df2e56Smrg        wire = (char *) rWire;
5222f7df2e56Smrg        if (sWire->nDoodads > 0) {
5223f7df2e56Smrg            register int d;
5224f7df2e56Smrg
5225f7df2e56Smrg            for (d = 0; d < sWire->nDoodads; d++) {
5226f7df2e56Smrg                status = _CheckSetDoodad(&wire, geom, section, client);
5227f7df2e56Smrg                if (status != Success)
5228f7df2e56Smrg                    return status;
5229f7df2e56Smrg            }
5230f7df2e56Smrg        }
5231f7df2e56Smrg        if (sWire->nOverlays > 0) {
5232f7df2e56Smrg            register int o;
5233f7df2e56Smrg
5234f7df2e56Smrg            for (o = 0; o < sWire->nOverlays; o++) {
5235f7df2e56Smrg                status = _CheckSetOverlay(&wire, geom, section, client);
5236f7df2e56Smrg                if (status != Success)
5237f7df2e56Smrg                    return status;
5238f7df2e56Smrg            }
5239f7df2e56Smrg        }
5240f7df2e56Smrg        sWire = (xkbSectionWireDesc *) wire;
5241f7df2e56Smrg    }
5242f7df2e56Smrg    wire = (char *) sWire;
5243f7df2e56Smrg    *wire_inout = wire;
5244f7df2e56Smrg    return Success;
5245f7df2e56Smrg}
5246f7df2e56Smrg
5247f7df2e56Smrgstatic Status
5248f7df2e56Smrg_CheckSetShapes(XkbGeometryPtr geom,
5249f7df2e56Smrg                xkbSetGeometryReq * req, char **wire_inout, ClientPtr client)
5250f7df2e56Smrg{
5251f7df2e56Smrg    register int i;
5252f7df2e56Smrg    char *wire;
5253f7df2e56Smrg
5254f7df2e56Smrg    wire = *wire_inout;
5255f7df2e56Smrg    if (req->nShapes < 1) {
5256f7df2e56Smrg        client->errorValue = _XkbErrCode2(0x06, req->nShapes);
5257f7df2e56Smrg        return BadValue;
525805b261ecSmrg    }
525905b261ecSmrg    else {
5260f7df2e56Smrg        xkbShapeWireDesc *shapeWire;
5261f7df2e56Smrg        XkbShapePtr shape;
5262f7df2e56Smrg        register int o;
5263f7df2e56Smrg
5264f7df2e56Smrg        shapeWire = (xkbShapeWireDesc *) wire;
5265f7df2e56Smrg        for (i = 0; i < req->nShapes; i++) {
5266f7df2e56Smrg            xkbOutlineWireDesc *olWire;
5267f7df2e56Smrg            XkbOutlinePtr ol;
5268f7df2e56Smrg
5269f7df2e56Smrg            shape =
5270f7df2e56Smrg                XkbAddGeomShape(geom, shapeWire->name, shapeWire->nOutlines);
5271f7df2e56Smrg            if (!shape)
5272f7df2e56Smrg                return BadAlloc;
5273f7df2e56Smrg            olWire = (xkbOutlineWireDesc *) (&shapeWire[1]);
5274f7df2e56Smrg            for (o = 0; o < shapeWire->nOutlines; o++) {
5275f7df2e56Smrg                register int p;
5276f7df2e56Smrg                XkbPointPtr pt;
5277f7df2e56Smrg                xkbPointWireDesc *ptWire;
5278f7df2e56Smrg
5279f7df2e56Smrg                ol = XkbAddGeomOutline(shape, olWire->nPoints);
5280f7df2e56Smrg                if (!ol)
5281f7df2e56Smrg                    return BadAlloc;
5282f7df2e56Smrg                ol->corner_radius = olWire->cornerRadius;
5283f7df2e56Smrg                ptWire = (xkbPointWireDesc *) &olWire[1];
5284f7df2e56Smrg                for (p = 0, pt = ol->points; p < olWire->nPoints; p++, pt++) {
5285f7df2e56Smrg                    pt->x = ptWire[p].x;
5286f7df2e56Smrg                    pt->y = ptWire[p].y;
5287f7df2e56Smrg                    if (client->swapped) {
5288f7df2e56Smrg                        swaps(&pt->x);
5289f7df2e56Smrg                        swaps(&pt->y);
5290f7df2e56Smrg                    }
5291f7df2e56Smrg                }
5292f7df2e56Smrg                ol->num_points = olWire->nPoints;
5293f7df2e56Smrg                olWire = (xkbOutlineWireDesc *) (&ptWire[olWire->nPoints]);
5294f7df2e56Smrg            }
5295f7df2e56Smrg            if (shapeWire->primaryNdx != XkbNoShape)
5296f7df2e56Smrg                shape->primary = &shape->outlines[shapeWire->primaryNdx];
5297f7df2e56Smrg            if (shapeWire->approxNdx != XkbNoShape)
5298f7df2e56Smrg                shape->approx = &shape->outlines[shapeWire->approxNdx];
5299f7df2e56Smrg            shapeWire = (xkbShapeWireDesc *) olWire;
5300f7df2e56Smrg        }
5301f7df2e56Smrg        wire = (char *) shapeWire;
5302f7df2e56Smrg    }
5303f7df2e56Smrg    if (geom->num_shapes != req->nShapes) {
5304f7df2e56Smrg        client->errorValue = _XkbErrCode3(0x07, geom->num_shapes, req->nShapes);
5305f7df2e56Smrg        return BadMatch;
5306f7df2e56Smrg    }
5307f7df2e56Smrg
5308f7df2e56Smrg    *wire_inout = wire;
530905b261ecSmrg    return Success;
531005b261ecSmrg}
531105b261ecSmrg
531205b261ecSmrgstatic Status
5313f7df2e56Smrg_CheckSetGeom(XkbGeometryPtr geom, xkbSetGeometryReq * req, ClientPtr client)
531405b261ecSmrg{
5315f7df2e56Smrg    register int i;
5316f7df2e56Smrg    Status status;
5317f7df2e56Smrg    char *wire;
531805b261ecSmrg
5319f7df2e56Smrg    wire = (char *) &req[1];
53201e26616aSmrg    status = _GetCountedString(&wire, client, &geom->label_font);
53211e26616aSmrg    if (status != Success)
53221e26616aSmrg        return status;
53231e26616aSmrg
53241e26616aSmrg    for (i = 0; i < req->nProperties; i++) {
5325f7df2e56Smrg        char *name, *val;
53261e26616aSmrg
53271e26616aSmrg        status = _GetCountedString(&wire, client, &name);
53281e26616aSmrg        if (status != Success)
53291e26616aSmrg            return status;
53301e26616aSmrg        status = _GetCountedString(&wire, client, &val);
53311e26616aSmrg        if (status != Success) {
53326747b715Smrg            free(name);
53331e26616aSmrg            return status;
533405b261ecSmrg        }
5335f7df2e56Smrg        if (XkbAddGeomProperty(geom, name, val) == NULL) {
53366747b715Smrg            free(name);
53376747b715Smrg            free(val);
5338f7df2e56Smrg            return BadAlloc;
533905b261ecSmrg        }
53406747b715Smrg        free(name);
53416747b715Smrg        free(val);
534205b261ecSmrg    }
534305b261ecSmrg
5344f7df2e56Smrg    if (req->nColors < 2) {
5345f7df2e56Smrg        client->errorValue = _XkbErrCode3(0x01, 2, req->nColors);
5346f7df2e56Smrg        return BadValue;
534705b261ecSmrg    }
5348f7df2e56Smrg    if (req->baseColorNdx > req->nColors) {
5349f7df2e56Smrg        client->errorValue =
5350f7df2e56Smrg            _XkbErrCode3(0x03, req->nColors, req->baseColorNdx);
5351f7df2e56Smrg        return BadMatch;
535205b261ecSmrg    }
5353f7df2e56Smrg    if (req->labelColorNdx > req->nColors) {
5354f7df2e56Smrg        client->errorValue =
5355f7df2e56Smrg            _XkbErrCode3(0x03, req->nColors, req->labelColorNdx);
5356f7df2e56Smrg        return BadMatch;
535705b261ecSmrg    }
5358f7df2e56Smrg    if (req->labelColorNdx == req->baseColorNdx) {
5359f7df2e56Smrg        client->errorValue = _XkbErrCode3(0x04, req->baseColorNdx,
5360f7df2e56Smrg                                          req->labelColorNdx);
5361f7df2e56Smrg        return BadMatch;
536205b261ecSmrg    }
536305b261ecSmrg
53641e26616aSmrg    for (i = 0; i < req->nColors; i++) {
5365f7df2e56Smrg        char *name;
5366f7df2e56Smrg
53671e26616aSmrg        status = _GetCountedString(&wire, client, &name);
53681e26616aSmrg        if (status != Success)
53691e26616aSmrg            return status;
5370f7df2e56Smrg        if (!XkbAddGeomColor(geom, name, geom->num_colors)) {
53716747b715Smrg            free(name);
5372f7df2e56Smrg            return BadAlloc;
537305b261ecSmrg        }
53746747b715Smrg        free(name);
537505b261ecSmrg    }
5376f7df2e56Smrg    if (req->nColors != geom->num_colors) {
5377f7df2e56Smrg        client->errorValue = _XkbErrCode3(0x05, req->nColors, geom->num_colors);
5378f7df2e56Smrg        return BadMatch;
537905b261ecSmrg    }
5380f7df2e56Smrg    geom->label_color = &geom->colors[req->labelColorNdx];
5381f7df2e56Smrg    geom->base_color = &geom->colors[req->baseColorNdx];
538205b261ecSmrg
5383f7df2e56Smrg    if ((status = _CheckSetShapes(geom, req, &wire, client)) != Success)
5384f7df2e56Smrg        return status;
538505b261ecSmrg
5386f7df2e56Smrg    if ((status = _CheckSetSections(geom, req, &wire, client)) != Success)
5387f7df2e56Smrg        return status;
538805b261ecSmrg
5389f7df2e56Smrg    for (i = 0; i < req->nDoodads; i++) {
5390f7df2e56Smrg        status = _CheckSetDoodad(&wire, geom, NULL, client);
5391f7df2e56Smrg        if (status != Success)
5392f7df2e56Smrg            return status;
539305b261ecSmrg    }
539405b261ecSmrg
5395f7df2e56Smrg    for (i = 0; i < req->nKeyAliases; i++) {
5396f7df2e56Smrg        if (XkbAddGeomKeyAlias(geom, &wire[XkbKeyNameLength], wire) == NULL)
5397f7df2e56Smrg            return BadAlloc;
5398f7df2e56Smrg        wire += 2 * XkbKeyNameLength;
539905b261ecSmrg    }
540005b261ecSmrg    return Success;
540105b261ecSmrg}
540205b261ecSmrg
54034642e01fSmrgstatic int
5404f7df2e56Smrg_XkbSetGeometry(ClientPtr client, DeviceIntPtr dev, xkbSetGeometryReq * stuff)
540505b261ecSmrg{
5406f7df2e56Smrg    XkbDescPtr xkb;
5407f7df2e56Smrg    Bool new_name;
5408f7df2e56Smrg    xkbNewKeyboardNotify nkn;
5409f7df2e56Smrg    XkbGeometryPtr geom, old;
5410f7df2e56Smrg    XkbGeometrySizesRec sizes;
5411f7df2e56Smrg    Status status;
5412f7df2e56Smrg
5413f7df2e56Smrg    xkb = dev->key->xkbInfo->desc;
5414f7df2e56Smrg    old = xkb->geom;
5415f7df2e56Smrg    xkb->geom = NULL;
5416f7df2e56Smrg
5417f7df2e56Smrg    sizes.which = XkbGeomAllMask;
5418f7df2e56Smrg    sizes.num_properties = stuff->nProperties;
5419f7df2e56Smrg    sizes.num_colors = stuff->nColors;
5420f7df2e56Smrg    sizes.num_shapes = stuff->nShapes;
5421f7df2e56Smrg    sizes.num_sections = stuff->nSections;
5422f7df2e56Smrg    sizes.num_doodads = stuff->nDoodads;
5423f7df2e56Smrg    sizes.num_key_aliases = stuff->nKeyAliases;
5424f7df2e56Smrg    if ((status = XkbAllocGeometry(xkb, &sizes)) != Success) {
5425f7df2e56Smrg        xkb->geom = old;
54264642e01fSmrg        return status;
542705b261ecSmrg    }
5428f7df2e56Smrg    geom = xkb->geom;
5429f7df2e56Smrg    geom->name = stuff->name;
5430f7df2e56Smrg    geom->width_mm = stuff->widthMM;
5431f7df2e56Smrg    geom->height_mm = stuff->heightMM;
5432f7df2e56Smrg    if ((status = _CheckSetGeom(geom, stuff, client)) != Success) {
5433f7df2e56Smrg        XkbFreeGeometry(geom, XkbGeomAllMask, TRUE);
5434f7df2e56Smrg        xkb->geom = old;
54354642e01fSmrg        return status;
543605b261ecSmrg    }
5437f7df2e56Smrg    new_name = (xkb->names->geometry != geom->name);
5438f7df2e56Smrg    xkb->names->geometry = geom->name;
543905b261ecSmrg    if (old)
5440f7df2e56Smrg        XkbFreeGeometry(old, XkbGeomAllMask, TRUE);
544105b261ecSmrg    if (new_name) {
5442f7df2e56Smrg        xkbNamesNotify nn;
5443f7df2e56Smrg
54446747b715Smrg        memset(&nn, 0, sizeof(xkbNamesNotify));
5445f7df2e56Smrg        nn.changed = XkbGeometryNameMask;
5446f7df2e56Smrg        XkbSendNamesNotify(dev, &nn);
5447f7df2e56Smrg    }
5448f7df2e56Smrg    nkn.deviceID = nkn.oldDeviceID = dev->id;
5449f7df2e56Smrg    nkn.minKeyCode = nkn.oldMinKeyCode = xkb->min_key_code;
5450f7df2e56Smrg    nkn.maxKeyCode = nkn.oldMaxKeyCode = xkb->max_key_code;
5451f7df2e56Smrg    nkn.requestMajor = XkbReqCode;
5452f7df2e56Smrg    nkn.requestMinor = X_kbSetGeometry;
5453f7df2e56Smrg    nkn.changed = XkbNKN_GeometryMask;
5454f7df2e56Smrg    XkbSendNewKeyboardNotify(dev, &nkn);
545505b261ecSmrg    return Success;
545605b261ecSmrg}
545705b261ecSmrg
54584642e01fSmrgint
54594642e01fSmrgProcXkbSetGeometry(ClientPtr client)
54604642e01fSmrg{
5461f7df2e56Smrg    DeviceIntPtr dev;
5462f7df2e56Smrg    int rc;
54634642e01fSmrg
54644642e01fSmrg    REQUEST(xkbSetGeometryReq);
54654642e01fSmrg    REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq);
54664642e01fSmrg
5467f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
5468f7df2e56Smrg        return BadAccess;
54694642e01fSmrg
54704642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
54714642e01fSmrg    CHK_ATOM_OR_NONE(stuff->name);
54724642e01fSmrg
54734642e01fSmrg    rc = _XkbSetGeometry(client, dev, stuff);
54744642e01fSmrg    if (rc != Success)
54754642e01fSmrg        return rc;
54764642e01fSmrg
5477f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
54784642e01fSmrg        DeviceIntPtr other;
5479f7df2e56Smrg
5480f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
5481f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
5482f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
5483f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
5484f7df2e56Smrg                              DixManageAccess);
54854642e01fSmrg                if (rc == Success)
54864642e01fSmrg                    _XkbSetGeometry(client, other, stuff);
54874642e01fSmrg            }
54884642e01fSmrg        }
54894642e01fSmrg    }
54904642e01fSmrg
54914642e01fSmrg    return Success;
54924642e01fSmrg}
54934642e01fSmrg
549405b261ecSmrg/***====================================================================***/
549505b261ecSmrg
549605b261ecSmrgint
549705b261ecSmrgProcXkbPerClientFlags(ClientPtr client)
549805b261ecSmrg{
5499f7df2e56Smrg    DeviceIntPtr dev;
5500f7df2e56Smrg    xkbPerClientFlagsReply rep;
5501f7df2e56Smrg    XkbInterestPtr interest;
55024642e01fSmrg    Mask access_mode = DixGetAttrAccess | DixSetAttrAccess;
550305b261ecSmrg
550405b261ecSmrg    REQUEST(xkbPerClientFlagsReq);
550505b261ecSmrg    REQUEST_SIZE_MATCH(xkbPerClientFlagsReq);
550605b261ecSmrg
5507f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
5508f7df2e56Smrg        return BadAccess;
550905b261ecSmrg
55104642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
5511f7df2e56Smrg    CHK_MASK_LEGAL(0x01, stuff->change, XkbPCF_AllFlagsMask);
5512f7df2e56Smrg    CHK_MASK_MATCH(0x02, stuff->change, stuff->value);
551305b261ecSmrg
5514f7df2e56Smrg    interest = XkbFindClientResource((DevicePtr) dev, client);
551505b261ecSmrg    if (stuff->change) {
5516f7df2e56Smrg        client->xkbClientFlags &= ~stuff->change;
5517f7df2e56Smrg        client->xkbClientFlags |= stuff->value;
551805b261ecSmrg    }
5519f7df2e56Smrg    if (stuff->change & XkbPCF_AutoResetControlsMask) {
5520f7df2e56Smrg        Bool want;
5521f7df2e56Smrg
5522f7df2e56Smrg        want = stuff->value & XkbPCF_AutoResetControlsMask;
5523f7df2e56Smrg        if (interest && !want) {
5524f7df2e56Smrg            interest->autoCtrls = interest->autoCtrlValues = 0;
5525f7df2e56Smrg        }
5526f7df2e56Smrg        else if (want && (!interest)) {
5527f7df2e56Smrg            XID id = FakeClientID(client->index);
5528f7df2e56Smrg
5529f7df2e56Smrg            if (!AddResource(id, RT_XKBCLIENT, dev))
5530f7df2e56Smrg                return BadAlloc;
5531f7df2e56Smrg            interest = XkbAddClientResource((DevicePtr) dev, client, id);
5532f7df2e56Smrg            if (!interest)
5533f7df2e56Smrg                return BadAlloc;
5534f7df2e56Smrg        }
5535f7df2e56Smrg        if (interest && want) {
5536f7df2e56Smrg            register unsigned affect;
5537f7df2e56Smrg
5538f7df2e56Smrg            affect = stuff->ctrlsToChange;
5539f7df2e56Smrg
5540f7df2e56Smrg            CHK_MASK_LEGAL(0x03, affect, XkbAllBooleanCtrlsMask);
5541f7df2e56Smrg            CHK_MASK_MATCH(0x04, affect, stuff->autoCtrls);
5542f7df2e56Smrg            CHK_MASK_MATCH(0x05, stuff->autoCtrls, stuff->autoCtrlValues);
5543f7df2e56Smrg
5544f7df2e56Smrg            interest->autoCtrls &= ~affect;
5545f7df2e56Smrg            interest->autoCtrlValues &= ~affect;
5546f7df2e56Smrg            interest->autoCtrls |= stuff->autoCtrls & affect;
5547f7df2e56Smrg            interest->autoCtrlValues |= stuff->autoCtrlValues & affect;
5548f7df2e56Smrg        }
554905b261ecSmrg    }
5550f7df2e56Smrg
5551f7df2e56Smrg    rep = (xkbPerClientFlagsReply) {
5552f7df2e56Smrg        .type = X_Reply,
5553f7df2e56Smrg        .sequenceNumber = client->sequence,
5554f7df2e56Smrg        .length = 0,
5555f7df2e56Smrg        .supported = XkbPCF_AllFlagsMask,
5556f7df2e56Smrg        .value = client->xkbClientFlags & XkbPCF_AllFlagsMask,
5557f7df2e56Smrg        .autoCtrls = interest ? interest->autoCtrls : 0,
5558f7df2e56Smrg        .autoCtrlValues =  interest ? interest->autoCtrlValues : 0,
5559f7df2e56Smrg    };
5560f7df2e56Smrg    if (client->swapped) {
5561f7df2e56Smrg        swaps(&rep.sequenceNumber);
5562f7df2e56Smrg        swapl(&rep.supported);
5563f7df2e56Smrg        swapl(&rep.value);
5564f7df2e56Smrg        swapl(&rep.autoCtrls);
5565f7df2e56Smrg        swapl(&rep.autoCtrlValues);
556605b261ecSmrg    }
5567f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbPerClientFlagsReply), &rep);
55686747b715Smrg    return Success;
556905b261ecSmrg}
557005b261ecSmrg
557105b261ecSmrg/***====================================================================***/
557205b261ecSmrg
557305b261ecSmrg/* all latin-1 alphanumerics, plus parens, minus, underscore, slash */
557405b261ecSmrg/* and wildcards */
557505b261ecSmrgstatic unsigned char componentSpecLegal[] = {
5576f7df2e56Smrg    0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x87,
5577f7df2e56Smrg    0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07,
5578f7df2e56Smrg    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5579f7df2e56Smrg    0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
558005b261ecSmrg};
558105b261ecSmrg
558205b261ecSmrg/* same as above but accepts percent, plus and bar too */
558305b261ecSmrgstatic unsigned char componentExprLegal[] = {
5584f7df2e56Smrg    0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0xff, 0x87,
5585f7df2e56Smrg    0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x17,
5586f7df2e56Smrg    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5587f7df2e56Smrg    0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
558805b261ecSmrg};
558905b261ecSmrg
559005b261ecSmrgstatic char *
5591f7df2e56SmrgGetComponentSpec(unsigned char **pWire, Bool allowExpr, int *errRtrn)
559205b261ecSmrg{
5593f7df2e56Smrg    int len;
5594f7df2e56Smrg    register int i;
5595f7df2e56Smrg    unsigned char *wire, *str, *tmp, *legal;
5596f7df2e56Smrg
5597f7df2e56Smrg    if (allowExpr)
5598f7df2e56Smrg        legal = &componentExprLegal[0];
5599f7df2e56Smrg    else
5600f7df2e56Smrg        legal = &componentSpecLegal[0];
5601f7df2e56Smrg
5602f7df2e56Smrg    wire = *pWire;
5603f7df2e56Smrg    len = (*(unsigned char *) wire++);
5604f7df2e56Smrg    if (len > 0) {
5605f7df2e56Smrg        str = calloc(1, len + 1);
5606f7df2e56Smrg        if (str) {
5607f7df2e56Smrg            tmp = str;
5608f7df2e56Smrg            for (i = 0; i < len; i++) {
5609f7df2e56Smrg                if (legal[(*wire) / 8] & (1 << ((*wire) % 8)))
5610f7df2e56Smrg                    *tmp++ = *wire++;
5611f7df2e56Smrg                else
5612f7df2e56Smrg                    wire++;
5613f7df2e56Smrg            }
5614f7df2e56Smrg            if (tmp != str)
5615f7df2e56Smrg                *tmp++ = '\0';
5616f7df2e56Smrg            else {
5617f7df2e56Smrg                free(str);
5618f7df2e56Smrg                str = NULL;
5619f7df2e56Smrg            }
5620f7df2e56Smrg        }
5621f7df2e56Smrg        else {
5622f7df2e56Smrg            *errRtrn = BadAlloc;
5623f7df2e56Smrg        }
562405b261ecSmrg    }
562505b261ecSmrg    else {
5626f7df2e56Smrg        str = NULL;
562705b261ecSmrg    }
5628f7df2e56Smrg    *pWire = wire;
5629f7df2e56Smrg    return (char *) str;
563005b261ecSmrg}
563105b261ecSmrg
563205b261ecSmrg/***====================================================================***/
563305b261ecSmrg
563405b261ecSmrgint
563505b261ecSmrgProcXkbListComponents(ClientPtr client)
563605b261ecSmrg{
5637f7df2e56Smrg    DeviceIntPtr dev;
5638f7df2e56Smrg    xkbListComponentsReply rep;
5639f7df2e56Smrg    unsigned len;
5640f7df2e56Smrg    unsigned char *str;
5641f7df2e56Smrg    uint8_t size;
5642f7df2e56Smrg    int i;
564305b261ecSmrg
564405b261ecSmrg    REQUEST(xkbListComponentsReq);
564505b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbListComponentsReq);
564605b261ecSmrg
5647f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
5648f7df2e56Smrg        return BadAccess;
564905b261ecSmrg
56504642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
565105b261ecSmrg
5652f7df2e56Smrg    /* The request is followed by six Pascal strings (i.e. size in characters
5653f7df2e56Smrg     * followed by a string pattern) describing what the client wants us to
5654f7df2e56Smrg     * list.  We don't care, but might as well check they haven't got the
5655f7df2e56Smrg     * length wrong. */
5656f7df2e56Smrg    str = (unsigned char *) &stuff[1];
5657f7df2e56Smrg    for (i = 0; i < 6; i++) {
5658f7df2e56Smrg        size = *((uint8_t *)str);
5659f7df2e56Smrg        len = (str + size + 1) - ((unsigned char *) stuff);
5660f7df2e56Smrg        if ((XkbPaddedSize(len) / 4) > stuff->length)
5661f7df2e56Smrg            return BadLength;
5662f7df2e56Smrg        str += (size + 1);
5663f7df2e56Smrg    }
5664f7df2e56Smrg    if ((XkbPaddedSize(len) / 4) != stuff->length)
5665f7df2e56Smrg        return BadLength;
5666f7df2e56Smrg    rep = (xkbListComponentsReply) {
5667f7df2e56Smrg        .type = X_Reply,
5668f7df2e56Smrg        .deviceID = dev->id,
5669f7df2e56Smrg        .sequenceNumber = client->sequence,
5670f7df2e56Smrg        .length = 0,
5671f7df2e56Smrg        .nKeymaps = 0,
5672f7df2e56Smrg        .nKeycodes = 0,
5673f7df2e56Smrg        .nTypes = 0,
5674f7df2e56Smrg        .nCompatMaps = 0,
5675f7df2e56Smrg        .nSymbols = 0,
5676f7df2e56Smrg        .nGeometries = 0,
5677f7df2e56Smrg        .extra = 0
5678f7df2e56Smrg    };
567905b261ecSmrg    if (client->swapped) {
5680f7df2e56Smrg        swaps(&rep.sequenceNumber);
5681f7df2e56Smrg        swapl(&rep.length);
5682f7df2e56Smrg        swaps(&rep.nKeymaps);
5683f7df2e56Smrg        swaps(&rep.nKeycodes);
5684f7df2e56Smrg        swaps(&rep.nTypes);
5685f7df2e56Smrg        swaps(&rep.nCompatMaps);
5686f7df2e56Smrg        swaps(&rep.nSymbols);
5687f7df2e56Smrg        swaps(&rep.nGeometries);
5688f7df2e56Smrg        swaps(&rep.extra);
5689f7df2e56Smrg    }
5690f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbListComponentsReply), &rep);
56916747b715Smrg    return Success;
569205b261ecSmrg}
569305b261ecSmrg
569405b261ecSmrg/***====================================================================***/
569505b261ecSmrgint
569605b261ecSmrgProcXkbGetKbdByName(ClientPtr client)
569705b261ecSmrg{
5698f7df2e56Smrg    DeviceIntPtr dev;
5699f7df2e56Smrg    DeviceIntPtr tmpd;
5700f7df2e56Smrg    DeviceIntPtr master;
5701f7df2e56Smrg    xkbGetKbdByNameReply rep = { 0 };
5702f7df2e56Smrg    xkbGetMapReply mrep = { 0 };
5703f7df2e56Smrg    xkbGetCompatMapReply crep = { 0 };
5704f7df2e56Smrg    xkbGetIndicatorMapReply irep = { 0 };
5705f7df2e56Smrg    xkbGetNamesReply nrep = { 0 };
5706f7df2e56Smrg    xkbGetGeometryReply grep = { 0 };
5707f7df2e56Smrg    XkbComponentNamesRec names = { 0 };
5708f7df2e56Smrg    XkbDescPtr xkb, new;
5709f7df2e56Smrg    XkbEventCauseRec cause;
5710f7df2e56Smrg    unsigned char *str;
5711f7df2e56Smrg    char mapFile[PATH_MAX];
5712f7df2e56Smrg    unsigned len;
5713f7df2e56Smrg    unsigned fwant, fneed, reported;
5714f7df2e56Smrg    int status;
5715f7df2e56Smrg    Bool geom_changed;
5716f7df2e56Smrg    XkbSrvLedInfoPtr old_sli;
5717f7df2e56Smrg    XkbSrvLedInfoPtr sli;
57184642e01fSmrg    Mask access_mode = DixGetAttrAccess | DixManageAccess;
571905b261ecSmrg
572005b261ecSmrg    REQUEST(xkbGetKbdByNameReq);
572105b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq);
572205b261ecSmrg
5723f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
5724f7df2e56Smrg        return BadAccess;
572505b261ecSmrg
57264642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
5727f7df2e56Smrg    master = GetMaster(dev, MASTER_KEYBOARD);
572805b261ecSmrg
572905b261ecSmrg    xkb = dev->key->xkbInfo->desc;
5730f7df2e56Smrg    status = Success;
5731f7df2e56Smrg    str = (unsigned char *) &stuff[1];
5732f7df2e56Smrg    if (GetComponentSpec(&str, TRUE, &status))  /* keymap, unsupported */
57336747b715Smrg        return BadMatch;
5734f7df2e56Smrg    names.keycodes = GetComponentSpec(&str, TRUE, &status);
5735f7df2e56Smrg    names.types = GetComponentSpec(&str, TRUE, &status);
5736f7df2e56Smrg    names.compat = GetComponentSpec(&str, TRUE, &status);
5737f7df2e56Smrg    names.symbols = GetComponentSpec(&str, TRUE, &status);
5738f7df2e56Smrg    names.geometry = GetComponentSpec(&str, TRUE, &status);
5739f7df2e56Smrg    if (status != Success)
5740f7df2e56Smrg        return status;
5741f7df2e56Smrg    len = str - ((unsigned char *) stuff);
5742f7df2e56Smrg    if ((XkbPaddedSize(len) / 4) != stuff->length)
5743f7df2e56Smrg        return BadLength;
5744f7df2e56Smrg
5745f7df2e56Smrg    CHK_MASK_LEGAL(0x01, stuff->want, XkbGBN_AllComponentsMask);
5746f7df2e56Smrg    CHK_MASK_LEGAL(0x02, stuff->need, XkbGBN_AllComponentsMask);
5747f7df2e56Smrg
574805b261ecSmrg    if (stuff->load)
5749f7df2e56Smrg        fwant = XkbGBN_AllComponentsMask;
5750f7df2e56Smrg    else
5751f7df2e56Smrg        fwant = stuff->want | stuff->need;
5752f7df2e56Smrg    if ((!names.compat) &&
5753f7df2e56Smrg        (fwant & (XkbGBN_CompatMapMask | XkbGBN_IndicatorMapMask))) {
5754f7df2e56Smrg        names.compat = Xstrdup("%");
575505b261ecSmrg    }
5756f7df2e56Smrg    if ((!names.types) && (fwant & (XkbGBN_TypesMask))) {
5757f7df2e56Smrg        names.types = Xstrdup("%");
57584642e01fSmrg    }
5759f7df2e56Smrg    if ((!names.symbols) && (fwant & XkbGBN_SymbolsMask)) {
5760f7df2e56Smrg        names.symbols = Xstrdup("%");
57614642e01fSmrg    }
5762f7df2e56Smrg    geom_changed = ((names.geometry != NULL) &&
5763f7df2e56Smrg                    (strcmp(names.geometry, "%") != 0));
5764f7df2e56Smrg    if ((!names.geometry) && (fwant & XkbGBN_GeometryMask)) {
5765f7df2e56Smrg        names.geometry = Xstrdup("%");
5766f7df2e56Smrg        geom_changed = FALSE;
576705b261ecSmrg    }
576805b261ecSmrg
57696747b715Smrg    memset(mapFile, 0, PATH_MAX);
5770f7df2e56Smrg    rep.type = X_Reply;
577105b261ecSmrg    rep.deviceID = dev->id;
577205b261ecSmrg    rep.sequenceNumber = client->sequence;
577305b261ecSmrg    rep.length = 0;
577405b261ecSmrg    rep.minKeyCode = xkb->min_key_code;
577505b261ecSmrg    rep.maxKeyCode = xkb->max_key_code;
5776f7df2e56Smrg    rep.loaded = FALSE;
5777f7df2e56Smrg    fwant =
5778f7df2e56Smrg        XkbConvertGetByNameComponents(TRUE, stuff->want) | XkmVirtualModsMask;
5779f7df2e56Smrg    fneed = XkbConvertGetByNameComponents(TRUE, stuff->need);
5780f7df2e56Smrg    rep.reported = XkbConvertGetByNameComponents(FALSE, fwant | fneed);
578105b261ecSmrg    if (stuff->load) {
5782f7df2e56Smrg        fneed |= XkmKeymapRequired;
5783f7df2e56Smrg        fwant |= XkmKeymapLegal;
578405b261ecSmrg    }
5785f7df2e56Smrg    if ((fwant | fneed) & XkmSymbolsMask) {
5786f7df2e56Smrg        fneed |= XkmKeyNamesIndex | XkmTypesIndex;
5787f7df2e56Smrg        fwant |= XkmIndicatorsIndex;
578805b261ecSmrg    }
578905b261ecSmrg
579005b261ecSmrg    /* We pass dev in here so we can get the old names out if needed. */
5791f7df2e56Smrg    rep.found = XkbDDXLoadKeymapByNames(dev, &names, fwant, fneed, &new,
5792f7df2e56Smrg                                        mapFile, PATH_MAX);
5793f7df2e56Smrg    rep.newKeyboard = FALSE;
5794f7df2e56Smrg    rep.pad1 = rep.pad2 = rep.pad3 = rep.pad4 = 0;
5795f7df2e56Smrg
5796f7df2e56Smrg    stuff->want |= stuff->need;
5797f7df2e56Smrg    if (new == NULL)
5798f7df2e56Smrg        rep.reported = 0;
579905b261ecSmrg    else {
5800f7df2e56Smrg        if (stuff->load)
5801f7df2e56Smrg            rep.loaded = TRUE;
5802f7df2e56Smrg        if (stuff->load ||
5803f7df2e56Smrg            ((rep.reported & XkbGBN_SymbolsMask) && (new->compat))) {
5804f7df2e56Smrg            XkbChangesRec changes;
5805f7df2e56Smrg
5806f7df2e56Smrg            memset(&changes, 0, sizeof(changes));
5807f7df2e56Smrg            XkbUpdateDescActions(new,
5808f7df2e56Smrg                                 new->min_key_code, XkbNumKeys(new), &changes);
5809f7df2e56Smrg        }
581005b261ecSmrg
5811f7df2e56Smrg        if (new->map == NULL)
5812f7df2e56Smrg            rep.reported &= ~(XkbGBN_SymbolsMask | XkbGBN_TypesMask);
5813f7df2e56Smrg        else if (rep.reported & (XkbGBN_SymbolsMask | XkbGBN_TypesMask)) {
5814f7df2e56Smrg            mrep.type = X_Reply;
5815f7df2e56Smrg            mrep.deviceID = dev->id;
5816f7df2e56Smrg            mrep.sequenceNumber = client->sequence;
5817f7df2e56Smrg            mrep.length =
5818f7df2e56Smrg                ((SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply)) >> 2);
5819f7df2e56Smrg            mrep.minKeyCode = new->min_key_code;
5820f7df2e56Smrg            mrep.maxKeyCode = new->max_key_code;
5821f7df2e56Smrg            mrep.present = 0;
5822f7df2e56Smrg            mrep.totalSyms = mrep.totalActs =
5823f7df2e56Smrg                mrep.totalKeyBehaviors = mrep.totalKeyExplicit =
5824f7df2e56Smrg                mrep.totalModMapKeys = mrep.totalVModMapKeys = 0;
5825f7df2e56Smrg            if (rep.reported & (XkbGBN_TypesMask | XkbGBN_ClientSymbolsMask)) {
5826f7df2e56Smrg                mrep.present |= XkbKeyTypesMask;
5827f7df2e56Smrg                mrep.firstType = 0;
5828f7df2e56Smrg                mrep.nTypes = mrep.totalTypes = new->map->num_types;
5829f7df2e56Smrg            }
5830f7df2e56Smrg            else {
5831f7df2e56Smrg                mrep.firstType = mrep.nTypes = 0;
5832f7df2e56Smrg                mrep.totalTypes = 0;
5833f7df2e56Smrg            }
5834f7df2e56Smrg            if (rep.reported & XkbGBN_ClientSymbolsMask) {
5835f7df2e56Smrg                mrep.present |= (XkbKeySymsMask | XkbModifierMapMask);
5836f7df2e56Smrg                mrep.firstKeySym = mrep.firstModMapKey = new->min_key_code;
5837f7df2e56Smrg                mrep.nKeySyms = mrep.nModMapKeys = XkbNumKeys(new);
5838f7df2e56Smrg            }
5839f7df2e56Smrg            else {
5840f7df2e56Smrg                mrep.firstKeySym = mrep.firstModMapKey = 0;
5841f7df2e56Smrg                mrep.nKeySyms = mrep.nModMapKeys = 0;
5842f7df2e56Smrg            }
5843f7df2e56Smrg            if (rep.reported & XkbGBN_ServerSymbolsMask) {
5844f7df2e56Smrg                mrep.present |= XkbAllServerInfoMask;
5845f7df2e56Smrg                mrep.virtualMods = ~0;
5846f7df2e56Smrg                mrep.firstKeyAct = mrep.firstKeyBehavior =
5847f7df2e56Smrg                    mrep.firstKeyExplicit = new->min_key_code;
5848f7df2e56Smrg                mrep.nKeyActs = mrep.nKeyBehaviors =
5849f7df2e56Smrg                    mrep.nKeyExplicit = XkbNumKeys(new);
5850f7df2e56Smrg                mrep.firstVModMapKey = new->min_key_code;
5851f7df2e56Smrg                mrep.nVModMapKeys = XkbNumKeys(new);
5852f7df2e56Smrg            }
5853f7df2e56Smrg            else {
5854f7df2e56Smrg                mrep.virtualMods = 0;
5855f7df2e56Smrg                mrep.firstKeyAct = mrep.firstKeyBehavior =
5856f7df2e56Smrg                    mrep.firstKeyExplicit = 0;
5857f7df2e56Smrg                mrep.nKeyActs = mrep.nKeyBehaviors = mrep.nKeyExplicit = 0;
5858f7df2e56Smrg            }
5859f7df2e56Smrg            XkbComputeGetMapReplySize(new, &mrep);
5860f7df2e56Smrg            rep.length += SIZEOF(xGenericReply) / 4 + mrep.length;
5861f7df2e56Smrg        }
5862f7df2e56Smrg        if (new->compat == NULL)
5863f7df2e56Smrg            rep.reported &= ~XkbGBN_CompatMapMask;
5864f7df2e56Smrg        else if (rep.reported & XkbGBN_CompatMapMask) {
5865f7df2e56Smrg            crep.type = X_Reply;
5866f7df2e56Smrg            crep.deviceID = dev->id;
5867f7df2e56Smrg            crep.sequenceNumber = client->sequence;
5868f7df2e56Smrg            crep.length = 0;
5869f7df2e56Smrg            crep.groups = XkbAllGroupsMask;
5870f7df2e56Smrg            crep.firstSI = 0;
5871f7df2e56Smrg            crep.nSI = crep.nTotalSI = new->compat->num_si;
5872f7df2e56Smrg            XkbComputeGetCompatMapReplySize(new->compat, &crep);
5873f7df2e56Smrg            rep.length += SIZEOF(xGenericReply) / 4 + crep.length;
5874f7df2e56Smrg        }
5875f7df2e56Smrg        if (new->indicators == NULL)
5876f7df2e56Smrg            rep.reported &= ~XkbGBN_IndicatorMapMask;
5877f7df2e56Smrg        else if (rep.reported & XkbGBN_IndicatorMapMask) {
5878f7df2e56Smrg            irep.type = X_Reply;
5879f7df2e56Smrg            irep.deviceID = dev->id;
5880f7df2e56Smrg            irep.sequenceNumber = client->sequence;
5881f7df2e56Smrg            irep.length = 0;
5882f7df2e56Smrg            irep.which = XkbAllIndicatorsMask;
5883f7df2e56Smrg            XkbComputeGetIndicatorMapReplySize(new->indicators, &irep);
5884f7df2e56Smrg            rep.length += SIZEOF(xGenericReply) / 4 + irep.length;
5885f7df2e56Smrg        }
5886f7df2e56Smrg        if (new->names == NULL)
5887f7df2e56Smrg            rep.reported &= ~(XkbGBN_OtherNamesMask | XkbGBN_KeyNamesMask);
5888f7df2e56Smrg        else if (rep.reported & (XkbGBN_OtherNamesMask | XkbGBN_KeyNamesMask)) {
5889f7df2e56Smrg            nrep.type = X_Reply;
5890f7df2e56Smrg            nrep.deviceID = dev->id;
5891f7df2e56Smrg            nrep.sequenceNumber = client->sequence;
5892f7df2e56Smrg            nrep.length = 0;
5893f7df2e56Smrg            nrep.minKeyCode = new->min_key_code;
5894f7df2e56Smrg            nrep.maxKeyCode = new->max_key_code;
5895f7df2e56Smrg            if (rep.reported & XkbGBN_OtherNamesMask) {
5896f7df2e56Smrg                nrep.which = XkbAllNamesMask;
5897f7df2e56Smrg                if (new->map != NULL)
5898f7df2e56Smrg                    nrep.nTypes = new->map->num_types;
5899f7df2e56Smrg                else
5900f7df2e56Smrg                    nrep.nTypes = 0;
5901f7df2e56Smrg                nrep.nKTLevels = 0;
5902f7df2e56Smrg                nrep.groupNames = XkbAllGroupsMask;
5903f7df2e56Smrg                nrep.virtualMods = XkbAllVirtualModsMask;
5904f7df2e56Smrg                nrep.indicators = XkbAllIndicatorsMask;
5905f7df2e56Smrg                nrep.nRadioGroups = new->names->num_rg;
5906f7df2e56Smrg            }
5907f7df2e56Smrg            else {
5908f7df2e56Smrg                nrep.which = 0;
5909f7df2e56Smrg                nrep.nTypes = 0;
5910f7df2e56Smrg                nrep.nKTLevels = 0;
5911f7df2e56Smrg                nrep.groupNames = 0;
5912f7df2e56Smrg                nrep.virtualMods = 0;
5913f7df2e56Smrg                nrep.indicators = 0;
5914f7df2e56Smrg                nrep.nRadioGroups = 0;
5915f7df2e56Smrg            }
5916f7df2e56Smrg            if (rep.reported & XkbGBN_KeyNamesMask) {
5917f7df2e56Smrg                nrep.which |= XkbKeyNamesMask;
5918f7df2e56Smrg                nrep.firstKey = new->min_key_code;
5919f7df2e56Smrg                nrep.nKeys = XkbNumKeys(new);
5920f7df2e56Smrg                nrep.nKeyAliases = new->names->num_key_aliases;
5921f7df2e56Smrg                if (nrep.nKeyAliases)
5922f7df2e56Smrg                    nrep.which |= XkbKeyAliasesMask;
5923f7df2e56Smrg            }
5924f7df2e56Smrg            else {
5925f7df2e56Smrg                nrep.which &= ~(XkbKeyNamesMask | XkbKeyAliasesMask);
5926f7df2e56Smrg                nrep.firstKey = nrep.nKeys = 0;
5927f7df2e56Smrg                nrep.nKeyAliases = 0;
5928f7df2e56Smrg            }
5929f7df2e56Smrg            XkbComputeGetNamesReplySize(new, &nrep);
5930f7df2e56Smrg            rep.length += SIZEOF(xGenericReply) / 4 + nrep.length;
5931f7df2e56Smrg        }
5932f7df2e56Smrg        if (new->geom == NULL)
5933f7df2e56Smrg            rep.reported &= ~XkbGBN_GeometryMask;
5934f7df2e56Smrg        else if (rep.reported & XkbGBN_GeometryMask) {
5935f7df2e56Smrg            grep.type = X_Reply;
5936f7df2e56Smrg            grep.deviceID = dev->id;
5937f7df2e56Smrg            grep.sequenceNumber = client->sequence;
5938f7df2e56Smrg            grep.length = 0;
5939f7df2e56Smrg            grep.found = TRUE;
5940f7df2e56Smrg            grep.pad = 0;
5941f7df2e56Smrg            grep.widthMM = grep.heightMM = 0;
5942f7df2e56Smrg            grep.nProperties = grep.nColors = grep.nShapes = 0;
5943f7df2e56Smrg            grep.nSections = grep.nDoodads = 0;
5944f7df2e56Smrg            grep.baseColorNdx = grep.labelColorNdx = 0;
5945f7df2e56Smrg            XkbComputeGetGeometryReplySize(new->geom, &grep, None);
5946f7df2e56Smrg            rep.length += SIZEOF(xGenericReply) / 4 + grep.length;
5947f7df2e56Smrg        }
5948f7df2e56Smrg    }
5949f7df2e56Smrg
5950f7df2e56Smrg    reported = rep.reported;
5951f7df2e56Smrg    if (client->swapped) {
5952f7df2e56Smrg        swaps(&rep.sequenceNumber);
5953f7df2e56Smrg        swapl(&rep.length);
5954f7df2e56Smrg        swaps(&rep.found);
5955f7df2e56Smrg        swaps(&rep.reported);
5956f7df2e56Smrg    }
5957f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetKbdByNameReply), &rep);
5958f7df2e56Smrg    if (reported & (XkbGBN_SymbolsMask | XkbGBN_TypesMask))
5959f7df2e56Smrg        XkbSendMap(client, new, &mrep);
5960f7df2e56Smrg    if (reported & XkbGBN_CompatMapMask)
5961f7df2e56Smrg        XkbSendCompatMap(client, new->compat, &crep);
5962f7df2e56Smrg    if (reported & XkbGBN_IndicatorMapMask)
5963f7df2e56Smrg        XkbSendIndicatorMap(client, new->indicators, &irep);
5964f7df2e56Smrg    if (reported & (XkbGBN_KeyNamesMask | XkbGBN_OtherNamesMask))
5965f7df2e56Smrg        XkbSendNames(client, new, &nrep);
5966f7df2e56Smrg    if (reported & XkbGBN_GeometryMask)
5967f7df2e56Smrg        XkbSendGeometry(client, new->geom, &grep, FALSE);
5968f7df2e56Smrg    if (rep.loaded) {
5969f7df2e56Smrg        XkbDescPtr old_xkb;
5970f7df2e56Smrg        xkbNewKeyboardNotify nkn;
5971f7df2e56Smrg
5972f7df2e56Smrg        old_xkb = xkb;
5973f7df2e56Smrg        xkb = new;
5974f7df2e56Smrg        dev->key->xkbInfo->desc = xkb;
5975f7df2e56Smrg        new = old_xkb;          /* so it'll get freed automatically */
5976f7df2e56Smrg
5977f7df2e56Smrg        XkbCopyControls(xkb, old_xkb);
5978f7df2e56Smrg
5979f7df2e56Smrg        nkn.deviceID = nkn.oldDeviceID = dev->id;
5980f7df2e56Smrg        nkn.minKeyCode = new->min_key_code;
5981f7df2e56Smrg        nkn.maxKeyCode = new->max_key_code;
5982f7df2e56Smrg        nkn.oldMinKeyCode = xkb->min_key_code;
5983f7df2e56Smrg        nkn.oldMaxKeyCode = xkb->max_key_code;
5984f7df2e56Smrg        nkn.requestMajor = XkbReqCode;
5985f7df2e56Smrg        nkn.requestMinor = X_kbGetKbdByName;
5986f7df2e56Smrg        nkn.changed = XkbNKN_KeycodesMask;
5987f7df2e56Smrg        if (geom_changed)
5988f7df2e56Smrg            nkn.changed |= XkbNKN_GeometryMask;
5989f7df2e56Smrg        XkbSendNewKeyboardNotify(dev, &nkn);
5990f7df2e56Smrg
5991f7df2e56Smrg        /* Update the map and LED info on the device itself, as well as
5992f7df2e56Smrg         * any slaves if it's an MD, or its MD if it's an SD and was the
5993f7df2e56Smrg         * last device used on that MD. */
599405b261ecSmrg        for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
5995f7df2e56Smrg            if (tmpd != dev && GetMaster(tmpd, MASTER_KEYBOARD) != dev &&
5996f7df2e56Smrg                (tmpd != master || dev != master->lastSlave))
5997f7df2e56Smrg                continue;
5998f7df2e56Smrg
5999f7df2e56Smrg            if (tmpd != dev)
6000f7df2e56Smrg                XkbDeviceApplyKeymap(tmpd, xkb);
6001f7df2e56Smrg
6002f7df2e56Smrg            if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) {
6003f7df2e56Smrg                old_sli = tmpd->kbdfeed->xkb_sli;
6004f7df2e56Smrg                tmpd->kbdfeed->xkb_sli = NULL;
6005f7df2e56Smrg                sli = XkbAllocSrvLedInfo(tmpd, tmpd->kbdfeed, NULL, 0);
6006f7df2e56Smrg                if (sli) {
6007f7df2e56Smrg                    sli->explicitState = old_sli->explicitState;
6008f7df2e56Smrg                    sli->effectiveState = old_sli->effectiveState;
600905b261ecSmrg                }
6010f7df2e56Smrg                tmpd->kbdfeed->xkb_sli = sli;
6011f7df2e56Smrg                XkbFreeSrvLedInfo(old_sli);
601205b261ecSmrg            }
601305b261ecSmrg        }
6014f7df2e56Smrg    }
6015f7df2e56Smrg    if ((new != NULL) && (new != xkb)) {
6016f7df2e56Smrg        XkbFreeKeyboard(new, XkbAllComponentsMask, TRUE);
6017f7df2e56Smrg        new = NULL;
601805b261ecSmrg    }
60199ace9065Smrg    XkbFreeComponentNames(&names, FALSE);
6020f7df2e56Smrg    XkbSetCauseXkbReq(&cause, X_kbGetKbdByName, client);
6021f7df2e56Smrg    XkbUpdateAllDeviceIndicators(NULL, &cause);
6022f7df2e56Smrg
60236747b715Smrg    return Success;
602405b261ecSmrg}
602505b261ecSmrg
602605b261ecSmrg/***====================================================================***/
602705b261ecSmrg
602805b261ecSmrgstatic int
6029f7df2e56SmrgComputeDeviceLedInfoSize(DeviceIntPtr dev,
6030f7df2e56Smrg                         unsigned int what, XkbSrvLedInfoPtr sli)
603105b261ecSmrg{
6032f7df2e56Smrg    int nNames, nMaps;
6033f7df2e56Smrg    register unsigned n, bit;
6034f7df2e56Smrg
6035f7df2e56Smrg    if (sli == NULL)
6036f7df2e56Smrg        return 0;
6037f7df2e56Smrg    nNames = nMaps = 0;
6038f7df2e56Smrg    if ((what & XkbXI_IndicatorNamesMask) == 0)
6039f7df2e56Smrg        sli->namesPresent = 0;
6040f7df2e56Smrg    if ((what & XkbXI_IndicatorMapsMask) == 0)
6041f7df2e56Smrg        sli->mapsPresent = 0;
6042f7df2e56Smrg
6043f7df2e56Smrg    for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6044f7df2e56Smrg        if (sli->names && sli->names[n] != None) {
6045f7df2e56Smrg            sli->namesPresent |= bit;
6046f7df2e56Smrg            nNames++;
6047f7df2e56Smrg        }
6048f7df2e56Smrg        if (sli->maps && XkbIM_InUse(&sli->maps[n])) {
6049f7df2e56Smrg            sli->mapsPresent |= bit;
6050f7df2e56Smrg            nMaps++;
6051f7df2e56Smrg        }
6052f7df2e56Smrg    }
6053f7df2e56Smrg    return (nNames * 4) + (nMaps * SIZEOF(xkbIndicatorMapWireDesc));
605405b261ecSmrg}
605505b261ecSmrg
6056f7df2e56Smrgstatic int
6057f7df2e56SmrgCheckDeviceLedFBs(DeviceIntPtr dev,
6058f7df2e56Smrg                  int class,
6059f7df2e56Smrg                  int id, xkbGetDeviceInfoReply * rep, ClientPtr client)
606005b261ecSmrg{
6061f7df2e56Smrg    int nFBs = 0;
6062f7df2e56Smrg    int length = 0;
6063f7df2e56Smrg    Bool classOk;
6064f7df2e56Smrg
6065f7df2e56Smrg    if (class == XkbDfltXIClass) {
6066f7df2e56Smrg        if (dev->kbdfeed)
6067f7df2e56Smrg            class = KbdFeedbackClass;
6068f7df2e56Smrg        else if (dev->leds)
6069f7df2e56Smrg            class = LedFeedbackClass;
6070f7df2e56Smrg        else {
6071f7df2e56Smrg            client->errorValue = _XkbErrCode2(XkbErr_BadClass, class);
6072f7df2e56Smrg            return XkbKeyboardErrorCode;
6073f7df2e56Smrg        }
6074f7df2e56Smrg    }
6075f7df2e56Smrg    classOk = FALSE;
6076f7df2e56Smrg    if ((dev->kbdfeed) &&
6077f7df2e56Smrg        ((class == KbdFeedbackClass) || (class == XkbAllXIClasses))) {
6078f7df2e56Smrg        KbdFeedbackPtr kf;
6079f7df2e56Smrg
6080f7df2e56Smrg        classOk = TRUE;
6081f7df2e56Smrg        for (kf = dev->kbdfeed; (kf); kf = kf->next) {
6082f7df2e56Smrg            if ((id != XkbAllXIIds) && (id != XkbDfltXIId) &&
6083f7df2e56Smrg                (id != kf->ctrl.id))
6084f7df2e56Smrg                continue;
6085f7df2e56Smrg            nFBs++;
6086f7df2e56Smrg            length += SIZEOF(xkbDeviceLedsWireDesc);
6087f7df2e56Smrg            if (!kf->xkb_sli)
6088f7df2e56Smrg                kf->xkb_sli = XkbAllocSrvLedInfo(dev, kf, NULL, 0);
6089f7df2e56Smrg            length += ComputeDeviceLedInfoSize(dev, rep->present, kf->xkb_sli);
6090f7df2e56Smrg            if (id != XkbAllXIIds)
6091f7df2e56Smrg                break;
6092f7df2e56Smrg        }
6093f7df2e56Smrg    }
6094f7df2e56Smrg    if ((dev->leds) &&
6095f7df2e56Smrg        ((class == LedFeedbackClass) || (class == XkbAllXIClasses))) {
6096f7df2e56Smrg        LedFeedbackPtr lf;
6097f7df2e56Smrg
6098f7df2e56Smrg        classOk = TRUE;
6099f7df2e56Smrg        for (lf = dev->leds; (lf); lf = lf->next) {
6100f7df2e56Smrg            if ((id != XkbAllXIIds) && (id != XkbDfltXIId) &&
6101f7df2e56Smrg                (id != lf->ctrl.id))
6102f7df2e56Smrg                continue;
6103f7df2e56Smrg            nFBs++;
6104f7df2e56Smrg            length += SIZEOF(xkbDeviceLedsWireDesc);
6105f7df2e56Smrg            if (!lf->xkb_sli)
6106f7df2e56Smrg                lf->xkb_sli = XkbAllocSrvLedInfo(dev, NULL, lf, 0);
6107f7df2e56Smrg            length += ComputeDeviceLedInfoSize(dev, rep->present, lf->xkb_sli);
6108f7df2e56Smrg            if (id != XkbAllXIIds)
6109f7df2e56Smrg                break;
6110f7df2e56Smrg        }
6111f7df2e56Smrg    }
6112f7df2e56Smrg    if (nFBs > 0) {
6113f7df2e56Smrg        rep->nDeviceLedFBs = nFBs;
6114f7df2e56Smrg        rep->length += (length / 4);
6115f7df2e56Smrg        return Success;
6116f7df2e56Smrg    }
6117f7df2e56Smrg    if (classOk)
6118f7df2e56Smrg        client->errorValue = _XkbErrCode2(XkbErr_BadId, id);
6119f7df2e56Smrg    else
6120f7df2e56Smrg        client->errorValue = _XkbErrCode2(XkbErr_BadClass, class);
612105b261ecSmrg    return XkbKeyboardErrorCode;
612205b261ecSmrg}
612305b261ecSmrg
612405b261ecSmrgstatic int
6125f7df2e56SmrgSendDeviceLedInfo(XkbSrvLedInfoPtr sli, ClientPtr client)
612605b261ecSmrg{
6127f7df2e56Smrg    xkbDeviceLedsWireDesc wire;
6128f7df2e56Smrg    int length;
6129f7df2e56Smrg
6130f7df2e56Smrg    length = 0;
6131f7df2e56Smrg    wire.ledClass = sli->class;
6132f7df2e56Smrg    wire.ledID = sli->id;
6133f7df2e56Smrg    wire.namesPresent = sli->namesPresent;
6134f7df2e56Smrg    wire.mapsPresent = sli->mapsPresent;
6135f7df2e56Smrg    wire.physIndicators = sli->physIndicators;
6136f7df2e56Smrg    wire.state = sli->effectiveState;
613705b261ecSmrg    if (client->swapped) {
6138f7df2e56Smrg        swaps(&wire.ledClass);
6139f7df2e56Smrg        swaps(&wire.ledID);
6140f7df2e56Smrg        swapl(&wire.namesPresent);
6141f7df2e56Smrg        swapl(&wire.mapsPresent);
6142f7df2e56Smrg        swapl(&wire.physIndicators);
6143f7df2e56Smrg        swapl(&wire.state);
6144f7df2e56Smrg    }
6145f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbDeviceLedsWireDesc), &wire);
6146f7df2e56Smrg    length += SIZEOF(xkbDeviceLedsWireDesc);
6147f7df2e56Smrg    if (sli->namesPresent | sli->mapsPresent) {
6148f7df2e56Smrg        register unsigned i, bit;
6149f7df2e56Smrg
6150f7df2e56Smrg        if (sli->namesPresent) {
6151f7df2e56Smrg            CARD32 awire;
6152f7df2e56Smrg
6153f7df2e56Smrg            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
6154f7df2e56Smrg                if (sli->namesPresent & bit) {
6155f7df2e56Smrg                    awire = (CARD32) sli->names[i];
6156f7df2e56Smrg                    if (client->swapped) {
6157f7df2e56Smrg                        swapl(&awire);
6158f7df2e56Smrg                    }
6159f7df2e56Smrg                    WriteToClient(client, 4, &awire);
6160f7df2e56Smrg                    length += 4;
6161f7df2e56Smrg                }
6162f7df2e56Smrg            }
6163f7df2e56Smrg        }
6164f7df2e56Smrg        if (sli->mapsPresent) {
6165f7df2e56Smrg            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
6166f7df2e56Smrg                xkbIndicatorMapWireDesc iwire;
6167f7df2e56Smrg
6168f7df2e56Smrg                if (sli->mapsPresent & bit) {
6169f7df2e56Smrg                    iwire.flags = sli->maps[i].flags;
6170f7df2e56Smrg                    iwire.whichGroups = sli->maps[i].which_groups;
6171f7df2e56Smrg                    iwire.groups = sli->maps[i].groups;
6172f7df2e56Smrg                    iwire.whichMods = sli->maps[i].which_mods;
6173f7df2e56Smrg                    iwire.mods = sli->maps[i].mods.mask;
6174f7df2e56Smrg                    iwire.realMods = sli->maps[i].mods.real_mods;
6175f7df2e56Smrg                    iwire.virtualMods = sli->maps[i].mods.vmods;
6176f7df2e56Smrg                    iwire.ctrls = sli->maps[i].ctrls;
6177f7df2e56Smrg                    if (client->swapped) {
6178f7df2e56Smrg                        swaps(&iwire.virtualMods);
6179f7df2e56Smrg                        swapl(&iwire.ctrls);
6180f7df2e56Smrg                    }
6181f7df2e56Smrg                    WriteToClient(client, SIZEOF(xkbIndicatorMapWireDesc),
6182f7df2e56Smrg                                  &iwire);
6183f7df2e56Smrg                    length += SIZEOF(xkbIndicatorMapWireDesc);
6184f7df2e56Smrg                }
6185f7df2e56Smrg            }
6186f7df2e56Smrg        }
618705b261ecSmrg    }
618805b261ecSmrg    return length;
618905b261ecSmrg}
619005b261ecSmrg
619105b261ecSmrgstatic int
6192f7df2e56SmrgSendDeviceLedFBs(DeviceIntPtr dev,
6193f7df2e56Smrg                 int class, int id, unsigned wantLength, ClientPtr client)
619405b261ecSmrg{
6195f7df2e56Smrg    int length = 0;
6196f7df2e56Smrg
6197f7df2e56Smrg    if (class == XkbDfltXIClass) {
6198f7df2e56Smrg        if (dev->kbdfeed)
6199f7df2e56Smrg            class = KbdFeedbackClass;
6200f7df2e56Smrg        else if (dev->leds)
6201f7df2e56Smrg            class = LedFeedbackClass;
6202f7df2e56Smrg    }
6203f7df2e56Smrg    if ((dev->kbdfeed) &&
6204f7df2e56Smrg        ((class == KbdFeedbackClass) || (class == XkbAllXIClasses))) {
6205f7df2e56Smrg        KbdFeedbackPtr kf;
6206f7df2e56Smrg
6207f7df2e56Smrg        for (kf = dev->kbdfeed; (kf); kf = kf->next) {
6208f7df2e56Smrg            if ((id == XkbAllXIIds) || (id == XkbDfltXIId) ||
6209f7df2e56Smrg                (id == kf->ctrl.id)) {
6210f7df2e56Smrg                length += SendDeviceLedInfo(kf->xkb_sli, client);
6211f7df2e56Smrg                if (id != XkbAllXIIds)
6212f7df2e56Smrg                    break;
6213f7df2e56Smrg            }
6214f7df2e56Smrg        }
6215f7df2e56Smrg    }
6216f7df2e56Smrg    if ((dev->leds) &&
6217f7df2e56Smrg        ((class == LedFeedbackClass) || (class == XkbAllXIClasses))) {
6218f7df2e56Smrg        LedFeedbackPtr lf;
6219f7df2e56Smrg
6220f7df2e56Smrg        for (lf = dev->leds; (lf); lf = lf->next) {
6221f7df2e56Smrg            if ((id == XkbAllXIIds) || (id == XkbDfltXIId) ||
6222f7df2e56Smrg                (id == lf->ctrl.id)) {
6223f7df2e56Smrg                length += SendDeviceLedInfo(lf->xkb_sli, client);
6224f7df2e56Smrg                if (id != XkbAllXIIds)
6225f7df2e56Smrg                    break;
6226f7df2e56Smrg            }
6227f7df2e56Smrg        }
6228f7df2e56Smrg    }
6229f7df2e56Smrg    if (length == wantLength)
6230f7df2e56Smrg        return Success;
6231f7df2e56Smrg    else
6232f7df2e56Smrg        return BadLength;
623305b261ecSmrg}
623405b261ecSmrg
623505b261ecSmrgint
623605b261ecSmrgProcXkbGetDeviceInfo(ClientPtr client)
623705b261ecSmrg{
6238f7df2e56Smrg    DeviceIntPtr dev;
6239f7df2e56Smrg    xkbGetDeviceInfoReply rep;
6240f7df2e56Smrg    int status, nDeviceLedFBs;
6241f7df2e56Smrg    unsigned length, nameLen;
6242f7df2e56Smrg    CARD16 ledClass, ledID;
6243f7df2e56Smrg    unsigned wanted;
6244f7df2e56Smrg    char *str;
624505b261ecSmrg
624605b261ecSmrg    REQUEST(xkbGetDeviceInfoReq);
624705b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq);
624805b261ecSmrg
6249f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
6250f7df2e56Smrg        return BadAccess;
625105b261ecSmrg
6252f7df2e56Smrg    wanted = stuff->wanted;
625305b261ecSmrg
62544642e01fSmrg    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
6255f7df2e56Smrg    CHK_MASK_LEGAL(0x01, wanted, XkbXI_AllDeviceFeaturesMask);
6256f7df2e56Smrg
6257f7df2e56Smrg    if ((!dev->button) || ((stuff->nBtns < 1) && (!stuff->allBtns)))
6258f7df2e56Smrg        wanted &= ~XkbXI_ButtonActionsMask;
6259f7df2e56Smrg    if ((!dev->kbdfeed) && (!dev->leds))
6260f7df2e56Smrg        wanted &= ~XkbXI_IndicatorsMask;
6261f7df2e56Smrg
6262f7df2e56Smrg    nameLen = XkbSizeCountedString(dev->name);
6263f7df2e56Smrg    rep = (xkbGetDeviceInfoReply) {
6264f7df2e56Smrg        .type = X_Reply,
6265f7df2e56Smrg        .deviceID = dev->id,
6266f7df2e56Smrg        .sequenceNumber = client->sequence,
6267f7df2e56Smrg        .length = nameLen / 4,
6268f7df2e56Smrg        .present = wanted,
6269f7df2e56Smrg        .supported = XkbXI_AllDeviceFeaturesMask,
6270f7df2e56Smrg        .unsupported = 0,
6271f7df2e56Smrg        .nDeviceLedFBs = 0,
6272f7df2e56Smrg        .firstBtnWanted = 0,
6273f7df2e56Smrg        .nBtnsWanted = 0,
6274f7df2e56Smrg        .firstBtnRtrn = 0,
6275f7df2e56Smrg        .nBtnsRtrn = 0,
6276f7df2e56Smrg        .totalBtns = dev->button ? dev->button->numButtons : 0,
6277f7df2e56Smrg        .hasOwnState = (dev->key && dev->key->xkbInfo),
6278f7df2e56Smrg        .dfltKbdFB = dev->kbdfeed ? dev->kbdfeed->ctrl.id : XkbXINone,
6279f7df2e56Smrg        .dfltLedFB = dev->leds ? dev->leds->ctrl.id : XkbXINone,
6280f7df2e56Smrg        .devType = dev->xinput_type
6281f7df2e56Smrg    };
6282f7df2e56Smrg
6283f7df2e56Smrg    ledClass = stuff->ledClass;
6284f7df2e56Smrg    ledID = stuff->ledID;
6285f7df2e56Smrg
6286f7df2e56Smrg    if (wanted & XkbXI_ButtonActionsMask) {
6287f7df2e56Smrg        if (stuff->allBtns) {
6288f7df2e56Smrg            stuff->firstBtn = 0;
6289f7df2e56Smrg            stuff->nBtns = dev->button->numButtons;
6290f7df2e56Smrg        }
629105b261ecSmrg
6292f7df2e56Smrg        if ((stuff->firstBtn + stuff->nBtns) > dev->button->numButtons) {
6293f7df2e56Smrg            client->errorValue = _XkbErrCode4(0x02, dev->button->numButtons,
6294f7df2e56Smrg                                              stuff->firstBtn, stuff->nBtns);
6295f7df2e56Smrg            return BadValue;
6296f7df2e56Smrg        }
6297f7df2e56Smrg        else {
6298f7df2e56Smrg            rep.firstBtnWanted = stuff->firstBtn;
6299f7df2e56Smrg            rep.nBtnsWanted = stuff->nBtns;
6300f7df2e56Smrg            if (dev->button->xkb_acts != NULL) {
6301f7df2e56Smrg                XkbAction *act;
6302f7df2e56Smrg                register int i;
6303f7df2e56Smrg
6304f7df2e56Smrg                rep.firstBtnRtrn = stuff->firstBtn;
6305f7df2e56Smrg                rep.nBtnsRtrn = stuff->nBtns;
6306f7df2e56Smrg                act = &dev->button->xkb_acts[rep.firstBtnWanted];
6307f7df2e56Smrg                for (i = 0; i < rep.nBtnsRtrn; i++, act++) {
6308f7df2e56Smrg                    if (act->type != XkbSA_NoAction)
6309f7df2e56Smrg                        break;
6310f7df2e56Smrg                }
6311f7df2e56Smrg                rep.firstBtnRtrn += i;
6312f7df2e56Smrg                rep.nBtnsRtrn -= i;
6313f7df2e56Smrg                act =
6314f7df2e56Smrg                    &dev->button->xkb_acts[rep.firstBtnRtrn + rep.nBtnsRtrn -
6315f7df2e56Smrg                                           1];
6316f7df2e56Smrg                for (i = 0; i < rep.nBtnsRtrn; i++, act--) {
6317f7df2e56Smrg                    if (act->type != XkbSA_NoAction)
6318f7df2e56Smrg                        break;
6319f7df2e56Smrg                }
6320f7df2e56Smrg                rep.nBtnsRtrn -= i;
6321f7df2e56Smrg            }
6322f7df2e56Smrg            rep.length += (rep.nBtnsRtrn * SIZEOF(xkbActionWireDesc)) / 4;
6323f7df2e56Smrg        }
6324f7df2e56Smrg    }
632505b261ecSmrg
6326f7df2e56Smrg    if (wanted & XkbXI_IndicatorsMask) {
6327f7df2e56Smrg        status = CheckDeviceLedFBs(dev, ledClass, ledID, &rep, client);
6328f7df2e56Smrg        if (status != Success)
6329f7df2e56Smrg            return status;
6330f7df2e56Smrg    }
6331f7df2e56Smrg    length = rep.length * 4;
633205b261ecSmrg    nDeviceLedFBs = rep.nDeviceLedFBs;
633305b261ecSmrg    if (client->swapped) {
6334f7df2e56Smrg        swaps(&rep.sequenceNumber);
6335f7df2e56Smrg        swapl(&rep.length);
6336f7df2e56Smrg        swaps(&rep.present);
6337f7df2e56Smrg        swaps(&rep.supported);
6338f7df2e56Smrg        swaps(&rep.unsupported);
6339f7df2e56Smrg        swaps(&rep.nDeviceLedFBs);
6340f7df2e56Smrg        swaps(&rep.dfltKbdFB);
6341f7df2e56Smrg        swaps(&rep.dfltLedFB);
6342f7df2e56Smrg        swapl(&rep.devType);
6343f7df2e56Smrg    }
6344f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetDeviceInfoReply), &rep);
6345f7df2e56Smrg
6346f7df2e56Smrg    str = malloc(nameLen);
6347f7df2e56Smrg    if (!str)
6348f7df2e56Smrg        return BadAlloc;
6349f7df2e56Smrg    XkbWriteCountedString(str, dev->name, client->swapped);
6350f7df2e56Smrg    WriteToClient(client, nameLen, str);
63516747b715Smrg    free(str);
6352f7df2e56Smrg    length -= nameLen;
6353f7df2e56Smrg
6354f7df2e56Smrg    if (rep.nBtnsRtrn > 0) {
6355f7df2e56Smrg        int sz;
6356f7df2e56Smrg        xkbActionWireDesc *awire;
6357f7df2e56Smrg
6358f7df2e56Smrg        sz = rep.nBtnsRtrn * SIZEOF(xkbActionWireDesc);
6359f7df2e56Smrg        awire = (xkbActionWireDesc *) &dev->button->xkb_acts[rep.firstBtnRtrn];
6360f7df2e56Smrg        WriteToClient(client, sz, awire);
6361f7df2e56Smrg        length -= sz;
6362f7df2e56Smrg    }
6363f7df2e56Smrg    if (nDeviceLedFBs > 0) {
6364f7df2e56Smrg        status = SendDeviceLedFBs(dev, ledClass, ledID, length, client);
6365f7df2e56Smrg        if (status != Success)
6366f7df2e56Smrg            return status;
6367f7df2e56Smrg    }
6368f7df2e56Smrg    else if (length != 0) {
6369f7df2e56Smrg        ErrorF("[xkb] Internal Error!  BadLength in ProcXkbGetDeviceInfo\n");
6370f7df2e56Smrg        ErrorF("[xkb]                  Wrote %d fewer bytes than expected\n",
6371f7df2e56Smrg               length);
6372f7df2e56Smrg        return BadLength;
637305b261ecSmrg    }
63746747b715Smrg    return Success;
637505b261ecSmrg}
637605b261ecSmrg
637705b261ecSmrgstatic char *
6378f7df2e56SmrgCheckSetDeviceIndicators(char *wire,
6379f7df2e56Smrg                         DeviceIntPtr dev,
6380f7df2e56Smrg                         int num, int *status_rtrn, ClientPtr client)
638105b261ecSmrg{
6382f7df2e56Smrg    xkbDeviceLedsWireDesc *ledWire;
6383f7df2e56Smrg    int i;
6384f7df2e56Smrg    XkbSrvLedInfoPtr sli;
6385f7df2e56Smrg
6386f7df2e56Smrg    ledWire = (xkbDeviceLedsWireDesc *) wire;
6387f7df2e56Smrg    for (i = 0; i < num; i++) {
6388f7df2e56Smrg        if (client->swapped) {
6389f7df2e56Smrg            swaps(&ledWire->ledClass);
6390f7df2e56Smrg            swaps(&ledWire->ledID);
6391f7df2e56Smrg            swapl(&ledWire->namesPresent);
6392f7df2e56Smrg            swapl(&ledWire->mapsPresent);
6393f7df2e56Smrg            swapl(&ledWire->physIndicators);
6394f7df2e56Smrg        }
6395f7df2e56Smrg
6396f7df2e56Smrg        sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID,
6397f7df2e56Smrg                                XkbXI_IndicatorsMask);
6398f7df2e56Smrg        if (sli != NULL) {
6399f7df2e56Smrg            register int n;
6400f7df2e56Smrg            register unsigned bit;
6401f7df2e56Smrg            int nMaps, nNames;
6402f7df2e56Smrg            CARD32 *atomWire;
6403f7df2e56Smrg            xkbIndicatorMapWireDesc *mapWire;
6404f7df2e56Smrg
6405f7df2e56Smrg            nMaps = nNames = 0;
6406f7df2e56Smrg            for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6407f7df2e56Smrg                if (ledWire->namesPresent & bit)
6408f7df2e56Smrg                    nNames++;
6409f7df2e56Smrg                if (ledWire->mapsPresent & bit)
6410f7df2e56Smrg                    nMaps++;
6411f7df2e56Smrg            }
6412f7df2e56Smrg            atomWire = (CARD32 *) &ledWire[1];
6413f7df2e56Smrg            if (nNames > 0) {
6414f7df2e56Smrg                for (n = 0; n < nNames; n++) {
6415f7df2e56Smrg                    if (client->swapped) {
6416f7df2e56Smrg                        swapl(atomWire);
6417f7df2e56Smrg                    }
6418f7df2e56Smrg                    CHK_ATOM_OR_NONE3(((Atom) (*atomWire)), client->errorValue,
6419f7df2e56Smrg                                      *status_rtrn, NULL);
6420f7df2e56Smrg                    atomWire++;
6421f7df2e56Smrg                }
6422f7df2e56Smrg            }
6423f7df2e56Smrg            mapWire = (xkbIndicatorMapWireDesc *) atomWire;
6424f7df2e56Smrg            if (nMaps > 0) {
6425f7df2e56Smrg                for (n = 0; n < nMaps; n++) {
6426f7df2e56Smrg                    if (client->swapped) {
6427f7df2e56Smrg                        swaps(&mapWire->virtualMods);
6428f7df2e56Smrg                        swapl(&mapWire->ctrls);
6429f7df2e56Smrg                    }
6430f7df2e56Smrg                    CHK_MASK_LEGAL3(0x21, mapWire->whichGroups,
6431f7df2e56Smrg                                    XkbIM_UseAnyGroup,
6432f7df2e56Smrg                                    client->errorValue, *status_rtrn, NULL);
6433f7df2e56Smrg                    CHK_MASK_LEGAL3(0x22, mapWire->whichMods, XkbIM_UseAnyMods,
6434f7df2e56Smrg                                    client->errorValue, *status_rtrn, NULL);
6435f7df2e56Smrg                    mapWire++;
6436f7df2e56Smrg                }
6437f7df2e56Smrg            }
6438f7df2e56Smrg            ledWire = (xkbDeviceLedsWireDesc *) mapWire;
6439f7df2e56Smrg        }
6440f7df2e56Smrg        else {
6441f7df2e56Smrg            /* SHOULD NEVER HAPPEN */
6442f7df2e56Smrg            return (char *) ledWire;
6443f7df2e56Smrg        }
6444f7df2e56Smrg    }
6445f7df2e56Smrg    return (char *) ledWire;
644605b261ecSmrg}
644705b261ecSmrg
644805b261ecSmrgstatic char *
6449f7df2e56SmrgSetDeviceIndicators(char *wire,
6450f7df2e56Smrg                    DeviceIntPtr dev,
6451f7df2e56Smrg                    unsigned changed,
6452f7df2e56Smrg                    int num,
6453f7df2e56Smrg                    int *status_rtrn,
6454f7df2e56Smrg                    ClientPtr client, xkbExtensionDeviceNotify * ev)
645505b261ecSmrg{
6456f7df2e56Smrg    xkbDeviceLedsWireDesc *ledWire;
6457f7df2e56Smrg    int i;
6458f7df2e56Smrg    XkbEventCauseRec cause;
6459f7df2e56Smrg    unsigned namec, mapc, statec;
6460f7df2e56Smrg    xkbExtensionDeviceNotify ed;
6461f7df2e56Smrg    XkbChangesRec changes;
6462f7df2e56Smrg    DeviceIntPtr kbd;
6463f7df2e56Smrg
6464f7df2e56Smrg    memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify));
6465f7df2e56Smrg    memset((char *) &changes, 0, sizeof(XkbChangesRec));
6466f7df2e56Smrg    XkbSetCauseXkbReq(&cause, X_kbSetDeviceInfo, client);
6467f7df2e56Smrg    ledWire = (xkbDeviceLedsWireDesc *) wire;
6468f7df2e56Smrg    for (i = 0; i < num; i++) {
6469f7df2e56Smrg        register int n;
6470f7df2e56Smrg        register unsigned bit;
6471f7df2e56Smrg        CARD32 *atomWire;
6472f7df2e56Smrg        xkbIndicatorMapWireDesc *mapWire;
6473f7df2e56Smrg        XkbSrvLedInfoPtr sli;
6474f7df2e56Smrg
6475f7df2e56Smrg        namec = mapc = statec = 0;
6476f7df2e56Smrg        sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID,
6477f7df2e56Smrg                                XkbXI_IndicatorMapsMask);
6478f7df2e56Smrg        if (!sli) {
6479f7df2e56Smrg            /* SHOULD NEVER HAPPEN!! */
6480f7df2e56Smrg            return (char *) ledWire;
6481f7df2e56Smrg        }
648205b261ecSmrg
6483f7df2e56Smrg        atomWire = (CARD32 *) &ledWire[1];
6484f7df2e56Smrg        if (changed & XkbXI_IndicatorNamesMask) {
6485f7df2e56Smrg            namec = sli->namesPresent | ledWire->namesPresent;
6486f7df2e56Smrg            memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom));
6487f7df2e56Smrg        }
6488f7df2e56Smrg        if (ledWire->namesPresent) {
6489f7df2e56Smrg            sli->namesPresent = ledWire->namesPresent;
6490f7df2e56Smrg            memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom));
6491f7df2e56Smrg            for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6492f7df2e56Smrg                if (ledWire->namesPresent & bit) {
6493f7df2e56Smrg                    sli->names[n] = (Atom) *atomWire;
6494f7df2e56Smrg                    if (sli->names[n] == None)
6495f7df2e56Smrg                        ledWire->namesPresent &= ~bit;
6496f7df2e56Smrg                    atomWire++;
6497f7df2e56Smrg                }
6498f7df2e56Smrg            }
6499f7df2e56Smrg        }
6500f7df2e56Smrg        mapWire = (xkbIndicatorMapWireDesc *) atomWire;
6501f7df2e56Smrg        if (changed & XkbXI_IndicatorMapsMask) {
6502f7df2e56Smrg            mapc = sli->mapsPresent | ledWire->mapsPresent;
6503f7df2e56Smrg            sli->mapsPresent = ledWire->mapsPresent;
6504f7df2e56Smrg            memset((char *) sli->maps, 0,
6505f7df2e56Smrg                   XkbNumIndicators * sizeof(XkbIndicatorMapRec));
6506f7df2e56Smrg        }
6507f7df2e56Smrg        if (ledWire->mapsPresent) {
6508f7df2e56Smrg            for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6509f7df2e56Smrg                if (ledWire->mapsPresent & bit) {
6510f7df2e56Smrg                    sli->maps[n].flags = mapWire->flags;
6511f7df2e56Smrg                    sli->maps[n].which_groups = mapWire->whichGroups;
6512f7df2e56Smrg                    sli->maps[n].groups = mapWire->groups;
6513f7df2e56Smrg                    sli->maps[n].which_mods = mapWire->whichMods;
6514f7df2e56Smrg                    sli->maps[n].mods.mask = mapWire->mods;
6515f7df2e56Smrg                    sli->maps[n].mods.real_mods = mapWire->realMods;
6516f7df2e56Smrg                    sli->maps[n].mods.vmods = mapWire->virtualMods;
6517f7df2e56Smrg                    sli->maps[n].ctrls = mapWire->ctrls;
6518f7df2e56Smrg                    mapWire++;
6519f7df2e56Smrg                }
6520f7df2e56Smrg            }
6521f7df2e56Smrg        }
6522f7df2e56Smrg        if (changed & XkbXI_IndicatorStateMask) {
6523f7df2e56Smrg            statec = sli->effectiveState ^ ledWire->state;
6524f7df2e56Smrg            sli->explicitState &= ~statec;
6525f7df2e56Smrg            sli->explicitState |= (ledWire->state & statec);
6526f7df2e56Smrg        }
6527f7df2e56Smrg        if (namec)
6528f7df2e56Smrg            XkbApplyLedNameChanges(dev, sli, namec, &ed, &changes, &cause);
6529f7df2e56Smrg        if (mapc)
6530f7df2e56Smrg            XkbApplyLedMapChanges(dev, sli, mapc, &ed, &changes, &cause);
6531f7df2e56Smrg        if (statec)
6532f7df2e56Smrg            XkbApplyLedStateChanges(dev, sli, statec, &ed, &changes, &cause);
6533f7df2e56Smrg
6534f7df2e56Smrg        kbd = dev;
6535f7df2e56Smrg        if ((sli->flags & XkbSLI_HasOwnState) == 0)
6536f7df2e56Smrg            kbd = inputInfo.keyboard;
6537f7df2e56Smrg
6538f7df2e56Smrg        XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause);
6539f7df2e56Smrg        ledWire = (xkbDeviceLedsWireDesc *) mapWire;
6540f7df2e56Smrg    }
6541f7df2e56Smrg    return (char *) ledWire;
6542f7df2e56Smrg}
654305b261ecSmrg
65444642e01fSmrgstatic int
65454642e01fSmrg_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev,
6546f7df2e56Smrg                  xkbSetDeviceInfoReq * stuff)
65474642e01fSmrg{
6548f7df2e56Smrg    char *wire;
6549f7df2e56Smrg
6550f7df2e56Smrg    wire = (char *) &stuff[1];
6551f7df2e56Smrg    if (stuff->change & XkbXI_ButtonActionsMask) {
6552f7df2e56Smrg        if (!dev->button) {
6553f7df2e56Smrg            client->errorValue = _XkbErrCode2(XkbErr_BadClass, ButtonClass);
6554f7df2e56Smrg            return XkbKeyboardErrorCode;
6555f7df2e56Smrg        }
6556f7df2e56Smrg        if ((stuff->firstBtn + stuff->nBtns) > dev->button->numButtons) {
6557f7df2e56Smrg            client->errorValue =
6558f7df2e56Smrg                _XkbErrCode4(0x02, stuff->firstBtn, stuff->nBtns,
6559f7df2e56Smrg                             dev->button->numButtons);
6560f7df2e56Smrg            return BadMatch;
6561f7df2e56Smrg        }
6562f7df2e56Smrg        wire += (stuff->nBtns * SIZEOF(xkbActionWireDesc));
6563f7df2e56Smrg    }
6564f7df2e56Smrg    if (stuff->change & XkbXI_IndicatorsMask) {
6565f7df2e56Smrg        int status = Success;
6566f7df2e56Smrg
6567f7df2e56Smrg        wire = CheckSetDeviceIndicators(wire, dev, stuff->nDeviceLedFBs,
6568f7df2e56Smrg                                        &status, client);
6569f7df2e56Smrg        if (status != Success)
6570f7df2e56Smrg            return status;
6571f7df2e56Smrg    }
6572f7df2e56Smrg    if (((wire - ((char *) stuff)) / 4) != stuff->length)
6573f7df2e56Smrg        return BadLength;
657405b261ecSmrg
65754642e01fSmrg    return Success;
65764642e01fSmrg}
65774642e01fSmrg
65784642e01fSmrgstatic int
65794642e01fSmrg_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev,
6580f7df2e56Smrg                       xkbSetDeviceInfoReq * stuff)
65814642e01fSmrg{
6582f7df2e56Smrg    char *wire;
6583f7df2e56Smrg    xkbExtensionDeviceNotify ed;
6584f7df2e56Smrg
6585f7df2e56Smrg    memset((char *) &ed, 0, SIZEOF(xkbExtensionDeviceNotify));
6586f7df2e56Smrg    ed.deviceID = dev->id;
6587f7df2e56Smrg    wire = (char *) &stuff[1];
6588f7df2e56Smrg    if (stuff->change & XkbXI_ButtonActionsMask) {
6589f7df2e56Smrg        int nBtns, sz, i;
6590f7df2e56Smrg        XkbAction *acts;
6591f7df2e56Smrg        DeviceIntPtr kbd;
6592f7df2e56Smrg
6593f7df2e56Smrg        nBtns = dev->button->numButtons;
6594f7df2e56Smrg        acts = dev->button->xkb_acts;
6595f7df2e56Smrg        if (acts == NULL) {
6596f7df2e56Smrg            acts = calloc(nBtns, sizeof(XkbAction));
6597f7df2e56Smrg            if (!acts)
6598f7df2e56Smrg                return BadAlloc;
6599f7df2e56Smrg            dev->button->xkb_acts = acts;
6600f7df2e56Smrg        }
6601f7df2e56Smrg        sz = stuff->nBtns * SIZEOF(xkbActionWireDesc);
6602f7df2e56Smrg        memcpy((char *) &acts[stuff->firstBtn], (char *) wire, sz);
6603f7df2e56Smrg        wire += sz;
6604f7df2e56Smrg        ed.reason |= XkbXI_ButtonActionsMask;
6605f7df2e56Smrg        ed.firstBtn = stuff->firstBtn;
6606f7df2e56Smrg        ed.nBtns = stuff->nBtns;
6607f7df2e56Smrg
6608f7df2e56Smrg        if (dev->key)
6609f7df2e56Smrg            kbd = dev;
6610f7df2e56Smrg        else
6611f7df2e56Smrg            kbd = inputInfo.keyboard;
6612f7df2e56Smrg        acts = &dev->button->xkb_acts[stuff->firstBtn];
6613f7df2e56Smrg        for (i = 0; i < stuff->nBtns; i++, acts++) {
6614f7df2e56Smrg            if (acts->type != XkbSA_NoAction)
6615f7df2e56Smrg                XkbSetActionKeyMods(kbd->key->xkbInfo->desc, acts, 0);
6616f7df2e56Smrg        }
6617f7df2e56Smrg    }
6618f7df2e56Smrg    if (stuff->change & XkbXI_IndicatorsMask) {
6619f7df2e56Smrg        int status = Success;
6620f7df2e56Smrg
6621f7df2e56Smrg        wire = SetDeviceIndicators(wire, dev, stuff->change,
6622f7df2e56Smrg                                   stuff->nDeviceLedFBs, &status, client, &ed);
6623f7df2e56Smrg        if (status != Success)
6624f7df2e56Smrg            return status;
6625f7df2e56Smrg    }
6626f7df2e56Smrg    if ((stuff->change) && (ed.reason))
6627f7df2e56Smrg        XkbSendExtensionDeviceNotify(dev, client, &ed);
66284642e01fSmrg    return Success;
66294642e01fSmrg}
66304642e01fSmrg
66314642e01fSmrgint
66324642e01fSmrgProcXkbSetDeviceInfo(ClientPtr client)
66334642e01fSmrg{
6634f7df2e56Smrg    DeviceIntPtr dev;
6635f7df2e56Smrg    int rc;
66364642e01fSmrg
66374642e01fSmrg    REQUEST(xkbSetDeviceInfoReq);
66384642e01fSmrg    REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq);
66394642e01fSmrg
6640f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
6641f7df2e56Smrg        return BadAccess;
66424642e01fSmrg
66434642e01fSmrg    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
6644f7df2e56Smrg    CHK_MASK_LEGAL(0x01, stuff->change, XkbXI_AllFeaturesMask);
66454642e01fSmrg
66464642e01fSmrg    rc = _XkbSetDeviceInfoCheck(client, dev, stuff);
66474642e01fSmrg
66484642e01fSmrg    if (rc != Success)
66494642e01fSmrg        return rc;
66504642e01fSmrg
6651f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd ||
6652f7df2e56Smrg        stuff->deviceSpec == XkbUseCorePtr) {
66534642e01fSmrg        DeviceIntPtr other;
6654f7df2e56Smrg
6655f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
6656f7df2e56Smrg            if (((other != dev) && !IsMaster(other) &&
6657f7df2e56Smrg                 GetMaster(other, MASTER_KEYBOARD) == dev) &&
66584642e01fSmrg                ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
6659f7df2e56Smrg                 (stuff->deviceSpec == XkbUseCorePtr && other->button))) {
6660f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
6661f7df2e56Smrg                              DixManageAccess);
6662f7df2e56Smrg                if (rc == Success) {
66634642e01fSmrg                    rc = _XkbSetDeviceInfoCheck(client, other, stuff);
66644642e01fSmrg                    if (rc != Success)
66654642e01fSmrg                        return rc;
66664642e01fSmrg                }
66674642e01fSmrg            }
66684642e01fSmrg        }
66694642e01fSmrg    }
66704642e01fSmrg
66714642e01fSmrg    /* checks done, apply */
66724642e01fSmrg    rc = _XkbSetDeviceInfo(client, dev, stuff);
66734642e01fSmrg    if (rc != Success)
66744642e01fSmrg        return rc;
66754642e01fSmrg
6676f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd ||
6677f7df2e56Smrg        stuff->deviceSpec == XkbUseCorePtr) {
66784642e01fSmrg        DeviceIntPtr other;
6679f7df2e56Smrg
6680f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
6681f7df2e56Smrg            if (((other != dev) && !IsMaster(other) &&
6682f7df2e56Smrg                 GetMaster(other, MASTER_KEYBOARD) == dev) &&
66834642e01fSmrg                ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
6684f7df2e56Smrg                 (stuff->deviceSpec == XkbUseCorePtr && other->button))) {
6685f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
6686f7df2e56Smrg                              DixManageAccess);
6687f7df2e56Smrg                if (rc == Success) {
66884642e01fSmrg                    rc = _XkbSetDeviceInfo(client, other, stuff);
66894642e01fSmrg                    if (rc != Success)
66904642e01fSmrg                        return rc;
66914642e01fSmrg                }
66924642e01fSmrg            }
66934642e01fSmrg        }
66944642e01fSmrg    }
66954642e01fSmrg
66966747b715Smrg    return Success;
669705b261ecSmrg}
669805b261ecSmrg
669905b261ecSmrg/***====================================================================***/
670005b261ecSmrg
670105b261ecSmrgint
670205b261ecSmrgProcXkbSetDebuggingFlags(ClientPtr client)
670305b261ecSmrg{
6704f7df2e56Smrg    CARD32 newFlags, newCtrls, extraLength;
6705f7df2e56Smrg    xkbSetDebuggingFlagsReply rep;
6706f7df2e56Smrg    int rc;
670705b261ecSmrg
670805b261ecSmrg    REQUEST(xkbSetDebuggingFlagsReq);
670905b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq);
671005b261ecSmrg
67114642e01fSmrg    rc = XaceHook(XACE_SERVER_ACCESS, client, DixDebugAccess);
67124642e01fSmrg    if (rc != Success)
6713f7df2e56Smrg        return rc;
67144642e01fSmrg
6715f7df2e56Smrg    newFlags = xkbDebugFlags & (~stuff->affectFlags);
6716f7df2e56Smrg    newFlags |= (stuff->flags & stuff->affectFlags);
6717f7df2e56Smrg    newCtrls = xkbDebugCtrls & (~stuff->affectCtrls);
6718f7df2e56Smrg    newCtrls |= (stuff->ctrls & stuff->affectCtrls);
671905b261ecSmrg    if (xkbDebugFlags || newFlags || stuff->msgLength) {
6720f7df2e56Smrg        ErrorF("[xkb] XkbDebug: Setting debug flags to 0x%lx\n",
6721f7df2e56Smrg               (long) newFlags);
6722f7df2e56Smrg        if (newCtrls != xkbDebugCtrls)
6723f7df2e56Smrg            ErrorF("[xkb] XkbDebug: Setting debug controls to 0x%lx\n",
6724f7df2e56Smrg                   (long) newCtrls);
6725f7df2e56Smrg    }
6726f7df2e56Smrg    extraLength = (stuff->length << 2) - sz_xkbSetDebuggingFlagsReq;
6727f7df2e56Smrg    if (stuff->msgLength > 0) {
6728f7df2e56Smrg        char *msg;
6729f7df2e56Smrg
6730f7df2e56Smrg        if (extraLength < XkbPaddedSize(stuff->msgLength)) {
6731f7df2e56Smrg            ErrorF
6732f7df2e56Smrg                ("[xkb] XkbDebug: msgLength= %d, length= %ld (should be %d)\n",
6733f7df2e56Smrg                 stuff->msgLength, (long) extraLength,
6734f7df2e56Smrg                 XkbPaddedSize(stuff->msgLength));
6735f7df2e56Smrg            return BadLength;
6736f7df2e56Smrg        }
6737f7df2e56Smrg        msg = (char *) &stuff[1];
6738f7df2e56Smrg        if (msg[stuff->msgLength - 1] != '\0') {
6739f7df2e56Smrg            ErrorF("[xkb] XkbDebug: message not null-terminated\n");
6740f7df2e56Smrg            return BadValue;
6741f7df2e56Smrg        }
6742f7df2e56Smrg        ErrorF("[xkb] XkbDebug: %s\n", msg);
674305b261ecSmrg    }
674405b261ecSmrg    xkbDebugFlags = newFlags;
674505b261ecSmrg    xkbDebugCtrls = newCtrls;
674605b261ecSmrg
6747f7df2e56Smrg    rep = (xkbSetDebuggingFlagsReply) {
6748f7df2e56Smrg        .type = X_Reply,
6749f7df2e56Smrg        .sequenceNumber = client->sequence,
6750f7df2e56Smrg        .length = 0,
6751f7df2e56Smrg        .currentFlags = newFlags,
6752f7df2e56Smrg        .currentCtrls = newCtrls,
6753f7df2e56Smrg        .supportedFlags = ~0,
6754f7df2e56Smrg        .supportedCtrls = ~0
6755f7df2e56Smrg    };
6756f7df2e56Smrg    if (client->swapped) {
6757f7df2e56Smrg        swaps(&rep.sequenceNumber);
6758f7df2e56Smrg        swapl(&rep.currentFlags);
6759f7df2e56Smrg        swapl(&rep.currentCtrls);
6760f7df2e56Smrg        swapl(&rep.supportedFlags);
6761f7df2e56Smrg        swapl(&rep.supportedCtrls);
6762f7df2e56Smrg    }
6763f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbSetDebuggingFlagsReply), &rep);
67646747b715Smrg    return Success;
676505b261ecSmrg}
676605b261ecSmrg
676705b261ecSmrg/***====================================================================***/
676805b261ecSmrg
676905b261ecSmrgstatic int
6770f7df2e56SmrgProcXkbDispatch(ClientPtr client)
677105b261ecSmrg{
677205b261ecSmrg    REQUEST(xReq);
6773f7df2e56Smrg    switch (stuff->data) {
677405b261ecSmrg    case X_kbUseExtension:
6775f7df2e56Smrg        return ProcXkbUseExtension(client);
677605b261ecSmrg    case X_kbSelectEvents:
6777f7df2e56Smrg        return ProcXkbSelectEvents(client);
677805b261ecSmrg    case X_kbBell:
6779f7df2e56Smrg        return ProcXkbBell(client);
678005b261ecSmrg    case X_kbGetState:
6781f7df2e56Smrg        return ProcXkbGetState(client);
678205b261ecSmrg    case X_kbLatchLockState:
6783f7df2e56Smrg        return ProcXkbLatchLockState(client);
678405b261ecSmrg    case X_kbGetControls:
6785f7df2e56Smrg        return ProcXkbGetControls(client);
678605b261ecSmrg    case X_kbSetControls:
6787f7df2e56Smrg        return ProcXkbSetControls(client);
678805b261ecSmrg    case X_kbGetMap:
6789f7df2e56Smrg        return ProcXkbGetMap(client);
679005b261ecSmrg    case X_kbSetMap:
6791f7df2e56Smrg        return ProcXkbSetMap(client);
679205b261ecSmrg    case X_kbGetCompatMap:
6793f7df2e56Smrg        return ProcXkbGetCompatMap(client);
679405b261ecSmrg    case X_kbSetCompatMap:
6795f7df2e56Smrg        return ProcXkbSetCompatMap(client);
679605b261ecSmrg    case X_kbGetIndicatorState:
6797f7df2e56Smrg        return ProcXkbGetIndicatorState(client);
679805b261ecSmrg    case X_kbGetIndicatorMap:
6799f7df2e56Smrg        return ProcXkbGetIndicatorMap(client);
680005b261ecSmrg    case X_kbSetIndicatorMap:
6801f7df2e56Smrg        return ProcXkbSetIndicatorMap(client);
680205b261ecSmrg    case X_kbGetNamedIndicator:
6803f7df2e56Smrg        return ProcXkbGetNamedIndicator(client);
680405b261ecSmrg    case X_kbSetNamedIndicator:
6805f7df2e56Smrg        return ProcXkbSetNamedIndicator(client);
680605b261ecSmrg    case X_kbGetNames:
6807f7df2e56Smrg        return ProcXkbGetNames(client);
680805b261ecSmrg    case X_kbSetNames:
6809f7df2e56Smrg        return ProcXkbSetNames(client);
681005b261ecSmrg    case X_kbGetGeometry:
6811f7df2e56Smrg        return ProcXkbGetGeometry(client);
681205b261ecSmrg    case X_kbSetGeometry:
6813f7df2e56Smrg        return ProcXkbSetGeometry(client);
681405b261ecSmrg    case X_kbPerClientFlags:
6815f7df2e56Smrg        return ProcXkbPerClientFlags(client);
681605b261ecSmrg    case X_kbListComponents:
6817f7df2e56Smrg        return ProcXkbListComponents(client);
681805b261ecSmrg    case X_kbGetKbdByName:
6819f7df2e56Smrg        return ProcXkbGetKbdByName(client);
682005b261ecSmrg    case X_kbGetDeviceInfo:
6821f7df2e56Smrg        return ProcXkbGetDeviceInfo(client);
682205b261ecSmrg    case X_kbSetDeviceInfo:
6823f7df2e56Smrg        return ProcXkbSetDeviceInfo(client);
682405b261ecSmrg    case X_kbSetDebuggingFlags:
6825f7df2e56Smrg        return ProcXkbSetDebuggingFlags(client);
682605b261ecSmrg    default:
6827f7df2e56Smrg        return BadRequest;
682805b261ecSmrg    }
682905b261ecSmrg}
683005b261ecSmrg
683105b261ecSmrgstatic int
6832f7df2e56SmrgXkbClientGone(void *data, XID id)
683305b261ecSmrg{
6834f7df2e56Smrg    DevicePtr pXDev = (DevicePtr) data;
683505b261ecSmrg
6836f7df2e56Smrg    if (!XkbRemoveResourceClient(pXDev, id)) {
6837f7df2e56Smrg        ErrorF
6838f7df2e56Smrg            ("[xkb] Internal Error! bad RemoveResourceClient in XkbClientGone\n");
683905b261ecSmrg    }
684005b261ecSmrg    return 1;
684105b261ecSmrg}
684205b261ecSmrg
684305b261ecSmrgvoid
684405b261ecSmrgXkbExtensionInit(void)
684505b261ecSmrg{
684605b261ecSmrg    ExtensionEntry *extEntry;
684705b261ecSmrg
68486747b715Smrg    RT_XKBCLIENT = CreateNewResourceType(XkbClientGone, "XkbClient");
68496747b715Smrg    if (!RT_XKBCLIENT)
6850f7df2e56Smrg        return;
68516747b715Smrg
68526747b715Smrg    if (!XkbInitPrivates())
6853f7df2e56Smrg        return;
68546747b715Smrg
685505b261ecSmrg    if ((extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors,
6856f7df2e56Smrg                                 ProcXkbDispatch, SProcXkbDispatch,
6857f7df2e56Smrg                                 NULL, StandardMinorOpcode))) {
6858f7df2e56Smrg        XkbReqCode = (unsigned char) extEntry->base;
6859f7df2e56Smrg        XkbEventBase = (unsigned char) extEntry->eventBase;
6860f7df2e56Smrg        XkbErrorBase = (unsigned char) extEntry->errorBase;
6861f7df2e56Smrg        XkbKeyboardErrorCode = XkbErrorBase + XkbKeyboard;
686205b261ecSmrg    }
686305b261ecSmrg    return;
686405b261ecSmrg}
6865