xkb.c revision 7e31ba66
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;
1757e31ba66Smrg        if (stuff->wantedMajor == 0)
1767e31ba66Smrg            client->xkbClientFlags |= _XkbClientIsAncient;
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)) {
23917e31ba66Smrg        if (client->xkbClientFlags & _XkbClientIsAncient) {
23927e31ba66Smrg            /* pre 1.0 versions of Xlib have a bug */
2393f7df2e56Smrg            req->minKeyCode = xkb->min_key_code;
2394f7df2e56Smrg            req->maxKeyCode = xkb->max_key_code;
2395f7df2e56Smrg        }
2396f7df2e56Smrg        else {
2397f7df2e56Smrg            if (!XkbIsLegalKeycode(req->minKeyCode)) {
2398f7df2e56Smrg                client->errorValue =
2399f7df2e56Smrg                    _XkbErrCode3(2, req->minKeyCode, req->maxKeyCode);
2400f7df2e56Smrg                return BadValue;
2401f7df2e56Smrg            }
2402f7df2e56Smrg            if (req->minKeyCode > req->maxKeyCode) {
2403f7df2e56Smrg                client->errorValue =
2404f7df2e56Smrg                    _XkbErrCode3(3, req->minKeyCode, req->maxKeyCode);
2405f7df2e56Smrg                return BadMatch;
2406f7df2e56Smrg            }
2407f7df2e56Smrg        }
240805b261ecSmrg    }
240905b261ecSmrg
24104642e01fSmrg    if ((req->present & XkbKeyTypesMask) &&
2411f7df2e56Smrg        (!CheckKeyTypes(client, xkb, req, (xkbKeyTypeWireDesc **) &values,
2412f7df2e56Smrg                        &nTypes, mapWidths))) {
2413f7df2e56Smrg        client->errorValue = nTypes;
2414f7df2e56Smrg        return BadValue;
241505b261ecSmrg    }
24169ace9065Smrg
24179ace9065Smrg    /* symsPerKey/mapWidths must be filled regardless of client-side flags */
24189ace9065Smrg    map = &xkb->map->key_sym_map[xkb->min_key_code];
2419f7df2e56Smrg    for (i = xkb->min_key_code; i < xkb->max_key_code; i++, map++) {
2420f7df2e56Smrg        register int g, ng, w;
2421f7df2e56Smrg
2422f7df2e56Smrg        ng = XkbNumGroups(map->group_info);
2423f7df2e56Smrg        for (w = g = 0; g < ng; g++) {
2424f7df2e56Smrg            if (map->kt_index[g] >= (unsigned) nTypes) {
2425f7df2e56Smrg                client->errorValue = _XkbErrCode4(0x13, i, g, map->kt_index[g]);
2426f7df2e56Smrg                return 0;
2427f7df2e56Smrg            }
2428f7df2e56Smrg            if (mapWidths[map->kt_index[g]] > w)
2429f7df2e56Smrg                w = mapWidths[map->kt_index[g]];
2430f7df2e56Smrg        }
2431f7df2e56Smrg        symsPerKey[i] = w * ng;
24329ace9065Smrg    }
24339ace9065Smrg
24344642e01fSmrg    if ((req->present & XkbKeySymsMask) &&
2435f7df2e56Smrg        (!CheckKeySyms(client, xkb, req, nTypes, mapWidths, symsPerKey,
2436f7df2e56Smrg                       (xkbSymMapWireDesc **) &values, &error))) {
2437f7df2e56Smrg        client->errorValue = error;
2438f7df2e56Smrg        return BadValue;
243905b261ecSmrg    }
244005b261ecSmrg
24414642e01fSmrg    if ((req->present & XkbKeyActionsMask) &&
2442f7df2e56Smrg        (!CheckKeyActions(xkb, req, nTypes, mapWidths, symsPerKey,
2443f7df2e56Smrg                          (CARD8 **) &values, &nActions))) {
2444f7df2e56Smrg        client->errorValue = nActions;
2445f7df2e56Smrg        return BadValue;
244605b261ecSmrg    }
244705b261ecSmrg
24484642e01fSmrg    if ((req->present & XkbKeyBehaviorsMask) &&
2449f7df2e56Smrg        (!CheckKeyBehaviors
2450f7df2e56Smrg         (xkb, req, (xkbBehaviorWireDesc **) &values, &error))) {
2451f7df2e56Smrg        client->errorValue = error;
2452f7df2e56Smrg        return BadValue;
245305b261ecSmrg    }
245405b261ecSmrg
24554642e01fSmrg    if ((req->present & XkbVirtualModsMask) &&
2456f7df2e56Smrg        (!CheckVirtualMods(xkb, req, (CARD8 **) &values, &error))) {
2457f7df2e56Smrg        client->errorValue = error;
2458f7df2e56Smrg        return BadValue;
245905b261ecSmrg    }
2460f7df2e56Smrg    if ((req->present & XkbExplicitComponentsMask) &&
2461f7df2e56Smrg        (!CheckKeyExplicit(xkb, req, (CARD8 **) &values, &error))) {
2462f7df2e56Smrg        client->errorValue = error;
2463f7df2e56Smrg        return BadValue;
246405b261ecSmrg    }
2465f7df2e56Smrg    if ((req->present & XkbModifierMapMask) &&
2466f7df2e56Smrg        (!CheckModifierMap(xkb, req, (CARD8 **) &values, &error))) {
2467f7df2e56Smrg        client->errorValue = error;
2468f7df2e56Smrg        return BadValue;
246905b261ecSmrg    }
2470f7df2e56Smrg    if ((req->present & XkbVirtualModMapMask) &&
2471f7df2e56Smrg        (!CheckVirtualModMap
2472f7df2e56Smrg         (xkb, req, (xkbVModMapWireDesc **) &values, &error))) {
2473f7df2e56Smrg        client->errorValue = error;
2474f7df2e56Smrg        return BadValue;
247505b261ecSmrg    }
24764642e01fSmrg
2477f7df2e56Smrg    if (((values - ((char *) req)) / 4) != req->length) {
2478f7df2e56Smrg        ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after check)\n");
2479f7df2e56Smrg        client->errorValue = values - ((char *) &req[1]);
2480f7df2e56Smrg        return BadLength;
248105b261ecSmrg    }
24824642e01fSmrg
24834642e01fSmrg    return Success;
24844642e01fSmrg}
24854642e01fSmrg
24864642e01fSmrg/**
24874642e01fSmrg * Apply the given request on the given device.
24884642e01fSmrg */
24894642e01fSmrgstatic int
2490f7df2e56Smrg_XkbSetMap(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq * req, char *values)
24914642e01fSmrg{
2492f7df2e56Smrg    XkbEventCauseRec cause;
2493f7df2e56Smrg    XkbChangesRec change;
2494f7df2e56Smrg    Bool sentNKN;
2495f7df2e56Smrg    XkbSrvInfoPtr xkbi;
2496f7df2e56Smrg    XkbDescPtr xkb;
24974642e01fSmrg
2498f7df2e56Smrg    xkbi = dev->key->xkbInfo;
24994642e01fSmrg    xkb = xkbi->desc;
25004642e01fSmrg
2501f7df2e56Smrg    XkbSetCauseXkbReq(&cause, X_kbSetMap, client);
25026747b715Smrg    memset(&change, 0, sizeof(change));
25036747b715Smrg    sentNKN = FALSE;
2504f7df2e56Smrg    if ((xkb->min_key_code != req->minKeyCode) ||
2505f7df2e56Smrg        (xkb->max_key_code != req->maxKeyCode)) {
2506f7df2e56Smrg        Status status;
2507f7df2e56Smrg        xkbNewKeyboardNotify nkn;
2508f7df2e56Smrg
2509f7df2e56Smrg        nkn.deviceID = nkn.oldDeviceID = dev->id;
2510f7df2e56Smrg        nkn.oldMinKeyCode = xkb->min_key_code;
2511f7df2e56Smrg        nkn.oldMaxKeyCode = xkb->max_key_code;
2512f7df2e56Smrg        status = XkbChangeKeycodeRange(xkb, req->minKeyCode,
2513f7df2e56Smrg                                       req->maxKeyCode, &change);
2514f7df2e56Smrg        if (status != Success)
2515f7df2e56Smrg            return status;      /* oh-oh. what about the other keyboards? */
2516f7df2e56Smrg        nkn.minKeyCode = xkb->min_key_code;
2517f7df2e56Smrg        nkn.maxKeyCode = xkb->max_key_code;
2518f7df2e56Smrg        nkn.requestMajor = XkbReqCode;
2519f7df2e56Smrg        nkn.requestMinor = X_kbSetMap;
2520f7df2e56Smrg        nkn.changed = XkbNKN_KeycodesMask;
2521f7df2e56Smrg        XkbSendNewKeyboardNotify(dev, &nkn);
2522f7df2e56Smrg        sentNKN = TRUE;
2523f7df2e56Smrg    }
2524f7df2e56Smrg
2525f7df2e56Smrg    if (req->present & XkbKeyTypesMask) {
2526f7df2e56Smrg        values = SetKeyTypes(xkb, req, (xkbKeyTypeWireDesc *) values, &change);
2527f7df2e56Smrg        if (!values)
2528f7df2e56Smrg            goto allocFailure;
2529f7df2e56Smrg    }
2530f7df2e56Smrg    if (req->present & XkbKeySymsMask) {
2531f7df2e56Smrg        values =
2532f7df2e56Smrg            SetKeySyms(client, xkb, req, (xkbSymMapWireDesc *) values, &change,
2533f7df2e56Smrg                       dev);
2534f7df2e56Smrg        if (!values)
2535f7df2e56Smrg            goto allocFailure;
2536f7df2e56Smrg    }
2537f7df2e56Smrg    if (req->present & XkbKeyActionsMask) {
2538f7df2e56Smrg        values = SetKeyActions(xkb, req, (CARD8 *) values, &change);
2539f7df2e56Smrg        if (!values)
2540f7df2e56Smrg            goto allocFailure;
2541f7df2e56Smrg    }
2542f7df2e56Smrg    if (req->present & XkbKeyBehaviorsMask) {
2543f7df2e56Smrg        values =
2544f7df2e56Smrg            SetKeyBehaviors(xkbi, req, (xkbBehaviorWireDesc *) values, &change);
2545f7df2e56Smrg        if (!values)
2546f7df2e56Smrg            goto allocFailure;
2547f7df2e56Smrg    }
2548f7df2e56Smrg    if (req->present & XkbVirtualModsMask)
2549f7df2e56Smrg        values = SetVirtualMods(xkbi, req, (CARD8 *) values, &change);
2550f7df2e56Smrg    if (req->present & XkbExplicitComponentsMask)
2551f7df2e56Smrg        values = SetKeyExplicit(xkbi, req, (CARD8 *) values, &change);
2552f7df2e56Smrg    if (req->present & XkbModifierMapMask)
2553f7df2e56Smrg        values = SetModifierMap(xkbi, req, (CARD8 *) values, &change);
2554f7df2e56Smrg    if (req->present & XkbVirtualModMapMask)
2555f7df2e56Smrg        values =
2556f7df2e56Smrg            SetVirtualModMap(xkbi, req, (xkbVModMapWireDesc *) values, &change);
2557f7df2e56Smrg    if (((values - ((char *) req)) / 4) != req->length) {
2558f7df2e56Smrg        ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after set)\n");
2559f7df2e56Smrg        client->errorValue = values - ((char *) &req[1]);
2560f7df2e56Smrg        return BadLength;
2561f7df2e56Smrg    }
2562f7df2e56Smrg    if (req->flags & XkbSetMapRecomputeActions) {
2563f7df2e56Smrg        KeyCode first, last, firstMM, lastMM;
2564f7df2e56Smrg
2565f7df2e56Smrg        if (change.map.num_key_syms > 0) {
2566f7df2e56Smrg            first = change.map.first_key_sym;
2567f7df2e56Smrg            last = first + change.map.num_key_syms - 1;
2568f7df2e56Smrg        }
2569f7df2e56Smrg        else
2570f7df2e56Smrg            first = last = 0;
2571f7df2e56Smrg        if (change.map.num_modmap_keys > 0) {
2572f7df2e56Smrg            firstMM = change.map.first_modmap_key;
25737e31ba66Smrg            lastMM = firstMM + change.map.num_modmap_keys - 1;
2574f7df2e56Smrg        }
2575f7df2e56Smrg        else
2576f7df2e56Smrg            firstMM = lastMM = 0;
2577f7df2e56Smrg        if ((last > 0) && (lastMM > 0)) {
2578f7df2e56Smrg            if (firstMM < first)
2579f7df2e56Smrg                first = firstMM;
2580f7df2e56Smrg            if (lastMM > last)
2581f7df2e56Smrg                last = lastMM;
2582f7df2e56Smrg        }
2583f7df2e56Smrg        else if (lastMM > 0) {
2584f7df2e56Smrg            first = firstMM;
2585f7df2e56Smrg            last = lastMM;
2586f7df2e56Smrg        }
2587f7df2e56Smrg        if (last > 0) {
2588f7df2e56Smrg            unsigned check = 0;
2589f7df2e56Smrg
2590f7df2e56Smrg            XkbUpdateActions(dev, first, (last - first + 1), &change, &check,
2591f7df2e56Smrg                             &cause);
2592f7df2e56Smrg            if (check)
2593f7df2e56Smrg                XkbCheckSecondaryEffects(xkbi, check, &change, &cause);
2594f7df2e56Smrg        }
259505b261ecSmrg    }
259605b261ecSmrg    if (!sentNKN)
2597f7df2e56Smrg        XkbSendNotification(dev, &change, &cause);
259805b261ecSmrg
25994642e01fSmrg    return Success;
2600f7df2e56Smrg allocFailure:
260105b261ecSmrg    return BadAlloc;
260205b261ecSmrg}
260305b261ecSmrg
26044642e01fSmrgint
26054642e01fSmrgProcXkbSetMap(ClientPtr client)
26064642e01fSmrg{
2607f7df2e56Smrg    DeviceIntPtr dev;
2608f7df2e56Smrg    char *tmp;
2609f7df2e56Smrg    int rc;
26104642e01fSmrg
26114642e01fSmrg    REQUEST(xkbSetMapReq);
26124642e01fSmrg    REQUEST_AT_LEAST_SIZE(xkbSetMapReq);
26134642e01fSmrg
2614f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
2615f7df2e56Smrg        return BadAccess;
26164642e01fSmrg
26174642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
2618f7df2e56Smrg    CHK_MASK_LEGAL(0x01, stuff->present, XkbAllMapComponentsMask);
26194642e01fSmrg
2620f7df2e56Smrg    tmp = (char *) &stuff[1];
26214642e01fSmrg
26224642e01fSmrg    /* Check if we can to the SetMap on the requested device. If this
26234642e01fSmrg       succeeds, do the same thing for all extension devices (if needed).
26244642e01fSmrg       If any of them fails, fail.  */
26254642e01fSmrg    rc = _XkbSetMapChecks(client, dev, stuff, tmp);
26264642e01fSmrg
26274642e01fSmrg    if (rc != Success)
26284642e01fSmrg        return rc;
26294642e01fSmrg
26307e31ba66Smrg    DeviceIntPtr master = GetMaster(dev, MASTER_KEYBOARD);
26317e31ba66Smrg
2632f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
26334642e01fSmrg        DeviceIntPtr other;
2634f7df2e56Smrg
2635f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
2636f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
2637f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
2638f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
2639f7df2e56Smrg                              DixManageAccess);
2640f7df2e56Smrg                if (rc == Success) {
26414642e01fSmrg                    rc = _XkbSetMapChecks(client, other, stuff, tmp);
26424642e01fSmrg                    if (rc != Success)
26434642e01fSmrg                        return rc;
26444642e01fSmrg                }
26454642e01fSmrg            }
26464642e01fSmrg        }
26477e31ba66Smrg    } else {
26487e31ba66Smrg        DeviceIntPtr other;
26497e31ba66Smrg
26507e31ba66Smrg        for (other = inputInfo.devices; other; other = other->next) {
26517e31ba66Smrg            if (other != dev && GetMaster(other, MASTER_KEYBOARD) != dev &&
26527e31ba66Smrg                (other != master || dev != master->lastSlave))
26537e31ba66Smrg                continue;
26547e31ba66Smrg
26557e31ba66Smrg            rc = _XkbSetMapChecks(client, other, stuff, tmp);
26567e31ba66Smrg            if (rc != Success)
26577e31ba66Smrg                return rc;
26587e31ba66Smrg        }
26594642e01fSmrg    }
26604642e01fSmrg
26617e31ba66Smrg    /* We know now that we will succeed with the SetMap. In theory anyway. */
26624642e01fSmrg    rc = _XkbSetMap(client, dev, stuff, tmp);
26634642e01fSmrg    if (rc != Success)
26644642e01fSmrg        return rc;
26654642e01fSmrg
2666f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
26674642e01fSmrg        DeviceIntPtr other;
2668f7df2e56Smrg
2669f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
2670f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
2671f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
2672f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
2673f7df2e56Smrg                              DixManageAccess);
26744642e01fSmrg                if (rc == Success)
26754642e01fSmrg                    _XkbSetMap(client, other, stuff, tmp);
26764642e01fSmrg                /* ignore rc. if the SetMap failed although the check above
26774642e01fSmrg                   reported true there isn't much we can do. we still need to
26784642e01fSmrg                   set all other devices, hoping that at least they stay in
26794642e01fSmrg                   sync. */
26804642e01fSmrg            }
26814642e01fSmrg        }
26827e31ba66Smrg    } else {
26837e31ba66Smrg        DeviceIntPtr other;
26847e31ba66Smrg
26857e31ba66Smrg        for (other = inputInfo.devices; other; other = other->next) {
26867e31ba66Smrg            if (other != dev && GetMaster(other, MASTER_KEYBOARD) != dev &&
26877e31ba66Smrg                (other != master || dev != master->lastSlave))
26887e31ba66Smrg                continue;
26897e31ba66Smrg
26907e31ba66Smrg            _XkbSetMap(client, other, stuff, tmp); //ignore rc
26917e31ba66Smrg        }
26924642e01fSmrg    }
26934642e01fSmrg
26946747b715Smrg    return Success;
26954642e01fSmrg}
26964642e01fSmrg
269705b261ecSmrg/***====================================================================***/
269805b261ecSmrg
269905b261ecSmrgstatic Status
2700f7df2e56SmrgXkbComputeGetCompatMapReplySize(XkbCompatMapPtr compat,
2701f7df2e56Smrg                                xkbGetCompatMapReply * rep)
270205b261ecSmrg{
2703f7df2e56Smrg    unsigned size, nGroups;
2704f7df2e56Smrg
2705f7df2e56Smrg    nGroups = 0;
2706f7df2e56Smrg    if (rep->groups != 0) {
2707f7df2e56Smrg        register int i, bit;
2708f7df2e56Smrg
2709f7df2e56Smrg        for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2710f7df2e56Smrg            if (rep->groups & bit)
2711f7df2e56Smrg                nGroups++;
2712f7df2e56Smrg        }
2713f7df2e56Smrg    }
2714f7df2e56Smrg    size = nGroups * SIZEOF(xkbModsWireDesc);
2715f7df2e56Smrg    size += (rep->nSI * SIZEOF(xkbSymInterpretWireDesc));
2716f7df2e56Smrg    rep->length = size / 4;
271705b261ecSmrg    return Success;
271805b261ecSmrg}
271905b261ecSmrg
272005b261ecSmrgstatic int
2721f7df2e56SmrgXkbSendCompatMap(ClientPtr client,
2722f7df2e56Smrg                 XkbCompatMapPtr compat, xkbGetCompatMapReply * rep)
272305b261ecSmrg{
2724f7df2e56Smrg    char *data;
2725f7df2e56Smrg    int size;
2726f7df2e56Smrg
2727f7df2e56Smrg    if (rep->length > 0) {
2728f7df2e56Smrg        data = xallocarray(rep->length, 4);
2729f7df2e56Smrg        if (data) {
2730f7df2e56Smrg            register unsigned i, bit;
2731f7df2e56Smrg            xkbModsWireDesc *grp;
2732f7df2e56Smrg            XkbSymInterpretPtr sym = &compat->sym_interpret[rep->firstSI];
2733f7df2e56Smrg            xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *) data;
2734f7df2e56Smrg
2735f7df2e56Smrg            size = rep->length * 4;
2736f7df2e56Smrg
2737f7df2e56Smrg            for (i = 0; i < rep->nSI; i++, sym++, wire++) {
2738f7df2e56Smrg                wire->sym = sym->sym;
2739f7df2e56Smrg                wire->mods = sym->mods;
2740f7df2e56Smrg                wire->match = sym->match;
2741f7df2e56Smrg                wire->virtualMod = sym->virtual_mod;
2742f7df2e56Smrg                wire->flags = sym->flags;
2743f7df2e56Smrg                memcpy((char *) &wire->act, (char *) &sym->act,
2744f7df2e56Smrg                       sz_xkbActionWireDesc);
2745f7df2e56Smrg                if (client->swapped) {
2746f7df2e56Smrg                    swapl(&wire->sym);
2747f7df2e56Smrg                }
2748f7df2e56Smrg            }
2749f7df2e56Smrg            if (rep->groups) {
2750f7df2e56Smrg                grp = (xkbModsWireDesc *) wire;
2751f7df2e56Smrg                for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2752f7df2e56Smrg                    if (rep->groups & bit) {
2753f7df2e56Smrg                        grp->mask = compat->groups[i].mask;
2754f7df2e56Smrg                        grp->realMods = compat->groups[i].real_mods;
2755f7df2e56Smrg                        grp->virtualMods = compat->groups[i].vmods;
2756f7df2e56Smrg                        if (client->swapped) {
2757f7df2e56Smrg                            swaps(&grp->virtualMods);
2758f7df2e56Smrg                        }
2759f7df2e56Smrg                        grp++;
2760f7df2e56Smrg                    }
2761f7df2e56Smrg                }
2762f7df2e56Smrg                wire = (xkbSymInterpretWireDesc *) grp;
2763f7df2e56Smrg            }
2764f7df2e56Smrg        }
2765f7df2e56Smrg        else
2766f7df2e56Smrg            return BadAlloc;
2767f7df2e56Smrg    }
2768f7df2e56Smrg    else
2769f7df2e56Smrg        data = NULL;
277005b261ecSmrg
277105b261ecSmrg    if (client->swapped) {
2772f7df2e56Smrg        swaps(&rep->sequenceNumber);
2773f7df2e56Smrg        swapl(&rep->length);
2774f7df2e56Smrg        swaps(&rep->firstSI);
2775f7df2e56Smrg        swaps(&rep->nSI);
2776f7df2e56Smrg        swaps(&rep->nTotalSI);
277705b261ecSmrg    }
277805b261ecSmrg
2779f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetCompatMapReply), rep);
278005b261ecSmrg    if (data) {
2781f7df2e56Smrg        WriteToClient(client, size, data);
2782f7df2e56Smrg        free((char *) data);
278305b261ecSmrg    }
27846747b715Smrg    return Success;
278505b261ecSmrg}
278605b261ecSmrg
278705b261ecSmrgint
278805b261ecSmrgProcXkbGetCompatMap(ClientPtr client)
278905b261ecSmrg{
2790f7df2e56Smrg    xkbGetCompatMapReply rep;
2791f7df2e56Smrg    DeviceIntPtr dev;
2792f7df2e56Smrg    XkbDescPtr xkb;
2793f7df2e56Smrg    XkbCompatMapPtr compat;
279405b261ecSmrg
279505b261ecSmrg    REQUEST(xkbGetCompatMapReq);
279605b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetCompatMapReq);
279705b261ecSmrg
2798f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
2799f7df2e56Smrg        return BadAccess;
280005b261ecSmrg
28014642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
280205b261ecSmrg
280305b261ecSmrg    xkb = dev->key->xkbInfo->desc;
2804f7df2e56Smrg    compat = xkb->compat;
280505b261ecSmrg
2806f7df2e56Smrg    rep = (xkbGetCompatMapReply) {
2807f7df2e56Smrg        .type = X_Reply,
2808f7df2e56Smrg        .sequenceNumber = client->sequence,
2809f7df2e56Smrg        .length = 0,
2810f7df2e56Smrg        .deviceID = dev->id,
2811f7df2e56Smrg        .firstSI = stuff->firstSI,
2812f7df2e56Smrg        .nSI = stuff->nSI
2813f7df2e56Smrg    };
281405b261ecSmrg    if (stuff->getAllSI) {
2815f7df2e56Smrg        rep.firstSI = 0;
2816f7df2e56Smrg        rep.nSI = compat->num_si;
281705b261ecSmrg    }
2818f7df2e56Smrg    else if ((((unsigned) stuff->nSI) > 0) &&
2819f7df2e56Smrg             ((unsigned) (stuff->firstSI + stuff->nSI - 1) >= compat->num_si)) {
2820f7df2e56Smrg        client->errorValue = _XkbErrCode2(0x05, compat->num_si);
2821f7df2e56Smrg        return BadValue;
282205b261ecSmrg    }
282305b261ecSmrg    rep.nTotalSI = compat->num_si;
2824f7df2e56Smrg    rep.groups = stuff->groups;
2825f7df2e56Smrg    XkbComputeGetCompatMapReplySize(compat, &rep);
2826f7df2e56Smrg    return XkbSendCompatMap(client, compat, &rep);
282705b261ecSmrg}
282805b261ecSmrg
28294642e01fSmrg/**
28304642e01fSmrg * Apply the given request on the given device.
28316747b715Smrg * If dryRun is TRUE, then value checks are performed, but the device isn't
28324642e01fSmrg * modified.
28334642e01fSmrg */
28344642e01fSmrgstatic int
28354642e01fSmrg_XkbSetCompatMap(ClientPtr client, DeviceIntPtr dev,
2836f7df2e56Smrg                 xkbSetCompatMapReq * req, char *data, BOOL dryRun)
283705b261ecSmrg{
2838f7df2e56Smrg    XkbSrvInfoPtr xkbi;
2839f7df2e56Smrg    XkbDescPtr xkb;
2840f7df2e56Smrg    XkbCompatMapPtr compat;
2841f7df2e56Smrg    int nGroups;
2842f7df2e56Smrg    unsigned i, bit;
284305b261ecSmrg
284405b261ecSmrg    xkbi = dev->key->xkbInfo;
28454642e01fSmrg    xkb = xkbi->desc;
28464642e01fSmrg    compat = xkb->compat;
28474642e01fSmrg
2848f7df2e56Smrg    if ((req->nSI > 0) || (req->truncateSI)) {
2849f7df2e56Smrg        xkbSymInterpretWireDesc *wire;
2850f7df2e56Smrg
2851f7df2e56Smrg        if (req->firstSI > compat->num_si) {
2852f7df2e56Smrg            client->errorValue = _XkbErrCode2(0x02, compat->num_si);
2853f7df2e56Smrg            return BadValue;
2854f7df2e56Smrg        }
2855f7df2e56Smrg        wire = (xkbSymInterpretWireDesc *) data;
2856f7df2e56Smrg        wire += req->nSI;
2857f7df2e56Smrg        data = (char *) wire;
285805b261ecSmrg    }
28594642e01fSmrg
2860f7df2e56Smrg    nGroups = 0;
2861f7df2e56Smrg    if (req->groups != 0) {
2862f7df2e56Smrg        for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2863f7df2e56Smrg            if (req->groups & bit)
2864f7df2e56Smrg                nGroups++;
2865f7df2e56Smrg        }
286605b261ecSmrg    }
2867f7df2e56Smrg    data += nGroups * SIZEOF(xkbModsWireDesc);
2868f7df2e56Smrg    if (((data - ((char *) req)) / 4) != req->length) {
2869f7df2e56Smrg        return BadLength;
287005b261ecSmrg    }
28714642e01fSmrg
28724642e01fSmrg    /* Done all the checks we can do */
28734642e01fSmrg    if (dryRun)
28744642e01fSmrg        return Success;
28754642e01fSmrg
2876f7df2e56Smrg    data = (char *) &req[1];
2877f7df2e56Smrg    if (req->nSI > 0) {
2878f7df2e56Smrg        xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *) data;
2879f7df2e56Smrg        XkbSymInterpretPtr sym;
2880f7df2e56Smrg        unsigned int skipped = 0;
2881f7df2e56Smrg
2882f7df2e56Smrg        if ((unsigned) (req->firstSI + req->nSI) > compat->num_si) {
2883f7df2e56Smrg            compat->num_si = req->firstSI + req->nSI;
2884f7df2e56Smrg            compat->sym_interpret = reallocarray(compat->sym_interpret,
2885f7df2e56Smrg                                                 compat->num_si,
2886f7df2e56Smrg                                                 sizeof(XkbSymInterpretRec));
2887f7df2e56Smrg            if (!compat->sym_interpret) {
2888f7df2e56Smrg                compat->num_si = 0;
2889f7df2e56Smrg                return BadAlloc;
2890f7df2e56Smrg            }
2891f7df2e56Smrg        }
2892f7df2e56Smrg        else if (req->truncateSI) {
2893f7df2e56Smrg            compat->num_si = req->firstSI + req->nSI;
2894f7df2e56Smrg        }
2895f7df2e56Smrg        sym = &compat->sym_interpret[req->firstSI];
2896f7df2e56Smrg        for (i = 0; i < req->nSI; i++, wire++) {
2897f7df2e56Smrg            if (client->swapped) {
2898f7df2e56Smrg                swapl(&wire->sym);
2899f7df2e56Smrg            }
2900f7df2e56Smrg            if (wire->sym == NoSymbol && wire->match == XkbSI_AnyOfOrNone &&
2901f7df2e56Smrg                (wire->mods & 0xff) == 0xff &&
2902f7df2e56Smrg                wire->act.type == XkbSA_XFree86Private) {
2903f7df2e56Smrg                ErrorF("XKB: Skipping broken Any+AnyOfOrNone(All) -> Private "
2904f7df2e56Smrg                       "action from client\n");
2905f7df2e56Smrg                skipped++;
2906f7df2e56Smrg                continue;
2907f7df2e56Smrg            }
2908f7df2e56Smrg            sym->sym = wire->sym;
2909f7df2e56Smrg            sym->mods = wire->mods;
2910f7df2e56Smrg            sym->match = wire->match;
2911f7df2e56Smrg            sym->flags = wire->flags;
2912f7df2e56Smrg            sym->virtual_mod = wire->virtualMod;
2913f7df2e56Smrg            memcpy((char *) &sym->act, (char *) &wire->act,
2914f7df2e56Smrg                   SIZEOF(xkbActionWireDesc));
2915f7df2e56Smrg            sym++;
2916f7df2e56Smrg        }
2917f7df2e56Smrg        if (skipped) {
2918f7df2e56Smrg            if (req->firstSI + req->nSI < compat->num_si)
2919f7df2e56Smrg                memmove(sym, sym + skipped,
2920f7df2e56Smrg                        (compat->num_si - req->firstSI - req->nSI) *
2921f7df2e56Smrg                        sizeof(*sym));
2922f7df2e56Smrg            compat->num_si -= skipped;
2923f7df2e56Smrg        }
2924f7df2e56Smrg        data = (char *) wire;
292505b261ecSmrg    }
29264642e01fSmrg    else if (req->truncateSI) {
2927f7df2e56Smrg        compat->num_si = req->firstSI;
2928f7df2e56Smrg    }
2929f7df2e56Smrg
2930f7df2e56Smrg    if (req->groups != 0) {
2931f7df2e56Smrg        xkbModsWireDesc *wire = (xkbModsWireDesc *) data;
2932f7df2e56Smrg
2933f7df2e56Smrg        for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2934f7df2e56Smrg            if (req->groups & bit) {
2935f7df2e56Smrg                if (client->swapped) {
2936f7df2e56Smrg                    swaps(&wire->virtualMods);
2937f7df2e56Smrg                }
2938f7df2e56Smrg                compat->groups[i].mask = wire->realMods;
2939f7df2e56Smrg                compat->groups[i].real_mods = wire->realMods;
2940f7df2e56Smrg                compat->groups[i].vmods = wire->virtualMods;
2941f7df2e56Smrg                if (wire->virtualMods != 0) {
2942f7df2e56Smrg                    unsigned tmp;
2943f7df2e56Smrg
2944f7df2e56Smrg                    tmp = XkbMaskForVMask(xkb, wire->virtualMods);
2945f7df2e56Smrg                    compat->groups[i].mask |= tmp;
2946f7df2e56Smrg                }
2947f7df2e56Smrg                data += SIZEOF(xkbModsWireDesc);
2948f7df2e56Smrg                wire = (xkbModsWireDesc *) data;
2949f7df2e56Smrg            }
2950f7df2e56Smrg        }
2951f7df2e56Smrg    }
2952f7df2e56Smrg    i = XkbPaddedSize((data - ((char *) req)));
2953f7df2e56Smrg    if ((i / 4) != req->length) {
2954f7df2e56Smrg        ErrorF("[xkb] Internal length error on read in _XkbSetCompatMap\n");
2955f7df2e56Smrg        return BadLength;
295605b261ecSmrg    }
29574642e01fSmrg
295805b261ecSmrg    if (dev->xkb_interest) {
2959f7df2e56Smrg        xkbCompatMapNotify ev;
2960f7df2e56Smrg
2961f7df2e56Smrg        ev.deviceID = dev->id;
2962f7df2e56Smrg        ev.changedGroups = req->groups;
2963f7df2e56Smrg        ev.firstSI = req->firstSI;
2964f7df2e56Smrg        ev.nSI = req->nSI;
2965f7df2e56Smrg        ev.nTotalSI = compat->num_si;
2966f7df2e56Smrg        XkbSendCompatMapNotify(dev, &ev);
296705b261ecSmrg    }
296805b261ecSmrg
29694642e01fSmrg    if (req->recomputeActions) {
2970f7df2e56Smrg        XkbChangesRec change;
2971f7df2e56Smrg        unsigned check;
2972f7df2e56Smrg        XkbEventCauseRec cause;
2973f7df2e56Smrg
2974f7df2e56Smrg        XkbSetCauseXkbReq(&cause, X_kbSetCompatMap, client);
2975f7df2e56Smrg        memset(&change, 0, sizeof(XkbChangesRec));
2976f7df2e56Smrg        XkbUpdateActions(dev, xkb->min_key_code, XkbNumKeys(xkb), &change,
2977f7df2e56Smrg                         &check, &cause);
2978f7df2e56Smrg        if (check)
2979f7df2e56Smrg            XkbCheckSecondaryEffects(xkbi, check, &change, &cause);
2980f7df2e56Smrg        XkbSendNotification(dev, &change, &cause);
298105b261ecSmrg    }
29824642e01fSmrg    return Success;
29834642e01fSmrg}
29844642e01fSmrg
29854642e01fSmrgint
29864642e01fSmrgProcXkbSetCompatMap(ClientPtr client)
29874642e01fSmrg{
2988f7df2e56Smrg    DeviceIntPtr dev;
2989f7df2e56Smrg    char *data;
2990f7df2e56Smrg    int rc;
29914642e01fSmrg
29924642e01fSmrg    REQUEST(xkbSetCompatMapReq);
29934642e01fSmrg    REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq);
29944642e01fSmrg
2995f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
2996f7df2e56Smrg        return BadAccess;
29974642e01fSmrg
29984642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
29994642e01fSmrg
3000f7df2e56Smrg    data = (char *) &stuff[1];
30014642e01fSmrg
30024642e01fSmrg    /* check first using a dry-run */
30034642e01fSmrg    rc = _XkbSetCompatMap(client, dev, stuff, data, TRUE);
30044642e01fSmrg    if (rc != Success)
30054642e01fSmrg        return rc;
3006f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
30074642e01fSmrg        DeviceIntPtr other;
3008f7df2e56Smrg
3009f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
3010f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
3011f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
3012f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
3013f7df2e56Smrg                              DixManageAccess);
3014f7df2e56Smrg                if (rc == Success) {
30154642e01fSmrg                    /* dry-run */
30164642e01fSmrg                    rc = _XkbSetCompatMap(client, other, stuff, data, TRUE);
30174642e01fSmrg                    if (rc != Success)
30184642e01fSmrg                        return rc;
30194642e01fSmrg                }
30204642e01fSmrg            }
30214642e01fSmrg        }
30224642e01fSmrg    }
30234642e01fSmrg
30244642e01fSmrg    /* Yay, the dry-runs succeed. Let's apply */
30254642e01fSmrg    rc = _XkbSetCompatMap(client, dev, stuff, data, FALSE);
30264642e01fSmrg    if (rc != Success)
30274642e01fSmrg        return rc;
3028f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
30294642e01fSmrg        DeviceIntPtr other;
3030f7df2e56Smrg
3031f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
3032f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
3033f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
3034f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
3035f7df2e56Smrg                              DixManageAccess);
3036f7df2e56Smrg                if (rc == Success) {
30374642e01fSmrg                    rc = _XkbSetCompatMap(client, other, stuff, data, FALSE);
30384642e01fSmrg                    if (rc != Success)
30394642e01fSmrg                        return rc;
30404642e01fSmrg                }
30414642e01fSmrg            }
30424642e01fSmrg        }
30434642e01fSmrg    }
30444642e01fSmrg
30456747b715Smrg    return Success;
304605b261ecSmrg}
304705b261ecSmrg
304805b261ecSmrg/***====================================================================***/
304905b261ecSmrg
305005b261ecSmrgint
305105b261ecSmrgProcXkbGetIndicatorState(ClientPtr client)
305205b261ecSmrg{
3053f7df2e56Smrg    xkbGetIndicatorStateReply rep;
3054f7df2e56Smrg    XkbSrvLedInfoPtr sli;
3055f7df2e56Smrg    DeviceIntPtr dev;
305605b261ecSmrg
305705b261ecSmrg    REQUEST(xkbGetIndicatorStateReq);
305805b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq);
305905b261ecSmrg
3060f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
3061f7df2e56Smrg        return BadAccess;
306205b261ecSmrg
30634642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
306405b261ecSmrg
3065f7df2e56Smrg    sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
3066f7df2e56Smrg                            XkbXI_IndicatorStateMask);
306705b261ecSmrg    if (!sli)
3068f7df2e56Smrg        return BadAlloc;
306905b261ecSmrg
3070f7df2e56Smrg    rep = (xkbGetIndicatorStateReply) {
3071f7df2e56Smrg        .type = X_Reply,
3072f7df2e56Smrg        .deviceID = dev->id,
3073f7df2e56Smrg        .sequenceNumber = client->sequence,
3074f7df2e56Smrg        .length = 0,
3075f7df2e56Smrg        .state = sli->effectiveState
3076f7df2e56Smrg    };
307705b261ecSmrg
307805b261ecSmrg    if (client->swapped) {
3079f7df2e56Smrg        swaps(&rep.sequenceNumber);
3080f7df2e56Smrg        swapl(&rep.state);
308105b261ecSmrg    }
3082f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetIndicatorStateReply), &rep);
30836747b715Smrg    return Success;
308405b261ecSmrg}
308505b261ecSmrg
308605b261ecSmrg/***====================================================================***/
308705b261ecSmrg
308805b261ecSmrgstatic Status
3089f7df2e56SmrgXkbComputeGetIndicatorMapReplySize(XkbIndicatorPtr indicators,
3090f7df2e56Smrg                                   xkbGetIndicatorMapReply * rep)
309105b261ecSmrg{
3092f7df2e56Smrg    register int i, bit;
3093f7df2e56Smrg    int nIndicators;
309405b261ecSmrg
309505b261ecSmrg    rep->realIndicators = indicators->phys_indicators;
3096f7df2e56Smrg    for (i = nIndicators = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3097f7df2e56Smrg        if (rep->which & bit)
3098f7df2e56Smrg            nIndicators++;
309905b261ecSmrg    }
3100f7df2e56Smrg    rep->length = (nIndicators * SIZEOF(xkbIndicatorMapWireDesc)) / 4;
3101f7df2e56Smrg    rep->nIndicators = nIndicators;
310205b261ecSmrg    return Success;
310305b261ecSmrg}
310405b261ecSmrg
310505b261ecSmrgstatic int
3106f7df2e56SmrgXkbSendIndicatorMap(ClientPtr client,
3107f7df2e56Smrg                    XkbIndicatorPtr indicators, xkbGetIndicatorMapReply * rep)
310805b261ecSmrg{
3109f7df2e56Smrg    int length;
3110f7df2e56Smrg    CARD8 *map;
3111f7df2e56Smrg    register int i;
3112f7df2e56Smrg    register unsigned bit;
3113f7df2e56Smrg
3114f7df2e56Smrg    if (rep->length > 0) {
3115f7df2e56Smrg        CARD8 *to;
3116f7df2e56Smrg
3117f7df2e56Smrg        to = map = xallocarray(rep->length, 4);
3118f7df2e56Smrg        if (map) {
3119f7df2e56Smrg            xkbIndicatorMapWireDesc *wire = (xkbIndicatorMapWireDesc *) to;
3120f7df2e56Smrg
3121f7df2e56Smrg            length = rep->length * 4;
3122f7df2e56Smrg
3123f7df2e56Smrg            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3124f7df2e56Smrg                if (rep->which & bit) {
3125f7df2e56Smrg                    wire->flags = indicators->maps[i].flags;
3126f7df2e56Smrg                    wire->whichGroups = indicators->maps[i].which_groups;
3127f7df2e56Smrg                    wire->groups = indicators->maps[i].groups;
3128f7df2e56Smrg                    wire->whichMods = indicators->maps[i].which_mods;
3129f7df2e56Smrg                    wire->mods = indicators->maps[i].mods.mask;
3130f7df2e56Smrg                    wire->realMods = indicators->maps[i].mods.real_mods;
3131f7df2e56Smrg                    wire->virtualMods = indicators->maps[i].mods.vmods;
3132f7df2e56Smrg                    wire->ctrls = indicators->maps[i].ctrls;
3133f7df2e56Smrg                    if (client->swapped) {
3134f7df2e56Smrg                        swaps(&wire->virtualMods);
3135f7df2e56Smrg                        swapl(&wire->ctrls);
3136f7df2e56Smrg                    }
3137f7df2e56Smrg                    wire++;
3138f7df2e56Smrg                }
3139f7df2e56Smrg            }
3140f7df2e56Smrg            to = (CARD8 *) wire;
3141f7df2e56Smrg            if ((to - map) != length) {
3142f7df2e56Smrg                client->errorValue = _XkbErrCode2(0xff, length);
3143f7df2e56Smrg                free(map);
3144f7df2e56Smrg                return BadLength;
3145f7df2e56Smrg            }
3146f7df2e56Smrg        }
3147f7df2e56Smrg        else
3148f7df2e56Smrg            return BadAlloc;
3149f7df2e56Smrg    }
3150f7df2e56Smrg    else
3151f7df2e56Smrg        map = NULL;
315205b261ecSmrg    if (client->swapped) {
3153f7df2e56Smrg        swaps(&rep->sequenceNumber);
3154f7df2e56Smrg        swapl(&rep->length);
3155f7df2e56Smrg        swapl(&rep->which);
3156f7df2e56Smrg        swapl(&rep->realIndicators);
315705b261ecSmrg    }
3158f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetIndicatorMapReply), rep);
315905b261ecSmrg    if (map) {
3160f7df2e56Smrg        WriteToClient(client, length, map);
3161f7df2e56Smrg        free((char *) map);
316205b261ecSmrg    }
31636747b715Smrg    return Success;
316405b261ecSmrg}
316505b261ecSmrg
316605b261ecSmrgint
316705b261ecSmrgProcXkbGetIndicatorMap(ClientPtr client)
316805b261ecSmrg{
3169f7df2e56Smrg    xkbGetIndicatorMapReply rep;
3170f7df2e56Smrg    DeviceIntPtr dev;
3171f7df2e56Smrg    XkbDescPtr xkb;
3172f7df2e56Smrg    XkbIndicatorPtr leds;
317305b261ecSmrg
317405b261ecSmrg    REQUEST(xkbGetIndicatorMapReq);
317505b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq);
317605b261ecSmrg
3177f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
3178f7df2e56Smrg        return BadAccess;
317905b261ecSmrg
31804642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
318105b261ecSmrg
3182f7df2e56Smrg    xkb = dev->key->xkbInfo->desc;
3183f7df2e56Smrg    leds = xkb->indicators;
3184f7df2e56Smrg
3185f7df2e56Smrg    rep = (xkbGetIndicatorMapReply) {
3186f7df2e56Smrg        .type = X_Reply,
3187f7df2e56Smrg        .deviceID = dev->id,
3188f7df2e56Smrg        .sequenceNumber = client->sequence,
3189f7df2e56Smrg        .length = 0,
3190f7df2e56Smrg        .which = stuff->which
3191f7df2e56Smrg    };
3192f7df2e56Smrg    XkbComputeGetIndicatorMapReplySize(leds, &rep);
3193f7df2e56Smrg    return XkbSendIndicatorMap(client, leds, &rep);
319405b261ecSmrg}
319505b261ecSmrg
31964642e01fSmrg/**
31974642e01fSmrg * Apply the given map to the given device. Which specifies which components
31984642e01fSmrg * to apply.
31994642e01fSmrg */
32004642e01fSmrgstatic int
32014642e01fSmrg_XkbSetIndicatorMap(ClientPtr client, DeviceIntPtr dev,
3202f7df2e56Smrg                    int which, xkbIndicatorMapWireDesc * desc)
32034642e01fSmrg{
3204f7df2e56Smrg    XkbSrvInfoPtr xkbi;
3205f7df2e56Smrg    XkbSrvLedInfoPtr sli;
3206f7df2e56Smrg    XkbEventCauseRec cause;
3207f7df2e56Smrg    int i, bit;
32084642e01fSmrg
32094642e01fSmrg    xkbi = dev->key->xkbInfo;
32104642e01fSmrg
3211f7df2e56Smrg    sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
3212f7df2e56Smrg                            XkbXI_IndicatorMapsMask);
32134642e01fSmrg    if (!sli)
3214f7df2e56Smrg        return BadAlloc;
32154642e01fSmrg
32164642e01fSmrg    for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3217f7df2e56Smrg        if (which & bit) {
3218f7df2e56Smrg            sli->maps[i].flags = desc->flags;
3219f7df2e56Smrg            sli->maps[i].which_groups = desc->whichGroups;
3220f7df2e56Smrg            sli->maps[i].groups = desc->groups;
3221f7df2e56Smrg            sli->maps[i].which_mods = desc->whichMods;
3222f7df2e56Smrg            sli->maps[i].mods.mask = desc->mods;
3223f7df2e56Smrg            sli->maps[i].mods.real_mods = desc->mods;
3224f7df2e56Smrg            sli->maps[i].mods.vmods = desc->virtualMods;
3225f7df2e56Smrg            sli->maps[i].ctrls = desc->ctrls;
3226f7df2e56Smrg            if (desc->virtualMods != 0) {
3227f7df2e56Smrg                unsigned tmp;
3228f7df2e56Smrg
3229f7df2e56Smrg                tmp = XkbMaskForVMask(xkbi->desc, desc->virtualMods);
3230f7df2e56Smrg                sli->maps[i].mods.mask = desc->mods | tmp;
3231f7df2e56Smrg            }
3232f7df2e56Smrg            desc++;
3233f7df2e56Smrg        }
3234f7df2e56Smrg    }
3235f7df2e56Smrg
3236f7df2e56Smrg    XkbSetCauseXkbReq(&cause, X_kbSetIndicatorMap, client);
3237f7df2e56Smrg    XkbApplyLedMapChanges(dev, sli, which, NULL, NULL, &cause);
32384642e01fSmrg
32394642e01fSmrg    return Success;
32404642e01fSmrg}
32414642e01fSmrg
324205b261ecSmrgint
324305b261ecSmrgProcXkbSetIndicatorMap(ClientPtr client)
324405b261ecSmrg{
3245f7df2e56Smrg    int i, bit;
3246f7df2e56Smrg    int nIndicators;
3247f7df2e56Smrg    DeviceIntPtr dev;
3248f7df2e56Smrg    xkbIndicatorMapWireDesc *from;
3249f7df2e56Smrg    int rc;
325005b261ecSmrg
325105b261ecSmrg    REQUEST(xkbSetIndicatorMapReq);
325205b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq);
325305b261ecSmrg
3254f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
3255f7df2e56Smrg        return BadAccess;
325605b261ecSmrg
32574642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
325805b261ecSmrg
3259f7df2e56Smrg    if (stuff->which == 0)
3260f7df2e56Smrg        return Success;
326105b261ecSmrg
3262f7df2e56Smrg    for (nIndicators = i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3263f7df2e56Smrg        if (stuff->which & bit)
3264f7df2e56Smrg            nIndicators++;
326505b261ecSmrg    }
3266f7df2e56Smrg    if (stuff->length != ((SIZEOF(xkbSetIndicatorMapReq) +
3267f7df2e56Smrg                           (nIndicators * SIZEOF(xkbIndicatorMapWireDesc))) /
3268f7df2e56Smrg                          4)) {
3269f7df2e56Smrg        return BadLength;
327005b261ecSmrg    }
327105b261ecSmrg
3272f7df2e56Smrg    from = (xkbIndicatorMapWireDesc *) &stuff[1];
3273f7df2e56Smrg    for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3274f7df2e56Smrg        if (stuff->which & bit) {
3275f7df2e56Smrg            if (client->swapped) {
3276f7df2e56Smrg                swaps(&from->virtualMods);
3277f7df2e56Smrg                swapl(&from->ctrls);
3278f7df2e56Smrg            }
3279f7df2e56Smrg            CHK_MASK_LEGAL(i, from->whichGroups, XkbIM_UseAnyGroup);
3280f7df2e56Smrg            CHK_MASK_LEGAL(i, from->whichMods, XkbIM_UseAnyMods);
3281f7df2e56Smrg            from++;
3282f7df2e56Smrg        }
328305b261ecSmrg    }
328405b261ecSmrg
3285f7df2e56Smrg    from = (xkbIndicatorMapWireDesc *) &stuff[1];
32864642e01fSmrg    rc = _XkbSetIndicatorMap(client, dev, stuff->which, from);
32874642e01fSmrg    if (rc != Success)
32884642e01fSmrg        return rc;
32894642e01fSmrg
3290f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
32914642e01fSmrg        DeviceIntPtr other;
3292f7df2e56Smrg
3293f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
3294f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
3295f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
3296f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
3297f7df2e56Smrg                              DixSetAttrAccess);
32984642e01fSmrg                if (rc == Success)
32994642e01fSmrg                    _XkbSetIndicatorMap(client, other, stuff->which, from);
33004642e01fSmrg            }
33014642e01fSmrg        }
330205b261ecSmrg    }
330305b261ecSmrg
33044642e01fSmrg    return Success;
330505b261ecSmrg}
330605b261ecSmrg
330705b261ecSmrg/***====================================================================***/
330805b261ecSmrg
330905b261ecSmrgint
331005b261ecSmrgProcXkbGetNamedIndicator(ClientPtr client)
331105b261ecSmrg{
3312f7df2e56Smrg    DeviceIntPtr dev;
3313f7df2e56Smrg    xkbGetNamedIndicatorReply rep;
3314f7df2e56Smrg    register int i = 0;
3315f7df2e56Smrg    XkbSrvLedInfoPtr sli;
3316f7df2e56Smrg    XkbIndicatorMapPtr map = NULL;
331705b261ecSmrg
331805b261ecSmrg    REQUEST(xkbGetNamedIndicatorReq);
331905b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq);
332005b261ecSmrg
3321f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
3322f7df2e56Smrg        return BadAccess;
332305b261ecSmrg
33244642e01fSmrg    CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
332505b261ecSmrg    CHK_ATOM_ONLY(stuff->indicator);
332605b261ecSmrg
3327f7df2e56Smrg    sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID, 0);
332805b261ecSmrg    if (!sli)
3329f7df2e56Smrg        return BadAlloc;
3330f7df2e56Smrg
3331f7df2e56Smrg    i = 0;
3332f7df2e56Smrg    map = NULL;
3333f7df2e56Smrg    if ((sli->names) && (sli->maps)) {
3334f7df2e56Smrg        for (i = 0; i < XkbNumIndicators; i++) {
3335f7df2e56Smrg            if (stuff->indicator == sli->names[i]) {
3336f7df2e56Smrg                map = &sli->maps[i];
333705b261ecSmrg                break;
333805b261ecSmrg            }
333905b261ecSmrg        }
334005b261ecSmrg    }
334105b261ecSmrg
3342f7df2e56Smrg    rep = (xkbGetNamedIndicatorReply) {
3343f7df2e56Smrg        .type = X_Reply,
3344f7df2e56Smrg        .sequenceNumber = client->sequence,
3345f7df2e56Smrg        .length = 0,
3346f7df2e56Smrg        .deviceID = dev->id,
3347f7df2e56Smrg        .indicator = stuff->indicator
3348f7df2e56Smrg    };
3349f7df2e56Smrg    if (map != NULL) {
3350f7df2e56Smrg        rep.found = TRUE;
3351f7df2e56Smrg        rep.on = ((sli->effectiveState & (1 << i)) != 0);
3352f7df2e56Smrg        rep.realIndicator = ((sli->physIndicators & (1 << i)) != 0);
3353f7df2e56Smrg        rep.ndx = i;
3354f7df2e56Smrg        rep.flags = map->flags;
3355f7df2e56Smrg        rep.whichGroups = map->which_groups;
3356f7df2e56Smrg        rep.groups = map->groups;
3357f7df2e56Smrg        rep.whichMods = map->which_mods;
3358f7df2e56Smrg        rep.mods = map->mods.mask;
3359f7df2e56Smrg        rep.realMods = map->mods.real_mods;
3360f7df2e56Smrg        rep.virtualMods = map->mods.vmods;
3361f7df2e56Smrg        rep.ctrls = map->ctrls;
3362f7df2e56Smrg        rep.supported = TRUE;
3363f7df2e56Smrg    }
3364f7df2e56Smrg    else {
3365f7df2e56Smrg        rep.found = FALSE;
3366f7df2e56Smrg        rep.on = FALSE;
3367f7df2e56Smrg        rep.realIndicator = FALSE;
3368f7df2e56Smrg        rep.ndx = XkbNoIndicator;
3369f7df2e56Smrg        rep.flags = 0;
3370f7df2e56Smrg        rep.whichGroups = 0;
3371f7df2e56Smrg        rep.groups = 0;
3372f7df2e56Smrg        rep.whichMods = 0;
3373f7df2e56Smrg        rep.mods = 0;
3374f7df2e56Smrg        rep.realMods = 0;
3375f7df2e56Smrg        rep.virtualMods = 0;
3376f7df2e56Smrg        rep.ctrls = 0;
3377f7df2e56Smrg        rep.supported = TRUE;
3378f7df2e56Smrg    }
3379f7df2e56Smrg    if (client->swapped) {
3380f7df2e56Smrg        swapl(&rep.length);
3381f7df2e56Smrg        swaps(&rep.sequenceNumber);
3382f7df2e56Smrg        swapl(&rep.indicator);
3383f7df2e56Smrg        swaps(&rep.virtualMods);
3384f7df2e56Smrg        swapl(&rep.ctrls);
3385f7df2e56Smrg    }
3386f7df2e56Smrg
3387f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetNamedIndicatorReply), &rep);
33886747b715Smrg    return Success;
338905b261ecSmrg}
339005b261ecSmrg
33914642e01fSmrg/**
33924642e01fSmrg * Find the IM on the device.
33934642e01fSmrg * Returns the map, or NULL if the map doesn't exist.
33944642e01fSmrg * If the return value is NULL, led_return is undefined. Otherwise, led_return
33954642e01fSmrg * is set to the led index of the map.
33964642e01fSmrg */
33974642e01fSmrgstatic XkbIndicatorMapPtr
3398f7df2e56Smrg_XkbFindNamedIndicatorMap(XkbSrvLedInfoPtr sli, Atom indicator, int *led_return)
33994642e01fSmrg{
3400f7df2e56Smrg    XkbIndicatorMapPtr map;
340105b261ecSmrg
34024642e01fSmrg    /* search for the right indicator */
34034642e01fSmrg    map = NULL;
340405b261ecSmrg    if (sli->names && sli->maps) {
3405f7df2e56Smrg        int led;
34066747b715Smrg
3407f7df2e56Smrg        for (led = 0; (led < XkbNumIndicators) && (map == NULL); led++) {
3408f7df2e56Smrg            if (sli->names[led] == indicator) {
3409f7df2e56Smrg                map = &sli->maps[led];
3410f7df2e56Smrg                *led_return = led;
3411f7df2e56Smrg                break;
3412f7df2e56Smrg            }
3413f7df2e56Smrg        }
341405b261ecSmrg    }
341505b261ecSmrg
34164642e01fSmrg    return map;
34174642e01fSmrg}
34184642e01fSmrg
34194642e01fSmrg/**
34206747b715Smrg * Creates an indicator map on the device. If dryRun is TRUE, it only checks
34214642e01fSmrg * if creation is possible, but doesn't actually create it.
34224642e01fSmrg */
34234642e01fSmrgstatic int
34244642e01fSmrg_XkbCreateIndicatorMap(DeviceIntPtr dev, Atom indicator,
34254642e01fSmrg                       int ledClass, int ledID,
3426f7df2e56Smrg                       XkbIndicatorMapPtr * map_return, int *led_return,
34274642e01fSmrg                       Bool dryRun)
34284642e01fSmrg{
3429f7df2e56Smrg    XkbSrvLedInfoPtr sli;
3430f7df2e56Smrg    XkbIndicatorMapPtr map;
3431f7df2e56Smrg    int led;
34324642e01fSmrg
34334642e01fSmrg    sli = XkbFindSrvLedInfo(dev, ledClass, ledID, XkbXI_IndicatorsMask);
34344642e01fSmrg    if (!sli)
34354642e01fSmrg        return BadAlloc;
34364642e01fSmrg
34374642e01fSmrg    map = _XkbFindNamedIndicatorMap(sli, indicator, &led);
34384642e01fSmrg
3439f7df2e56Smrg    if (!map) {
34404642e01fSmrg        /* find first unused indicator maps and assign the name to it */
3441f7df2e56Smrg        for (led = 0, map = NULL; (led < XkbNumIndicators) && (map == NULL);
3442f7df2e56Smrg             led++) {
34434642e01fSmrg            if ((sli->names) && (sli->maps) && (sli->names[led] == None) &&
3444f7df2e56Smrg                (!XkbIM_InUse(&sli->maps[led]))) {
34454642e01fSmrg                map = &sli->maps[led];
34464642e01fSmrg                if (!dryRun)
34474642e01fSmrg                    sli->names[led] = indicator;
34484642e01fSmrg                break;
34494642e01fSmrg            }
34504642e01fSmrg        }
34514642e01fSmrg    }
34524642e01fSmrg
34534642e01fSmrg    if (!map)
34544642e01fSmrg        return BadAlloc;
34554642e01fSmrg
34564642e01fSmrg    *led_return = led;
34574642e01fSmrg    *map_return = map;
34584642e01fSmrg    return Success;
34594642e01fSmrg}
34604642e01fSmrg
34614642e01fSmrgstatic int
34624642e01fSmrg_XkbSetNamedIndicator(ClientPtr client, DeviceIntPtr dev,
3463f7df2e56Smrg                      xkbSetNamedIndicatorReq * stuff)
34644642e01fSmrg{
3465f7df2e56Smrg    unsigned int extDevReason;
3466f7df2e56Smrg    unsigned int statec, namec, mapc;
3467f7df2e56Smrg    XkbSrvLedInfoPtr sli;
3468f7df2e56Smrg    int led = 0;
3469f7df2e56Smrg    XkbIndicatorMapPtr map;
3470f7df2e56Smrg    DeviceIntPtr kbd;
3471f7df2e56Smrg    XkbEventCauseRec cause;
3472f7df2e56Smrg    xkbExtensionDeviceNotify ed;
3473f7df2e56Smrg    XkbChangesRec changes;
3474f7df2e56Smrg    int rc;
34754642e01fSmrg
34764642e01fSmrg    rc = _XkbCreateIndicatorMap(dev, stuff->indicator, stuff->ledClass,
34774642e01fSmrg                                stuff->ledID, &map, &led, FALSE);
3478f7df2e56Smrg    if (rc != Success || !map)  /* oh-oh */
34794642e01fSmrg        return rc;
34804642e01fSmrg
34814642e01fSmrg    sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID,
34824642e01fSmrg                            XkbXI_IndicatorsMask);
34834642e01fSmrg    if (!sli)
34844642e01fSmrg        return BadAlloc;
34854642e01fSmrg
34864642e01fSmrg    namec = mapc = statec = 0;
34874642e01fSmrg    extDevReason = 0;
34884642e01fSmrg
3489f7df2e56Smrg    namec |= (1 << led);
34904642e01fSmrg    sli->namesPresent |= ((stuff->indicator != None) ? (1 << led) : 0);
34914642e01fSmrg    extDevReason |= XkbXI_IndicatorNamesMask;
34924642e01fSmrg
34934642e01fSmrg    if (stuff->setMap) {
34944642e01fSmrg        map->flags = stuff->flags;
34954642e01fSmrg        map->which_groups = stuff->whichGroups;
34964642e01fSmrg        map->groups = stuff->groups;
34974642e01fSmrg        map->which_mods = stuff->whichMods;
34984642e01fSmrg        map->mods.mask = stuff->realMods;
34994642e01fSmrg        map->mods.real_mods = stuff->realMods;
3500f7df2e56Smrg        map->mods.vmods = stuff->virtualMods;
35014642e01fSmrg        map->ctrls = stuff->ctrls;
3502f7df2e56Smrg        mapc |= (1 << led);
35034642e01fSmrg    }
35044642e01fSmrg
3505f7df2e56Smrg    if ((stuff->setState) && ((map->flags & XkbIM_NoExplicit) == 0)) {
3506f7df2e56Smrg        if (stuff->on)
3507f7df2e56Smrg            sli->explicitState |= (1 << led);
3508f7df2e56Smrg        else
3509f7df2e56Smrg            sli->explicitState &= ~(1 << led);
35104642e01fSmrg        statec |= ((sli->effectiveState ^ sli->explicitState) & (1 << led));
351105b261ecSmrg    }
35124642e01fSmrg
3513f7df2e56Smrg    memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify));
3514f7df2e56Smrg    memset((char *) &changes, 0, sizeof(XkbChangesRec));
3515f7df2e56Smrg    XkbSetCauseXkbReq(&cause, X_kbSetNamedIndicator, client);
351605b261ecSmrg    if (namec)
3517f7df2e56Smrg        XkbApplyLedNameChanges(dev, sli, namec, &ed, &changes, &cause);
351805b261ecSmrg    if (mapc)
3519f7df2e56Smrg        XkbApplyLedMapChanges(dev, sli, mapc, &ed, &changes, &cause);
352005b261ecSmrg    if (statec)
3521f7df2e56Smrg        XkbApplyLedStateChanges(dev, sli, statec, &ed, &changes, &cause);
352205b261ecSmrg
35234642e01fSmrg    kbd = dev;
3524f7df2e56Smrg    if ((sli->flags & XkbSLI_HasOwnState) == 0)
35254642e01fSmrg        kbd = inputInfo.keyboard;
35264642e01fSmrg    XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause);
35274642e01fSmrg
35284642e01fSmrg    return Success;
35294642e01fSmrg}
35304642e01fSmrg
35314642e01fSmrgint
35324642e01fSmrgProcXkbSetNamedIndicator(ClientPtr client)
35334642e01fSmrg{
3534f7df2e56Smrg    int rc;
3535f7df2e56Smrg    DeviceIntPtr dev;
3536f7df2e56Smrg    int led = 0;
3537f7df2e56Smrg    XkbIndicatorMapPtr map;
35384642e01fSmrg
35394642e01fSmrg    REQUEST(xkbSetNamedIndicatorReq);
35404642e01fSmrg    REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq);
35414642e01fSmrg
3542f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
3543f7df2e56Smrg        return BadAccess;
35444642e01fSmrg
35454642e01fSmrg    CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
35464642e01fSmrg    CHK_ATOM_ONLY(stuff->indicator);
3547f7df2e56Smrg    CHK_MASK_LEGAL(0x10, stuff->whichGroups, XkbIM_UseAnyGroup);
3548f7df2e56Smrg    CHK_MASK_LEGAL(0x11, stuff->whichMods, XkbIM_UseAnyMods);
35494642e01fSmrg
35504642e01fSmrg    /* Dry-run for checks */
35514642e01fSmrg    rc = _XkbCreateIndicatorMap(dev, stuff->indicator,
35524642e01fSmrg                                stuff->ledClass, stuff->ledID,
35534642e01fSmrg                                &map, &led, TRUE);
3554f7df2e56Smrg    if (rc != Success || !map)  /* couldn't be created or didn't exist */
35554642e01fSmrg        return rc;
35564642e01fSmrg
35574642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd ||
3558f7df2e56Smrg        stuff->deviceSpec == XkbUseCorePtr) {
35594642e01fSmrg        DeviceIntPtr other;
3560f7df2e56Smrg
3561f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
3562f7df2e56Smrg            if ((other != dev) && !IsMaster(other) &&
3563f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev && (other->kbdfeed ||
3564f7df2e56Smrg                                                             other->leds) &&
3565f7df2e56Smrg                (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess)
3566f7df2e56Smrg                 == Success)) {
35674642e01fSmrg                rc = _XkbCreateIndicatorMap(other, stuff->indicator,
3568f7df2e56Smrg                                            stuff->ledClass, stuff->ledID, &map,
3569f7df2e56Smrg                                            &led, TRUE);
35704642e01fSmrg                if (rc != Success || !map)
35714642e01fSmrg                    return rc;
35724642e01fSmrg            }
35734642e01fSmrg        }
35744642e01fSmrg    }
35754642e01fSmrg
35764642e01fSmrg    /* All checks passed, let's do it */
35774642e01fSmrg    rc = _XkbSetNamedIndicator(client, dev, stuff);
35784642e01fSmrg    if (rc != Success)
35794642e01fSmrg        return rc;
35804642e01fSmrg
35814642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd ||
3582f7df2e56Smrg        stuff->deviceSpec == XkbUseCorePtr) {
35834642e01fSmrg        DeviceIntPtr other;
3584f7df2e56Smrg
3585f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
3586f7df2e56Smrg            if ((other != dev) && !IsMaster(other) &&
3587f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev && (other->kbdfeed ||
3588f7df2e56Smrg                                                             other->leds) &&
3589f7df2e56Smrg                (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess)
3590f7df2e56Smrg                 == Success)) {
35914642e01fSmrg                _XkbSetNamedIndicator(client, other, stuff);
35924642e01fSmrg            }
35934642e01fSmrg        }
35944642e01fSmrg    }
35954642e01fSmrg
35966747b715Smrg    return Success;
359705b261ecSmrg}
359805b261ecSmrg
359905b261ecSmrg/***====================================================================***/
360005b261ecSmrg
360105b261ecSmrgstatic CARD32
3602f7df2e56Smrg_XkbCountAtoms(Atom *atoms, int maxAtoms, int *count)
360305b261ecSmrg{
3604f7df2e56Smrg    register unsigned int i, bit, nAtoms;
3605f7df2e56Smrg    register CARD32 atomsPresent;
360605b261ecSmrg
3607f7df2e56Smrg    for (i = nAtoms = atomsPresent = 0, bit = 1; i < maxAtoms; i++, bit <<= 1) {
3608f7df2e56Smrg        if (atoms[i] != None) {
3609f7df2e56Smrg            atomsPresent |= bit;
3610f7df2e56Smrg            nAtoms++;
3611f7df2e56Smrg        }
361205b261ecSmrg    }
361305b261ecSmrg    if (count)
3614f7df2e56Smrg        *count = nAtoms;
361505b261ecSmrg    return atomsPresent;
361605b261ecSmrg}
361705b261ecSmrg
361805b261ecSmrgstatic char *
3619f7df2e56Smrg_XkbWriteAtoms(char *wire, Atom *atoms, int maxAtoms, int swap)
362005b261ecSmrg{
3621f7df2e56Smrg    register unsigned int i;
3622f7df2e56Smrg    Atom *atm;
3623f7df2e56Smrg
3624f7df2e56Smrg    atm = (Atom *) wire;
3625f7df2e56Smrg    for (i = 0; i < maxAtoms; i++) {
3626f7df2e56Smrg        if (atoms[i] != None) {
3627f7df2e56Smrg            *atm = atoms[i];
3628f7df2e56Smrg            if (swap) {
3629f7df2e56Smrg                swapl(atm);
3630f7df2e56Smrg            }
3631f7df2e56Smrg            atm++;
3632f7df2e56Smrg        }
3633f7df2e56Smrg    }
3634f7df2e56Smrg    return (char *) atm;
363505b261ecSmrg}
363605b261ecSmrg
363705b261ecSmrgstatic Status
3638f7df2e56SmrgXkbComputeGetNamesReplySize(XkbDescPtr xkb, xkbGetNamesReply * rep)
363905b261ecSmrg{
3640f7df2e56Smrg    register unsigned which, length;
3641f7df2e56Smrg    register int i;
3642f7df2e56Smrg
3643f7df2e56Smrg    rep->minKeyCode = xkb->min_key_code;
3644f7df2e56Smrg    rep->maxKeyCode = xkb->max_key_code;
3645f7df2e56Smrg    which = rep->which;
3646f7df2e56Smrg    length = 0;
3647f7df2e56Smrg    if (xkb->names != NULL) {
3648f7df2e56Smrg        if (which & XkbKeycodesNameMask)
3649f7df2e56Smrg            length++;
3650f7df2e56Smrg        if (which & XkbGeometryNameMask)
3651f7df2e56Smrg            length++;
3652f7df2e56Smrg        if (which & XkbSymbolsNameMask)
3653f7df2e56Smrg            length++;
3654f7df2e56Smrg        if (which & XkbPhysSymbolsNameMask)
3655f7df2e56Smrg            length++;
3656f7df2e56Smrg        if (which & XkbTypesNameMask)
3657f7df2e56Smrg            length++;
3658f7df2e56Smrg        if (which & XkbCompatNameMask)
3659f7df2e56Smrg            length++;
3660f7df2e56Smrg    }
3661f7df2e56Smrg    else
3662f7df2e56Smrg        which &= ~XkbComponentNamesMask;
3663f7df2e56Smrg
3664f7df2e56Smrg    if (xkb->map != NULL) {
3665f7df2e56Smrg        if (which & XkbKeyTypeNamesMask)
3666f7df2e56Smrg            length += xkb->map->num_types;
3667f7df2e56Smrg        rep->nTypes = xkb->map->num_types;
3668f7df2e56Smrg        if (which & XkbKTLevelNamesMask) {
3669f7df2e56Smrg            XkbKeyTypePtr pType = xkb->map->types;
3670f7df2e56Smrg            int nKTLevels = 0;
3671f7df2e56Smrg
3672f7df2e56Smrg            length += XkbPaddedSize(xkb->map->num_types) / 4;
3673f7df2e56Smrg            for (i = 0; i < xkb->map->num_types; i++, pType++) {
3674f7df2e56Smrg                if (pType->level_names != NULL)
3675f7df2e56Smrg                    nKTLevels += pType->num_levels;
3676f7df2e56Smrg            }
3677f7df2e56Smrg            rep->nKTLevels = nKTLevels;
3678f7df2e56Smrg            length += nKTLevels;
3679f7df2e56Smrg        }
368005b261ecSmrg    }
368105b261ecSmrg    else {
3682f7df2e56Smrg        rep->nTypes = 0;
3683f7df2e56Smrg        rep->nKTLevels = 0;
3684f7df2e56Smrg        which &= ~(XkbKeyTypeNamesMask | XkbKTLevelNamesMask);
3685f7df2e56Smrg    }
3686f7df2e56Smrg
3687f7df2e56Smrg    rep->minKeyCode = xkb->min_key_code;
3688f7df2e56Smrg    rep->maxKeyCode = xkb->max_key_code;
3689f7df2e56Smrg    rep->indicators = 0;
3690f7df2e56Smrg    rep->virtualMods = 0;
3691f7df2e56Smrg    rep->groupNames = 0;
3692f7df2e56Smrg    if (xkb->names != NULL) {
3693f7df2e56Smrg        if (which & XkbIndicatorNamesMask) {
3694f7df2e56Smrg            int nLeds;
3695f7df2e56Smrg
3696f7df2e56Smrg            rep->indicators =
3697f7df2e56Smrg                _XkbCountAtoms(xkb->names->indicators, XkbNumIndicators,
3698f7df2e56Smrg                               &nLeds);
3699f7df2e56Smrg            length += nLeds;
3700f7df2e56Smrg            if (nLeds == 0)
3701f7df2e56Smrg                which &= ~XkbIndicatorNamesMask;
3702f7df2e56Smrg        }
3703f7df2e56Smrg
3704f7df2e56Smrg        if (which & XkbVirtualModNamesMask) {
3705f7df2e56Smrg            int nVMods;
3706f7df2e56Smrg
3707f7df2e56Smrg            rep->virtualMods =
3708f7df2e56Smrg                _XkbCountAtoms(xkb->names->vmods, XkbNumVirtualMods, &nVMods);
3709f7df2e56Smrg            length += nVMods;
3710f7df2e56Smrg            if (nVMods == 0)
3711f7df2e56Smrg                which &= ~XkbVirtualModNamesMask;
3712f7df2e56Smrg        }
3713f7df2e56Smrg
3714f7df2e56Smrg        if (which & XkbGroupNamesMask) {
3715f7df2e56Smrg            int nGroups;
3716f7df2e56Smrg
3717f7df2e56Smrg            rep->groupNames =
3718f7df2e56Smrg                _XkbCountAtoms(xkb->names->groups, XkbNumKbdGroups, &nGroups);
3719f7df2e56Smrg            length += nGroups;
3720f7df2e56Smrg            if (nGroups == 0)
3721f7df2e56Smrg                which &= ~XkbGroupNamesMask;
3722f7df2e56Smrg        }
3723f7df2e56Smrg
3724f7df2e56Smrg        if ((which & XkbKeyNamesMask) && (xkb->names->keys))
3725f7df2e56Smrg            length += rep->nKeys;
3726f7df2e56Smrg        else
3727f7df2e56Smrg            which &= ~XkbKeyNamesMask;
3728f7df2e56Smrg
3729f7df2e56Smrg        if ((which & XkbKeyAliasesMask) &&
3730f7df2e56Smrg            (xkb->names->key_aliases) && (xkb->names->num_key_aliases > 0)) {
3731f7df2e56Smrg            rep->nKeyAliases = xkb->names->num_key_aliases;
3732f7df2e56Smrg            length += rep->nKeyAliases * 2;
3733f7df2e56Smrg        }
3734f7df2e56Smrg        else {
3735f7df2e56Smrg            which &= ~XkbKeyAliasesMask;
3736f7df2e56Smrg            rep->nKeyAliases = 0;
3737f7df2e56Smrg        }
3738f7df2e56Smrg
3739f7df2e56Smrg        if ((which & XkbRGNamesMask) && (xkb->names->num_rg > 0))
3740f7df2e56Smrg            length += xkb->names->num_rg;
3741f7df2e56Smrg        else
3742f7df2e56Smrg            which &= ~XkbRGNamesMask;
374305b261ecSmrg    }
374405b261ecSmrg    else {
3745f7df2e56Smrg        which &= ~(XkbIndicatorNamesMask | XkbVirtualModNamesMask);
3746f7df2e56Smrg        which &= ~(XkbGroupNamesMask | XkbKeyNamesMask | XkbKeyAliasesMask);
3747f7df2e56Smrg        which &= ~XkbRGNamesMask;
374805b261ecSmrg    }
374905b261ecSmrg
3750f7df2e56Smrg    rep->length = length;
3751f7df2e56Smrg    rep->which = which;
375205b261ecSmrg    return Success;
375305b261ecSmrg}
375405b261ecSmrg
375505b261ecSmrgstatic int
3756f7df2e56SmrgXkbSendNames(ClientPtr client, XkbDescPtr xkb, xkbGetNamesReply * rep)
375705b261ecSmrg{
3758f7df2e56Smrg    register unsigned i, length, which;
3759f7df2e56Smrg    char *start;
3760f7df2e56Smrg    char *desc;
376105b261ecSmrg
3762f7df2e56Smrg    length = rep->length * 4;
3763f7df2e56Smrg    which = rep->which;
376405b261ecSmrg    if (client->swapped) {
3765f7df2e56Smrg        swaps(&rep->sequenceNumber);
3766f7df2e56Smrg        swapl(&rep->length);
3767f7df2e56Smrg        swapl(&rep->which);
3768f7df2e56Smrg        swaps(&rep->virtualMods);
3769f7df2e56Smrg        swapl(&rep->indicators);
377005b261ecSmrg    }
377105b261ecSmrg
37729ace9065Smrg    start = desc = calloc(1, length);
3773f7df2e56Smrg    if (!start)
3774f7df2e56Smrg        return BadAlloc;
377505b261ecSmrg    if (xkb->names) {
3776f7df2e56Smrg        if (which & XkbKeycodesNameMask) {
3777f7df2e56Smrg            *((CARD32 *) desc) = xkb->names->keycodes;
377805b261ecSmrg            if (client->swapped) {
3779f7df2e56Smrg                swapl((int *) desc);
378005b261ecSmrg            }
3781f7df2e56Smrg            desc += 4;
378205b261ecSmrg        }
3783f7df2e56Smrg        if (which & XkbGeometryNameMask) {
3784f7df2e56Smrg            *((CARD32 *) desc) = xkb->names->geometry;
378505b261ecSmrg            if (client->swapped) {
3786f7df2e56Smrg                swapl((int *) desc);
378705b261ecSmrg            }
3788f7df2e56Smrg            desc += 4;
378905b261ecSmrg        }
3790f7df2e56Smrg        if (which & XkbSymbolsNameMask) {
3791f7df2e56Smrg            *((CARD32 *) desc) = xkb->names->symbols;
379205b261ecSmrg            if (client->swapped) {
3793f7df2e56Smrg                swapl((int *) desc);
379405b261ecSmrg            }
3795f7df2e56Smrg            desc += 4;
379605b261ecSmrg        }
3797f7df2e56Smrg        if (which & XkbPhysSymbolsNameMask) {
3798f7df2e56Smrg            register CARD32 *atm = (CARD32 *) desc;
3799f7df2e56Smrg
3800f7df2e56Smrg            atm[0] = (CARD32) xkb->names->phys_symbols;
380105b261ecSmrg            if (client->swapped) {
3802f7df2e56Smrg                swapl(&atm[0]);
380305b261ecSmrg            }
3804f7df2e56Smrg            desc += 4;
380505b261ecSmrg        }
3806f7df2e56Smrg        if (which & XkbTypesNameMask) {
3807f7df2e56Smrg            *((CARD32 *) desc) = (CARD32) xkb->names->types;
380805b261ecSmrg            if (client->swapped) {
3809f7df2e56Smrg                swapl((int *) desc);
381005b261ecSmrg            }
3811f7df2e56Smrg            desc += 4;
381205b261ecSmrg        }
3813f7df2e56Smrg        if (which & XkbCompatNameMask) {
3814f7df2e56Smrg            *((CARD32 *) desc) = (CARD32) xkb->names->compat;
381505b261ecSmrg            if (client->swapped) {
3816f7df2e56Smrg                swapl((int *) desc);
381705b261ecSmrg            }
3818f7df2e56Smrg            desc += 4;
381905b261ecSmrg        }
3820f7df2e56Smrg        if (which & XkbKeyTypeNamesMask) {
3821f7df2e56Smrg            register CARD32 *atm = (CARD32 *) desc;
3822f7df2e56Smrg            register XkbKeyTypePtr type = xkb->map->types;
382305b261ecSmrg
3824f7df2e56Smrg            for (i = 0; i < xkb->map->num_types; i++, atm++, type++) {
3825f7df2e56Smrg                *atm = (CARD32) type->name;
382605b261ecSmrg                if (client->swapped) {
3827f7df2e56Smrg                    swapl(atm);
382805b261ecSmrg                }
382905b261ecSmrg            }
3830f7df2e56Smrg            desc = (char *) atm;
383105b261ecSmrg        }
3832f7df2e56Smrg        if (which & XkbKTLevelNamesMask && xkb->map) {
383305b261ecSmrg            XkbKeyTypePtr type = xkb->map->types;
383405b261ecSmrg            register CARD32 *atm;
3835f7df2e56Smrg
3836f7df2e56Smrg            for (i = 0; i < rep->nTypes; i++, type++) {
383705b261ecSmrg                *desc++ = type->num_levels;
383805b261ecSmrg            }
3839f7df2e56Smrg            desc += XkbPaddedSize(rep->nTypes) - rep->nTypes;
384005b261ecSmrg
3841f7df2e56Smrg            atm = (CARD32 *) desc;
384205b261ecSmrg            type = xkb->map->types;
3843f7df2e56Smrg            for (i = 0; i < xkb->map->num_types; i++, type++) {
384405b261ecSmrg                register unsigned l;
3845f7df2e56Smrg
384605b261ecSmrg                if (type->level_names) {
3847f7df2e56Smrg                    for (l = 0; l < type->num_levels; l++, atm++) {
3848f7df2e56Smrg                        *atm = type->level_names[l];
384905b261ecSmrg                        if (client->swapped) {
3850f7df2e56Smrg                            swapl(atm);
385105b261ecSmrg                        }
385205b261ecSmrg                    }
3853f7df2e56Smrg                    desc += type->num_levels * 4;
385405b261ecSmrg                }
385505b261ecSmrg            }
385605b261ecSmrg        }
3857f7df2e56Smrg        if (which & XkbIndicatorNamesMask) {
3858f7df2e56Smrg            desc =
3859f7df2e56Smrg                _XkbWriteAtoms(desc, xkb->names->indicators, XkbNumIndicators,
3860f7df2e56Smrg                               client->swapped);
386105b261ecSmrg        }
3862f7df2e56Smrg        if (which & XkbVirtualModNamesMask) {
3863f7df2e56Smrg            desc = _XkbWriteAtoms(desc, xkb->names->vmods, XkbNumVirtualMods,
3864f7df2e56Smrg                                  client->swapped);
386505b261ecSmrg        }
3866f7df2e56Smrg        if (which & XkbGroupNamesMask) {
3867f7df2e56Smrg            desc = _XkbWriteAtoms(desc, xkb->names->groups, XkbNumKbdGroups,
3868f7df2e56Smrg                                  client->swapped);
386905b261ecSmrg        }
3870f7df2e56Smrg        if (which & XkbKeyNamesMask) {
3871f7df2e56Smrg            for (i = 0; i < rep->nKeys; i++, desc += sizeof(XkbKeyNameRec)) {
3872f7df2e56Smrg                *((XkbKeyNamePtr) desc) = xkb->names->keys[i + rep->firstKey];
387305b261ecSmrg            }
387405b261ecSmrg        }
3875f7df2e56Smrg        if (which & XkbKeyAliasesMask) {
3876f7df2e56Smrg            XkbKeyAliasPtr pAl;
3877f7df2e56Smrg
3878f7df2e56Smrg            pAl = xkb->names->key_aliases;
3879f7df2e56Smrg            for (i = 0; i < rep->nKeyAliases;
3880f7df2e56Smrg                 i++, pAl++, desc += 2 * XkbKeyNameLength) {
3881f7df2e56Smrg                *((XkbKeyAliasPtr) desc) = *pAl;
388205b261ecSmrg            }
388305b261ecSmrg        }
3884f7df2e56Smrg        if ((which & XkbRGNamesMask) && (rep->nRadioGroups > 0)) {
3885f7df2e56Smrg            register CARD32 *atm = (CARD32 *) desc;
3886f7df2e56Smrg
3887f7df2e56Smrg            for (i = 0; i < rep->nRadioGroups; i++, atm++) {
3888f7df2e56Smrg                *atm = (CARD32) xkb->names->radio_groups[i];
388905b261ecSmrg                if (client->swapped) {
3890f7df2e56Smrg                    swapl(atm);
389105b261ecSmrg                }
389205b261ecSmrg            }
3893f7df2e56Smrg            desc += rep->nRadioGroups * 4;
389405b261ecSmrg        }
389505b261ecSmrg    }
389605b261ecSmrg
3897f7df2e56Smrg    if ((desc - start) != (length)) {
3898f7df2e56Smrg        ErrorF("[xkb] BOGUS LENGTH in write names, expected %d, got %ld\n",
3899f7df2e56Smrg               length, (unsigned long) (desc - start));
390005b261ecSmrg    }
3901f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetNamesReply), rep);
390205b261ecSmrg    WriteToClient(client, length, start);
3903f7df2e56Smrg    free((char *) start);
39046747b715Smrg    return Success;
390505b261ecSmrg}
390605b261ecSmrg
390705b261ecSmrgint
390805b261ecSmrgProcXkbGetNames(ClientPtr client)
390905b261ecSmrg{
3910f7df2e56Smrg    DeviceIntPtr dev;
3911f7df2e56Smrg    XkbDescPtr xkb;
3912f7df2e56Smrg    xkbGetNamesReply rep;
391305b261ecSmrg
391405b261ecSmrg    REQUEST(xkbGetNamesReq);
391505b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetNamesReq);
391605b261ecSmrg
3917f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
3918f7df2e56Smrg        return BadAccess;
391905b261ecSmrg
39204642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
3921f7df2e56Smrg    CHK_MASK_LEGAL(0x01, stuff->which, XkbAllNamesMask);
392205b261ecSmrg
392305b261ecSmrg    xkb = dev->key->xkbInfo->desc;
3924f7df2e56Smrg    rep = (xkbGetNamesReply) {
3925f7df2e56Smrg        .type = X_Reply,
3926f7df2e56Smrg        .deviceID = dev->id,
3927f7df2e56Smrg        .sequenceNumber = client->sequence,
3928f7df2e56Smrg        .length = 0,
3929f7df2e56Smrg        .which = stuff->which,
3930f7df2e56Smrg        .nTypes = xkb->map->num_types,
3931f7df2e56Smrg        .firstKey = xkb->min_key_code,
3932f7df2e56Smrg        .nKeys = XkbNumKeys(xkb),
3933f7df2e56Smrg        .nKeyAliases = xkb->names ? xkb->names->num_key_aliases : 0,
3934f7df2e56Smrg        .nRadioGroups = xkb->names ? xkb->names->num_rg : 0
3935f7df2e56Smrg    };
3936f7df2e56Smrg    XkbComputeGetNamesReplySize(xkb, &rep);
3937f7df2e56Smrg    return XkbSendNames(client, xkb, &rep);
393805b261ecSmrg}
393905b261ecSmrg
394005b261ecSmrg/***====================================================================***/
394105b261ecSmrg
394205b261ecSmrgstatic CARD32 *
3943f7df2e56Smrg_XkbCheckAtoms(CARD32 *wire, int nAtoms, int swapped, Atom *pError)
394405b261ecSmrg{
3945f7df2e56Smrg    register int i;
3946f7df2e56Smrg
3947f7df2e56Smrg    for (i = 0; i < nAtoms; i++, wire++) {
3948f7df2e56Smrg        if (swapped) {
3949f7df2e56Smrg            swapl(wire);
3950f7df2e56Smrg        }
3951f7df2e56Smrg        if ((((Atom) *wire) != None) && (!ValidAtom((Atom) *wire))) {
3952f7df2e56Smrg            *pError = ((Atom) *wire);
3953f7df2e56Smrg            return NULL;
3954f7df2e56Smrg        }
395505b261ecSmrg    }
395605b261ecSmrg    return wire;
395705b261ecSmrg}
395805b261ecSmrg
395905b261ecSmrgstatic CARD32 *
3960f7df2e56Smrg_XkbCheckMaskedAtoms(CARD32 *wire, int nAtoms, CARD32 present, int swapped,
3961f7df2e56Smrg                     Atom *pError)
396205b261ecSmrg{
3963f7df2e56Smrg    register unsigned i, bit;
3964f7df2e56Smrg
3965f7df2e56Smrg    for (i = 0, bit = 1; (i < nAtoms) && (present); i++, bit <<= 1) {
3966f7df2e56Smrg        if ((present & bit) == 0)
3967f7df2e56Smrg            continue;
3968f7df2e56Smrg        if (swapped) {
3969f7df2e56Smrg            swapl(wire);
3970f7df2e56Smrg        }
3971f7df2e56Smrg        if ((((Atom) *wire) != None) && (!ValidAtom(((Atom) *wire)))) {
3972f7df2e56Smrg            *pError = (Atom) *wire;
3973f7df2e56Smrg            return NULL;
3974f7df2e56Smrg        }
3975f7df2e56Smrg        wire++;
397605b261ecSmrg    }
397705b261ecSmrg    return wire;
397805b261ecSmrg}
397905b261ecSmrg
398005b261ecSmrgstatic Atom *
3981f7df2e56Smrg_XkbCopyMaskedAtoms(Atom *wire, Atom *dest, int nAtoms, CARD32 present)
398205b261ecSmrg{
3983f7df2e56Smrg    register int i, bit;
398405b261ecSmrg
3985f7df2e56Smrg    for (i = 0, bit = 1; (i < nAtoms) && (present); i++, bit <<= 1) {
3986f7df2e56Smrg        if ((present & bit) == 0)
3987f7df2e56Smrg            continue;
3988f7df2e56Smrg        dest[i] = *wire++;
398905b261ecSmrg    }
399005b261ecSmrg    return wire;
399105b261ecSmrg}
399205b261ecSmrg
399305b261ecSmrgstatic Bool
3994f7df2e56Smrg_XkbCheckTypeName(Atom name, int typeNdx)
399505b261ecSmrg{
3996f7df2e56Smrg    const char *str;
399705b261ecSmrg
3998f7df2e56Smrg    str = NameForAtom(name);
3999f7df2e56Smrg    if ((strcmp(str, "ONE_LEVEL") == 0) || (strcmp(str, "TWO_LEVEL") == 0) ||
4000f7df2e56Smrg        (strcmp(str, "ALPHABETIC") == 0) || (strcmp(str, "KEYPAD") == 0))
4001f7df2e56Smrg        return FALSE;
40026747b715Smrg    return TRUE;
400305b261ecSmrg}
400405b261ecSmrg
40054642e01fSmrg/**
40064642e01fSmrg * Check the device-dependent data in the request against the device. Returns
40074642e01fSmrg * Success, or the appropriate error code.
40084642e01fSmrg */
40094642e01fSmrgstatic int
40104642e01fSmrg_XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
4011f7df2e56Smrg                  xkbSetNamesReq * stuff, CARD32 *data)
401205b261ecSmrg{
4013f7df2e56Smrg    XkbDescRec *xkb;
4014f7df2e56Smrg    CARD32 *tmp;
4015f7df2e56Smrg    Atom bad = None;
401605b261ecSmrg
40174642e01fSmrg    tmp = data;
40184642e01fSmrg    xkb = dev->key->xkbInfo->desc;
40194642e01fSmrg
40204642e01fSmrg    if (stuff->which & XkbKeyTypeNamesMask) {
40214642e01fSmrg        int i;
4022f7df2e56Smrg        CARD32 *old;
4023f7df2e56Smrg
4024f7df2e56Smrg        if (stuff->nTypes < 1) {
4025f7df2e56Smrg            client->errorValue = _XkbErrCode2(0x02, stuff->nTypes);
40264642e01fSmrg            return BadValue;
40274642e01fSmrg        }
4028f7df2e56Smrg        if ((unsigned) (stuff->firstType + stuff->nTypes - 1) >=
4029f7df2e56Smrg            xkb->map->num_types) {
4030f7df2e56Smrg            client->errorValue =
4031f7df2e56Smrg                _XkbErrCode4(0x03, stuff->firstType, stuff->nTypes,
4032f7df2e56Smrg                             xkb->map->num_types);
40334642e01fSmrg            return BadValue;
40344642e01fSmrg        }
4035f7df2e56Smrg        if (((unsigned) stuff->firstType) <= XkbLastRequiredType) {
4036f7df2e56Smrg            client->errorValue = _XkbErrCode2(0x04, stuff->firstType);
40374642e01fSmrg            return BadAccess;
40384642e01fSmrg        }
4039f7df2e56Smrg        old = tmp;
4040f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, stuff->nTypes, client->swapped, &bad);
40414642e01fSmrg        if (!tmp) {
4042f7df2e56Smrg            client->errorValue = bad;
40434642e01fSmrg            return BadAtom;
40444642e01fSmrg        }
4045f7df2e56Smrg        for (i = 0; i < stuff->nTypes; i++, old++) {
4046f7df2e56Smrg            if (!_XkbCheckTypeName((Atom) *old, stuff->firstType + i))
4047f7df2e56Smrg                client->errorValue = _XkbErrCode2(0x05, i);
40484642e01fSmrg        }
40494642e01fSmrg    }
4050f7df2e56Smrg    if (stuff->which & XkbKTLevelNamesMask) {
40514642e01fSmrg        unsigned i;
4052f7df2e56Smrg        XkbKeyTypePtr type;
4053f7df2e56Smrg        CARD8 *width;
4054f7df2e56Smrg
4055f7df2e56Smrg        if (stuff->nKTLevels < 1) {
4056f7df2e56Smrg            client->errorValue = _XkbErrCode2(0x05, stuff->nKTLevels);
40574642e01fSmrg            return BadValue;
40584642e01fSmrg        }
4059f7df2e56Smrg        if ((unsigned) (stuff->firstKTLevel + stuff->nKTLevels - 1) >=
4060f7df2e56Smrg            xkb->map->num_types) {
4061f7df2e56Smrg            client->errorValue = _XkbErrCode4(0x06, stuff->firstKTLevel,
4062f7df2e56Smrg                                              stuff->nKTLevels,
4063f7df2e56Smrg                                              xkb->map->num_types);
40644642e01fSmrg            return BadValue;
40654642e01fSmrg        }
4066f7df2e56Smrg        width = (CARD8 *) tmp;
4067f7df2e56Smrg        tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels));
40684642e01fSmrg        type = &xkb->map->types[stuff->firstKTLevel];
4069f7df2e56Smrg        for (i = 0; i < stuff->nKTLevels; i++, type++) {
4070f7df2e56Smrg            if (width[i] == 0)
40714642e01fSmrg                continue;
4072f7df2e56Smrg            else if (width[i] != type->num_levels) {
4073f7df2e56Smrg                client->errorValue = _XkbErrCode4(0x07, i + stuff->firstKTLevel,
4074f7df2e56Smrg                                                  type->num_levels, width[i]);
40754642e01fSmrg                return BadMatch;
40764642e01fSmrg            }
4077f7df2e56Smrg            tmp = _XkbCheckAtoms(tmp, width[i], client->swapped, &bad);
40784642e01fSmrg            if (!tmp) {
4079f7df2e56Smrg                client->errorValue = bad;
40804642e01fSmrg                return BadAtom;
40814642e01fSmrg            }
40824642e01fSmrg        }
40834642e01fSmrg    }
4084f7df2e56Smrg    if (stuff->which & XkbIndicatorNamesMask) {
4085f7df2e56Smrg        if (stuff->indicators == 0) {
4086f7df2e56Smrg            client->errorValue = 0x08;
40874642e01fSmrg            return BadMatch;
40884642e01fSmrg        }
4089f7df2e56Smrg        tmp = _XkbCheckMaskedAtoms(tmp, XkbNumIndicators, stuff->indicators,
4090f7df2e56Smrg                                   client->swapped, &bad);
40914642e01fSmrg        if (!tmp) {
4092f7df2e56Smrg            client->errorValue = bad;
40934642e01fSmrg            return BadAtom;
40944642e01fSmrg        }
40954642e01fSmrg    }
4096f7df2e56Smrg    if (stuff->which & XkbVirtualModNamesMask) {
4097f7df2e56Smrg        if (stuff->virtualMods == 0) {
4098f7df2e56Smrg            client->errorValue = 0x09;
40994642e01fSmrg            return BadMatch;
41004642e01fSmrg        }
4101f7df2e56Smrg        tmp = _XkbCheckMaskedAtoms(tmp, XkbNumVirtualMods,
4102f7df2e56Smrg                                   (CARD32) stuff->virtualMods,
4103f7df2e56Smrg                                   client->swapped, &bad);
41044642e01fSmrg        if (!tmp) {
41054642e01fSmrg            client->errorValue = bad;
41064642e01fSmrg            return BadAtom;
41074642e01fSmrg        }
41084642e01fSmrg    }
4109f7df2e56Smrg    if (stuff->which & XkbGroupNamesMask) {
4110f7df2e56Smrg        if (stuff->groupNames == 0) {
4111f7df2e56Smrg            client->errorValue = 0x0a;
41124642e01fSmrg            return BadMatch;
41134642e01fSmrg        }
4114f7df2e56Smrg        tmp = _XkbCheckMaskedAtoms(tmp, XkbNumKbdGroups,
4115f7df2e56Smrg                                   (CARD32) stuff->groupNames,
4116f7df2e56Smrg                                   client->swapped, &bad);
41174642e01fSmrg        if (!tmp) {
41184642e01fSmrg            client->errorValue = bad;
41194642e01fSmrg            return BadAtom;
41204642e01fSmrg        }
41214642e01fSmrg    }
4122f7df2e56Smrg    if (stuff->which & XkbKeyNamesMask) {
4123f7df2e56Smrg        if (stuff->firstKey < (unsigned) xkb->min_key_code) {
4124f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x0b, xkb->min_key_code,
4125f7df2e56Smrg                                              stuff->firstKey);
41264642e01fSmrg            return BadValue;
41274642e01fSmrg        }
4128f7df2e56Smrg        if (((unsigned) (stuff->firstKey + stuff->nKeys - 1) >
4129f7df2e56Smrg             xkb->max_key_code) || (stuff->nKeys < 1)) {
4130f7df2e56Smrg            client->errorValue =
4131f7df2e56Smrg                _XkbErrCode4(0x0c, xkb->max_key_code, stuff->firstKey,
4132f7df2e56Smrg                             stuff->nKeys);
41334642e01fSmrg            return BadValue;
41344642e01fSmrg        }
4135f7df2e56Smrg        tmp += stuff->nKeys;
41364642e01fSmrg    }
4137f7df2e56Smrg    if ((stuff->which & XkbKeyAliasesMask) && (stuff->nKeyAliases > 0)) {
4138f7df2e56Smrg        tmp += stuff->nKeyAliases * 2;
41394642e01fSmrg    }
4140f7df2e56Smrg    if (stuff->which & XkbRGNamesMask) {
4141f7df2e56Smrg        if (stuff->nRadioGroups < 1) {
4142f7df2e56Smrg            client->errorValue = _XkbErrCode2(0x0d, stuff->nRadioGroups);
41434642e01fSmrg            return BadValue;
41444642e01fSmrg        }
4145f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, stuff->nRadioGroups, client->swapped, &bad);
41464642e01fSmrg        if (!tmp) {
4147f7df2e56Smrg            client->errorValue = bad;
41484642e01fSmrg            return BadAtom;
41494642e01fSmrg        }
41504642e01fSmrg    }
4151f7df2e56Smrg    if ((tmp - ((CARD32 *) stuff)) != stuff->length) {
41524642e01fSmrg        client->errorValue = stuff->length;
41534642e01fSmrg        return BadLength;
41544642e01fSmrg    }
41554642e01fSmrg
41564642e01fSmrg    return Success;
41574642e01fSmrg}
41584642e01fSmrg
41594642e01fSmrgstatic int
4160f7df2e56Smrg_XkbSetNames(ClientPtr client, DeviceIntPtr dev, xkbSetNamesReq * stuff)
41614642e01fSmrg{
4162f7df2e56Smrg    XkbDescRec *xkb;
4163f7df2e56Smrg    XkbNamesRec *names;
4164f7df2e56Smrg    CARD32 *tmp;
4165f7df2e56Smrg    xkbNamesNotify nn;
41664642e01fSmrg
4167f7df2e56Smrg    tmp = (CARD32 *) &stuff[1];
41684642e01fSmrg    xkb = dev->key->xkbInfo->desc;
41694642e01fSmrg    names = xkb->names;
41704642e01fSmrg
4171f7df2e56Smrg    if (XkbAllocNames(xkb, stuff->which, stuff->nRadioGroups,
4172f7df2e56Smrg                      stuff->nKeyAliases) != Success) {
41734642e01fSmrg        return BadAlloc;
41744642e01fSmrg    }
41754642e01fSmrg
41766747b715Smrg    memset(&nn, 0, sizeof(xkbNamesNotify));
4177f7df2e56Smrg    nn.changed = stuff->which;
4178f7df2e56Smrg    tmp = (CARD32 *) &stuff[1];
4179f7df2e56Smrg    if (stuff->which & XkbKeycodesNameMask)
4180f7df2e56Smrg        names->keycodes = *tmp++;
4181f7df2e56Smrg    if (stuff->which & XkbGeometryNameMask)
4182f7df2e56Smrg        names->geometry = *tmp++;
4183f7df2e56Smrg    if (stuff->which & XkbSymbolsNameMask)
4184f7df2e56Smrg        names->symbols = *tmp++;
4185f7df2e56Smrg    if (stuff->which & XkbPhysSymbolsNameMask)
4186f7df2e56Smrg        names->phys_symbols = *tmp++;
4187f7df2e56Smrg    if (stuff->which & XkbTypesNameMask)
4188f7df2e56Smrg        names->types = *tmp++;
4189f7df2e56Smrg    if (stuff->which & XkbCompatNameMask)
4190f7df2e56Smrg        names->compat = *tmp++;
4191f7df2e56Smrg    if ((stuff->which & XkbKeyTypeNamesMask) && (stuff->nTypes > 0)) {
41924642e01fSmrg        register unsigned i;
41934642e01fSmrg        register XkbKeyTypePtr type;
41944642e01fSmrg
4195f7df2e56Smrg        type = &xkb->map->types[stuff->firstType];
4196f7df2e56Smrg        for (i = 0; i < stuff->nTypes; i++, type++) {
4197f7df2e56Smrg            type->name = *tmp++;
41984642e01fSmrg        }
4199f7df2e56Smrg        nn.firstType = stuff->firstType;
4200f7df2e56Smrg        nn.nTypes = stuff->nTypes;
42014642e01fSmrg    }
4202f7df2e56Smrg    if (stuff->which & XkbKTLevelNamesMask) {
4203f7df2e56Smrg        register XkbKeyTypePtr type;
42044642e01fSmrg        register unsigned i;
42054642e01fSmrg        CARD8 *width;
42064642e01fSmrg
4207f7df2e56Smrg        width = (CARD8 *) tmp;
4208f7df2e56Smrg        tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels));
4209f7df2e56Smrg        type = &xkb->map->types[stuff->firstKTLevel];
4210f7df2e56Smrg        for (i = 0; i < stuff->nKTLevels; i++, type++) {
4211f7df2e56Smrg            if (width[i] > 0) {
42124642e01fSmrg                if (type->level_names) {
42134642e01fSmrg                    register unsigned n;
4214f7df2e56Smrg
4215f7df2e56Smrg                    for (n = 0; n < width[i]; n++) {
4216f7df2e56Smrg                        type->level_names[n] = tmp[n];
42174642e01fSmrg                    }
42184642e01fSmrg                }
4219f7df2e56Smrg                tmp += width[i];
42204642e01fSmrg            }
42214642e01fSmrg        }
4222f7df2e56Smrg        nn.firstLevelName = 0;
4223f7df2e56Smrg        nn.nLevelNames = stuff->nTypes;
4224f7df2e56Smrg    }
4225f7df2e56Smrg    if (stuff->which & XkbIndicatorNamesMask) {
4226f7df2e56Smrg        tmp = _XkbCopyMaskedAtoms(tmp, names->indicators, XkbNumIndicators,
4227f7df2e56Smrg                                  stuff->indicators);
4228f7df2e56Smrg        nn.changedIndicators = stuff->indicators;
4229f7df2e56Smrg    }
4230f7df2e56Smrg    if (stuff->which & XkbVirtualModNamesMask) {
4231f7df2e56Smrg        tmp = _XkbCopyMaskedAtoms(tmp, names->vmods, XkbNumVirtualMods,
4232f7df2e56Smrg                                  stuff->virtualMods);
4233f7df2e56Smrg        nn.changedVirtualMods = stuff->virtualMods;
4234f7df2e56Smrg    }
4235f7df2e56Smrg    if (stuff->which & XkbGroupNamesMask) {
4236f7df2e56Smrg        tmp = _XkbCopyMaskedAtoms(tmp, names->groups, XkbNumKbdGroups,
4237f7df2e56Smrg                                  stuff->groupNames);
4238f7df2e56Smrg        nn.changedVirtualMods = stuff->groupNames;
4239f7df2e56Smrg    }
4240f7df2e56Smrg    if (stuff->which & XkbKeyNamesMask) {
4241f7df2e56Smrg        memcpy((char *) &names->keys[stuff->firstKey], (char *) tmp,
4242f7df2e56Smrg               stuff->nKeys * XkbKeyNameLength);
4243f7df2e56Smrg        tmp += stuff->nKeys;
4244f7df2e56Smrg        nn.firstKey = stuff->firstKey;
4245f7df2e56Smrg        nn.nKeys = stuff->nKeys;
4246f7df2e56Smrg    }
4247f7df2e56Smrg    if (stuff->which & XkbKeyAliasesMask) {
4248f7df2e56Smrg        if (stuff->nKeyAliases > 0) {
4249f7df2e56Smrg            register int na = stuff->nKeyAliases;
4250f7df2e56Smrg
4251f7df2e56Smrg            if (XkbAllocNames(xkb, XkbKeyAliasesMask, 0, na) != Success)
42524642e01fSmrg                return BadAlloc;
4253f7df2e56Smrg            memcpy((char *) names->key_aliases, (char *) tmp,
4254f7df2e56Smrg                   stuff->nKeyAliases * sizeof(XkbKeyAliasRec));
4255f7df2e56Smrg            tmp += stuff->nKeyAliases * 2;
42564642e01fSmrg        }
4257f7df2e56Smrg        else if (names->key_aliases != NULL) {
42586747b715Smrg            free(names->key_aliases);
4259f7df2e56Smrg            names->key_aliases = NULL;
4260f7df2e56Smrg            names->num_key_aliases = 0;
42614642e01fSmrg        }
4262f7df2e56Smrg        nn.nAliases = names->num_key_aliases;
42634642e01fSmrg    }
4264f7df2e56Smrg    if (stuff->which & XkbRGNamesMask) {
4265f7df2e56Smrg        if (stuff->nRadioGroups > 0) {
4266f7df2e56Smrg            register unsigned i, nrg;
4267f7df2e56Smrg
4268f7df2e56Smrg            nrg = stuff->nRadioGroups;
4269f7df2e56Smrg            if (XkbAllocNames(xkb, XkbRGNamesMask, nrg, 0) != Success)
42704642e01fSmrg                return BadAlloc;
42714642e01fSmrg
4272f7df2e56Smrg            for (i = 0; i < stuff->nRadioGroups; i++) {
4273f7df2e56Smrg                names->radio_groups[i] = tmp[i];
42744642e01fSmrg            }
4275f7df2e56Smrg            tmp += stuff->nRadioGroups;
42764642e01fSmrg        }
42774642e01fSmrg        else if (names->radio_groups) {
42786747b715Smrg            free(names->radio_groups);
4279f7df2e56Smrg            names->radio_groups = NULL;
4280f7df2e56Smrg            names->num_rg = 0;
42814642e01fSmrg        }
4282f7df2e56Smrg        nn.nRadioGroups = names->num_rg;
42834642e01fSmrg    }
42844642e01fSmrg    if (nn.changed) {
42854642e01fSmrg        Bool needExtEvent;
4286f7df2e56Smrg
4287f7df2e56Smrg        needExtEvent = (nn.changed & XkbIndicatorNamesMask) != 0;
4288f7df2e56Smrg        XkbSendNamesNotify(dev, &nn);
42894642e01fSmrg        if (needExtEvent) {
4290f7df2e56Smrg            XkbSrvLedInfoPtr sli;
4291f7df2e56Smrg            xkbExtensionDeviceNotify edev;
4292f7df2e56Smrg            register int i;
4293f7df2e56Smrg            register unsigned bit;
4294f7df2e56Smrg
4295f7df2e56Smrg            sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
4296f7df2e56Smrg                                    XkbXI_IndicatorsMask);
4297f7df2e56Smrg            sli->namesPresent = 0;
4298f7df2e56Smrg            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
4299f7df2e56Smrg                if (names->indicators[i] != None)
4300f7df2e56Smrg                    sli->namesPresent |= bit;
43014642e01fSmrg            }
43026747b715Smrg            memset(&edev, 0, sizeof(xkbExtensionDeviceNotify));
4303f7df2e56Smrg            edev.reason = XkbXI_IndicatorNamesMask;
4304f7df2e56Smrg            edev.ledClass = KbdFeedbackClass;
4305f7df2e56Smrg            edev.ledID = dev->kbdfeed->ctrl.id;
4306f7df2e56Smrg            edev.ledsDefined = sli->namesPresent | sli->mapsPresent;
4307f7df2e56Smrg            edev.ledState = sli->effectiveState;
4308f7df2e56Smrg            edev.firstBtn = 0;
4309f7df2e56Smrg            edev.nBtns = 0;
4310f7df2e56Smrg            edev.supported = XkbXI_AllFeaturesMask;
4311f7df2e56Smrg            edev.unsupported = 0;
4312f7df2e56Smrg            XkbSendExtensionDeviceNotify(dev, client, &edev);
43134642e01fSmrg        }
43144642e01fSmrg    }
43154642e01fSmrg    return Success;
43164642e01fSmrg}
43174642e01fSmrg
43184642e01fSmrgint
43194642e01fSmrgProcXkbSetNames(ClientPtr client)
43204642e01fSmrg{
4321f7df2e56Smrg    DeviceIntPtr dev;
4322f7df2e56Smrg    CARD32 *tmp;
4323f7df2e56Smrg    Atom bad;
4324f7df2e56Smrg    int rc;
43254642e01fSmrg
432605b261ecSmrg    REQUEST(xkbSetNamesReq);
432705b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetNamesReq);
432805b261ecSmrg
4329f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
4330f7df2e56Smrg        return BadAccess;
433105b261ecSmrg
43324642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
4333f7df2e56Smrg    CHK_MASK_LEGAL(0x01, stuff->which, XkbAllNamesMask);
433405b261ecSmrg
43354642e01fSmrg    /* check device-independent stuff */
4336f7df2e56Smrg    tmp = (CARD32 *) &stuff[1];
4337f7df2e56Smrg
4338f7df2e56Smrg    if (stuff->which & XkbKeycodesNameMask) {
4339f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4340f7df2e56Smrg        if (!tmp) {
4341f7df2e56Smrg            client->errorValue = bad;
4342f7df2e56Smrg            return BadAtom;
4343f7df2e56Smrg        }
4344f7df2e56Smrg    }
4345f7df2e56Smrg    if (stuff->which & XkbGeometryNameMask) {
4346f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4347f7df2e56Smrg        if (!tmp) {
4348f7df2e56Smrg            client->errorValue = bad;
4349f7df2e56Smrg            return BadAtom;
4350f7df2e56Smrg        }
4351f7df2e56Smrg    }
4352f7df2e56Smrg    if (stuff->which & XkbSymbolsNameMask) {
4353f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4354f7df2e56Smrg        if (!tmp) {
4355f7df2e56Smrg            client->errorValue = bad;
4356f7df2e56Smrg            return BadAtom;
4357f7df2e56Smrg        }
4358f7df2e56Smrg    }
4359f7df2e56Smrg    if (stuff->which & XkbPhysSymbolsNameMask) {
4360f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4361f7df2e56Smrg        if (!tmp) {
4362f7df2e56Smrg            client->errorValue = bad;
4363f7df2e56Smrg            return BadAtom;
4364f7df2e56Smrg        }
4365f7df2e56Smrg    }
4366f7df2e56Smrg    if (stuff->which & XkbTypesNameMask) {
4367f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4368f7df2e56Smrg        if (!tmp) {
4369f7df2e56Smrg            client->errorValue = bad;
4370f7df2e56Smrg            return BadAtom;
4371f7df2e56Smrg        }
4372f7df2e56Smrg    }
4373f7df2e56Smrg    if (stuff->which & XkbCompatNameMask) {
4374f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4375f7df2e56Smrg        if (!tmp) {
4376f7df2e56Smrg            client->errorValue = bad;
4377f7df2e56Smrg            return BadAtom;
4378f7df2e56Smrg        }
437905b261ecSmrg    }
43804642e01fSmrg
43814642e01fSmrg    /* start of device-dependent tests */
43824642e01fSmrg    rc = _XkbSetNamesCheck(client, dev, stuff, tmp);
43834642e01fSmrg    if (rc != Success)
43844642e01fSmrg        return rc;
43854642e01fSmrg
4386f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
43874642e01fSmrg        DeviceIntPtr other;
43884642e01fSmrg
4389f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
4390f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
4391f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
4392f7df2e56Smrg
4393f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
4394f7df2e56Smrg                              DixManageAccess);
4395f7df2e56Smrg                if (rc == Success) {
43964642e01fSmrg                    rc = _XkbSetNamesCheck(client, other, stuff, tmp);
43974642e01fSmrg                    if (rc != Success)
43984642e01fSmrg                        return rc;
43994642e01fSmrg                }
44004642e01fSmrg            }
44014642e01fSmrg        }
440205b261ecSmrg    }
440305b261ecSmrg
440405b261ecSmrg    /* everything is okay -- update names */
440505b261ecSmrg
44064642e01fSmrg    rc = _XkbSetNames(client, dev, stuff);
44074642e01fSmrg    if (rc != Success)
44084642e01fSmrg        return rc;
440905b261ecSmrg
4410f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
44114642e01fSmrg        DeviceIntPtr other;
44124642e01fSmrg
4413f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
4414f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
4415f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
4416f7df2e56Smrg
4417f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
4418f7df2e56Smrg                              DixManageAccess);
44194642e01fSmrg                if (rc == Success)
44204642e01fSmrg                    _XkbSetNames(client, other, stuff);
44214642e01fSmrg            }
44224642e01fSmrg        }
442305b261ecSmrg    }
44244642e01fSmrg
44254642e01fSmrg    /* everything is okay -- update names */
44264642e01fSmrg
44276747b715Smrg    return Success;
442805b261ecSmrg}
442905b261ecSmrg
443005b261ecSmrg/***====================================================================***/
443105b261ecSmrg
44324642e01fSmrg#include "xkbgeom.h"
443305b261ecSmrg
443405b261ecSmrg#define	XkbSizeCountedString(s)  ((s)?((((2+strlen(s))+3)/4)*4):4)
443505b261ecSmrg
4436f7df2e56Smrg/**
4437f7df2e56Smrg * Write the zero-terminated string str into wire as a pascal string with a
4438f7df2e56Smrg * 16-bit length field prefixed before the actual string.
4439f7df2e56Smrg *
4440f7df2e56Smrg * @param wire The destination array, usually the wire struct
4441f7df2e56Smrg * @param str The source string as zero-terminated C string
4442f7df2e56Smrg * @param swap If TRUE, the length field is swapped.
4443f7df2e56Smrg *
4444f7df2e56Smrg * @return The input string in the format <string length><string> with a
4445f7df2e56Smrg * (swapped) 16 bit string length, non-zero terminated.
4446f7df2e56Smrg */
444705b261ecSmrgstatic char *
4448f7df2e56SmrgXkbWriteCountedString(char *wire, const char *str, Bool swap)
444905b261ecSmrg{
4450f7df2e56Smrg    CARD16 len, *pLen, paddedLen;
445105b261ecSmrg
44526747b715Smrg    if (!str)
44536747b715Smrg        return wire;
44546747b715Smrg
4455f7df2e56Smrg    len = strlen(str);
4456f7df2e56Smrg    pLen = (CARD16 *) wire;
4457f7df2e56Smrg    *pLen = len;
445805b261ecSmrg    if (swap) {
4459f7df2e56Smrg        swaps(pLen);
446005b261ecSmrg    }
4461f7df2e56Smrg    paddedLen = pad_to_int32(sizeof(len) + len) - sizeof(len);
4462f7df2e56Smrg    strncpy(&wire[sizeof(len)], str, paddedLen);
4463f7df2e56Smrg    wire += sizeof(len) + paddedLen;
446405b261ecSmrg    return wire;
446505b261ecSmrg}
446605b261ecSmrg
446705b261ecSmrgstatic int
446805b261ecSmrgXkbSizeGeomProperties(XkbGeometryPtr geom)
446905b261ecSmrg{
4470f7df2e56Smrg    register int i, size;
4471f7df2e56Smrg    XkbPropertyPtr prop;
4472f7df2e56Smrg
4473f7df2e56Smrg    for (size = i = 0, prop = geom->properties; i < geom->num_properties;
4474f7df2e56Smrg         i++, prop++) {
4475f7df2e56Smrg        size += XkbSizeCountedString(prop->name);
4476f7df2e56Smrg        size += XkbSizeCountedString(prop->value);
447705b261ecSmrg    }
447805b261ecSmrg    return size;
447905b261ecSmrg}
448005b261ecSmrg
448105b261ecSmrgstatic char *
4482f7df2e56SmrgXkbWriteGeomProperties(char *wire, XkbGeometryPtr geom, Bool swap)
448305b261ecSmrg{
4484f7df2e56Smrg    register int i;
4485f7df2e56Smrg    register XkbPropertyPtr prop;
4486f7df2e56Smrg
4487f7df2e56Smrg    for (i = 0, prop = geom->properties; i < geom->num_properties; i++, prop++) {
4488f7df2e56Smrg        wire = XkbWriteCountedString(wire, prop->name, swap);
4489f7df2e56Smrg        wire = XkbWriteCountedString(wire, prop->value, swap);
449005b261ecSmrg    }
449105b261ecSmrg    return wire;
449205b261ecSmrg}
449305b261ecSmrg
449405b261ecSmrgstatic int
449505b261ecSmrgXkbSizeGeomKeyAliases(XkbGeometryPtr geom)
449605b261ecSmrg{
4497f7df2e56Smrg    return geom->num_key_aliases * (2 * XkbKeyNameLength);
449805b261ecSmrg}
449905b261ecSmrg
450005b261ecSmrgstatic char *
4501f7df2e56SmrgXkbWriteGeomKeyAliases(char *wire, XkbGeometryPtr geom, Bool swap)
450205b261ecSmrg{
4503f7df2e56Smrg    register int sz;
4504f7df2e56Smrg
4505f7df2e56Smrg    sz = geom->num_key_aliases * (XkbKeyNameLength * 2);
4506f7df2e56Smrg    if (sz > 0) {
4507f7df2e56Smrg        memcpy(wire, (char *) geom->key_aliases, sz);
4508f7df2e56Smrg        wire += sz;
450905b261ecSmrg    }
451005b261ecSmrg    return wire;
451105b261ecSmrg}
451205b261ecSmrg
451305b261ecSmrgstatic int
451405b261ecSmrgXkbSizeGeomColors(XkbGeometryPtr geom)
451505b261ecSmrg{
4516f7df2e56Smrg    register int i, size;
4517f7df2e56Smrg    register XkbColorPtr color;
451805b261ecSmrg
4519f7df2e56Smrg    for (i = size = 0, color = geom->colors; i < geom->num_colors; i++, color++) {
4520f7df2e56Smrg        size += XkbSizeCountedString(color->spec);
452105b261ecSmrg    }
452205b261ecSmrg    return size;
452305b261ecSmrg}
452405b261ecSmrg
452505b261ecSmrgstatic char *
4526f7df2e56SmrgXkbWriteGeomColors(char *wire, XkbGeometryPtr geom, Bool swap)
452705b261ecSmrg{
4528f7df2e56Smrg    register int i;
4529f7df2e56Smrg    register XkbColorPtr color;
453005b261ecSmrg
4531f7df2e56Smrg    for (i = 0, color = geom->colors; i < geom->num_colors; i++, color++) {
4532f7df2e56Smrg        wire = XkbWriteCountedString(wire, color->spec, swap);
453305b261ecSmrg    }
453405b261ecSmrg    return wire;
453505b261ecSmrg}
453605b261ecSmrg
453705b261ecSmrgstatic int
453805b261ecSmrgXkbSizeGeomShapes(XkbGeometryPtr geom)
453905b261ecSmrg{
4540f7df2e56Smrg    register int i, size;
4541f7df2e56Smrg    register XkbShapePtr shape;
4542f7df2e56Smrg
4543f7df2e56Smrg    for (i = size = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) {
4544f7df2e56Smrg        register int n;
4545f7df2e56Smrg        register XkbOutlinePtr ol;
4546f7df2e56Smrg
4547f7df2e56Smrg        size += SIZEOF(xkbShapeWireDesc);
4548f7df2e56Smrg        for (n = 0, ol = shape->outlines; n < shape->num_outlines; n++, ol++) {
4549f7df2e56Smrg            size += SIZEOF(xkbOutlineWireDesc);
4550f7df2e56Smrg            size += ol->num_points * SIZEOF(xkbPointWireDesc);
4551f7df2e56Smrg        }
455205b261ecSmrg    }
455305b261ecSmrg    return size;
455405b261ecSmrg}
455505b261ecSmrg
455605b261ecSmrgstatic char *
4557f7df2e56SmrgXkbWriteGeomShapes(char *wire, XkbGeometryPtr geom, Bool swap)
455805b261ecSmrg{
4559f7df2e56Smrg    int i;
4560f7df2e56Smrg    XkbShapePtr shape;
4561f7df2e56Smrg    xkbShapeWireDesc *shapeWire;
4562f7df2e56Smrg
4563f7df2e56Smrg    for (i = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) {
4564f7df2e56Smrg        register int o;
4565f7df2e56Smrg        XkbOutlinePtr ol;
4566f7df2e56Smrg        xkbOutlineWireDesc *olWire;
4567f7df2e56Smrg
4568f7df2e56Smrg        shapeWire = (xkbShapeWireDesc *) wire;
4569f7df2e56Smrg        shapeWire->name = shape->name;
4570f7df2e56Smrg        shapeWire->nOutlines = shape->num_outlines;
4571f7df2e56Smrg        if (shape->primary != NULL)
4572f7df2e56Smrg            shapeWire->primaryNdx = XkbOutlineIndex(shape, shape->primary);
4573f7df2e56Smrg        else
4574f7df2e56Smrg            shapeWire->primaryNdx = XkbNoShape;
4575f7df2e56Smrg        if (shape->approx != NULL)
4576f7df2e56Smrg            shapeWire->approxNdx = XkbOutlineIndex(shape, shape->approx);
4577f7df2e56Smrg        else
4578f7df2e56Smrg            shapeWire->approxNdx = XkbNoShape;
4579f7df2e56Smrg        shapeWire->pad = 0;
4580f7df2e56Smrg        if (swap) {
4581f7df2e56Smrg            swapl(&shapeWire->name);
4582f7df2e56Smrg        }
4583f7df2e56Smrg        wire = (char *) &shapeWire[1];
4584f7df2e56Smrg        for (o = 0, ol = shape->outlines; o < shape->num_outlines; o++, ol++) {
4585f7df2e56Smrg            register int p;
4586f7df2e56Smrg            XkbPointPtr pt;
4587f7df2e56Smrg            xkbPointWireDesc *ptWire;
4588f7df2e56Smrg
4589f7df2e56Smrg            olWire = (xkbOutlineWireDesc *) wire;
4590f7df2e56Smrg            olWire->nPoints = ol->num_points;
4591f7df2e56Smrg            olWire->cornerRadius = ol->corner_radius;
4592f7df2e56Smrg            olWire->pad = 0;
4593f7df2e56Smrg            wire = (char *) &olWire[1];
4594f7df2e56Smrg            ptWire = (xkbPointWireDesc *) wire;
4595f7df2e56Smrg            for (p = 0, pt = ol->points; p < ol->num_points; p++, pt++) {
4596f7df2e56Smrg                ptWire[p].x = pt->x;
4597f7df2e56Smrg                ptWire[p].y = pt->y;
4598f7df2e56Smrg                if (swap) {
4599f7df2e56Smrg                    swaps(&ptWire[p].x);
4600f7df2e56Smrg                    swaps(&ptWire[p].y);
4601f7df2e56Smrg                }
4602f7df2e56Smrg            }
4603f7df2e56Smrg            wire = (char *) &ptWire[ol->num_points];
4604f7df2e56Smrg        }
460505b261ecSmrg    }
460605b261ecSmrg    return wire;
460705b261ecSmrg}
460805b261ecSmrg
460905b261ecSmrgstatic int
4610f7df2e56SmrgXkbSizeGeomDoodads(int num_doodads, XkbDoodadPtr doodad)
461105b261ecSmrg{
4612f7df2e56Smrg    register int i, size;
4613f7df2e56Smrg
4614f7df2e56Smrg    for (i = size = 0; i < num_doodads; i++, doodad++) {
4615f7df2e56Smrg        size += SIZEOF(xkbAnyDoodadWireDesc);
4616f7df2e56Smrg        if (doodad->any.type == XkbTextDoodad) {
4617f7df2e56Smrg            size += XkbSizeCountedString(doodad->text.text);
4618f7df2e56Smrg            size += XkbSizeCountedString(doodad->text.font);
4619f7df2e56Smrg        }
4620f7df2e56Smrg        else if (doodad->any.type == XkbLogoDoodad) {
4621f7df2e56Smrg            size += XkbSizeCountedString(doodad->logo.logo_name);
4622f7df2e56Smrg        }
462305b261ecSmrg    }
462405b261ecSmrg    return size;
462505b261ecSmrg}
462605b261ecSmrg
462705b261ecSmrgstatic char *
4628f7df2e56SmrgXkbWriteGeomDoodads(char *wire, int num_doodads, XkbDoodadPtr doodad, Bool swap)
462905b261ecSmrg{
4630f7df2e56Smrg    register int i;
4631f7df2e56Smrg    xkbDoodadWireDesc *doodadWire;
4632f7df2e56Smrg
4633f7df2e56Smrg    for (i = 0; i < num_doodads; i++, doodad++) {
4634f7df2e56Smrg        doodadWire = (xkbDoodadWireDesc *) wire;
4635f7df2e56Smrg        wire = (char *) &doodadWire[1];
4636f7df2e56Smrg        memset(doodadWire, 0, SIZEOF(xkbDoodadWireDesc));
4637f7df2e56Smrg        doodadWire->any.name = doodad->any.name;
4638f7df2e56Smrg        doodadWire->any.type = doodad->any.type;
4639f7df2e56Smrg        doodadWire->any.priority = doodad->any.priority;
4640f7df2e56Smrg        doodadWire->any.top = doodad->any.top;
4641f7df2e56Smrg        doodadWire->any.left = doodad->any.left;
4642f7df2e56Smrg        if (swap) {
4643f7df2e56Smrg            swapl(&doodadWire->any.name);
4644f7df2e56Smrg            swaps(&doodadWire->any.top);
4645f7df2e56Smrg            swaps(&doodadWire->any.left);
4646f7df2e56Smrg        }
4647f7df2e56Smrg        switch (doodad->any.type) {
4648f7df2e56Smrg        case XkbOutlineDoodad:
4649f7df2e56Smrg        case XkbSolidDoodad:
4650f7df2e56Smrg            doodadWire->shape.angle = doodad->shape.angle;
4651f7df2e56Smrg            doodadWire->shape.colorNdx = doodad->shape.color_ndx;
4652f7df2e56Smrg            doodadWire->shape.shapeNdx = doodad->shape.shape_ndx;
4653f7df2e56Smrg            if (swap) {
4654f7df2e56Smrg                swaps(&doodadWire->shape.angle);
4655f7df2e56Smrg            }
4656f7df2e56Smrg            break;
4657f7df2e56Smrg        case XkbTextDoodad:
4658f7df2e56Smrg            doodadWire->text.angle = doodad->text.angle;
4659f7df2e56Smrg            doodadWire->text.width = doodad->text.width;
4660f7df2e56Smrg            doodadWire->text.height = doodad->text.height;
4661f7df2e56Smrg            doodadWire->text.colorNdx = doodad->text.color_ndx;
4662f7df2e56Smrg            if (swap) {
4663f7df2e56Smrg                swaps(&doodadWire->text.angle);
4664f7df2e56Smrg                swaps(&doodadWire->text.width);
4665f7df2e56Smrg                swaps(&doodadWire->text.height);
4666f7df2e56Smrg            }
4667f7df2e56Smrg            wire = XkbWriteCountedString(wire, doodad->text.text, swap);
4668f7df2e56Smrg            wire = XkbWriteCountedString(wire, doodad->text.font, swap);
4669f7df2e56Smrg            break;
4670f7df2e56Smrg        case XkbIndicatorDoodad:
4671f7df2e56Smrg            doodadWire->indicator.shapeNdx = doodad->indicator.shape_ndx;
4672f7df2e56Smrg            doodadWire->indicator.onColorNdx = doodad->indicator.on_color_ndx;
4673f7df2e56Smrg            doodadWire->indicator.offColorNdx = doodad->indicator.off_color_ndx;
4674f7df2e56Smrg            break;
4675f7df2e56Smrg        case XkbLogoDoodad:
4676f7df2e56Smrg            doodadWire->logo.angle = doodad->logo.angle;
4677f7df2e56Smrg            doodadWire->logo.colorNdx = doodad->logo.color_ndx;
4678f7df2e56Smrg            doodadWire->logo.shapeNdx = doodad->logo.shape_ndx;
4679f7df2e56Smrg            wire = XkbWriteCountedString(wire, doodad->logo.logo_name, swap);
4680f7df2e56Smrg            break;
4681f7df2e56Smrg        default:
4682f7df2e56Smrg            ErrorF("[xkb] Unknown doodad type %d in XkbWriteGeomDoodads\n",
4683f7df2e56Smrg                   doodad->any.type);
4684f7df2e56Smrg            ErrorF("[xkb] Ignored\n");
4685f7df2e56Smrg            break;
4686f7df2e56Smrg        }
468705b261ecSmrg    }
468805b261ecSmrg    return wire;
468905b261ecSmrg}
469005b261ecSmrg
469105b261ecSmrgstatic char *
4692f7df2e56SmrgXkbWriteGeomOverlay(char *wire, XkbOverlayPtr ol, Bool swap)
469305b261ecSmrg{
4694f7df2e56Smrg    register int r;
4695f7df2e56Smrg    XkbOverlayRowPtr row;
4696f7df2e56Smrg    xkbOverlayWireDesc *olWire;
4697f7df2e56Smrg
4698f7df2e56Smrg    olWire = (xkbOverlayWireDesc *) wire;
4699f7df2e56Smrg    olWire->name = ol->name;
4700f7df2e56Smrg    olWire->nRows = ol->num_rows;
4701f7df2e56Smrg    olWire->pad1 = 0;
4702f7df2e56Smrg    olWire->pad2 = 0;
4703f7df2e56Smrg    if (swap) {
4704f7df2e56Smrg        swapl(&olWire->name);
4705f7df2e56Smrg    }
4706f7df2e56Smrg    wire = (char *) &olWire[1];
4707f7df2e56Smrg    for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) {
4708f7df2e56Smrg        unsigned int k;
4709f7df2e56Smrg        XkbOverlayKeyPtr key;
4710f7df2e56Smrg        xkbOverlayRowWireDesc *rowWire;
4711f7df2e56Smrg
4712f7df2e56Smrg        rowWire = (xkbOverlayRowWireDesc *) wire;
4713f7df2e56Smrg        rowWire->rowUnder = row->row_under;
4714f7df2e56Smrg        rowWire->nKeys = row->num_keys;
4715f7df2e56Smrg        rowWire->pad1 = 0;
4716f7df2e56Smrg        wire = (char *) &rowWire[1];
4717f7df2e56Smrg        for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
4718f7df2e56Smrg            xkbOverlayKeyWireDesc *keyWire;
4719f7df2e56Smrg
4720f7df2e56Smrg            keyWire = (xkbOverlayKeyWireDesc *) wire;
4721f7df2e56Smrg            memcpy(keyWire->over, key->over.name, XkbKeyNameLength);
4722f7df2e56Smrg            memcpy(keyWire->under, key->under.name, XkbKeyNameLength);
4723f7df2e56Smrg            wire = (char *) &keyWire[1];
4724f7df2e56Smrg        }
4725f7df2e56Smrg    }
4726f7df2e56Smrg    return wire;
472705b261ecSmrg}
472805b261ecSmrg
472905b261ecSmrgstatic int
473005b261ecSmrgXkbSizeGeomSections(XkbGeometryPtr geom)
473105b261ecSmrg{
4732f7df2e56Smrg    register int i, size;
4733f7df2e56Smrg    XkbSectionPtr section;
4734f7df2e56Smrg
4735f7df2e56Smrg    for (i = size = 0, section = geom->sections; i < geom->num_sections;
4736f7df2e56Smrg         i++, section++) {
4737f7df2e56Smrg        size += SIZEOF(xkbSectionWireDesc);
4738f7df2e56Smrg        if (section->rows) {
4739f7df2e56Smrg            int r;
4740f7df2e56Smrg            XkbRowPtr row;
4741f7df2e56Smrg
4742f7df2e56Smrg            for (r = 0, row = section->rows; r < section->num_rows; row++, r++) {
4743f7df2e56Smrg                size += SIZEOF(xkbRowWireDesc);
4744f7df2e56Smrg                size += row->num_keys * SIZEOF(xkbKeyWireDesc);
4745f7df2e56Smrg            }
4746f7df2e56Smrg        }
4747f7df2e56Smrg        if (section->doodads)
4748f7df2e56Smrg            size += XkbSizeGeomDoodads(section->num_doodads, section->doodads);
4749f7df2e56Smrg        if (section->overlays) {
4750f7df2e56Smrg            int o;
4751f7df2e56Smrg            XkbOverlayPtr ol;
4752f7df2e56Smrg
4753f7df2e56Smrg            for (o = 0, ol = section->overlays; o < section->num_overlays;
4754f7df2e56Smrg                 o++, ol++) {
4755f7df2e56Smrg                int r;
4756f7df2e56Smrg                XkbOverlayRowPtr row;
4757f7df2e56Smrg
4758f7df2e56Smrg                size += SIZEOF(xkbOverlayWireDesc);
4759f7df2e56Smrg                for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) {
4760f7df2e56Smrg                    size += SIZEOF(xkbOverlayRowWireDesc);
4761f7df2e56Smrg                    size += row->num_keys * SIZEOF(xkbOverlayKeyWireDesc);
4762f7df2e56Smrg                }
4763f7df2e56Smrg            }
4764f7df2e56Smrg        }
476505b261ecSmrg    }
476605b261ecSmrg    return size;
476705b261ecSmrg}
476805b261ecSmrg
476905b261ecSmrgstatic char *
4770f7df2e56SmrgXkbWriteGeomSections(char *wire, XkbGeometryPtr geom, Bool swap)
477105b261ecSmrg{
4772f7df2e56Smrg    register int i;
4773f7df2e56Smrg    XkbSectionPtr section;
4774f7df2e56Smrg    xkbSectionWireDesc *sectionWire;
4775f7df2e56Smrg
4776f7df2e56Smrg    for (i = 0, section = geom->sections; i < geom->num_sections;
4777f7df2e56Smrg         i++, section++) {
4778f7df2e56Smrg        sectionWire = (xkbSectionWireDesc *) wire;
4779f7df2e56Smrg        sectionWire->name = section->name;
4780f7df2e56Smrg        sectionWire->top = section->top;
4781f7df2e56Smrg        sectionWire->left = section->left;
4782f7df2e56Smrg        sectionWire->width = section->width;
4783f7df2e56Smrg        sectionWire->height = section->height;
4784f7df2e56Smrg        sectionWire->angle = section->angle;
4785f7df2e56Smrg        sectionWire->priority = section->priority;
4786f7df2e56Smrg        sectionWire->nRows = section->num_rows;
4787f7df2e56Smrg        sectionWire->nDoodads = section->num_doodads;
4788f7df2e56Smrg        sectionWire->nOverlays = section->num_overlays;
4789f7df2e56Smrg        sectionWire->pad = 0;
4790f7df2e56Smrg        if (swap) {
4791f7df2e56Smrg            swapl(&sectionWire->name);
4792f7df2e56Smrg            swaps(&sectionWire->top);
4793f7df2e56Smrg            swaps(&sectionWire->left);
4794f7df2e56Smrg            swaps(&sectionWire->width);
4795f7df2e56Smrg            swaps(&sectionWire->height);
4796f7df2e56Smrg            swaps(&sectionWire->angle);
4797f7df2e56Smrg        }
4798f7df2e56Smrg        wire = (char *) &sectionWire[1];
4799f7df2e56Smrg        if (section->rows) {
4800f7df2e56Smrg            int r;
4801f7df2e56Smrg            XkbRowPtr row;
4802f7df2e56Smrg            xkbRowWireDesc *rowWire;
4803f7df2e56Smrg
4804f7df2e56Smrg            for (r = 0, row = section->rows; r < section->num_rows; r++, row++) {
4805f7df2e56Smrg                rowWire = (xkbRowWireDesc *) wire;
4806f7df2e56Smrg                rowWire->top = row->top;
4807f7df2e56Smrg                rowWire->left = row->left;
4808f7df2e56Smrg                rowWire->nKeys = row->num_keys;
4809f7df2e56Smrg                rowWire->vertical = row->vertical;
4810f7df2e56Smrg                rowWire->pad = 0;
4811f7df2e56Smrg                if (swap) {
4812f7df2e56Smrg                    swaps(&rowWire->top);
4813f7df2e56Smrg                    swaps(&rowWire->left);
4814f7df2e56Smrg                }
4815f7df2e56Smrg                wire = (char *) &rowWire[1];
4816f7df2e56Smrg                if (row->keys) {
4817f7df2e56Smrg                    int k;
4818f7df2e56Smrg                    XkbKeyPtr key;
4819f7df2e56Smrg                    xkbKeyWireDesc *keyWire;
4820f7df2e56Smrg
4821f7df2e56Smrg                    keyWire = (xkbKeyWireDesc *) wire;
4822f7df2e56Smrg                    for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
4823f7df2e56Smrg                        memcpy(keyWire[k].name, key->name.name,
4824f7df2e56Smrg                               XkbKeyNameLength);
4825f7df2e56Smrg                        keyWire[k].gap = key->gap;
4826f7df2e56Smrg                        keyWire[k].shapeNdx = key->shape_ndx;
4827f7df2e56Smrg                        keyWire[k].colorNdx = key->color_ndx;
4828f7df2e56Smrg                        if (swap) {
4829f7df2e56Smrg                            swaps(&keyWire[k].gap);
4830f7df2e56Smrg                        }
4831f7df2e56Smrg                    }
4832f7df2e56Smrg                    wire = (char *) &keyWire[row->num_keys];
4833f7df2e56Smrg                }
4834f7df2e56Smrg            }
4835f7df2e56Smrg        }
4836f7df2e56Smrg        if (section->doodads) {
4837f7df2e56Smrg            wire = XkbWriteGeomDoodads(wire,
4838f7df2e56Smrg                                       section->num_doodads, section->doodads,
4839f7df2e56Smrg                                       swap);
4840f7df2e56Smrg        }
4841f7df2e56Smrg        if (section->overlays) {
4842f7df2e56Smrg            register int o;
4843f7df2e56Smrg
4844f7df2e56Smrg            for (o = 0; o < section->num_overlays; o++) {
4845f7df2e56Smrg                wire = XkbWriteGeomOverlay(wire, &section->overlays[o], swap);
4846f7df2e56Smrg            }
4847f7df2e56Smrg        }
484805b261ecSmrg    }
484905b261ecSmrg    return wire;
485005b261ecSmrg}
485105b261ecSmrg
485205b261ecSmrgstatic Status
4853f7df2e56SmrgXkbComputeGetGeometryReplySize(XkbGeometryPtr geom,
4854f7df2e56Smrg                               xkbGetGeometryReply * rep, Atom name)
485505b261ecSmrg{
4856f7df2e56Smrg    int len;
4857f7df2e56Smrg
4858f7df2e56Smrg    if (geom != NULL) {
4859f7df2e56Smrg        len = XkbSizeCountedString(geom->label_font);
4860f7df2e56Smrg        len += XkbSizeGeomProperties(geom);
4861f7df2e56Smrg        len += XkbSizeGeomColors(geom);
4862f7df2e56Smrg        len += XkbSizeGeomShapes(geom);
4863f7df2e56Smrg        len += XkbSizeGeomSections(geom);
4864f7df2e56Smrg        len += XkbSizeGeomDoodads(geom->num_doodads, geom->doodads);
4865f7df2e56Smrg        len += XkbSizeGeomKeyAliases(geom);
4866f7df2e56Smrg        rep->length = len / 4;
4867f7df2e56Smrg        rep->found = TRUE;
4868f7df2e56Smrg        rep->name = geom->name;
4869f7df2e56Smrg        rep->widthMM = geom->width_mm;
4870f7df2e56Smrg        rep->heightMM = geom->height_mm;
4871f7df2e56Smrg        rep->nProperties = geom->num_properties;
4872f7df2e56Smrg        rep->nColors = geom->num_colors;
4873f7df2e56Smrg        rep->nShapes = geom->num_shapes;
4874f7df2e56Smrg        rep->nSections = geom->num_sections;
4875f7df2e56Smrg        rep->nDoodads = geom->num_doodads;
4876f7df2e56Smrg        rep->nKeyAliases = geom->num_key_aliases;
4877f7df2e56Smrg        rep->baseColorNdx = XkbGeomColorIndex(geom, geom->base_color);
4878f7df2e56Smrg        rep->labelColorNdx = XkbGeomColorIndex(geom, geom->label_color);
487905b261ecSmrg    }
488005b261ecSmrg    else {
4881f7df2e56Smrg        rep->length = 0;
4882f7df2e56Smrg        rep->found = FALSE;
4883f7df2e56Smrg        rep->name = name;
4884f7df2e56Smrg        rep->widthMM = rep->heightMM = 0;
4885f7df2e56Smrg        rep->nProperties = rep->nColors = rep->nShapes = 0;
4886f7df2e56Smrg        rep->nSections = rep->nDoodads = 0;
4887f7df2e56Smrg        rep->nKeyAliases = 0;
4888f7df2e56Smrg        rep->labelColorNdx = rep->baseColorNdx = 0;
488905b261ecSmrg    }
489005b261ecSmrg    return Success;
489105b261ecSmrg}
489205b261ecSmrgstatic int
4893f7df2e56SmrgXkbSendGeometry(ClientPtr client,
4894f7df2e56Smrg                XkbGeometryPtr geom, xkbGetGeometryReply * rep, Bool freeGeom)
489505b261ecSmrg{
4896f7df2e56Smrg    char *desc, *start;
4897f7df2e56Smrg    int len;
4898f7df2e56Smrg
4899f7df2e56Smrg    if (geom != NULL) {
4900f7df2e56Smrg        start = desc = xallocarray(rep->length, 4);
4901f7df2e56Smrg        if (!start)
4902f7df2e56Smrg            return BadAlloc;
4903f7df2e56Smrg        len = rep->length * 4;
4904f7df2e56Smrg        desc = XkbWriteCountedString(desc, geom->label_font, client->swapped);
4905f7df2e56Smrg        if (rep->nProperties > 0)
4906f7df2e56Smrg            desc = XkbWriteGeomProperties(desc, geom, client->swapped);
4907f7df2e56Smrg        if (rep->nColors > 0)
4908f7df2e56Smrg            desc = XkbWriteGeomColors(desc, geom, client->swapped);
4909f7df2e56Smrg        if (rep->nShapes > 0)
4910f7df2e56Smrg            desc = XkbWriteGeomShapes(desc, geom, client->swapped);
4911f7df2e56Smrg        if (rep->nSections > 0)
4912f7df2e56Smrg            desc = XkbWriteGeomSections(desc, geom, client->swapped);
4913f7df2e56Smrg        if (rep->nDoodads > 0)
4914f7df2e56Smrg            desc = XkbWriteGeomDoodads(desc, geom->num_doodads, geom->doodads,
4915f7df2e56Smrg                                       client->swapped);
4916f7df2e56Smrg        if (rep->nKeyAliases > 0)
4917f7df2e56Smrg            desc = XkbWriteGeomKeyAliases(desc, geom, client->swapped);
4918f7df2e56Smrg        if ((desc - start) != (len)) {
4919f7df2e56Smrg            ErrorF
4920f7df2e56Smrg                ("[xkb] BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n",
4921f7df2e56Smrg                 len, (unsigned long) (desc - start));
4922f7df2e56Smrg        }
492305b261ecSmrg    }
492405b261ecSmrg    else {
4925f7df2e56Smrg        len = 0;
4926f7df2e56Smrg        start = NULL;
492705b261ecSmrg    }
492805b261ecSmrg    if (client->swapped) {
4929f7df2e56Smrg        swaps(&rep->sequenceNumber);
4930f7df2e56Smrg        swapl(&rep->length);
4931f7df2e56Smrg        swapl(&rep->name);
4932f7df2e56Smrg        swaps(&rep->widthMM);
4933f7df2e56Smrg        swaps(&rep->heightMM);
4934f7df2e56Smrg        swaps(&rep->nProperties);
4935f7df2e56Smrg        swaps(&rep->nColors);
4936f7df2e56Smrg        swaps(&rep->nShapes);
4937f7df2e56Smrg        swaps(&rep->nSections);
4938f7df2e56Smrg        swaps(&rep->nDoodads);
4939f7df2e56Smrg        swaps(&rep->nKeyAliases);
4940f7df2e56Smrg    }
4941f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetGeometryReply), rep);
4942f7df2e56Smrg    if (len > 0)
4943f7df2e56Smrg        WriteToClient(client, len, start);
4944f7df2e56Smrg    if (start != NULL)
4945f7df2e56Smrg        free((char *) start);
494605b261ecSmrg    if (freeGeom)
4947f7df2e56Smrg        XkbFreeGeometry(geom, XkbGeomAllMask, TRUE);
49486747b715Smrg    return Success;
494905b261ecSmrg}
495005b261ecSmrg
495105b261ecSmrgint
495205b261ecSmrgProcXkbGetGeometry(ClientPtr client)
495305b261ecSmrg{
4954f7df2e56Smrg    DeviceIntPtr dev;
495505b261ecSmrg    xkbGetGeometryReply rep;
4956f7df2e56Smrg    XkbGeometryPtr geom;
4957f7df2e56Smrg    Bool shouldFree;
4958f7df2e56Smrg    Status status;
495905b261ecSmrg
496005b261ecSmrg    REQUEST(xkbGetGeometryReq);
496105b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetGeometryReq);
496205b261ecSmrg
4963f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
4964f7df2e56Smrg        return BadAccess;
496505b261ecSmrg
49664642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
496705b261ecSmrg    CHK_ATOM_OR_NONE(stuff->name);
496805b261ecSmrg
4969f7df2e56Smrg    geom = XkbLookupNamedGeometry(dev, stuff->name, &shouldFree);
4970f7df2e56Smrg    rep = (xkbGetGeometryReply) {
4971f7df2e56Smrg        .type = X_Reply,
4972f7df2e56Smrg        .deviceID = dev->id,
4973f7df2e56Smrg        .sequenceNumber = client->sequence,
4974f7df2e56Smrg        .length = 0
4975f7df2e56Smrg    };
4976f7df2e56Smrg    status = XkbComputeGetGeometryReplySize(geom, &rep, stuff->name);
4977f7df2e56Smrg    if (status != Success)
4978f7df2e56Smrg        return status;
4979f7df2e56Smrg    else
4980f7df2e56Smrg        return XkbSendGeometry(client, geom, &rep, shouldFree);
498105b261ecSmrg}
498205b261ecSmrg
498305b261ecSmrg/***====================================================================***/
498405b261ecSmrg
49851e26616aSmrgstatic Status
49861e26616aSmrg_GetCountedString(char **wire_inout, ClientPtr client, char **str)
498705b261ecSmrg{
49881e26616aSmrg    char *wire, *next;
49891e26616aSmrg    CARD16 len;
499005b261ecSmrg
49911e26616aSmrg    wire = *wire_inout;
49921e26616aSmrg    len = *(CARD16 *) wire;
49931e26616aSmrg    if (client->swapped) {
4994f7df2e56Smrg        swaps(&len);
499505b261ecSmrg    }
49961e26616aSmrg    next = wire + XkbPaddedSize(len + 2);
49971e26616aSmrg    /* Check we're still within the size of the request */
49981e26616aSmrg    if (client->req_len <
49991e26616aSmrg        bytes_to_int32(next - (char *) client->requestBuffer))
50001e26616aSmrg        return BadValue;
50011e26616aSmrg    *str = malloc(len + 1);
50021e26616aSmrg    if (!*str)
50031e26616aSmrg        return BadAlloc;
50041e26616aSmrg    memcpy(*str, &wire[2], len);
50051e26616aSmrg    *(*str + len) = '\0';
50061e26616aSmrg    *wire_inout = next;
50071e26616aSmrg    return Success;
500805b261ecSmrg}
500905b261ecSmrg
501005b261ecSmrgstatic Status
5011f7df2e56Smrg_CheckSetDoodad(char **wire_inout,
5012f7df2e56Smrg                XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client)
501305b261ecSmrg{
5014f7df2e56Smrg    char *wire;
5015f7df2e56Smrg    xkbDoodadWireDesc *dWire;
5016f7df2e56Smrg    xkbAnyDoodadWireDesc any;
5017f7df2e56Smrg    xkbTextDoodadWireDesc text;
5018f7df2e56Smrg    XkbDoodadPtr doodad;
50191e26616aSmrg    Status status;
502005b261ecSmrg
5021f7df2e56Smrg    dWire = (xkbDoodadWireDesc *) (*wire_inout);
5022f7df2e56Smrg    any = dWire->any;
5023f7df2e56Smrg    wire = (char *) &dWire[1];
502405b261ecSmrg    if (client->swapped) {
5025f7df2e56Smrg        swapl(&any.name);
5026f7df2e56Smrg        swaps(&any.top);
5027f7df2e56Smrg        swaps(&any.left);
5028f7df2e56Smrg        swaps(&any.angle);
502905b261ecSmrg    }
503005b261ecSmrg    CHK_ATOM_ONLY(dWire->any.name);
5031f7df2e56Smrg    doodad = XkbAddGeomDoodad(geom, section, any.name);
503205b261ecSmrg    if (!doodad)
5033f7df2e56Smrg        return BadAlloc;
5034f7df2e56Smrg    doodad->any.type = dWire->any.type;
5035f7df2e56Smrg    doodad->any.priority = dWire->any.priority;
5036f7df2e56Smrg    doodad->any.top = any.top;
5037f7df2e56Smrg    doodad->any.left = any.left;
5038f7df2e56Smrg    doodad->any.angle = any.angle;
503905b261ecSmrg    switch (doodad->any.type) {
5040f7df2e56Smrg    case XkbOutlineDoodad:
5041f7df2e56Smrg    case XkbSolidDoodad:
5042f7df2e56Smrg        if (dWire->shape.colorNdx >= geom->num_colors) {
5043f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x40, geom->num_colors,
5044f7df2e56Smrg                                              dWire->shape.colorNdx);
5045f7df2e56Smrg            return BadMatch;
5046f7df2e56Smrg        }
5047f7df2e56Smrg        if (dWire->shape.shapeNdx >= geom->num_shapes) {
5048f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x41, geom->num_shapes,
5049f7df2e56Smrg                                              dWire->shape.shapeNdx);
5050f7df2e56Smrg            return BadMatch;
5051f7df2e56Smrg        }
5052f7df2e56Smrg        doodad->shape.color_ndx = dWire->shape.colorNdx;
5053f7df2e56Smrg        doodad->shape.shape_ndx = dWire->shape.shapeNdx;
5054f7df2e56Smrg        break;
5055f7df2e56Smrg    case XkbTextDoodad:
5056f7df2e56Smrg        if (dWire->text.colorNdx >= geom->num_colors) {
5057f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x42, geom->num_colors,
5058f7df2e56Smrg                                              dWire->text.colorNdx);
5059f7df2e56Smrg            return BadMatch;
5060f7df2e56Smrg        }
5061f7df2e56Smrg        text = dWire->text;
5062f7df2e56Smrg        if (client->swapped) {
5063f7df2e56Smrg            swaps(&text.width);
5064f7df2e56Smrg            swaps(&text.height);
5065f7df2e56Smrg        }
5066f7df2e56Smrg        doodad->text.width = text.width;
5067f7df2e56Smrg        doodad->text.height = text.height;
5068f7df2e56Smrg        doodad->text.color_ndx = dWire->text.colorNdx;
5069f7df2e56Smrg        status = _GetCountedString(&wire, client, &doodad->text.text);
5070f7df2e56Smrg        if (status != Success)
5071f7df2e56Smrg            return status;
5072f7df2e56Smrg        status = _GetCountedString(&wire, client, &doodad->text.font);
5073f7df2e56Smrg        if (status != Success) {
5074f7df2e56Smrg            free (doodad->text.text);
5075f7df2e56Smrg            return status;
5076f7df2e56Smrg        }
5077f7df2e56Smrg        break;
5078f7df2e56Smrg    case XkbIndicatorDoodad:
5079f7df2e56Smrg        if (dWire->indicator.onColorNdx >= geom->num_colors) {
5080f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x43, geom->num_colors,
5081f7df2e56Smrg                                              dWire->indicator.onColorNdx);
5082f7df2e56Smrg            return BadMatch;
5083f7df2e56Smrg        }
5084f7df2e56Smrg        if (dWire->indicator.offColorNdx >= geom->num_colors) {
5085f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x44, geom->num_colors,
5086f7df2e56Smrg                                              dWire->indicator.offColorNdx);
5087f7df2e56Smrg            return BadMatch;
5088f7df2e56Smrg        }
5089f7df2e56Smrg        if (dWire->indicator.shapeNdx >= geom->num_shapes) {
5090f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x45, geom->num_shapes,
5091f7df2e56Smrg                                              dWire->indicator.shapeNdx);
5092f7df2e56Smrg            return BadMatch;
5093f7df2e56Smrg        }
5094f7df2e56Smrg        doodad->indicator.shape_ndx = dWire->indicator.shapeNdx;
5095f7df2e56Smrg        doodad->indicator.on_color_ndx = dWire->indicator.onColorNdx;
5096f7df2e56Smrg        doodad->indicator.off_color_ndx = dWire->indicator.offColorNdx;
5097f7df2e56Smrg        break;
5098f7df2e56Smrg    case XkbLogoDoodad:
5099f7df2e56Smrg        if (dWire->logo.colorNdx >= geom->num_colors) {
5100f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x46, geom->num_colors,
5101f7df2e56Smrg                                              dWire->logo.colorNdx);
5102f7df2e56Smrg            return BadMatch;
5103f7df2e56Smrg        }
5104f7df2e56Smrg        if (dWire->logo.shapeNdx >= geom->num_shapes) {
5105f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x47, geom->num_shapes,
5106f7df2e56Smrg                                              dWire->logo.shapeNdx);
5107f7df2e56Smrg            return BadMatch;
5108f7df2e56Smrg        }
5109f7df2e56Smrg        doodad->logo.color_ndx = dWire->logo.colorNdx;
5110f7df2e56Smrg        doodad->logo.shape_ndx = dWire->logo.shapeNdx;
5111f7df2e56Smrg        status = _GetCountedString(&wire, client, &doodad->logo.logo_name);
5112f7df2e56Smrg        if (status != Success)
5113f7df2e56Smrg            return status;
5114f7df2e56Smrg        break;
5115f7df2e56Smrg    default:
5116f7df2e56Smrg        client->errorValue = _XkbErrCode2(0x4F, dWire->any.type);
5117f7df2e56Smrg        return BadValue;
5118f7df2e56Smrg    }
5119f7df2e56Smrg    *wire_inout = wire;
5120f7df2e56Smrg    return Success;
5121f7df2e56Smrg}
5122f7df2e56Smrg
5123f7df2e56Smrgstatic Status
5124f7df2e56Smrg_CheckSetOverlay(char **wire_inout,
5125f7df2e56Smrg                 XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client)
512605b261ecSmrg{
5127f7df2e56Smrg    register int r;
5128f7df2e56Smrg    char *wire;
5129f7df2e56Smrg    XkbOverlayPtr ol;
5130f7df2e56Smrg    xkbOverlayWireDesc *olWire;
5131f7df2e56Smrg    xkbOverlayRowWireDesc *rWire;
513205b261ecSmrg
5133f7df2e56Smrg    wire = *wire_inout;
5134f7df2e56Smrg    olWire = (xkbOverlayWireDesc *) wire;
5135f7df2e56Smrg    if (client->swapped) {
5136f7df2e56Smrg        swapl(&olWire->name);
5137f7df2e56Smrg    }
5138f7df2e56Smrg    CHK_ATOM_ONLY(olWire->name);
5139f7df2e56Smrg    ol = XkbAddGeomOverlay(section, olWire->name, olWire->nRows);
5140f7df2e56Smrg    rWire = (xkbOverlayRowWireDesc *) &olWire[1];
5141f7df2e56Smrg    for (r = 0; r < olWire->nRows; r++) {
5142f7df2e56Smrg        register int k;
5143f7df2e56Smrg        xkbOverlayKeyWireDesc *kWire;
5144f7df2e56Smrg        XkbOverlayRowPtr row;
5145f7df2e56Smrg
5146f7df2e56Smrg        if (rWire->rowUnder > section->num_rows) {
5147f7df2e56Smrg            client->errorValue = _XkbErrCode4(0x20, r, section->num_rows,
5148f7df2e56Smrg                                              rWire->rowUnder);
5149f7df2e56Smrg            return BadMatch;
5150f7df2e56Smrg        }
5151f7df2e56Smrg        row = XkbAddGeomOverlayRow(ol, rWire->rowUnder, rWire->nKeys);
5152f7df2e56Smrg        kWire = (xkbOverlayKeyWireDesc *) &rWire[1];
5153f7df2e56Smrg        for (k = 0; k < rWire->nKeys; k++, kWire++) {
5154f7df2e56Smrg            if (XkbAddGeomOverlayKey(ol, row,
5155f7df2e56Smrg                                     (char *) kWire->over,
5156f7df2e56Smrg                                     (char *) kWire->under) == NULL) {
5157f7df2e56Smrg                client->errorValue = _XkbErrCode3(0x21, r, k);
5158f7df2e56Smrg                return BadMatch;
5159f7df2e56Smrg            }
5160f7df2e56Smrg        }
5161f7df2e56Smrg        rWire = (xkbOverlayRowWireDesc *) kWire;
5162f7df2e56Smrg    }
5163f7df2e56Smrg    olWire = (xkbOverlayWireDesc *) rWire;
5164f7df2e56Smrg    wire = (char *) olWire;
5165f7df2e56Smrg    *wire_inout = wire;
5166f7df2e56Smrg    return Success;
5167f7df2e56Smrg}
5168f7df2e56Smrg
5169f7df2e56Smrgstatic Status
5170f7df2e56Smrg_CheckSetSections(XkbGeometryPtr geom,
5171f7df2e56Smrg                  xkbSetGeometryReq * req, char **wire_inout, ClientPtr client)
5172f7df2e56Smrg{
5173f7df2e56Smrg    Status status;
5174f7df2e56Smrg    register int s;
5175f7df2e56Smrg    char *wire;
5176f7df2e56Smrg    xkbSectionWireDesc *sWire;
5177f7df2e56Smrg    XkbSectionPtr section;
5178f7df2e56Smrg
5179f7df2e56Smrg    wire = *wire_inout;
5180f7df2e56Smrg    if (req->nSections < 1)
5181f7df2e56Smrg        return Success;
5182f7df2e56Smrg    sWire = (xkbSectionWireDesc *) wire;
5183f7df2e56Smrg    for (s = 0; s < req->nSections; s++) {
5184f7df2e56Smrg        register int r;
5185f7df2e56Smrg        xkbRowWireDesc *rWire;
5186f7df2e56Smrg
5187f7df2e56Smrg        if (client->swapped) {
5188f7df2e56Smrg            swapl(&sWire->name);
5189f7df2e56Smrg            swaps(&sWire->top);
5190f7df2e56Smrg            swaps(&sWire->left);
5191f7df2e56Smrg            swaps(&sWire->width);
5192f7df2e56Smrg            swaps(&sWire->height);
5193f7df2e56Smrg            swaps(&sWire->angle);
5194f7df2e56Smrg        }
5195f7df2e56Smrg        CHK_ATOM_ONLY(sWire->name);
5196f7df2e56Smrg        section = XkbAddGeomSection(geom, sWire->name, sWire->nRows,
5197f7df2e56Smrg                                    sWire->nDoodads, sWire->nOverlays);
5198f7df2e56Smrg        if (!section)
5199f7df2e56Smrg            return BadAlloc;
5200f7df2e56Smrg        section->priority = sWire->priority;
5201f7df2e56Smrg        section->top = sWire->top;
5202f7df2e56Smrg        section->left = sWire->left;
5203f7df2e56Smrg        section->width = sWire->width;
5204f7df2e56Smrg        section->height = sWire->height;
5205f7df2e56Smrg        section->angle = sWire->angle;
5206f7df2e56Smrg        rWire = (xkbRowWireDesc *) &sWire[1];
5207f7df2e56Smrg        for (r = 0; r < sWire->nRows; r++) {
5208f7df2e56Smrg            register int k;
5209f7df2e56Smrg            XkbRowPtr row;
5210f7df2e56Smrg            xkbKeyWireDesc *kWire;
5211f7df2e56Smrg
5212f7df2e56Smrg            if (client->swapped) {
5213f7df2e56Smrg                swaps(&rWire->top);
5214f7df2e56Smrg                swaps(&rWire->left);
5215f7df2e56Smrg            }
5216f7df2e56Smrg            row = XkbAddGeomRow(section, rWire->nKeys);
5217f7df2e56Smrg            if (!row)
5218f7df2e56Smrg                return BadAlloc;
5219f7df2e56Smrg            row->top = rWire->top;
5220f7df2e56Smrg            row->left = rWire->left;
5221f7df2e56Smrg            row->vertical = rWire->vertical;
5222f7df2e56Smrg            kWire = (xkbKeyWireDesc *) &rWire[1];
5223f7df2e56Smrg            for (k = 0; k < rWire->nKeys; k++) {
5224f7df2e56Smrg                XkbKeyPtr key;
5225f7df2e56Smrg
5226f7df2e56Smrg                key = XkbAddGeomKey(row);
5227f7df2e56Smrg                if (!key)
5228f7df2e56Smrg                    return BadAlloc;
5229f7df2e56Smrg                memcpy(key->name.name, kWire[k].name, XkbKeyNameLength);
5230f7df2e56Smrg                key->gap = kWire[k].gap;
5231f7df2e56Smrg                key->shape_ndx = kWire[k].shapeNdx;
5232f7df2e56Smrg                key->color_ndx = kWire[k].colorNdx;
5233f7df2e56Smrg                if (key->shape_ndx >= geom->num_shapes) {
5234f7df2e56Smrg                    client->errorValue = _XkbErrCode3(0x10, key->shape_ndx,
5235f7df2e56Smrg                                                      geom->num_shapes);
5236f7df2e56Smrg                    return BadMatch;
5237f7df2e56Smrg                }
5238f7df2e56Smrg                if (key->color_ndx >= geom->num_colors) {
5239f7df2e56Smrg                    client->errorValue = _XkbErrCode3(0x11, key->color_ndx,
5240f7df2e56Smrg                                                      geom->num_colors);
5241f7df2e56Smrg                    return BadMatch;
5242f7df2e56Smrg                }
5243f7df2e56Smrg            }
5244f7df2e56Smrg            rWire = (xkbRowWireDesc *) &kWire[rWire->nKeys];
5245f7df2e56Smrg        }
5246f7df2e56Smrg        wire = (char *) rWire;
5247f7df2e56Smrg        if (sWire->nDoodads > 0) {
5248f7df2e56Smrg            register int d;
5249f7df2e56Smrg
5250f7df2e56Smrg            for (d = 0; d < sWire->nDoodads; d++) {
5251f7df2e56Smrg                status = _CheckSetDoodad(&wire, geom, section, client);
5252f7df2e56Smrg                if (status != Success)
5253f7df2e56Smrg                    return status;
5254f7df2e56Smrg            }
5255f7df2e56Smrg        }
5256f7df2e56Smrg        if (sWire->nOverlays > 0) {
5257f7df2e56Smrg            register int o;
5258f7df2e56Smrg
5259f7df2e56Smrg            for (o = 0; o < sWire->nOverlays; o++) {
5260f7df2e56Smrg                status = _CheckSetOverlay(&wire, geom, section, client);
5261f7df2e56Smrg                if (status != Success)
5262f7df2e56Smrg                    return status;
5263f7df2e56Smrg            }
5264f7df2e56Smrg        }
5265f7df2e56Smrg        sWire = (xkbSectionWireDesc *) wire;
5266f7df2e56Smrg    }
5267f7df2e56Smrg    wire = (char *) sWire;
5268f7df2e56Smrg    *wire_inout = wire;
5269f7df2e56Smrg    return Success;
5270f7df2e56Smrg}
5271f7df2e56Smrg
5272f7df2e56Smrgstatic Status
5273f7df2e56Smrg_CheckSetShapes(XkbGeometryPtr geom,
5274f7df2e56Smrg                xkbSetGeometryReq * req, char **wire_inout, ClientPtr client)
5275f7df2e56Smrg{
5276f7df2e56Smrg    register int i;
5277f7df2e56Smrg    char *wire;
5278f7df2e56Smrg
5279f7df2e56Smrg    wire = *wire_inout;
5280f7df2e56Smrg    if (req->nShapes < 1) {
5281f7df2e56Smrg        client->errorValue = _XkbErrCode2(0x06, req->nShapes);
5282f7df2e56Smrg        return BadValue;
528305b261ecSmrg    }
528405b261ecSmrg    else {
5285f7df2e56Smrg        xkbShapeWireDesc *shapeWire;
5286f7df2e56Smrg        XkbShapePtr shape;
5287f7df2e56Smrg        register int o;
5288f7df2e56Smrg
5289f7df2e56Smrg        shapeWire = (xkbShapeWireDesc *) wire;
5290f7df2e56Smrg        for (i = 0; i < req->nShapes; i++) {
5291f7df2e56Smrg            xkbOutlineWireDesc *olWire;
5292f7df2e56Smrg            XkbOutlinePtr ol;
5293f7df2e56Smrg
5294f7df2e56Smrg            shape =
5295f7df2e56Smrg                XkbAddGeomShape(geom, shapeWire->name, shapeWire->nOutlines);
5296f7df2e56Smrg            if (!shape)
5297f7df2e56Smrg                return BadAlloc;
5298f7df2e56Smrg            olWire = (xkbOutlineWireDesc *) (&shapeWire[1]);
5299f7df2e56Smrg            for (o = 0; o < shapeWire->nOutlines; o++) {
5300f7df2e56Smrg                register int p;
5301f7df2e56Smrg                XkbPointPtr pt;
5302f7df2e56Smrg                xkbPointWireDesc *ptWire;
5303f7df2e56Smrg
5304f7df2e56Smrg                ol = XkbAddGeomOutline(shape, olWire->nPoints);
5305f7df2e56Smrg                if (!ol)
5306f7df2e56Smrg                    return BadAlloc;
5307f7df2e56Smrg                ol->corner_radius = olWire->cornerRadius;
5308f7df2e56Smrg                ptWire = (xkbPointWireDesc *) &olWire[1];
5309f7df2e56Smrg                for (p = 0, pt = ol->points; p < olWire->nPoints; p++, pt++) {
5310f7df2e56Smrg                    pt->x = ptWire[p].x;
5311f7df2e56Smrg                    pt->y = ptWire[p].y;
5312f7df2e56Smrg                    if (client->swapped) {
5313f7df2e56Smrg                        swaps(&pt->x);
5314f7df2e56Smrg                        swaps(&pt->y);
5315f7df2e56Smrg                    }
5316f7df2e56Smrg                }
5317f7df2e56Smrg                ol->num_points = olWire->nPoints;
5318f7df2e56Smrg                olWire = (xkbOutlineWireDesc *) (&ptWire[olWire->nPoints]);
5319f7df2e56Smrg            }
5320f7df2e56Smrg            if (shapeWire->primaryNdx != XkbNoShape)
5321f7df2e56Smrg                shape->primary = &shape->outlines[shapeWire->primaryNdx];
5322f7df2e56Smrg            if (shapeWire->approxNdx != XkbNoShape)
5323f7df2e56Smrg                shape->approx = &shape->outlines[shapeWire->approxNdx];
5324f7df2e56Smrg            shapeWire = (xkbShapeWireDesc *) olWire;
5325f7df2e56Smrg        }
5326f7df2e56Smrg        wire = (char *) shapeWire;
5327f7df2e56Smrg    }
5328f7df2e56Smrg    if (geom->num_shapes != req->nShapes) {
5329f7df2e56Smrg        client->errorValue = _XkbErrCode3(0x07, geom->num_shapes, req->nShapes);
5330f7df2e56Smrg        return BadMatch;
5331f7df2e56Smrg    }
5332f7df2e56Smrg
5333f7df2e56Smrg    *wire_inout = wire;
533405b261ecSmrg    return Success;
533505b261ecSmrg}
533605b261ecSmrg
533705b261ecSmrgstatic Status
5338f7df2e56Smrg_CheckSetGeom(XkbGeometryPtr geom, xkbSetGeometryReq * req, ClientPtr client)
533905b261ecSmrg{
5340f7df2e56Smrg    register int i;
5341f7df2e56Smrg    Status status;
5342f7df2e56Smrg    char *wire;
534305b261ecSmrg
5344f7df2e56Smrg    wire = (char *) &req[1];
53451e26616aSmrg    status = _GetCountedString(&wire, client, &geom->label_font);
53461e26616aSmrg    if (status != Success)
53471e26616aSmrg        return status;
53481e26616aSmrg
53491e26616aSmrg    for (i = 0; i < req->nProperties; i++) {
5350f7df2e56Smrg        char *name, *val;
53511e26616aSmrg
53521e26616aSmrg        status = _GetCountedString(&wire, client, &name);
53531e26616aSmrg        if (status != Success)
53541e26616aSmrg            return status;
53551e26616aSmrg        status = _GetCountedString(&wire, client, &val);
53561e26616aSmrg        if (status != Success) {
53576747b715Smrg            free(name);
53581e26616aSmrg            return status;
535905b261ecSmrg        }
5360f7df2e56Smrg        if (XkbAddGeomProperty(geom, name, val) == NULL) {
53616747b715Smrg            free(name);
53626747b715Smrg            free(val);
5363f7df2e56Smrg            return BadAlloc;
536405b261ecSmrg        }
53656747b715Smrg        free(name);
53666747b715Smrg        free(val);
536705b261ecSmrg    }
536805b261ecSmrg
5369f7df2e56Smrg    if (req->nColors < 2) {
5370f7df2e56Smrg        client->errorValue = _XkbErrCode3(0x01, 2, req->nColors);
5371f7df2e56Smrg        return BadValue;
537205b261ecSmrg    }
5373f7df2e56Smrg    if (req->baseColorNdx > req->nColors) {
5374f7df2e56Smrg        client->errorValue =
5375f7df2e56Smrg            _XkbErrCode3(0x03, req->nColors, req->baseColorNdx);
5376f7df2e56Smrg        return BadMatch;
537705b261ecSmrg    }
5378f7df2e56Smrg    if (req->labelColorNdx > req->nColors) {
5379f7df2e56Smrg        client->errorValue =
5380f7df2e56Smrg            _XkbErrCode3(0x03, req->nColors, req->labelColorNdx);
5381f7df2e56Smrg        return BadMatch;
538205b261ecSmrg    }
5383f7df2e56Smrg    if (req->labelColorNdx == req->baseColorNdx) {
5384f7df2e56Smrg        client->errorValue = _XkbErrCode3(0x04, req->baseColorNdx,
5385f7df2e56Smrg                                          req->labelColorNdx);
5386f7df2e56Smrg        return BadMatch;
538705b261ecSmrg    }
538805b261ecSmrg
53891e26616aSmrg    for (i = 0; i < req->nColors; i++) {
5390f7df2e56Smrg        char *name;
5391f7df2e56Smrg
53921e26616aSmrg        status = _GetCountedString(&wire, client, &name);
53931e26616aSmrg        if (status != Success)
53941e26616aSmrg            return status;
5395f7df2e56Smrg        if (!XkbAddGeomColor(geom, name, geom->num_colors)) {
53966747b715Smrg            free(name);
5397f7df2e56Smrg            return BadAlloc;
539805b261ecSmrg        }
53996747b715Smrg        free(name);
540005b261ecSmrg    }
5401f7df2e56Smrg    if (req->nColors != geom->num_colors) {
5402f7df2e56Smrg        client->errorValue = _XkbErrCode3(0x05, req->nColors, geom->num_colors);
5403f7df2e56Smrg        return BadMatch;
540405b261ecSmrg    }
5405f7df2e56Smrg    geom->label_color = &geom->colors[req->labelColorNdx];
5406f7df2e56Smrg    geom->base_color = &geom->colors[req->baseColorNdx];
540705b261ecSmrg
5408f7df2e56Smrg    if ((status = _CheckSetShapes(geom, req, &wire, client)) != Success)
5409f7df2e56Smrg        return status;
541005b261ecSmrg
5411f7df2e56Smrg    if ((status = _CheckSetSections(geom, req, &wire, client)) != Success)
5412f7df2e56Smrg        return status;
541305b261ecSmrg
5414f7df2e56Smrg    for (i = 0; i < req->nDoodads; i++) {
5415f7df2e56Smrg        status = _CheckSetDoodad(&wire, geom, NULL, client);
5416f7df2e56Smrg        if (status != Success)
5417f7df2e56Smrg            return status;
541805b261ecSmrg    }
541905b261ecSmrg
5420f7df2e56Smrg    for (i = 0; i < req->nKeyAliases; i++) {
5421f7df2e56Smrg        if (XkbAddGeomKeyAlias(geom, &wire[XkbKeyNameLength], wire) == NULL)
5422f7df2e56Smrg            return BadAlloc;
5423f7df2e56Smrg        wire += 2 * XkbKeyNameLength;
542405b261ecSmrg    }
542505b261ecSmrg    return Success;
542605b261ecSmrg}
542705b261ecSmrg
54284642e01fSmrgstatic int
5429f7df2e56Smrg_XkbSetGeometry(ClientPtr client, DeviceIntPtr dev, xkbSetGeometryReq * stuff)
543005b261ecSmrg{
5431f7df2e56Smrg    XkbDescPtr xkb;
5432f7df2e56Smrg    Bool new_name;
5433f7df2e56Smrg    xkbNewKeyboardNotify nkn;
5434f7df2e56Smrg    XkbGeometryPtr geom, old;
5435f7df2e56Smrg    XkbGeometrySizesRec sizes;
5436f7df2e56Smrg    Status status;
5437f7df2e56Smrg
5438f7df2e56Smrg    xkb = dev->key->xkbInfo->desc;
5439f7df2e56Smrg    old = xkb->geom;
5440f7df2e56Smrg    xkb->geom = NULL;
5441f7df2e56Smrg
5442f7df2e56Smrg    sizes.which = XkbGeomAllMask;
5443f7df2e56Smrg    sizes.num_properties = stuff->nProperties;
5444f7df2e56Smrg    sizes.num_colors = stuff->nColors;
5445f7df2e56Smrg    sizes.num_shapes = stuff->nShapes;
5446f7df2e56Smrg    sizes.num_sections = stuff->nSections;
5447f7df2e56Smrg    sizes.num_doodads = stuff->nDoodads;
5448f7df2e56Smrg    sizes.num_key_aliases = stuff->nKeyAliases;
5449f7df2e56Smrg    if ((status = XkbAllocGeometry(xkb, &sizes)) != Success) {
5450f7df2e56Smrg        xkb->geom = old;
54514642e01fSmrg        return status;
545205b261ecSmrg    }
5453f7df2e56Smrg    geom = xkb->geom;
5454f7df2e56Smrg    geom->name = stuff->name;
5455f7df2e56Smrg    geom->width_mm = stuff->widthMM;
5456f7df2e56Smrg    geom->height_mm = stuff->heightMM;
5457f7df2e56Smrg    if ((status = _CheckSetGeom(geom, stuff, client)) != Success) {
5458f7df2e56Smrg        XkbFreeGeometry(geom, XkbGeomAllMask, TRUE);
5459f7df2e56Smrg        xkb->geom = old;
54604642e01fSmrg        return status;
546105b261ecSmrg    }
5462f7df2e56Smrg    new_name = (xkb->names->geometry != geom->name);
5463f7df2e56Smrg    xkb->names->geometry = geom->name;
546405b261ecSmrg    if (old)
5465f7df2e56Smrg        XkbFreeGeometry(old, XkbGeomAllMask, TRUE);
546605b261ecSmrg    if (new_name) {
5467f7df2e56Smrg        xkbNamesNotify nn;
5468f7df2e56Smrg
54696747b715Smrg        memset(&nn, 0, sizeof(xkbNamesNotify));
5470f7df2e56Smrg        nn.changed = XkbGeometryNameMask;
5471f7df2e56Smrg        XkbSendNamesNotify(dev, &nn);
5472f7df2e56Smrg    }
5473f7df2e56Smrg    nkn.deviceID = nkn.oldDeviceID = dev->id;
5474f7df2e56Smrg    nkn.minKeyCode = nkn.oldMinKeyCode = xkb->min_key_code;
5475f7df2e56Smrg    nkn.maxKeyCode = nkn.oldMaxKeyCode = xkb->max_key_code;
5476f7df2e56Smrg    nkn.requestMajor = XkbReqCode;
5477f7df2e56Smrg    nkn.requestMinor = X_kbSetGeometry;
5478f7df2e56Smrg    nkn.changed = XkbNKN_GeometryMask;
5479f7df2e56Smrg    XkbSendNewKeyboardNotify(dev, &nkn);
548005b261ecSmrg    return Success;
548105b261ecSmrg}
548205b261ecSmrg
54834642e01fSmrgint
54844642e01fSmrgProcXkbSetGeometry(ClientPtr client)
54854642e01fSmrg{
5486f7df2e56Smrg    DeviceIntPtr dev;
5487f7df2e56Smrg    int rc;
54884642e01fSmrg
54894642e01fSmrg    REQUEST(xkbSetGeometryReq);
54904642e01fSmrg    REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq);
54914642e01fSmrg
5492f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
5493f7df2e56Smrg        return BadAccess;
54944642e01fSmrg
54954642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
54964642e01fSmrg    CHK_ATOM_OR_NONE(stuff->name);
54974642e01fSmrg
54984642e01fSmrg    rc = _XkbSetGeometry(client, dev, stuff);
54994642e01fSmrg    if (rc != Success)
55004642e01fSmrg        return rc;
55014642e01fSmrg
5502f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
55034642e01fSmrg        DeviceIntPtr other;
5504f7df2e56Smrg
5505f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
5506f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
5507f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
5508f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
5509f7df2e56Smrg                              DixManageAccess);
55104642e01fSmrg                if (rc == Success)
55114642e01fSmrg                    _XkbSetGeometry(client, other, stuff);
55124642e01fSmrg            }
55134642e01fSmrg        }
55144642e01fSmrg    }
55154642e01fSmrg
55164642e01fSmrg    return Success;
55174642e01fSmrg}
55184642e01fSmrg
551905b261ecSmrg/***====================================================================***/
552005b261ecSmrg
552105b261ecSmrgint
552205b261ecSmrgProcXkbPerClientFlags(ClientPtr client)
552305b261ecSmrg{
5524f7df2e56Smrg    DeviceIntPtr dev;
5525f7df2e56Smrg    xkbPerClientFlagsReply rep;
5526f7df2e56Smrg    XkbInterestPtr interest;
55274642e01fSmrg    Mask access_mode = DixGetAttrAccess | DixSetAttrAccess;
552805b261ecSmrg
552905b261ecSmrg    REQUEST(xkbPerClientFlagsReq);
553005b261ecSmrg    REQUEST_SIZE_MATCH(xkbPerClientFlagsReq);
553105b261ecSmrg
5532f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
5533f7df2e56Smrg        return BadAccess;
553405b261ecSmrg
55354642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
5536f7df2e56Smrg    CHK_MASK_LEGAL(0x01, stuff->change, XkbPCF_AllFlagsMask);
5537f7df2e56Smrg    CHK_MASK_MATCH(0x02, stuff->change, stuff->value);
553805b261ecSmrg
5539f7df2e56Smrg    interest = XkbFindClientResource((DevicePtr) dev, client);
554005b261ecSmrg    if (stuff->change) {
5541f7df2e56Smrg        client->xkbClientFlags &= ~stuff->change;
5542f7df2e56Smrg        client->xkbClientFlags |= stuff->value;
554305b261ecSmrg    }
5544f7df2e56Smrg    if (stuff->change & XkbPCF_AutoResetControlsMask) {
5545f7df2e56Smrg        Bool want;
5546f7df2e56Smrg
5547f7df2e56Smrg        want = stuff->value & XkbPCF_AutoResetControlsMask;
5548f7df2e56Smrg        if (interest && !want) {
5549f7df2e56Smrg            interest->autoCtrls = interest->autoCtrlValues = 0;
5550f7df2e56Smrg        }
5551f7df2e56Smrg        else if (want && (!interest)) {
5552f7df2e56Smrg            XID id = FakeClientID(client->index);
5553f7df2e56Smrg
5554f7df2e56Smrg            if (!AddResource(id, RT_XKBCLIENT, dev))
5555f7df2e56Smrg                return BadAlloc;
5556f7df2e56Smrg            interest = XkbAddClientResource((DevicePtr) dev, client, id);
5557f7df2e56Smrg            if (!interest)
5558f7df2e56Smrg                return BadAlloc;
5559f7df2e56Smrg        }
5560f7df2e56Smrg        if (interest && want) {
5561f7df2e56Smrg            register unsigned affect;
5562f7df2e56Smrg
5563f7df2e56Smrg            affect = stuff->ctrlsToChange;
5564f7df2e56Smrg
5565f7df2e56Smrg            CHK_MASK_LEGAL(0x03, affect, XkbAllBooleanCtrlsMask);
5566f7df2e56Smrg            CHK_MASK_MATCH(0x04, affect, stuff->autoCtrls);
5567f7df2e56Smrg            CHK_MASK_MATCH(0x05, stuff->autoCtrls, stuff->autoCtrlValues);
5568f7df2e56Smrg
5569f7df2e56Smrg            interest->autoCtrls &= ~affect;
5570f7df2e56Smrg            interest->autoCtrlValues &= ~affect;
5571f7df2e56Smrg            interest->autoCtrls |= stuff->autoCtrls & affect;
5572f7df2e56Smrg            interest->autoCtrlValues |= stuff->autoCtrlValues & affect;
5573f7df2e56Smrg        }
557405b261ecSmrg    }
5575f7df2e56Smrg
5576f7df2e56Smrg    rep = (xkbPerClientFlagsReply) {
5577f7df2e56Smrg        .type = X_Reply,
5578f7df2e56Smrg        .sequenceNumber = client->sequence,
5579f7df2e56Smrg        .length = 0,
5580f7df2e56Smrg        .supported = XkbPCF_AllFlagsMask,
5581f7df2e56Smrg        .value = client->xkbClientFlags & XkbPCF_AllFlagsMask,
5582f7df2e56Smrg        .autoCtrls = interest ? interest->autoCtrls : 0,
5583f7df2e56Smrg        .autoCtrlValues =  interest ? interest->autoCtrlValues : 0,
5584f7df2e56Smrg    };
5585f7df2e56Smrg    if (client->swapped) {
5586f7df2e56Smrg        swaps(&rep.sequenceNumber);
5587f7df2e56Smrg        swapl(&rep.supported);
5588f7df2e56Smrg        swapl(&rep.value);
5589f7df2e56Smrg        swapl(&rep.autoCtrls);
5590f7df2e56Smrg        swapl(&rep.autoCtrlValues);
559105b261ecSmrg    }
5592f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbPerClientFlagsReply), &rep);
55936747b715Smrg    return Success;
559405b261ecSmrg}
559505b261ecSmrg
559605b261ecSmrg/***====================================================================***/
559705b261ecSmrg
559805b261ecSmrg/* all latin-1 alphanumerics, plus parens, minus, underscore, slash */
559905b261ecSmrg/* and wildcards */
560005b261ecSmrgstatic unsigned char componentSpecLegal[] = {
5601f7df2e56Smrg    0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x87,
5602f7df2e56Smrg    0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07,
5603f7df2e56Smrg    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5604f7df2e56Smrg    0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
560505b261ecSmrg};
560605b261ecSmrg
560705b261ecSmrg/* same as above but accepts percent, plus and bar too */
560805b261ecSmrgstatic unsigned char componentExprLegal[] = {
5609f7df2e56Smrg    0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0xff, 0x87,
5610f7df2e56Smrg    0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x17,
5611f7df2e56Smrg    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5612f7df2e56Smrg    0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
561305b261ecSmrg};
561405b261ecSmrg
561505b261ecSmrgstatic char *
5616f7df2e56SmrgGetComponentSpec(unsigned char **pWire, Bool allowExpr, int *errRtrn)
561705b261ecSmrg{
5618f7df2e56Smrg    int len;
5619f7df2e56Smrg    register int i;
5620f7df2e56Smrg    unsigned char *wire, *str, *tmp, *legal;
5621f7df2e56Smrg
5622f7df2e56Smrg    if (allowExpr)
5623f7df2e56Smrg        legal = &componentExprLegal[0];
5624f7df2e56Smrg    else
5625f7df2e56Smrg        legal = &componentSpecLegal[0];
5626f7df2e56Smrg
5627f7df2e56Smrg    wire = *pWire;
5628f7df2e56Smrg    len = (*(unsigned char *) wire++);
5629f7df2e56Smrg    if (len > 0) {
5630f7df2e56Smrg        str = calloc(1, len + 1);
5631f7df2e56Smrg        if (str) {
5632f7df2e56Smrg            tmp = str;
5633f7df2e56Smrg            for (i = 0; i < len; i++) {
5634f7df2e56Smrg                if (legal[(*wire) / 8] & (1 << ((*wire) % 8)))
5635f7df2e56Smrg                    *tmp++ = *wire++;
5636f7df2e56Smrg                else
5637f7df2e56Smrg                    wire++;
5638f7df2e56Smrg            }
5639f7df2e56Smrg            if (tmp != str)
5640f7df2e56Smrg                *tmp++ = '\0';
5641f7df2e56Smrg            else {
5642f7df2e56Smrg                free(str);
5643f7df2e56Smrg                str = NULL;
5644f7df2e56Smrg            }
5645f7df2e56Smrg        }
5646f7df2e56Smrg        else {
5647f7df2e56Smrg            *errRtrn = BadAlloc;
5648f7df2e56Smrg        }
564905b261ecSmrg    }
565005b261ecSmrg    else {
5651f7df2e56Smrg        str = NULL;
565205b261ecSmrg    }
5653f7df2e56Smrg    *pWire = wire;
5654f7df2e56Smrg    return (char *) str;
565505b261ecSmrg}
565605b261ecSmrg
565705b261ecSmrg/***====================================================================***/
565805b261ecSmrg
565905b261ecSmrgint
566005b261ecSmrgProcXkbListComponents(ClientPtr client)
566105b261ecSmrg{
5662f7df2e56Smrg    DeviceIntPtr dev;
5663f7df2e56Smrg    xkbListComponentsReply rep;
5664f7df2e56Smrg    unsigned len;
5665f7df2e56Smrg    unsigned char *str;
5666f7df2e56Smrg    uint8_t size;
5667f7df2e56Smrg    int i;
566805b261ecSmrg
566905b261ecSmrg    REQUEST(xkbListComponentsReq);
567005b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbListComponentsReq);
567105b261ecSmrg
5672f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
5673f7df2e56Smrg        return BadAccess;
567405b261ecSmrg
56754642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
567605b261ecSmrg
5677f7df2e56Smrg    /* The request is followed by six Pascal strings (i.e. size in characters
5678f7df2e56Smrg     * followed by a string pattern) describing what the client wants us to
5679f7df2e56Smrg     * list.  We don't care, but might as well check they haven't got the
5680f7df2e56Smrg     * length wrong. */
5681f7df2e56Smrg    str = (unsigned char *) &stuff[1];
5682f7df2e56Smrg    for (i = 0; i < 6; i++) {
5683f7df2e56Smrg        size = *((uint8_t *)str);
5684f7df2e56Smrg        len = (str + size + 1) - ((unsigned char *) stuff);
5685f7df2e56Smrg        if ((XkbPaddedSize(len) / 4) > stuff->length)
5686f7df2e56Smrg            return BadLength;
5687f7df2e56Smrg        str += (size + 1);
5688f7df2e56Smrg    }
5689f7df2e56Smrg    if ((XkbPaddedSize(len) / 4) != stuff->length)
5690f7df2e56Smrg        return BadLength;
5691f7df2e56Smrg    rep = (xkbListComponentsReply) {
5692f7df2e56Smrg        .type = X_Reply,
5693f7df2e56Smrg        .deviceID = dev->id,
5694f7df2e56Smrg        .sequenceNumber = client->sequence,
5695f7df2e56Smrg        .length = 0,
5696f7df2e56Smrg        .nKeymaps = 0,
5697f7df2e56Smrg        .nKeycodes = 0,
5698f7df2e56Smrg        .nTypes = 0,
5699f7df2e56Smrg        .nCompatMaps = 0,
5700f7df2e56Smrg        .nSymbols = 0,
5701f7df2e56Smrg        .nGeometries = 0,
5702f7df2e56Smrg        .extra = 0
5703f7df2e56Smrg    };
570405b261ecSmrg    if (client->swapped) {
5705f7df2e56Smrg        swaps(&rep.sequenceNumber);
5706f7df2e56Smrg        swapl(&rep.length);
5707f7df2e56Smrg        swaps(&rep.nKeymaps);
5708f7df2e56Smrg        swaps(&rep.nKeycodes);
5709f7df2e56Smrg        swaps(&rep.nTypes);
5710f7df2e56Smrg        swaps(&rep.nCompatMaps);
5711f7df2e56Smrg        swaps(&rep.nSymbols);
5712f7df2e56Smrg        swaps(&rep.nGeometries);
5713f7df2e56Smrg        swaps(&rep.extra);
5714f7df2e56Smrg    }
5715f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbListComponentsReply), &rep);
57166747b715Smrg    return Success;
571705b261ecSmrg}
571805b261ecSmrg
571905b261ecSmrg/***====================================================================***/
572005b261ecSmrgint
572105b261ecSmrgProcXkbGetKbdByName(ClientPtr client)
572205b261ecSmrg{
5723f7df2e56Smrg    DeviceIntPtr dev;
5724f7df2e56Smrg    DeviceIntPtr tmpd;
5725f7df2e56Smrg    DeviceIntPtr master;
5726f7df2e56Smrg    xkbGetKbdByNameReply rep = { 0 };
5727f7df2e56Smrg    xkbGetMapReply mrep = { 0 };
5728f7df2e56Smrg    xkbGetCompatMapReply crep = { 0 };
5729f7df2e56Smrg    xkbGetIndicatorMapReply irep = { 0 };
5730f7df2e56Smrg    xkbGetNamesReply nrep = { 0 };
5731f7df2e56Smrg    xkbGetGeometryReply grep = { 0 };
5732f7df2e56Smrg    XkbComponentNamesRec names = { 0 };
5733f7df2e56Smrg    XkbDescPtr xkb, new;
5734f7df2e56Smrg    XkbEventCauseRec cause;
5735f7df2e56Smrg    unsigned char *str;
5736f7df2e56Smrg    char mapFile[PATH_MAX];
5737f7df2e56Smrg    unsigned len;
5738f7df2e56Smrg    unsigned fwant, fneed, reported;
5739f7df2e56Smrg    int status;
5740f7df2e56Smrg    Bool geom_changed;
5741f7df2e56Smrg    XkbSrvLedInfoPtr old_sli;
5742f7df2e56Smrg    XkbSrvLedInfoPtr sli;
57434642e01fSmrg    Mask access_mode = DixGetAttrAccess | DixManageAccess;
574405b261ecSmrg
574505b261ecSmrg    REQUEST(xkbGetKbdByNameReq);
574605b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq);
574705b261ecSmrg
5748f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
5749f7df2e56Smrg        return BadAccess;
575005b261ecSmrg
57514642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
5752f7df2e56Smrg    master = GetMaster(dev, MASTER_KEYBOARD);
575305b261ecSmrg
575405b261ecSmrg    xkb = dev->key->xkbInfo->desc;
5755f7df2e56Smrg    status = Success;
5756f7df2e56Smrg    str = (unsigned char *) &stuff[1];
5757f7df2e56Smrg    if (GetComponentSpec(&str, TRUE, &status))  /* keymap, unsupported */
57586747b715Smrg        return BadMatch;
5759f7df2e56Smrg    names.keycodes = GetComponentSpec(&str, TRUE, &status);
5760f7df2e56Smrg    names.types = GetComponentSpec(&str, TRUE, &status);
5761f7df2e56Smrg    names.compat = GetComponentSpec(&str, TRUE, &status);
5762f7df2e56Smrg    names.symbols = GetComponentSpec(&str, TRUE, &status);
5763f7df2e56Smrg    names.geometry = GetComponentSpec(&str, TRUE, &status);
5764f7df2e56Smrg    if (status != Success)
5765f7df2e56Smrg        return status;
5766f7df2e56Smrg    len = str - ((unsigned char *) stuff);
5767f7df2e56Smrg    if ((XkbPaddedSize(len) / 4) != stuff->length)
5768f7df2e56Smrg        return BadLength;
5769f7df2e56Smrg
5770f7df2e56Smrg    CHK_MASK_LEGAL(0x01, stuff->want, XkbGBN_AllComponentsMask);
5771f7df2e56Smrg    CHK_MASK_LEGAL(0x02, stuff->need, XkbGBN_AllComponentsMask);
5772f7df2e56Smrg
577305b261ecSmrg    if (stuff->load)
5774f7df2e56Smrg        fwant = XkbGBN_AllComponentsMask;
5775f7df2e56Smrg    else
5776f7df2e56Smrg        fwant = stuff->want | stuff->need;
5777f7df2e56Smrg    if ((!names.compat) &&
5778f7df2e56Smrg        (fwant & (XkbGBN_CompatMapMask | XkbGBN_IndicatorMapMask))) {
5779f7df2e56Smrg        names.compat = Xstrdup("%");
578005b261ecSmrg    }
5781f7df2e56Smrg    if ((!names.types) && (fwant & (XkbGBN_TypesMask))) {
5782f7df2e56Smrg        names.types = Xstrdup("%");
57834642e01fSmrg    }
5784f7df2e56Smrg    if ((!names.symbols) && (fwant & XkbGBN_SymbolsMask)) {
5785f7df2e56Smrg        names.symbols = Xstrdup("%");
57864642e01fSmrg    }
5787f7df2e56Smrg    geom_changed = ((names.geometry != NULL) &&
5788f7df2e56Smrg                    (strcmp(names.geometry, "%") != 0));
5789f7df2e56Smrg    if ((!names.geometry) && (fwant & XkbGBN_GeometryMask)) {
5790f7df2e56Smrg        names.geometry = Xstrdup("%");
5791f7df2e56Smrg        geom_changed = FALSE;
579205b261ecSmrg    }
579305b261ecSmrg
57946747b715Smrg    memset(mapFile, 0, PATH_MAX);
5795f7df2e56Smrg    rep.type = X_Reply;
579605b261ecSmrg    rep.deviceID = dev->id;
579705b261ecSmrg    rep.sequenceNumber = client->sequence;
579805b261ecSmrg    rep.length = 0;
579905b261ecSmrg    rep.minKeyCode = xkb->min_key_code;
580005b261ecSmrg    rep.maxKeyCode = xkb->max_key_code;
5801f7df2e56Smrg    rep.loaded = FALSE;
5802f7df2e56Smrg    fwant =
5803f7df2e56Smrg        XkbConvertGetByNameComponents(TRUE, stuff->want) | XkmVirtualModsMask;
5804f7df2e56Smrg    fneed = XkbConvertGetByNameComponents(TRUE, stuff->need);
5805f7df2e56Smrg    rep.reported = XkbConvertGetByNameComponents(FALSE, fwant | fneed);
580605b261ecSmrg    if (stuff->load) {
5807f7df2e56Smrg        fneed |= XkmKeymapRequired;
5808f7df2e56Smrg        fwant |= XkmKeymapLegal;
580905b261ecSmrg    }
5810f7df2e56Smrg    if ((fwant | fneed) & XkmSymbolsMask) {
5811f7df2e56Smrg        fneed |= XkmKeyNamesIndex | XkmTypesIndex;
5812f7df2e56Smrg        fwant |= XkmIndicatorsIndex;
581305b261ecSmrg    }
581405b261ecSmrg
581505b261ecSmrg    /* We pass dev in here so we can get the old names out if needed. */
5816f7df2e56Smrg    rep.found = XkbDDXLoadKeymapByNames(dev, &names, fwant, fneed, &new,
5817f7df2e56Smrg                                        mapFile, PATH_MAX);
5818f7df2e56Smrg    rep.newKeyboard = FALSE;
5819f7df2e56Smrg    rep.pad1 = rep.pad2 = rep.pad3 = rep.pad4 = 0;
5820f7df2e56Smrg
5821f7df2e56Smrg    stuff->want |= stuff->need;
5822f7df2e56Smrg    if (new == NULL)
5823f7df2e56Smrg        rep.reported = 0;
582405b261ecSmrg    else {
5825f7df2e56Smrg        if (stuff->load)
5826f7df2e56Smrg            rep.loaded = TRUE;
5827f7df2e56Smrg        if (stuff->load ||
5828f7df2e56Smrg            ((rep.reported & XkbGBN_SymbolsMask) && (new->compat))) {
5829f7df2e56Smrg            XkbChangesRec changes;
5830f7df2e56Smrg
5831f7df2e56Smrg            memset(&changes, 0, sizeof(changes));
5832f7df2e56Smrg            XkbUpdateDescActions(new,
5833f7df2e56Smrg                                 new->min_key_code, XkbNumKeys(new), &changes);
5834f7df2e56Smrg        }
583505b261ecSmrg
5836f7df2e56Smrg        if (new->map == NULL)
5837f7df2e56Smrg            rep.reported &= ~(XkbGBN_SymbolsMask | XkbGBN_TypesMask);
5838f7df2e56Smrg        else if (rep.reported & (XkbGBN_SymbolsMask | XkbGBN_TypesMask)) {
5839f7df2e56Smrg            mrep.type = X_Reply;
5840f7df2e56Smrg            mrep.deviceID = dev->id;
5841f7df2e56Smrg            mrep.sequenceNumber = client->sequence;
5842f7df2e56Smrg            mrep.length =
5843f7df2e56Smrg                ((SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply)) >> 2);
5844f7df2e56Smrg            mrep.minKeyCode = new->min_key_code;
5845f7df2e56Smrg            mrep.maxKeyCode = new->max_key_code;
5846f7df2e56Smrg            mrep.present = 0;
5847f7df2e56Smrg            mrep.totalSyms = mrep.totalActs =
5848f7df2e56Smrg                mrep.totalKeyBehaviors = mrep.totalKeyExplicit =
5849f7df2e56Smrg                mrep.totalModMapKeys = mrep.totalVModMapKeys = 0;
5850f7df2e56Smrg            if (rep.reported & (XkbGBN_TypesMask | XkbGBN_ClientSymbolsMask)) {
5851f7df2e56Smrg                mrep.present |= XkbKeyTypesMask;
5852f7df2e56Smrg                mrep.firstType = 0;
5853f7df2e56Smrg                mrep.nTypes = mrep.totalTypes = new->map->num_types;
5854f7df2e56Smrg            }
5855f7df2e56Smrg            else {
5856f7df2e56Smrg                mrep.firstType = mrep.nTypes = 0;
5857f7df2e56Smrg                mrep.totalTypes = 0;
5858f7df2e56Smrg            }
5859f7df2e56Smrg            if (rep.reported & XkbGBN_ClientSymbolsMask) {
5860f7df2e56Smrg                mrep.present |= (XkbKeySymsMask | XkbModifierMapMask);
5861f7df2e56Smrg                mrep.firstKeySym = mrep.firstModMapKey = new->min_key_code;
5862f7df2e56Smrg                mrep.nKeySyms = mrep.nModMapKeys = XkbNumKeys(new);
5863f7df2e56Smrg            }
5864f7df2e56Smrg            else {
5865f7df2e56Smrg                mrep.firstKeySym = mrep.firstModMapKey = 0;
5866f7df2e56Smrg                mrep.nKeySyms = mrep.nModMapKeys = 0;
5867f7df2e56Smrg            }
5868f7df2e56Smrg            if (rep.reported & XkbGBN_ServerSymbolsMask) {
5869f7df2e56Smrg                mrep.present |= XkbAllServerInfoMask;
5870f7df2e56Smrg                mrep.virtualMods = ~0;
5871f7df2e56Smrg                mrep.firstKeyAct = mrep.firstKeyBehavior =
5872f7df2e56Smrg                    mrep.firstKeyExplicit = new->min_key_code;
5873f7df2e56Smrg                mrep.nKeyActs = mrep.nKeyBehaviors =
5874f7df2e56Smrg                    mrep.nKeyExplicit = XkbNumKeys(new);
5875f7df2e56Smrg                mrep.firstVModMapKey = new->min_key_code;
5876f7df2e56Smrg                mrep.nVModMapKeys = XkbNumKeys(new);
5877f7df2e56Smrg            }
5878f7df2e56Smrg            else {
5879f7df2e56Smrg                mrep.virtualMods = 0;
5880f7df2e56Smrg                mrep.firstKeyAct = mrep.firstKeyBehavior =
5881f7df2e56Smrg                    mrep.firstKeyExplicit = 0;
5882f7df2e56Smrg                mrep.nKeyActs = mrep.nKeyBehaviors = mrep.nKeyExplicit = 0;
5883f7df2e56Smrg            }
5884f7df2e56Smrg            XkbComputeGetMapReplySize(new, &mrep);
5885f7df2e56Smrg            rep.length += SIZEOF(xGenericReply) / 4 + mrep.length;
5886f7df2e56Smrg        }
5887f7df2e56Smrg        if (new->compat == NULL)
5888f7df2e56Smrg            rep.reported &= ~XkbGBN_CompatMapMask;
5889f7df2e56Smrg        else if (rep.reported & XkbGBN_CompatMapMask) {
5890f7df2e56Smrg            crep.type = X_Reply;
5891f7df2e56Smrg            crep.deviceID = dev->id;
5892f7df2e56Smrg            crep.sequenceNumber = client->sequence;
5893f7df2e56Smrg            crep.length = 0;
5894f7df2e56Smrg            crep.groups = XkbAllGroupsMask;
5895f7df2e56Smrg            crep.firstSI = 0;
5896f7df2e56Smrg            crep.nSI = crep.nTotalSI = new->compat->num_si;
5897f7df2e56Smrg            XkbComputeGetCompatMapReplySize(new->compat, &crep);
5898f7df2e56Smrg            rep.length += SIZEOF(xGenericReply) / 4 + crep.length;
5899f7df2e56Smrg        }
5900f7df2e56Smrg        if (new->indicators == NULL)
5901f7df2e56Smrg            rep.reported &= ~XkbGBN_IndicatorMapMask;
5902f7df2e56Smrg        else if (rep.reported & XkbGBN_IndicatorMapMask) {
5903f7df2e56Smrg            irep.type = X_Reply;
5904f7df2e56Smrg            irep.deviceID = dev->id;
5905f7df2e56Smrg            irep.sequenceNumber = client->sequence;
5906f7df2e56Smrg            irep.length = 0;
5907f7df2e56Smrg            irep.which = XkbAllIndicatorsMask;
5908f7df2e56Smrg            XkbComputeGetIndicatorMapReplySize(new->indicators, &irep);
5909f7df2e56Smrg            rep.length += SIZEOF(xGenericReply) / 4 + irep.length;
5910f7df2e56Smrg        }
5911f7df2e56Smrg        if (new->names == NULL)
5912f7df2e56Smrg            rep.reported &= ~(XkbGBN_OtherNamesMask | XkbGBN_KeyNamesMask);
5913f7df2e56Smrg        else if (rep.reported & (XkbGBN_OtherNamesMask | XkbGBN_KeyNamesMask)) {
5914f7df2e56Smrg            nrep.type = X_Reply;
5915f7df2e56Smrg            nrep.deviceID = dev->id;
5916f7df2e56Smrg            nrep.sequenceNumber = client->sequence;
5917f7df2e56Smrg            nrep.length = 0;
5918f7df2e56Smrg            nrep.minKeyCode = new->min_key_code;
5919f7df2e56Smrg            nrep.maxKeyCode = new->max_key_code;
5920f7df2e56Smrg            if (rep.reported & XkbGBN_OtherNamesMask) {
5921f7df2e56Smrg                nrep.which = XkbAllNamesMask;
5922f7df2e56Smrg                if (new->map != NULL)
5923f7df2e56Smrg                    nrep.nTypes = new->map->num_types;
5924f7df2e56Smrg                else
5925f7df2e56Smrg                    nrep.nTypes = 0;
5926f7df2e56Smrg                nrep.nKTLevels = 0;
5927f7df2e56Smrg                nrep.groupNames = XkbAllGroupsMask;
5928f7df2e56Smrg                nrep.virtualMods = XkbAllVirtualModsMask;
5929f7df2e56Smrg                nrep.indicators = XkbAllIndicatorsMask;
5930f7df2e56Smrg                nrep.nRadioGroups = new->names->num_rg;
5931f7df2e56Smrg            }
5932f7df2e56Smrg            else {
5933f7df2e56Smrg                nrep.which = 0;
5934f7df2e56Smrg                nrep.nTypes = 0;
5935f7df2e56Smrg                nrep.nKTLevels = 0;
5936f7df2e56Smrg                nrep.groupNames = 0;
5937f7df2e56Smrg                nrep.virtualMods = 0;
5938f7df2e56Smrg                nrep.indicators = 0;
5939f7df2e56Smrg                nrep.nRadioGroups = 0;
5940f7df2e56Smrg            }
5941f7df2e56Smrg            if (rep.reported & XkbGBN_KeyNamesMask) {
5942f7df2e56Smrg                nrep.which |= XkbKeyNamesMask;
5943f7df2e56Smrg                nrep.firstKey = new->min_key_code;
5944f7df2e56Smrg                nrep.nKeys = XkbNumKeys(new);
5945f7df2e56Smrg                nrep.nKeyAliases = new->names->num_key_aliases;
5946f7df2e56Smrg                if (nrep.nKeyAliases)
5947f7df2e56Smrg                    nrep.which |= XkbKeyAliasesMask;
5948f7df2e56Smrg            }
5949f7df2e56Smrg            else {
5950f7df2e56Smrg                nrep.which &= ~(XkbKeyNamesMask | XkbKeyAliasesMask);
5951f7df2e56Smrg                nrep.firstKey = nrep.nKeys = 0;
5952f7df2e56Smrg                nrep.nKeyAliases = 0;
5953f7df2e56Smrg            }
5954f7df2e56Smrg            XkbComputeGetNamesReplySize(new, &nrep);
5955f7df2e56Smrg            rep.length += SIZEOF(xGenericReply) / 4 + nrep.length;
5956f7df2e56Smrg        }
5957f7df2e56Smrg        if (new->geom == NULL)
5958f7df2e56Smrg            rep.reported &= ~XkbGBN_GeometryMask;
5959f7df2e56Smrg        else if (rep.reported & XkbGBN_GeometryMask) {
5960f7df2e56Smrg            grep.type = X_Reply;
5961f7df2e56Smrg            grep.deviceID = dev->id;
5962f7df2e56Smrg            grep.sequenceNumber = client->sequence;
5963f7df2e56Smrg            grep.length = 0;
5964f7df2e56Smrg            grep.found = TRUE;
5965f7df2e56Smrg            grep.pad = 0;
5966f7df2e56Smrg            grep.widthMM = grep.heightMM = 0;
5967f7df2e56Smrg            grep.nProperties = grep.nColors = grep.nShapes = 0;
5968f7df2e56Smrg            grep.nSections = grep.nDoodads = 0;
5969f7df2e56Smrg            grep.baseColorNdx = grep.labelColorNdx = 0;
5970f7df2e56Smrg            XkbComputeGetGeometryReplySize(new->geom, &grep, None);
5971f7df2e56Smrg            rep.length += SIZEOF(xGenericReply) / 4 + grep.length;
5972f7df2e56Smrg        }
5973f7df2e56Smrg    }
5974f7df2e56Smrg
5975f7df2e56Smrg    reported = rep.reported;
5976f7df2e56Smrg    if (client->swapped) {
5977f7df2e56Smrg        swaps(&rep.sequenceNumber);
5978f7df2e56Smrg        swapl(&rep.length);
5979f7df2e56Smrg        swaps(&rep.found);
5980f7df2e56Smrg        swaps(&rep.reported);
5981f7df2e56Smrg    }
5982f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetKbdByNameReply), &rep);
5983f7df2e56Smrg    if (reported & (XkbGBN_SymbolsMask | XkbGBN_TypesMask))
5984f7df2e56Smrg        XkbSendMap(client, new, &mrep);
5985f7df2e56Smrg    if (reported & XkbGBN_CompatMapMask)
5986f7df2e56Smrg        XkbSendCompatMap(client, new->compat, &crep);
5987f7df2e56Smrg    if (reported & XkbGBN_IndicatorMapMask)
5988f7df2e56Smrg        XkbSendIndicatorMap(client, new->indicators, &irep);
5989f7df2e56Smrg    if (reported & (XkbGBN_KeyNamesMask | XkbGBN_OtherNamesMask))
5990f7df2e56Smrg        XkbSendNames(client, new, &nrep);
5991f7df2e56Smrg    if (reported & XkbGBN_GeometryMask)
5992f7df2e56Smrg        XkbSendGeometry(client, new->geom, &grep, FALSE);
5993f7df2e56Smrg    if (rep.loaded) {
5994f7df2e56Smrg        XkbDescPtr old_xkb;
5995f7df2e56Smrg        xkbNewKeyboardNotify nkn;
5996f7df2e56Smrg
5997f7df2e56Smrg        old_xkb = xkb;
5998f7df2e56Smrg        xkb = new;
5999f7df2e56Smrg        dev->key->xkbInfo->desc = xkb;
6000f7df2e56Smrg        new = old_xkb;          /* so it'll get freed automatically */
6001f7df2e56Smrg
6002f7df2e56Smrg        XkbCopyControls(xkb, old_xkb);
6003f7df2e56Smrg
6004f7df2e56Smrg        nkn.deviceID = nkn.oldDeviceID = dev->id;
6005f7df2e56Smrg        nkn.minKeyCode = new->min_key_code;
6006f7df2e56Smrg        nkn.maxKeyCode = new->max_key_code;
6007f7df2e56Smrg        nkn.oldMinKeyCode = xkb->min_key_code;
6008f7df2e56Smrg        nkn.oldMaxKeyCode = xkb->max_key_code;
6009f7df2e56Smrg        nkn.requestMajor = XkbReqCode;
6010f7df2e56Smrg        nkn.requestMinor = X_kbGetKbdByName;
6011f7df2e56Smrg        nkn.changed = XkbNKN_KeycodesMask;
6012f7df2e56Smrg        if (geom_changed)
6013f7df2e56Smrg            nkn.changed |= XkbNKN_GeometryMask;
6014f7df2e56Smrg        XkbSendNewKeyboardNotify(dev, &nkn);
6015f7df2e56Smrg
6016f7df2e56Smrg        /* Update the map and LED info on the device itself, as well as
6017f7df2e56Smrg         * any slaves if it's an MD, or its MD if it's an SD and was the
6018f7df2e56Smrg         * last device used on that MD. */
601905b261ecSmrg        for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
6020f7df2e56Smrg            if (tmpd != dev && GetMaster(tmpd, MASTER_KEYBOARD) != dev &&
6021f7df2e56Smrg                (tmpd != master || dev != master->lastSlave))
6022f7df2e56Smrg                continue;
6023f7df2e56Smrg
6024f7df2e56Smrg            if (tmpd != dev)
6025f7df2e56Smrg                XkbDeviceApplyKeymap(tmpd, xkb);
6026f7df2e56Smrg
6027f7df2e56Smrg            if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) {
6028f7df2e56Smrg                old_sli = tmpd->kbdfeed->xkb_sli;
6029f7df2e56Smrg                tmpd->kbdfeed->xkb_sli = NULL;
6030f7df2e56Smrg                sli = XkbAllocSrvLedInfo(tmpd, tmpd->kbdfeed, NULL, 0);
6031f7df2e56Smrg                if (sli) {
6032f7df2e56Smrg                    sli->explicitState = old_sli->explicitState;
6033f7df2e56Smrg                    sli->effectiveState = old_sli->effectiveState;
603405b261ecSmrg                }
6035f7df2e56Smrg                tmpd->kbdfeed->xkb_sli = sli;
6036f7df2e56Smrg                XkbFreeSrvLedInfo(old_sli);
603705b261ecSmrg            }
603805b261ecSmrg        }
6039f7df2e56Smrg    }
6040f7df2e56Smrg    if ((new != NULL) && (new != xkb)) {
6041f7df2e56Smrg        XkbFreeKeyboard(new, XkbAllComponentsMask, TRUE);
6042f7df2e56Smrg        new = NULL;
604305b261ecSmrg    }
60449ace9065Smrg    XkbFreeComponentNames(&names, FALSE);
6045f7df2e56Smrg    XkbSetCauseXkbReq(&cause, X_kbGetKbdByName, client);
6046f7df2e56Smrg    XkbUpdateAllDeviceIndicators(NULL, &cause);
6047f7df2e56Smrg
60486747b715Smrg    return Success;
604905b261ecSmrg}
605005b261ecSmrg
605105b261ecSmrg/***====================================================================***/
605205b261ecSmrg
605305b261ecSmrgstatic int
6054f7df2e56SmrgComputeDeviceLedInfoSize(DeviceIntPtr dev,
6055f7df2e56Smrg                         unsigned int what, XkbSrvLedInfoPtr sli)
605605b261ecSmrg{
6057f7df2e56Smrg    int nNames, nMaps;
6058f7df2e56Smrg    register unsigned n, bit;
6059f7df2e56Smrg
6060f7df2e56Smrg    if (sli == NULL)
6061f7df2e56Smrg        return 0;
6062f7df2e56Smrg    nNames = nMaps = 0;
6063f7df2e56Smrg    if ((what & XkbXI_IndicatorNamesMask) == 0)
6064f7df2e56Smrg        sli->namesPresent = 0;
6065f7df2e56Smrg    if ((what & XkbXI_IndicatorMapsMask) == 0)
6066f7df2e56Smrg        sli->mapsPresent = 0;
6067f7df2e56Smrg
6068f7df2e56Smrg    for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6069f7df2e56Smrg        if (sli->names && sli->names[n] != None) {
6070f7df2e56Smrg            sli->namesPresent |= bit;
6071f7df2e56Smrg            nNames++;
6072f7df2e56Smrg        }
6073f7df2e56Smrg        if (sli->maps && XkbIM_InUse(&sli->maps[n])) {
6074f7df2e56Smrg            sli->mapsPresent |= bit;
6075f7df2e56Smrg            nMaps++;
6076f7df2e56Smrg        }
6077f7df2e56Smrg    }
6078f7df2e56Smrg    return (nNames * 4) + (nMaps * SIZEOF(xkbIndicatorMapWireDesc));
607905b261ecSmrg}
608005b261ecSmrg
6081f7df2e56Smrgstatic int
6082f7df2e56SmrgCheckDeviceLedFBs(DeviceIntPtr dev,
6083f7df2e56Smrg                  int class,
6084f7df2e56Smrg                  int id, xkbGetDeviceInfoReply * rep, ClientPtr client)
608505b261ecSmrg{
6086f7df2e56Smrg    int nFBs = 0;
6087f7df2e56Smrg    int length = 0;
6088f7df2e56Smrg    Bool classOk;
6089f7df2e56Smrg
6090f7df2e56Smrg    if (class == XkbDfltXIClass) {
6091f7df2e56Smrg        if (dev->kbdfeed)
6092f7df2e56Smrg            class = KbdFeedbackClass;
6093f7df2e56Smrg        else if (dev->leds)
6094f7df2e56Smrg            class = LedFeedbackClass;
6095f7df2e56Smrg        else {
6096f7df2e56Smrg            client->errorValue = _XkbErrCode2(XkbErr_BadClass, class);
6097f7df2e56Smrg            return XkbKeyboardErrorCode;
6098f7df2e56Smrg        }
6099f7df2e56Smrg    }
6100f7df2e56Smrg    classOk = FALSE;
6101f7df2e56Smrg    if ((dev->kbdfeed) &&
6102f7df2e56Smrg        ((class == KbdFeedbackClass) || (class == XkbAllXIClasses))) {
6103f7df2e56Smrg        KbdFeedbackPtr kf;
6104f7df2e56Smrg
6105f7df2e56Smrg        classOk = TRUE;
6106f7df2e56Smrg        for (kf = dev->kbdfeed; (kf); kf = kf->next) {
6107f7df2e56Smrg            if ((id != XkbAllXIIds) && (id != XkbDfltXIId) &&
6108f7df2e56Smrg                (id != kf->ctrl.id))
6109f7df2e56Smrg                continue;
6110f7df2e56Smrg            nFBs++;
6111f7df2e56Smrg            length += SIZEOF(xkbDeviceLedsWireDesc);
6112f7df2e56Smrg            if (!kf->xkb_sli)
6113f7df2e56Smrg                kf->xkb_sli = XkbAllocSrvLedInfo(dev, kf, NULL, 0);
6114f7df2e56Smrg            length += ComputeDeviceLedInfoSize(dev, rep->present, kf->xkb_sli);
6115f7df2e56Smrg            if (id != XkbAllXIIds)
6116f7df2e56Smrg                break;
6117f7df2e56Smrg        }
6118f7df2e56Smrg    }
6119f7df2e56Smrg    if ((dev->leds) &&
6120f7df2e56Smrg        ((class == LedFeedbackClass) || (class == XkbAllXIClasses))) {
6121f7df2e56Smrg        LedFeedbackPtr lf;
6122f7df2e56Smrg
6123f7df2e56Smrg        classOk = TRUE;
6124f7df2e56Smrg        for (lf = dev->leds; (lf); lf = lf->next) {
6125f7df2e56Smrg            if ((id != XkbAllXIIds) && (id != XkbDfltXIId) &&
6126f7df2e56Smrg                (id != lf->ctrl.id))
6127f7df2e56Smrg                continue;
6128f7df2e56Smrg            nFBs++;
6129f7df2e56Smrg            length += SIZEOF(xkbDeviceLedsWireDesc);
6130f7df2e56Smrg            if (!lf->xkb_sli)
6131f7df2e56Smrg                lf->xkb_sli = XkbAllocSrvLedInfo(dev, NULL, lf, 0);
6132f7df2e56Smrg            length += ComputeDeviceLedInfoSize(dev, rep->present, lf->xkb_sli);
6133f7df2e56Smrg            if (id != XkbAllXIIds)
6134f7df2e56Smrg                break;
6135f7df2e56Smrg        }
6136f7df2e56Smrg    }
6137f7df2e56Smrg    if (nFBs > 0) {
6138f7df2e56Smrg        rep->nDeviceLedFBs = nFBs;
6139f7df2e56Smrg        rep->length += (length / 4);
6140f7df2e56Smrg        return Success;
6141f7df2e56Smrg    }
6142f7df2e56Smrg    if (classOk)
6143f7df2e56Smrg        client->errorValue = _XkbErrCode2(XkbErr_BadId, id);
6144f7df2e56Smrg    else
6145f7df2e56Smrg        client->errorValue = _XkbErrCode2(XkbErr_BadClass, class);
614605b261ecSmrg    return XkbKeyboardErrorCode;
614705b261ecSmrg}
614805b261ecSmrg
614905b261ecSmrgstatic int
6150f7df2e56SmrgSendDeviceLedInfo(XkbSrvLedInfoPtr sli, ClientPtr client)
615105b261ecSmrg{
6152f7df2e56Smrg    xkbDeviceLedsWireDesc wire;
6153f7df2e56Smrg    int length;
6154f7df2e56Smrg
6155f7df2e56Smrg    length = 0;
6156f7df2e56Smrg    wire.ledClass = sli->class;
6157f7df2e56Smrg    wire.ledID = sli->id;
6158f7df2e56Smrg    wire.namesPresent = sli->namesPresent;
6159f7df2e56Smrg    wire.mapsPresent = sli->mapsPresent;
6160f7df2e56Smrg    wire.physIndicators = sli->physIndicators;
6161f7df2e56Smrg    wire.state = sli->effectiveState;
616205b261ecSmrg    if (client->swapped) {
6163f7df2e56Smrg        swaps(&wire.ledClass);
6164f7df2e56Smrg        swaps(&wire.ledID);
6165f7df2e56Smrg        swapl(&wire.namesPresent);
6166f7df2e56Smrg        swapl(&wire.mapsPresent);
6167f7df2e56Smrg        swapl(&wire.physIndicators);
6168f7df2e56Smrg        swapl(&wire.state);
6169f7df2e56Smrg    }
6170f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbDeviceLedsWireDesc), &wire);
6171f7df2e56Smrg    length += SIZEOF(xkbDeviceLedsWireDesc);
6172f7df2e56Smrg    if (sli->namesPresent | sli->mapsPresent) {
6173f7df2e56Smrg        register unsigned i, bit;
6174f7df2e56Smrg
6175f7df2e56Smrg        if (sli->namesPresent) {
6176f7df2e56Smrg            CARD32 awire;
6177f7df2e56Smrg
6178f7df2e56Smrg            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
6179f7df2e56Smrg                if (sli->namesPresent & bit) {
6180f7df2e56Smrg                    awire = (CARD32) sli->names[i];
6181f7df2e56Smrg                    if (client->swapped) {
6182f7df2e56Smrg                        swapl(&awire);
6183f7df2e56Smrg                    }
6184f7df2e56Smrg                    WriteToClient(client, 4, &awire);
6185f7df2e56Smrg                    length += 4;
6186f7df2e56Smrg                }
6187f7df2e56Smrg            }
6188f7df2e56Smrg        }
6189f7df2e56Smrg        if (sli->mapsPresent) {
6190f7df2e56Smrg            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
6191f7df2e56Smrg                xkbIndicatorMapWireDesc iwire;
6192f7df2e56Smrg
6193f7df2e56Smrg                if (sli->mapsPresent & bit) {
6194f7df2e56Smrg                    iwire.flags = sli->maps[i].flags;
6195f7df2e56Smrg                    iwire.whichGroups = sli->maps[i].which_groups;
6196f7df2e56Smrg                    iwire.groups = sli->maps[i].groups;
6197f7df2e56Smrg                    iwire.whichMods = sli->maps[i].which_mods;
6198f7df2e56Smrg                    iwire.mods = sli->maps[i].mods.mask;
6199f7df2e56Smrg                    iwire.realMods = sli->maps[i].mods.real_mods;
6200f7df2e56Smrg                    iwire.virtualMods = sli->maps[i].mods.vmods;
6201f7df2e56Smrg                    iwire.ctrls = sli->maps[i].ctrls;
6202f7df2e56Smrg                    if (client->swapped) {
6203f7df2e56Smrg                        swaps(&iwire.virtualMods);
6204f7df2e56Smrg                        swapl(&iwire.ctrls);
6205f7df2e56Smrg                    }
6206f7df2e56Smrg                    WriteToClient(client, SIZEOF(xkbIndicatorMapWireDesc),
6207f7df2e56Smrg                                  &iwire);
6208f7df2e56Smrg                    length += SIZEOF(xkbIndicatorMapWireDesc);
6209f7df2e56Smrg                }
6210f7df2e56Smrg            }
6211f7df2e56Smrg        }
621205b261ecSmrg    }
621305b261ecSmrg    return length;
621405b261ecSmrg}
621505b261ecSmrg
621605b261ecSmrgstatic int
6217f7df2e56SmrgSendDeviceLedFBs(DeviceIntPtr dev,
6218f7df2e56Smrg                 int class, int id, unsigned wantLength, ClientPtr client)
621905b261ecSmrg{
6220f7df2e56Smrg    int length = 0;
6221f7df2e56Smrg
6222f7df2e56Smrg    if (class == XkbDfltXIClass) {
6223f7df2e56Smrg        if (dev->kbdfeed)
6224f7df2e56Smrg            class = KbdFeedbackClass;
6225f7df2e56Smrg        else if (dev->leds)
6226f7df2e56Smrg            class = LedFeedbackClass;
6227f7df2e56Smrg    }
6228f7df2e56Smrg    if ((dev->kbdfeed) &&
6229f7df2e56Smrg        ((class == KbdFeedbackClass) || (class == XkbAllXIClasses))) {
6230f7df2e56Smrg        KbdFeedbackPtr kf;
6231f7df2e56Smrg
6232f7df2e56Smrg        for (kf = dev->kbdfeed; (kf); kf = kf->next) {
6233f7df2e56Smrg            if ((id == XkbAllXIIds) || (id == XkbDfltXIId) ||
6234f7df2e56Smrg                (id == kf->ctrl.id)) {
6235f7df2e56Smrg                length += SendDeviceLedInfo(kf->xkb_sli, client);
6236f7df2e56Smrg                if (id != XkbAllXIIds)
6237f7df2e56Smrg                    break;
6238f7df2e56Smrg            }
6239f7df2e56Smrg        }
6240f7df2e56Smrg    }
6241f7df2e56Smrg    if ((dev->leds) &&
6242f7df2e56Smrg        ((class == LedFeedbackClass) || (class == XkbAllXIClasses))) {
6243f7df2e56Smrg        LedFeedbackPtr lf;
6244f7df2e56Smrg
6245f7df2e56Smrg        for (lf = dev->leds; (lf); lf = lf->next) {
6246f7df2e56Smrg            if ((id == XkbAllXIIds) || (id == XkbDfltXIId) ||
6247f7df2e56Smrg                (id == lf->ctrl.id)) {
6248f7df2e56Smrg                length += SendDeviceLedInfo(lf->xkb_sli, client);
6249f7df2e56Smrg                if (id != XkbAllXIIds)
6250f7df2e56Smrg                    break;
6251f7df2e56Smrg            }
6252f7df2e56Smrg        }
6253f7df2e56Smrg    }
6254f7df2e56Smrg    if (length == wantLength)
6255f7df2e56Smrg        return Success;
6256f7df2e56Smrg    else
6257f7df2e56Smrg        return BadLength;
625805b261ecSmrg}
625905b261ecSmrg
626005b261ecSmrgint
626105b261ecSmrgProcXkbGetDeviceInfo(ClientPtr client)
626205b261ecSmrg{
6263f7df2e56Smrg    DeviceIntPtr dev;
6264f7df2e56Smrg    xkbGetDeviceInfoReply rep;
6265f7df2e56Smrg    int status, nDeviceLedFBs;
6266f7df2e56Smrg    unsigned length, nameLen;
6267f7df2e56Smrg    CARD16 ledClass, ledID;
6268f7df2e56Smrg    unsigned wanted;
6269f7df2e56Smrg    char *str;
627005b261ecSmrg
627105b261ecSmrg    REQUEST(xkbGetDeviceInfoReq);
627205b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq);
627305b261ecSmrg
6274f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
6275f7df2e56Smrg        return BadAccess;
627605b261ecSmrg
6277f7df2e56Smrg    wanted = stuff->wanted;
627805b261ecSmrg
62794642e01fSmrg    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
6280f7df2e56Smrg    CHK_MASK_LEGAL(0x01, wanted, XkbXI_AllDeviceFeaturesMask);
6281f7df2e56Smrg
6282f7df2e56Smrg    if ((!dev->button) || ((stuff->nBtns < 1) && (!stuff->allBtns)))
6283f7df2e56Smrg        wanted &= ~XkbXI_ButtonActionsMask;
6284f7df2e56Smrg    if ((!dev->kbdfeed) && (!dev->leds))
6285f7df2e56Smrg        wanted &= ~XkbXI_IndicatorsMask;
6286f7df2e56Smrg
6287f7df2e56Smrg    nameLen = XkbSizeCountedString(dev->name);
6288f7df2e56Smrg    rep = (xkbGetDeviceInfoReply) {
6289f7df2e56Smrg        .type = X_Reply,
6290f7df2e56Smrg        .deviceID = dev->id,
6291f7df2e56Smrg        .sequenceNumber = client->sequence,
6292f7df2e56Smrg        .length = nameLen / 4,
6293f7df2e56Smrg        .present = wanted,
6294f7df2e56Smrg        .supported = XkbXI_AllDeviceFeaturesMask,
6295f7df2e56Smrg        .unsupported = 0,
6296f7df2e56Smrg        .nDeviceLedFBs = 0,
6297f7df2e56Smrg        .firstBtnWanted = 0,
6298f7df2e56Smrg        .nBtnsWanted = 0,
6299f7df2e56Smrg        .firstBtnRtrn = 0,
6300f7df2e56Smrg        .nBtnsRtrn = 0,
6301f7df2e56Smrg        .totalBtns = dev->button ? dev->button->numButtons : 0,
6302f7df2e56Smrg        .hasOwnState = (dev->key && dev->key->xkbInfo),
6303f7df2e56Smrg        .dfltKbdFB = dev->kbdfeed ? dev->kbdfeed->ctrl.id : XkbXINone,
6304f7df2e56Smrg        .dfltLedFB = dev->leds ? dev->leds->ctrl.id : XkbXINone,
6305f7df2e56Smrg        .devType = dev->xinput_type
6306f7df2e56Smrg    };
6307f7df2e56Smrg
6308f7df2e56Smrg    ledClass = stuff->ledClass;
6309f7df2e56Smrg    ledID = stuff->ledID;
6310f7df2e56Smrg
6311f7df2e56Smrg    if (wanted & XkbXI_ButtonActionsMask) {
6312f7df2e56Smrg        if (stuff->allBtns) {
6313f7df2e56Smrg            stuff->firstBtn = 0;
6314f7df2e56Smrg            stuff->nBtns = dev->button->numButtons;
6315f7df2e56Smrg        }
631605b261ecSmrg
6317f7df2e56Smrg        if ((stuff->firstBtn + stuff->nBtns) > dev->button->numButtons) {
6318f7df2e56Smrg            client->errorValue = _XkbErrCode4(0x02, dev->button->numButtons,
6319f7df2e56Smrg                                              stuff->firstBtn, stuff->nBtns);
6320f7df2e56Smrg            return BadValue;
6321f7df2e56Smrg        }
6322f7df2e56Smrg        else {
6323f7df2e56Smrg            rep.firstBtnWanted = stuff->firstBtn;
6324f7df2e56Smrg            rep.nBtnsWanted = stuff->nBtns;
6325f7df2e56Smrg            if (dev->button->xkb_acts != NULL) {
6326f7df2e56Smrg                XkbAction *act;
6327f7df2e56Smrg                register int i;
6328f7df2e56Smrg
6329f7df2e56Smrg                rep.firstBtnRtrn = stuff->firstBtn;
6330f7df2e56Smrg                rep.nBtnsRtrn = stuff->nBtns;
6331f7df2e56Smrg                act = &dev->button->xkb_acts[rep.firstBtnWanted];
6332f7df2e56Smrg                for (i = 0; i < rep.nBtnsRtrn; i++, act++) {
6333f7df2e56Smrg                    if (act->type != XkbSA_NoAction)
6334f7df2e56Smrg                        break;
6335f7df2e56Smrg                }
6336f7df2e56Smrg                rep.firstBtnRtrn += i;
6337f7df2e56Smrg                rep.nBtnsRtrn -= i;
6338f7df2e56Smrg                act =
6339f7df2e56Smrg                    &dev->button->xkb_acts[rep.firstBtnRtrn + rep.nBtnsRtrn -
6340f7df2e56Smrg                                           1];
6341f7df2e56Smrg                for (i = 0; i < rep.nBtnsRtrn; i++, act--) {
6342f7df2e56Smrg                    if (act->type != XkbSA_NoAction)
6343f7df2e56Smrg                        break;
6344f7df2e56Smrg                }
6345f7df2e56Smrg                rep.nBtnsRtrn -= i;
6346f7df2e56Smrg            }
6347f7df2e56Smrg            rep.length += (rep.nBtnsRtrn * SIZEOF(xkbActionWireDesc)) / 4;
6348f7df2e56Smrg        }
6349f7df2e56Smrg    }
635005b261ecSmrg
6351f7df2e56Smrg    if (wanted & XkbXI_IndicatorsMask) {
6352f7df2e56Smrg        status = CheckDeviceLedFBs(dev, ledClass, ledID, &rep, client);
6353f7df2e56Smrg        if (status != Success)
6354f7df2e56Smrg            return status;
6355f7df2e56Smrg    }
6356f7df2e56Smrg    length = rep.length * 4;
635705b261ecSmrg    nDeviceLedFBs = rep.nDeviceLedFBs;
635805b261ecSmrg    if (client->swapped) {
6359f7df2e56Smrg        swaps(&rep.sequenceNumber);
6360f7df2e56Smrg        swapl(&rep.length);
6361f7df2e56Smrg        swaps(&rep.present);
6362f7df2e56Smrg        swaps(&rep.supported);
6363f7df2e56Smrg        swaps(&rep.unsupported);
6364f7df2e56Smrg        swaps(&rep.nDeviceLedFBs);
6365f7df2e56Smrg        swaps(&rep.dfltKbdFB);
6366f7df2e56Smrg        swaps(&rep.dfltLedFB);
6367f7df2e56Smrg        swapl(&rep.devType);
6368f7df2e56Smrg    }
6369f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetDeviceInfoReply), &rep);
6370f7df2e56Smrg
6371f7df2e56Smrg    str = malloc(nameLen);
6372f7df2e56Smrg    if (!str)
6373f7df2e56Smrg        return BadAlloc;
6374f7df2e56Smrg    XkbWriteCountedString(str, dev->name, client->swapped);
6375f7df2e56Smrg    WriteToClient(client, nameLen, str);
63766747b715Smrg    free(str);
6377f7df2e56Smrg    length -= nameLen;
6378f7df2e56Smrg
6379f7df2e56Smrg    if (rep.nBtnsRtrn > 0) {
6380f7df2e56Smrg        int sz;
6381f7df2e56Smrg        xkbActionWireDesc *awire;
6382f7df2e56Smrg
6383f7df2e56Smrg        sz = rep.nBtnsRtrn * SIZEOF(xkbActionWireDesc);
6384f7df2e56Smrg        awire = (xkbActionWireDesc *) &dev->button->xkb_acts[rep.firstBtnRtrn];
6385f7df2e56Smrg        WriteToClient(client, sz, awire);
6386f7df2e56Smrg        length -= sz;
6387f7df2e56Smrg    }
6388f7df2e56Smrg    if (nDeviceLedFBs > 0) {
6389f7df2e56Smrg        status = SendDeviceLedFBs(dev, ledClass, ledID, length, client);
6390f7df2e56Smrg        if (status != Success)
6391f7df2e56Smrg            return status;
6392f7df2e56Smrg    }
6393f7df2e56Smrg    else if (length != 0) {
6394f7df2e56Smrg        ErrorF("[xkb] Internal Error!  BadLength in ProcXkbGetDeviceInfo\n");
6395f7df2e56Smrg        ErrorF("[xkb]                  Wrote %d fewer bytes than expected\n",
6396f7df2e56Smrg               length);
6397f7df2e56Smrg        return BadLength;
639805b261ecSmrg    }
63996747b715Smrg    return Success;
640005b261ecSmrg}
640105b261ecSmrg
640205b261ecSmrgstatic char *
6403f7df2e56SmrgCheckSetDeviceIndicators(char *wire,
6404f7df2e56Smrg                         DeviceIntPtr dev,
6405f7df2e56Smrg                         int num, int *status_rtrn, ClientPtr client)
640605b261ecSmrg{
6407f7df2e56Smrg    xkbDeviceLedsWireDesc *ledWire;
6408f7df2e56Smrg    int i;
6409f7df2e56Smrg    XkbSrvLedInfoPtr sli;
6410f7df2e56Smrg
6411f7df2e56Smrg    ledWire = (xkbDeviceLedsWireDesc *) wire;
6412f7df2e56Smrg    for (i = 0; i < num; i++) {
6413f7df2e56Smrg        if (client->swapped) {
6414f7df2e56Smrg            swaps(&ledWire->ledClass);
6415f7df2e56Smrg            swaps(&ledWire->ledID);
6416f7df2e56Smrg            swapl(&ledWire->namesPresent);
6417f7df2e56Smrg            swapl(&ledWire->mapsPresent);
6418f7df2e56Smrg            swapl(&ledWire->physIndicators);
6419f7df2e56Smrg        }
6420f7df2e56Smrg
6421f7df2e56Smrg        sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID,
6422f7df2e56Smrg                                XkbXI_IndicatorsMask);
6423f7df2e56Smrg        if (sli != NULL) {
6424f7df2e56Smrg            register int n;
6425f7df2e56Smrg            register unsigned bit;
6426f7df2e56Smrg            int nMaps, nNames;
6427f7df2e56Smrg            CARD32 *atomWire;
6428f7df2e56Smrg            xkbIndicatorMapWireDesc *mapWire;
6429f7df2e56Smrg
6430f7df2e56Smrg            nMaps = nNames = 0;
6431f7df2e56Smrg            for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6432f7df2e56Smrg                if (ledWire->namesPresent & bit)
6433f7df2e56Smrg                    nNames++;
6434f7df2e56Smrg                if (ledWire->mapsPresent & bit)
6435f7df2e56Smrg                    nMaps++;
6436f7df2e56Smrg            }
6437f7df2e56Smrg            atomWire = (CARD32 *) &ledWire[1];
6438f7df2e56Smrg            if (nNames > 0) {
6439f7df2e56Smrg                for (n = 0; n < nNames; n++) {
6440f7df2e56Smrg                    if (client->swapped) {
6441f7df2e56Smrg                        swapl(atomWire);
6442f7df2e56Smrg                    }
6443f7df2e56Smrg                    CHK_ATOM_OR_NONE3(((Atom) (*atomWire)), client->errorValue,
6444f7df2e56Smrg                                      *status_rtrn, NULL);
6445f7df2e56Smrg                    atomWire++;
6446f7df2e56Smrg                }
6447f7df2e56Smrg            }
6448f7df2e56Smrg            mapWire = (xkbIndicatorMapWireDesc *) atomWire;
6449f7df2e56Smrg            if (nMaps > 0) {
6450f7df2e56Smrg                for (n = 0; n < nMaps; n++) {
6451f7df2e56Smrg                    if (client->swapped) {
6452f7df2e56Smrg                        swaps(&mapWire->virtualMods);
6453f7df2e56Smrg                        swapl(&mapWire->ctrls);
6454f7df2e56Smrg                    }
6455f7df2e56Smrg                    CHK_MASK_LEGAL3(0x21, mapWire->whichGroups,
6456f7df2e56Smrg                                    XkbIM_UseAnyGroup,
6457f7df2e56Smrg                                    client->errorValue, *status_rtrn, NULL);
6458f7df2e56Smrg                    CHK_MASK_LEGAL3(0x22, mapWire->whichMods, XkbIM_UseAnyMods,
6459f7df2e56Smrg                                    client->errorValue, *status_rtrn, NULL);
6460f7df2e56Smrg                    mapWire++;
6461f7df2e56Smrg                }
6462f7df2e56Smrg            }
6463f7df2e56Smrg            ledWire = (xkbDeviceLedsWireDesc *) mapWire;
6464f7df2e56Smrg        }
6465f7df2e56Smrg        else {
6466f7df2e56Smrg            /* SHOULD NEVER HAPPEN */
6467f7df2e56Smrg            return (char *) ledWire;
6468f7df2e56Smrg        }
6469f7df2e56Smrg    }
6470f7df2e56Smrg    return (char *) ledWire;
647105b261ecSmrg}
647205b261ecSmrg
647305b261ecSmrgstatic char *
6474f7df2e56SmrgSetDeviceIndicators(char *wire,
6475f7df2e56Smrg                    DeviceIntPtr dev,
6476f7df2e56Smrg                    unsigned changed,
6477f7df2e56Smrg                    int num,
6478f7df2e56Smrg                    int *status_rtrn,
6479f7df2e56Smrg                    ClientPtr client, xkbExtensionDeviceNotify * ev)
648005b261ecSmrg{
6481f7df2e56Smrg    xkbDeviceLedsWireDesc *ledWire;
6482f7df2e56Smrg    int i;
6483f7df2e56Smrg    XkbEventCauseRec cause;
6484f7df2e56Smrg    unsigned namec, mapc, statec;
6485f7df2e56Smrg    xkbExtensionDeviceNotify ed;
6486f7df2e56Smrg    XkbChangesRec changes;
6487f7df2e56Smrg    DeviceIntPtr kbd;
6488f7df2e56Smrg
6489f7df2e56Smrg    memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify));
6490f7df2e56Smrg    memset((char *) &changes, 0, sizeof(XkbChangesRec));
6491f7df2e56Smrg    XkbSetCauseXkbReq(&cause, X_kbSetDeviceInfo, client);
6492f7df2e56Smrg    ledWire = (xkbDeviceLedsWireDesc *) wire;
6493f7df2e56Smrg    for (i = 0; i < num; i++) {
6494f7df2e56Smrg        register int n;
6495f7df2e56Smrg        register unsigned bit;
6496f7df2e56Smrg        CARD32 *atomWire;
6497f7df2e56Smrg        xkbIndicatorMapWireDesc *mapWire;
6498f7df2e56Smrg        XkbSrvLedInfoPtr sli;
6499f7df2e56Smrg
6500f7df2e56Smrg        namec = mapc = statec = 0;
6501f7df2e56Smrg        sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID,
6502f7df2e56Smrg                                XkbXI_IndicatorMapsMask);
6503f7df2e56Smrg        if (!sli) {
6504f7df2e56Smrg            /* SHOULD NEVER HAPPEN!! */
6505f7df2e56Smrg            return (char *) ledWire;
6506f7df2e56Smrg        }
650705b261ecSmrg
6508f7df2e56Smrg        atomWire = (CARD32 *) &ledWire[1];
6509f7df2e56Smrg        if (changed & XkbXI_IndicatorNamesMask) {
6510f7df2e56Smrg            namec = sli->namesPresent | ledWire->namesPresent;
6511f7df2e56Smrg            memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom));
6512f7df2e56Smrg        }
6513f7df2e56Smrg        if (ledWire->namesPresent) {
6514f7df2e56Smrg            sli->namesPresent = ledWire->namesPresent;
6515f7df2e56Smrg            memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom));
6516f7df2e56Smrg            for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6517f7df2e56Smrg                if (ledWire->namesPresent & bit) {
6518f7df2e56Smrg                    sli->names[n] = (Atom) *atomWire;
6519f7df2e56Smrg                    if (sli->names[n] == None)
6520f7df2e56Smrg                        ledWire->namesPresent &= ~bit;
6521f7df2e56Smrg                    atomWire++;
6522f7df2e56Smrg                }
6523f7df2e56Smrg            }
6524f7df2e56Smrg        }
6525f7df2e56Smrg        mapWire = (xkbIndicatorMapWireDesc *) atomWire;
6526f7df2e56Smrg        if (changed & XkbXI_IndicatorMapsMask) {
6527f7df2e56Smrg            mapc = sli->mapsPresent | ledWire->mapsPresent;
6528f7df2e56Smrg            sli->mapsPresent = ledWire->mapsPresent;
6529f7df2e56Smrg            memset((char *) sli->maps, 0,
6530f7df2e56Smrg                   XkbNumIndicators * sizeof(XkbIndicatorMapRec));
6531f7df2e56Smrg        }
6532f7df2e56Smrg        if (ledWire->mapsPresent) {
6533f7df2e56Smrg            for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6534f7df2e56Smrg                if (ledWire->mapsPresent & bit) {
6535f7df2e56Smrg                    sli->maps[n].flags = mapWire->flags;
6536f7df2e56Smrg                    sli->maps[n].which_groups = mapWire->whichGroups;
6537f7df2e56Smrg                    sli->maps[n].groups = mapWire->groups;
6538f7df2e56Smrg                    sli->maps[n].which_mods = mapWire->whichMods;
6539f7df2e56Smrg                    sli->maps[n].mods.mask = mapWire->mods;
6540f7df2e56Smrg                    sli->maps[n].mods.real_mods = mapWire->realMods;
6541f7df2e56Smrg                    sli->maps[n].mods.vmods = mapWire->virtualMods;
6542f7df2e56Smrg                    sli->maps[n].ctrls = mapWire->ctrls;
6543f7df2e56Smrg                    mapWire++;
6544f7df2e56Smrg                }
6545f7df2e56Smrg            }
6546f7df2e56Smrg        }
6547f7df2e56Smrg        if (changed & XkbXI_IndicatorStateMask) {
6548f7df2e56Smrg            statec = sli->effectiveState ^ ledWire->state;
6549f7df2e56Smrg            sli->explicitState &= ~statec;
6550f7df2e56Smrg            sli->explicitState |= (ledWire->state & statec);
6551f7df2e56Smrg        }
6552f7df2e56Smrg        if (namec)
6553f7df2e56Smrg            XkbApplyLedNameChanges(dev, sli, namec, &ed, &changes, &cause);
6554f7df2e56Smrg        if (mapc)
6555f7df2e56Smrg            XkbApplyLedMapChanges(dev, sli, mapc, &ed, &changes, &cause);
6556f7df2e56Smrg        if (statec)
6557f7df2e56Smrg            XkbApplyLedStateChanges(dev, sli, statec, &ed, &changes, &cause);
6558f7df2e56Smrg
6559f7df2e56Smrg        kbd = dev;
6560f7df2e56Smrg        if ((sli->flags & XkbSLI_HasOwnState) == 0)
6561f7df2e56Smrg            kbd = inputInfo.keyboard;
6562f7df2e56Smrg
6563f7df2e56Smrg        XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause);
6564f7df2e56Smrg        ledWire = (xkbDeviceLedsWireDesc *) mapWire;
6565f7df2e56Smrg    }
6566f7df2e56Smrg    return (char *) ledWire;
6567f7df2e56Smrg}
656805b261ecSmrg
65694642e01fSmrgstatic int
65704642e01fSmrg_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev,
6571f7df2e56Smrg                  xkbSetDeviceInfoReq * stuff)
65724642e01fSmrg{
6573f7df2e56Smrg    char *wire;
6574f7df2e56Smrg
6575f7df2e56Smrg    wire = (char *) &stuff[1];
6576f7df2e56Smrg    if (stuff->change & XkbXI_ButtonActionsMask) {
6577f7df2e56Smrg        if (!dev->button) {
6578f7df2e56Smrg            client->errorValue = _XkbErrCode2(XkbErr_BadClass, ButtonClass);
6579f7df2e56Smrg            return XkbKeyboardErrorCode;
6580f7df2e56Smrg        }
6581f7df2e56Smrg        if ((stuff->firstBtn + stuff->nBtns) > dev->button->numButtons) {
6582f7df2e56Smrg            client->errorValue =
6583f7df2e56Smrg                _XkbErrCode4(0x02, stuff->firstBtn, stuff->nBtns,
6584f7df2e56Smrg                             dev->button->numButtons);
6585f7df2e56Smrg            return BadMatch;
6586f7df2e56Smrg        }
6587f7df2e56Smrg        wire += (stuff->nBtns * SIZEOF(xkbActionWireDesc));
6588f7df2e56Smrg    }
6589f7df2e56Smrg    if (stuff->change & XkbXI_IndicatorsMask) {
6590f7df2e56Smrg        int status = Success;
6591f7df2e56Smrg
6592f7df2e56Smrg        wire = CheckSetDeviceIndicators(wire, dev, stuff->nDeviceLedFBs,
6593f7df2e56Smrg                                        &status, client);
6594f7df2e56Smrg        if (status != Success)
6595f7df2e56Smrg            return status;
6596f7df2e56Smrg    }
6597f7df2e56Smrg    if (((wire - ((char *) stuff)) / 4) != stuff->length)
6598f7df2e56Smrg        return BadLength;
659905b261ecSmrg
66004642e01fSmrg    return Success;
66014642e01fSmrg}
66024642e01fSmrg
66034642e01fSmrgstatic int
66044642e01fSmrg_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev,
6605f7df2e56Smrg                       xkbSetDeviceInfoReq * stuff)
66064642e01fSmrg{
6607f7df2e56Smrg    char *wire;
6608f7df2e56Smrg    xkbExtensionDeviceNotify ed;
6609f7df2e56Smrg
6610f7df2e56Smrg    memset((char *) &ed, 0, SIZEOF(xkbExtensionDeviceNotify));
6611f7df2e56Smrg    ed.deviceID = dev->id;
6612f7df2e56Smrg    wire = (char *) &stuff[1];
6613f7df2e56Smrg    if (stuff->change & XkbXI_ButtonActionsMask) {
6614f7df2e56Smrg        int nBtns, sz, i;
6615f7df2e56Smrg        XkbAction *acts;
6616f7df2e56Smrg        DeviceIntPtr kbd;
6617f7df2e56Smrg
6618f7df2e56Smrg        nBtns = dev->button->numButtons;
6619f7df2e56Smrg        acts = dev->button->xkb_acts;
6620f7df2e56Smrg        if (acts == NULL) {
6621f7df2e56Smrg            acts = calloc(nBtns, sizeof(XkbAction));
6622f7df2e56Smrg            if (!acts)
6623f7df2e56Smrg                return BadAlloc;
6624f7df2e56Smrg            dev->button->xkb_acts = acts;
6625f7df2e56Smrg        }
6626f7df2e56Smrg        sz = stuff->nBtns * SIZEOF(xkbActionWireDesc);
6627f7df2e56Smrg        memcpy((char *) &acts[stuff->firstBtn], (char *) wire, sz);
6628f7df2e56Smrg        wire += sz;
6629f7df2e56Smrg        ed.reason |= XkbXI_ButtonActionsMask;
6630f7df2e56Smrg        ed.firstBtn = stuff->firstBtn;
6631f7df2e56Smrg        ed.nBtns = stuff->nBtns;
6632f7df2e56Smrg
6633f7df2e56Smrg        if (dev->key)
6634f7df2e56Smrg            kbd = dev;
6635f7df2e56Smrg        else
6636f7df2e56Smrg            kbd = inputInfo.keyboard;
6637f7df2e56Smrg        acts = &dev->button->xkb_acts[stuff->firstBtn];
6638f7df2e56Smrg        for (i = 0; i < stuff->nBtns; i++, acts++) {
6639f7df2e56Smrg            if (acts->type != XkbSA_NoAction)
6640f7df2e56Smrg                XkbSetActionKeyMods(kbd->key->xkbInfo->desc, acts, 0);
6641f7df2e56Smrg        }
6642f7df2e56Smrg    }
6643f7df2e56Smrg    if (stuff->change & XkbXI_IndicatorsMask) {
6644f7df2e56Smrg        int status = Success;
6645f7df2e56Smrg
6646f7df2e56Smrg        wire = SetDeviceIndicators(wire, dev, stuff->change,
6647f7df2e56Smrg                                   stuff->nDeviceLedFBs, &status, client, &ed);
6648f7df2e56Smrg        if (status != Success)
6649f7df2e56Smrg            return status;
6650f7df2e56Smrg    }
6651f7df2e56Smrg    if ((stuff->change) && (ed.reason))
6652f7df2e56Smrg        XkbSendExtensionDeviceNotify(dev, client, &ed);
66534642e01fSmrg    return Success;
66544642e01fSmrg}
66554642e01fSmrg
66564642e01fSmrgint
66574642e01fSmrgProcXkbSetDeviceInfo(ClientPtr client)
66584642e01fSmrg{
6659f7df2e56Smrg    DeviceIntPtr dev;
6660f7df2e56Smrg    int rc;
66614642e01fSmrg
66624642e01fSmrg    REQUEST(xkbSetDeviceInfoReq);
66634642e01fSmrg    REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq);
66644642e01fSmrg
6665f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
6666f7df2e56Smrg        return BadAccess;
66674642e01fSmrg
66684642e01fSmrg    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
6669f7df2e56Smrg    CHK_MASK_LEGAL(0x01, stuff->change, XkbXI_AllFeaturesMask);
66704642e01fSmrg
66714642e01fSmrg    rc = _XkbSetDeviceInfoCheck(client, dev, stuff);
66724642e01fSmrg
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 = _XkbSetDeviceInfoCheck(client, other, stuff);
66894642e01fSmrg                    if (rc != Success)
66904642e01fSmrg                        return rc;
66914642e01fSmrg                }
66924642e01fSmrg            }
66934642e01fSmrg        }
66944642e01fSmrg    }
66954642e01fSmrg
66964642e01fSmrg    /* checks done, apply */
66974642e01fSmrg    rc = _XkbSetDeviceInfo(client, dev, stuff);
66984642e01fSmrg    if (rc != Success)
66994642e01fSmrg        return rc;
67004642e01fSmrg
6701f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd ||
6702f7df2e56Smrg        stuff->deviceSpec == XkbUseCorePtr) {
67034642e01fSmrg        DeviceIntPtr other;
6704f7df2e56Smrg
6705f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
6706f7df2e56Smrg            if (((other != dev) && !IsMaster(other) &&
6707f7df2e56Smrg                 GetMaster(other, MASTER_KEYBOARD) == dev) &&
67084642e01fSmrg                ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
6709f7df2e56Smrg                 (stuff->deviceSpec == XkbUseCorePtr && other->button))) {
6710f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
6711f7df2e56Smrg                              DixManageAccess);
6712f7df2e56Smrg                if (rc == Success) {
67134642e01fSmrg                    rc = _XkbSetDeviceInfo(client, other, stuff);
67144642e01fSmrg                    if (rc != Success)
67154642e01fSmrg                        return rc;
67164642e01fSmrg                }
67174642e01fSmrg            }
67184642e01fSmrg        }
67194642e01fSmrg    }
67204642e01fSmrg
67216747b715Smrg    return Success;
672205b261ecSmrg}
672305b261ecSmrg
672405b261ecSmrg/***====================================================================***/
672505b261ecSmrg
672605b261ecSmrgint
672705b261ecSmrgProcXkbSetDebuggingFlags(ClientPtr client)
672805b261ecSmrg{
6729f7df2e56Smrg    CARD32 newFlags, newCtrls, extraLength;
6730f7df2e56Smrg    xkbSetDebuggingFlagsReply rep;
6731f7df2e56Smrg    int rc;
673205b261ecSmrg
673305b261ecSmrg    REQUEST(xkbSetDebuggingFlagsReq);
673405b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq);
673505b261ecSmrg
67364642e01fSmrg    rc = XaceHook(XACE_SERVER_ACCESS, client, DixDebugAccess);
67374642e01fSmrg    if (rc != Success)
6738f7df2e56Smrg        return rc;
67394642e01fSmrg
6740f7df2e56Smrg    newFlags = xkbDebugFlags & (~stuff->affectFlags);
6741f7df2e56Smrg    newFlags |= (stuff->flags & stuff->affectFlags);
6742f7df2e56Smrg    newCtrls = xkbDebugCtrls & (~stuff->affectCtrls);
6743f7df2e56Smrg    newCtrls |= (stuff->ctrls & stuff->affectCtrls);
674405b261ecSmrg    if (xkbDebugFlags || newFlags || stuff->msgLength) {
6745f7df2e56Smrg        ErrorF("[xkb] XkbDebug: Setting debug flags to 0x%lx\n",
6746f7df2e56Smrg               (long) newFlags);
6747f7df2e56Smrg        if (newCtrls != xkbDebugCtrls)
6748f7df2e56Smrg            ErrorF("[xkb] XkbDebug: Setting debug controls to 0x%lx\n",
6749f7df2e56Smrg                   (long) newCtrls);
6750f7df2e56Smrg    }
6751f7df2e56Smrg    extraLength = (stuff->length << 2) - sz_xkbSetDebuggingFlagsReq;
6752f7df2e56Smrg    if (stuff->msgLength > 0) {
6753f7df2e56Smrg        char *msg;
6754f7df2e56Smrg
6755f7df2e56Smrg        if (extraLength < XkbPaddedSize(stuff->msgLength)) {
6756f7df2e56Smrg            ErrorF
6757f7df2e56Smrg                ("[xkb] XkbDebug: msgLength= %d, length= %ld (should be %d)\n",
6758f7df2e56Smrg                 stuff->msgLength, (long) extraLength,
6759f7df2e56Smrg                 XkbPaddedSize(stuff->msgLength));
6760f7df2e56Smrg            return BadLength;
6761f7df2e56Smrg        }
6762f7df2e56Smrg        msg = (char *) &stuff[1];
6763f7df2e56Smrg        if (msg[stuff->msgLength - 1] != '\0') {
6764f7df2e56Smrg            ErrorF("[xkb] XkbDebug: message not null-terminated\n");
6765f7df2e56Smrg            return BadValue;
6766f7df2e56Smrg        }
6767f7df2e56Smrg        ErrorF("[xkb] XkbDebug: %s\n", msg);
676805b261ecSmrg    }
676905b261ecSmrg    xkbDebugFlags = newFlags;
677005b261ecSmrg    xkbDebugCtrls = newCtrls;
677105b261ecSmrg
6772f7df2e56Smrg    rep = (xkbSetDebuggingFlagsReply) {
6773f7df2e56Smrg        .type = X_Reply,
6774f7df2e56Smrg        .sequenceNumber = client->sequence,
6775f7df2e56Smrg        .length = 0,
6776f7df2e56Smrg        .currentFlags = newFlags,
6777f7df2e56Smrg        .currentCtrls = newCtrls,
6778f7df2e56Smrg        .supportedFlags = ~0,
6779f7df2e56Smrg        .supportedCtrls = ~0
6780f7df2e56Smrg    };
6781f7df2e56Smrg    if (client->swapped) {
6782f7df2e56Smrg        swaps(&rep.sequenceNumber);
6783f7df2e56Smrg        swapl(&rep.currentFlags);
6784f7df2e56Smrg        swapl(&rep.currentCtrls);
6785f7df2e56Smrg        swapl(&rep.supportedFlags);
6786f7df2e56Smrg        swapl(&rep.supportedCtrls);
6787f7df2e56Smrg    }
6788f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbSetDebuggingFlagsReply), &rep);
67896747b715Smrg    return Success;
679005b261ecSmrg}
679105b261ecSmrg
679205b261ecSmrg/***====================================================================***/
679305b261ecSmrg
679405b261ecSmrgstatic int
6795f7df2e56SmrgProcXkbDispatch(ClientPtr client)
679605b261ecSmrg{
679705b261ecSmrg    REQUEST(xReq);
6798f7df2e56Smrg    switch (stuff->data) {
679905b261ecSmrg    case X_kbUseExtension:
6800f7df2e56Smrg        return ProcXkbUseExtension(client);
680105b261ecSmrg    case X_kbSelectEvents:
6802f7df2e56Smrg        return ProcXkbSelectEvents(client);
680305b261ecSmrg    case X_kbBell:
6804f7df2e56Smrg        return ProcXkbBell(client);
680505b261ecSmrg    case X_kbGetState:
6806f7df2e56Smrg        return ProcXkbGetState(client);
680705b261ecSmrg    case X_kbLatchLockState:
6808f7df2e56Smrg        return ProcXkbLatchLockState(client);
680905b261ecSmrg    case X_kbGetControls:
6810f7df2e56Smrg        return ProcXkbGetControls(client);
681105b261ecSmrg    case X_kbSetControls:
6812f7df2e56Smrg        return ProcXkbSetControls(client);
681305b261ecSmrg    case X_kbGetMap:
6814f7df2e56Smrg        return ProcXkbGetMap(client);
681505b261ecSmrg    case X_kbSetMap:
6816f7df2e56Smrg        return ProcXkbSetMap(client);
681705b261ecSmrg    case X_kbGetCompatMap:
6818f7df2e56Smrg        return ProcXkbGetCompatMap(client);
681905b261ecSmrg    case X_kbSetCompatMap:
6820f7df2e56Smrg        return ProcXkbSetCompatMap(client);
682105b261ecSmrg    case X_kbGetIndicatorState:
6822f7df2e56Smrg        return ProcXkbGetIndicatorState(client);
682305b261ecSmrg    case X_kbGetIndicatorMap:
6824f7df2e56Smrg        return ProcXkbGetIndicatorMap(client);
682505b261ecSmrg    case X_kbSetIndicatorMap:
6826f7df2e56Smrg        return ProcXkbSetIndicatorMap(client);
682705b261ecSmrg    case X_kbGetNamedIndicator:
6828f7df2e56Smrg        return ProcXkbGetNamedIndicator(client);
682905b261ecSmrg    case X_kbSetNamedIndicator:
6830f7df2e56Smrg        return ProcXkbSetNamedIndicator(client);
683105b261ecSmrg    case X_kbGetNames:
6832f7df2e56Smrg        return ProcXkbGetNames(client);
683305b261ecSmrg    case X_kbSetNames:
6834f7df2e56Smrg        return ProcXkbSetNames(client);
683505b261ecSmrg    case X_kbGetGeometry:
6836f7df2e56Smrg        return ProcXkbGetGeometry(client);
683705b261ecSmrg    case X_kbSetGeometry:
6838f7df2e56Smrg        return ProcXkbSetGeometry(client);
683905b261ecSmrg    case X_kbPerClientFlags:
6840f7df2e56Smrg        return ProcXkbPerClientFlags(client);
684105b261ecSmrg    case X_kbListComponents:
6842f7df2e56Smrg        return ProcXkbListComponents(client);
684305b261ecSmrg    case X_kbGetKbdByName:
6844f7df2e56Smrg        return ProcXkbGetKbdByName(client);
684505b261ecSmrg    case X_kbGetDeviceInfo:
6846f7df2e56Smrg        return ProcXkbGetDeviceInfo(client);
684705b261ecSmrg    case X_kbSetDeviceInfo:
6848f7df2e56Smrg        return ProcXkbSetDeviceInfo(client);
684905b261ecSmrg    case X_kbSetDebuggingFlags:
6850f7df2e56Smrg        return ProcXkbSetDebuggingFlags(client);
685105b261ecSmrg    default:
6852f7df2e56Smrg        return BadRequest;
685305b261ecSmrg    }
685405b261ecSmrg}
685505b261ecSmrg
685605b261ecSmrgstatic int
6857f7df2e56SmrgXkbClientGone(void *data, XID id)
685805b261ecSmrg{
6859f7df2e56Smrg    DevicePtr pXDev = (DevicePtr) data;
686005b261ecSmrg
6861f7df2e56Smrg    if (!XkbRemoveResourceClient(pXDev, id)) {
6862f7df2e56Smrg        ErrorF
6863f7df2e56Smrg            ("[xkb] Internal Error! bad RemoveResourceClient in XkbClientGone\n");
686405b261ecSmrg    }
686505b261ecSmrg    return 1;
686605b261ecSmrg}
686705b261ecSmrg
686805b261ecSmrgvoid
686905b261ecSmrgXkbExtensionInit(void)
687005b261ecSmrg{
687105b261ecSmrg    ExtensionEntry *extEntry;
687205b261ecSmrg
68736747b715Smrg    RT_XKBCLIENT = CreateNewResourceType(XkbClientGone, "XkbClient");
68746747b715Smrg    if (!RT_XKBCLIENT)
6875f7df2e56Smrg        return;
68766747b715Smrg
68776747b715Smrg    if (!XkbInitPrivates())
6878f7df2e56Smrg        return;
68796747b715Smrg
688005b261ecSmrg    if ((extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors,
6881f7df2e56Smrg                                 ProcXkbDispatch, SProcXkbDispatch,
6882f7df2e56Smrg                                 NULL, StandardMinorOpcode))) {
6883f7df2e56Smrg        XkbReqCode = (unsigned char) extEntry->base;
6884f7df2e56Smrg        XkbEventBase = (unsigned char) extEntry->eventBase;
6885f7df2e56Smrg        XkbErrorBase = (unsigned char) extEntry->errorBase;
6886f7df2e56Smrg        XkbKeyboardErrorCode = XkbErrorBase + XkbKeyboard;
688705b261ecSmrg    }
688805b261ecSmrg    return;
688905b261ecSmrg}
6890