xkb.c revision 5a112b11
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
155806e81e9Smrgstatic Bool
156806e81e9Smrg_XkbCheckRequestBounds(ClientPtr client, void *stuff, void *from, void *to) {
157806e81e9Smrg    char *cstuff = (char *)stuff;
158806e81e9Smrg    char *cfrom = (char *)from;
159806e81e9Smrg    char *cto = (char *)to;
160806e81e9Smrg
161806e81e9Smrg    return cfrom < cto &&
162806e81e9Smrg           cfrom >= cstuff &&
163806e81e9Smrg           cfrom < cstuff + ((size_t)client->req_len << 2) &&
164806e81e9Smrg           cto >= cstuff &&
165806e81e9Smrg           cto <= cstuff + ((size_t)client->req_len << 2);
166806e81e9Smrg}
167806e81e9Smrg
16805b261ecSmrg/***====================================================================***/
16905b261ecSmrg
17005b261ecSmrgint
17105b261ecSmrgProcXkbUseExtension(ClientPtr client)
17205b261ecSmrg{
17305b261ecSmrg    REQUEST(xkbUseExtensionReq);
174f7df2e56Smrg    xkbUseExtensionReply rep;
175f7df2e56Smrg    int supported;
17605b261ecSmrg
17705b261ecSmrg    REQUEST_SIZE_MATCH(xkbUseExtensionReq);
1786747b715Smrg    if (stuff->wantedMajor != SERVER_XKB_MAJOR_VERSION) {
179f7df2e56Smrg        /* pre-release version 0.65 is compatible with 1.00 */
180f7df2e56Smrg        supported = ((SERVER_XKB_MAJOR_VERSION == 1) &&
181f7df2e56Smrg                     (stuff->wantedMajor == 0) && (stuff->wantedMinor == 65));
182f7df2e56Smrg    }
183f7df2e56Smrg    else
184f7df2e56Smrg        supported = 1;
185f7df2e56Smrg
186f7df2e56Smrg    if ((supported) && (!(client->xkbClientFlags & _XkbClientInitialized))) {
187f7df2e56Smrg        client->xkbClientFlags = _XkbClientInitialized;
1887e31ba66Smrg        if (stuff->wantedMajor == 0)
1897e31ba66Smrg            client->xkbClientFlags |= _XkbClientIsAncient;
190f7df2e56Smrg    }
191f7df2e56Smrg    else if (xkbDebugFlags & 0x1) {
192f7df2e56Smrg        ErrorF
193f7df2e56Smrg            ("[xkb] Rejecting client %d (0x%lx) (wants %d.%02d, have %d.%02d)\n",
194f7df2e56Smrg             client->index, (long) client->clientAsMask, stuff->wantedMajor,
195f7df2e56Smrg             stuff->wantedMinor, SERVER_XKB_MAJOR_VERSION,
196f7df2e56Smrg             SERVER_XKB_MINOR_VERSION);
197f7df2e56Smrg    }
198f7df2e56Smrg    rep = (xkbUseExtensionReply) {
199f7df2e56Smrg        .type = X_Reply,
200f7df2e56Smrg        .supported = supported,
201f7df2e56Smrg        .sequenceNumber = client->sequence,
202f7df2e56Smrg        .length = 0,
203f7df2e56Smrg        .serverMajor = SERVER_XKB_MAJOR_VERSION,
204f7df2e56Smrg        .serverMinor = SERVER_XKB_MINOR_VERSION
205f7df2e56Smrg    };
206f7df2e56Smrg    if (client->swapped) {
207f7df2e56Smrg        swaps(&rep.sequenceNumber);
208f7df2e56Smrg        swaps(&rep.serverMajor);
209f7df2e56Smrg        swaps(&rep.serverMinor);
21005b261ecSmrg    }
211f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbUseExtensionReply), &rep);
2126747b715Smrg    return Success;
21305b261ecSmrg}
21405b261ecSmrg
21505b261ecSmrg/***====================================================================***/
21605b261ecSmrg
21705b261ecSmrgint
21805b261ecSmrgProcXkbSelectEvents(ClientPtr client)
21905b261ecSmrg{
220f7df2e56Smrg    unsigned legal;
221f7df2e56Smrg    DeviceIntPtr dev;
222f7df2e56Smrg    XkbInterestPtr masks;
223f7df2e56Smrg
22405b261ecSmrg    REQUEST(xkbSelectEventsReq);
22505b261ecSmrg
22605b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSelectEventsReq);
22705b261ecSmrg
228f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
229f7df2e56Smrg        return BadAccess;
23005b261ecSmrg
2314642e01fSmrg    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixUseAccess);
23205b261ecSmrg
233f7df2e56Smrg    if (((stuff->affectWhich & XkbMapNotifyMask) != 0) && (stuff->affectMap)) {
234f7df2e56Smrg        client->mapNotifyMask &= ~stuff->affectMap;
235f7df2e56Smrg        client->mapNotifyMask |= (stuff->affectMap & stuff->map);
23605b261ecSmrg    }
237f7df2e56Smrg    if ((stuff->affectWhich & (~XkbMapNotifyMask)) == 0)
238f7df2e56Smrg        return Success;
239f7df2e56Smrg
240f7df2e56Smrg    masks = XkbFindClientResource((DevicePtr) dev, client);
241f7df2e56Smrg    if (!masks) {
242f7df2e56Smrg        XID id = FakeClientID(client->index);
24305b261ecSmrg
244f7df2e56Smrg        if (!AddResource(id, RT_XKBCLIENT, dev))
245f7df2e56Smrg            return BadAlloc;
246f7df2e56Smrg        masks = XkbAddClientResource((DevicePtr) dev, client, id);
24705b261ecSmrg    }
24805b261ecSmrg    if (masks) {
249f7df2e56Smrg        union {
250f7df2e56Smrg            CARD8 *c8;
251f7df2e56Smrg            CARD16 *c16;
252f7df2e56Smrg            CARD32 *c32;
253f7df2e56Smrg        } from, to;
254f7df2e56Smrg        register unsigned bit, ndx, maskLeft, dataLeft, size;
255f7df2e56Smrg
256f7df2e56Smrg        from.c8 = (CARD8 *) &stuff[1];
257f7df2e56Smrg        dataLeft = (stuff->length * 4) - SIZEOF(xkbSelectEventsReq);
258f7df2e56Smrg        maskLeft = (stuff->affectWhich & (~XkbMapNotifyMask));
259f7df2e56Smrg        for (ndx = 0, bit = 1; (maskLeft != 0); ndx++, bit <<= 1) {
260f7df2e56Smrg            if ((bit & maskLeft) == 0)
261f7df2e56Smrg                continue;
262f7df2e56Smrg            maskLeft &= ~bit;
263f7df2e56Smrg            switch (ndx) {
264f7df2e56Smrg            case XkbNewKeyboardNotify:
265f7df2e56Smrg                to.c16 = &client->newKeyboardNotifyMask;
266f7df2e56Smrg                legal = XkbAllNewKeyboardEventsMask;
267f7df2e56Smrg                size = 2;
268f7df2e56Smrg                break;
269f7df2e56Smrg            case XkbStateNotify:
270f7df2e56Smrg                to.c16 = &masks->stateNotifyMask;
271f7df2e56Smrg                legal = XkbAllStateEventsMask;
272f7df2e56Smrg                size = 2;
273f7df2e56Smrg                break;
274f7df2e56Smrg            case XkbControlsNotify:
275f7df2e56Smrg                to.c32 = &masks->ctrlsNotifyMask;
276f7df2e56Smrg                legal = XkbAllControlEventsMask;
277f7df2e56Smrg                size = 4;
278f7df2e56Smrg                break;
279f7df2e56Smrg            case XkbIndicatorStateNotify:
280f7df2e56Smrg                to.c32 = &masks->iStateNotifyMask;
281f7df2e56Smrg                legal = XkbAllIndicatorEventsMask;
282f7df2e56Smrg                size = 4;
283f7df2e56Smrg                break;
284f7df2e56Smrg            case XkbIndicatorMapNotify:
285f7df2e56Smrg                to.c32 = &masks->iMapNotifyMask;
286f7df2e56Smrg                legal = XkbAllIndicatorEventsMask;
287f7df2e56Smrg                size = 4;
288f7df2e56Smrg                break;
289f7df2e56Smrg            case XkbNamesNotify:
290f7df2e56Smrg                to.c16 = &masks->namesNotifyMask;
291f7df2e56Smrg                legal = XkbAllNameEventsMask;
292f7df2e56Smrg                size = 2;
293f7df2e56Smrg                break;
294f7df2e56Smrg            case XkbCompatMapNotify:
295f7df2e56Smrg                to.c8 = &masks->compatNotifyMask;
296f7df2e56Smrg                legal = XkbAllCompatMapEventsMask;
297f7df2e56Smrg                size = 1;
298f7df2e56Smrg                break;
299f7df2e56Smrg            case XkbBellNotify:
300f7df2e56Smrg                to.c8 = &masks->bellNotifyMask;
301f7df2e56Smrg                legal = XkbAllBellEventsMask;
302f7df2e56Smrg                size = 1;
303f7df2e56Smrg                break;
304f7df2e56Smrg            case XkbActionMessage:
305f7df2e56Smrg                to.c8 = &masks->actionMessageMask;
306f7df2e56Smrg                legal = XkbAllActionMessagesMask;
307f7df2e56Smrg                size = 1;
308f7df2e56Smrg                break;
309f7df2e56Smrg            case XkbAccessXNotify:
310f7df2e56Smrg                to.c16 = &masks->accessXNotifyMask;
311f7df2e56Smrg                legal = XkbAllAccessXEventsMask;
312f7df2e56Smrg                size = 2;
313f7df2e56Smrg                break;
314f7df2e56Smrg            case XkbExtensionDeviceNotify:
315f7df2e56Smrg                to.c16 = &masks->extDevNotifyMask;
316f7df2e56Smrg                legal = XkbAllExtensionDeviceEventsMask;
317f7df2e56Smrg                size = 2;
318f7df2e56Smrg                break;
319f7df2e56Smrg            default:
320f7df2e56Smrg                client->errorValue = _XkbErrCode2(33, bit);
321f7df2e56Smrg                return BadValue;
322f7df2e56Smrg            }
323f7df2e56Smrg
324f7df2e56Smrg            if (stuff->clear & bit) {
325f7df2e56Smrg                if (size == 2)
326f7df2e56Smrg                    to.c16[0] = 0;
327f7df2e56Smrg                else if (size == 4)
328f7df2e56Smrg                    to.c32[0] = 0;
329f7df2e56Smrg                else
330f7df2e56Smrg                    to.c8[0] = 0;
331f7df2e56Smrg            }
332f7df2e56Smrg            else if (stuff->selectAll & bit) {
333f7df2e56Smrg                if (size == 2)
334f7df2e56Smrg                    to.c16[0] = ~0;
335f7df2e56Smrg                else if (size == 4)
336f7df2e56Smrg                    to.c32[0] = ~0;
337f7df2e56Smrg                else
338f7df2e56Smrg                    to.c8[0] = ~0;
339f7df2e56Smrg            }
340f7df2e56Smrg            else {
341f7df2e56Smrg                if (dataLeft < (size * 2))
342f7df2e56Smrg                    return BadLength;
343f7df2e56Smrg                if (size == 2) {
344f7df2e56Smrg                    CHK_MASK_MATCH(ndx, from.c16[0], from.c16[1]);
345f7df2e56Smrg                    CHK_MASK_LEGAL(ndx, from.c16[0], legal);
346f7df2e56Smrg                    to.c16[0] &= ~from.c16[0];
347f7df2e56Smrg                    to.c16[0] |= (from.c16[0] & from.c16[1]);
348f7df2e56Smrg                }
349f7df2e56Smrg                else if (size == 4) {
350f7df2e56Smrg                    CHK_MASK_MATCH(ndx, from.c32[0], from.c32[1]);
351f7df2e56Smrg                    CHK_MASK_LEGAL(ndx, from.c32[0], legal);
352f7df2e56Smrg                    to.c32[0] &= ~from.c32[0];
353f7df2e56Smrg                    to.c32[0] |= (from.c32[0] & from.c32[1]);
354f7df2e56Smrg                }
355f7df2e56Smrg                else {
356f7df2e56Smrg                    CHK_MASK_MATCH(ndx, from.c8[0], from.c8[1]);
357f7df2e56Smrg                    CHK_MASK_LEGAL(ndx, from.c8[0], legal);
358f7df2e56Smrg                    to.c8[0] &= ~from.c8[0];
359f7df2e56Smrg                    to.c8[0] |= (from.c8[0] & from.c8[1]);
360f7df2e56Smrg                    size = 2;
361f7df2e56Smrg                }
362f7df2e56Smrg                from.c8 += (size * 2);
363f7df2e56Smrg                dataLeft -= (size * 2);
364f7df2e56Smrg            }
365f7df2e56Smrg        }
366f7df2e56Smrg        if (dataLeft > 2) {
367f7df2e56Smrg            ErrorF("[xkb] Extra data (%d bytes) after SelectEvents\n",
368f7df2e56Smrg                   dataLeft);
369f7df2e56Smrg            return BadLength;
370f7df2e56Smrg        }
371f7df2e56Smrg        return Success;
37205b261ecSmrg    }
37305b261ecSmrg    return BadAlloc;
37405b261ecSmrg}
37505b261ecSmrg
37605b261ecSmrg/***====================================================================***/
3774642e01fSmrg/**
3784642e01fSmrg * Ring a bell on the given device for the given client.
3794642e01fSmrg */
3804642e01fSmrgstatic int
3814642e01fSmrg_XkbBell(ClientPtr client, DeviceIntPtr dev, WindowPtr pWin,
3824642e01fSmrg         int bellClass, int bellID, int pitch, int duration,
3834642e01fSmrg         int percent, int forceSound, int eventOnly, Atom name)
3844642e01fSmrg{
385f7df2e56Smrg    int base;
386f7df2e56Smrg    void *ctrl;
387f7df2e56Smrg    int oldPitch, oldDuration;
388f7df2e56Smrg    int newPercent;
3894642e01fSmrg
3904642e01fSmrg    if (bellClass == KbdFeedbackClass) {
391f7df2e56Smrg        KbdFeedbackPtr k;
392f7df2e56Smrg
393f7df2e56Smrg        if (bellID == XkbDfltXIId)
394f7df2e56Smrg            k = dev->kbdfeed;
3954642e01fSmrg        else {
396f7df2e56Smrg            for (k = dev->kbdfeed; k; k = k->next) {
3974642e01fSmrg                if (k->ctrl.id == bellID)
3984642e01fSmrg                    break;
3994642e01fSmrg            }
4004642e01fSmrg        }
4014642e01fSmrg        if (!k) {
402f7df2e56Smrg            client->errorValue = _XkbErrCode2(0x5, bellID);
4034642e01fSmrg            return BadValue;
4044642e01fSmrg        }
4054642e01fSmrg        base = k->ctrl.bell;
406f7df2e56Smrg        ctrl = (void *) &(k->ctrl);
407f7df2e56Smrg        oldPitch = k->ctrl.bell_pitch;
408f7df2e56Smrg        oldDuration = k->ctrl.bell_duration;
409f7df2e56Smrg        if (pitch != 0) {
410f7df2e56Smrg            if (pitch == -1)
411f7df2e56Smrg                k->ctrl.bell_pitch = defaultKeyboardControl.bell_pitch;
412f7df2e56Smrg            else
413f7df2e56Smrg                k->ctrl.bell_pitch = pitch;
4144642e01fSmrg        }
415f7df2e56Smrg        if (duration != 0) {
416f7df2e56Smrg            if (duration == -1)
417f7df2e56Smrg                k->ctrl.bell_duration = defaultKeyboardControl.bell_duration;
418f7df2e56Smrg            else
419f7df2e56Smrg                k->ctrl.bell_duration = duration;
4204642e01fSmrg        }
4214642e01fSmrg    }
4224642e01fSmrg    else if (bellClass == BellFeedbackClass) {
423f7df2e56Smrg        BellFeedbackPtr b;
424f7df2e56Smrg
425f7df2e56Smrg        if (bellID == XkbDfltXIId)
426f7df2e56Smrg            b = dev->bell;
4274642e01fSmrg        else {
428f7df2e56Smrg            for (b = dev->bell; b; b = b->next) {
4294642e01fSmrg                if (b->ctrl.id == bellID)
4304642e01fSmrg                    break;
4314642e01fSmrg            }
4324642e01fSmrg        }
4334642e01fSmrg        if (!b) {
434f7df2e56Smrg            client->errorValue = _XkbErrCode2(0x6, bellID);
4354642e01fSmrg            return BadValue;
4364642e01fSmrg        }
4374642e01fSmrg        base = b->ctrl.percent;
438f7df2e56Smrg        ctrl = (void *) &(b->ctrl);
439f7df2e56Smrg        oldPitch = b->ctrl.pitch;
440f7df2e56Smrg        oldDuration = b->ctrl.duration;
441f7df2e56Smrg        if (pitch != 0) {
442f7df2e56Smrg            if (pitch == -1)
443f7df2e56Smrg                b->ctrl.pitch = defaultKeyboardControl.bell_pitch;
444f7df2e56Smrg            else
445f7df2e56Smrg                b->ctrl.pitch = pitch;
4464642e01fSmrg        }
447f7df2e56Smrg        if (duration != 0) {
448f7df2e56Smrg            if (duration == -1)
449f7df2e56Smrg                b->ctrl.duration = defaultKeyboardControl.bell_duration;
450f7df2e56Smrg            else
451f7df2e56Smrg                b->ctrl.duration = duration;
4524642e01fSmrg        }
4534642e01fSmrg    }
4544642e01fSmrg    else {
4554642e01fSmrg        client->errorValue = _XkbErrCode2(0x7, bellClass);
4564642e01fSmrg        return BadValue;
4574642e01fSmrg    }
4584642e01fSmrg
459f7df2e56Smrg    newPercent = (base * percent) / 100;
4604642e01fSmrg    if (percent < 0)
461f7df2e56Smrg        newPercent = base + newPercent;
462f7df2e56Smrg    else
463f7df2e56Smrg        newPercent = base - newPercent + percent;
4644642e01fSmrg
4654642e01fSmrg    XkbHandleBell(forceSound, eventOnly,
466f7df2e56Smrg                  dev, newPercent, ctrl, bellClass, name, pWin, client);
467f7df2e56Smrg    if ((pitch != 0) || (duration != 0)) {
4684642e01fSmrg        if (bellClass == KbdFeedbackClass) {
469f7df2e56Smrg            KbdFeedbackPtr k;
470f7df2e56Smrg
471f7df2e56Smrg            k = (KbdFeedbackPtr) ctrl;
472f7df2e56Smrg            if (pitch != 0)
473f7df2e56Smrg                k->ctrl.bell_pitch = oldPitch;
474f7df2e56Smrg            if (duration != 0)
475f7df2e56Smrg                k->ctrl.bell_duration = oldDuration;
4764642e01fSmrg        }
4774642e01fSmrg        else {
478f7df2e56Smrg            BellFeedbackPtr b;
479f7df2e56Smrg
480f7df2e56Smrg            b = (BellFeedbackPtr) ctrl;
481f7df2e56Smrg            if (pitch != 0)
482f7df2e56Smrg                b->ctrl.pitch = oldPitch;
483f7df2e56Smrg            if (duration != 0)
484f7df2e56Smrg                b->ctrl.duration = oldDuration;
4854642e01fSmrg        }
4864642e01fSmrg    }
4874642e01fSmrg
4884642e01fSmrg    return Success;
4894642e01fSmrg}
49005b261ecSmrg
49105b261ecSmrgint
49205b261ecSmrgProcXkbBell(ClientPtr client)
49305b261ecSmrg{
49405b261ecSmrg    REQUEST(xkbBellReq);
49505b261ecSmrg    DeviceIntPtr dev;
496f7df2e56Smrg    WindowPtr pWin;
4974642e01fSmrg    int rc;
49805b261ecSmrg
49905b261ecSmrg    REQUEST_SIZE_MATCH(xkbBellReq);
50005b261ecSmrg
501f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
502f7df2e56Smrg        return BadAccess;
50305b261ecSmrg
5044642e01fSmrg    CHK_BELL_DEVICE(dev, stuff->deviceSpec, client, DixBellAccess);
50505b261ecSmrg    CHK_ATOM_OR_NONE(stuff->name);
50605b261ecSmrg
5074642e01fSmrg    /* device-independent checks request for sane values */
508f7df2e56Smrg    if ((stuff->forceSound) && (stuff->eventOnly)) {
509f7df2e56Smrg        client->errorValue =
510f7df2e56Smrg            _XkbErrCode3(0x1, stuff->forceSound, stuff->eventOnly);
511f7df2e56Smrg        return BadMatch;
51205b261ecSmrg    }
51305b261ecSmrg    if (stuff->percent < -100 || stuff->percent > 100) {
514f7df2e56Smrg        client->errorValue = _XkbErrCode2(0x2, stuff->percent);
515f7df2e56Smrg        return BadValue;
51605b261ecSmrg    }
517f7df2e56Smrg    if (stuff->duration < -1) {
518f7df2e56Smrg        client->errorValue = _XkbErrCode2(0x3, stuff->duration);
519f7df2e56Smrg        return BadValue;
52005b261ecSmrg    }
521f7df2e56Smrg    if (stuff->pitch < -1) {
522f7df2e56Smrg        client->errorValue = _XkbErrCode2(0x4, stuff->pitch);
523f7df2e56Smrg        return BadValue;
52405b261ecSmrg    }
52505b261ecSmrg
52605b261ecSmrg    if (stuff->bellClass == XkbDfltXIClass) {
527f7df2e56Smrg        if (dev->kbdfeed != NULL)
528f7df2e56Smrg            stuff->bellClass = KbdFeedbackClass;
529f7df2e56Smrg        else
530f7df2e56Smrg            stuff->bellClass = BellFeedbackClass;
53105b261ecSmrg    }
5324642e01fSmrg
533f7df2e56Smrg    if (stuff->window != None) {
534f7df2e56Smrg        rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
535f7df2e56Smrg        if (rc != Success) {
536f7df2e56Smrg            client->errorValue = stuff->window;
537f7df2e56Smrg            return rc;
538f7df2e56Smrg        }
53905b261ecSmrg    }
540f7df2e56Smrg    else
541f7df2e56Smrg        pWin = NULL;
54205b261ecSmrg
5434642e01fSmrg    /* Client wants to ring a bell on the core keyboard?
5444642e01fSmrg       Ring the bell on the core keyboard (which does nothing, but if that
5454642e01fSmrg       fails the client is screwed anyway), and then on all extension devices.
5464642e01fSmrg       Fail if the core keyboard fails but not the extension devices.  this
5474642e01fSmrg       may cause some keyboards to ding and others to stay silent. Fix
5484642e01fSmrg       your client to use explicit keyboards to avoid this.
5494642e01fSmrg
5504642e01fSmrg       dev is the device the client requested.
5514642e01fSmrg     */
5524642e01fSmrg    rc = _XkbBell(client, dev, pWin, stuff->bellClass, stuff->bellID,
5534642e01fSmrg                  stuff->pitch, stuff->duration, stuff->percent,
5544642e01fSmrg                  stuff->forceSound, stuff->eventOnly, stuff->name);
5554642e01fSmrg
5564642e01fSmrg    if ((rc == Success) && ((stuff->deviceSpec == XkbUseCoreKbd) ||
557f7df2e56Smrg                            (stuff->deviceSpec == XkbUseCorePtr))) {
5584642e01fSmrg        DeviceIntPtr other;
559f7df2e56Smrg
560f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
561f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
562f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
5634642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixBellAccess);
5644642e01fSmrg                if (rc == Success)
5654642e01fSmrg                    _XkbBell(client, other, pWin, stuff->bellClass,
5664642e01fSmrg                             stuff->bellID, stuff->pitch, stuff->duration,
5674642e01fSmrg                             stuff->percent, stuff->forceSound,
5684642e01fSmrg                             stuff->eventOnly, stuff->name);
5694642e01fSmrg            }
5704642e01fSmrg        }
571f7df2e56Smrg        rc = Success;           /* reset to success, that's what we got for the VCK */
57205b261ecSmrg    }
5734642e01fSmrg
5744642e01fSmrg    return rc;
57505b261ecSmrg}
57605b261ecSmrg
57705b261ecSmrg/***====================================================================***/
57805b261ecSmrg
57905b261ecSmrgint
58005b261ecSmrgProcXkbGetState(ClientPtr client)
58105b261ecSmrg{
58205b261ecSmrg    REQUEST(xkbGetStateReq);
583f7df2e56Smrg    DeviceIntPtr dev;
584f7df2e56Smrg    xkbGetStateReply rep;
585f7df2e56Smrg    XkbStateRec *xkb;
58605b261ecSmrg
58705b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetStateReq);
58805b261ecSmrg
589f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
590f7df2e56Smrg        return BadAccess;
59105b261ecSmrg
5926747b715Smrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
59305b261ecSmrg
594f7df2e56Smrg    xkb = &dev->key->xkbInfo->state;
595f7df2e56Smrg    rep = (xkbGetStateReply) {
596f7df2e56Smrg        .type = X_Reply,
597f7df2e56Smrg        .deviceID = dev->id,
598f7df2e56Smrg        .sequenceNumber = client->sequence,
599f7df2e56Smrg        .length = 0,
600f7df2e56Smrg        .mods = XkbStateFieldFromRec(xkb) & 0xff,
601f7df2e56Smrg        .baseMods = xkb->base_mods,
602f7df2e56Smrg        .latchedMods = xkb->latched_mods,
603f7df2e56Smrg        .lockedMods = xkb->locked_mods,
604f7df2e56Smrg        .group = xkb->group,
605f7df2e56Smrg        .lockedGroup = xkb->locked_group,
606f7df2e56Smrg        .baseGroup = xkb->base_group,
607f7df2e56Smrg        .latchedGroup = xkb->latched_group,
608f7df2e56Smrg        .compatState = xkb->compat_state,
609f7df2e56Smrg        .ptrBtnState = xkb->ptr_buttons
610f7df2e56Smrg    };
61105b261ecSmrg    if (client->swapped) {
612f7df2e56Smrg        swaps(&rep.sequenceNumber);
613f7df2e56Smrg        swaps(&rep.ptrBtnState);
61405b261ecSmrg    }
615f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetStateReply), &rep);
6166747b715Smrg    return Success;
61705b261ecSmrg}
61805b261ecSmrg
61905b261ecSmrg/***====================================================================***/
62005b261ecSmrg
62105b261ecSmrgint
62205b261ecSmrgProcXkbLatchLockState(ClientPtr client)
62305b261ecSmrg{
62405b261ecSmrg    int status;
62505b261ecSmrg    DeviceIntPtr dev, tmpd;
626f7df2e56Smrg    XkbStateRec oldState, *newState;
62705b261ecSmrg    CARD16 changed;
62805b261ecSmrg    xkbStateNotify sn;
62905b261ecSmrg    XkbEventCauseRec cause;
63005b261ecSmrg
63105b261ecSmrg    REQUEST(xkbLatchLockStateReq);
63205b261ecSmrg    REQUEST_SIZE_MATCH(xkbLatchLockStateReq);
63305b261ecSmrg
63405b261ecSmrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
635f7df2e56Smrg        return BadAccess;
63605b261ecSmrg
6374642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
63805b261ecSmrg    CHK_MASK_MATCH(0x01, stuff->affectModLocks, stuff->modLocks);
63905b261ecSmrg    CHK_MASK_MATCH(0x01, stuff->affectModLatches, stuff->modLatches);
64005b261ecSmrg
64105b261ecSmrg    status = Success;
64205b261ecSmrg
64305b261ecSmrg    for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
644f7df2e56Smrg        if ((tmpd == dev) ||
645f7df2e56Smrg            (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) {
6466747b715Smrg            if (!tmpd->key || !tmpd->key->xkbInfo)
64705b261ecSmrg                continue;
64805b261ecSmrg
64905b261ecSmrg            oldState = tmpd->key->xkbInfo->state;
65005b261ecSmrg            newState = &tmpd->key->xkbInfo->state;
65105b261ecSmrg            if (stuff->affectModLocks) {
65205b261ecSmrg                newState->locked_mods &= ~stuff->affectModLocks;
653f7df2e56Smrg                newState->locked_mods |=
654f7df2e56Smrg                    (stuff->affectModLocks & stuff->modLocks);
65505b261ecSmrg            }
65605b261ecSmrg            if (status == Success && stuff->lockGroup)
65705b261ecSmrg                newState->locked_group = stuff->groupLock;
65805b261ecSmrg            if (status == Success && stuff->affectModLatches)
65905b261ecSmrg                status = XkbLatchModifiers(tmpd, stuff->affectModLatches,
66005b261ecSmrg                                           stuff->modLatches);
66105b261ecSmrg            if (status == Success && stuff->latchGroup)
66205b261ecSmrg                status = XkbLatchGroup(tmpd, stuff->groupLatch);
66305b261ecSmrg
66405b261ecSmrg            if (status != Success)
66505b261ecSmrg                return status;
66605b261ecSmrg
66705b261ecSmrg            XkbComputeDerivedState(tmpd->key->xkbInfo);
66805b261ecSmrg
66905b261ecSmrg            changed = XkbStateChangedFlags(&oldState, newState);
67005b261ecSmrg            if (changed) {
67105b261ecSmrg                sn.keycode = 0;
67205b261ecSmrg                sn.eventType = 0;
67305b261ecSmrg                sn.requestMajor = XkbReqCode;
67405b261ecSmrg                sn.requestMinor = X_kbLatchLockState;
67505b261ecSmrg                sn.changed = changed;
67605b261ecSmrg                XkbSendStateNotify(tmpd, &sn);
6776747b715Smrg                changed = XkbIndicatorsToUpdate(tmpd, changed, FALSE);
67805b261ecSmrg                if (changed) {
67905b261ecSmrg                    XkbSetCauseXkbReq(&cause, X_kbLatchLockState, client);
6806747b715Smrg                    XkbUpdateIndicators(tmpd, changed, TRUE, NULL, &cause);
681f7df2e56Smrg                }
68205b261ecSmrg            }
68305b261ecSmrg        }
68405b261ecSmrg    }
68505b261ecSmrg
6866747b715Smrg    return Success;
68705b261ecSmrg}
68805b261ecSmrg
68905b261ecSmrg/***====================================================================***/
69005b261ecSmrg
69105b261ecSmrgint
69205b261ecSmrgProcXkbGetControls(ClientPtr client)
69305b261ecSmrg{
69405b261ecSmrg    xkbGetControlsReply rep;
695f7df2e56Smrg    XkbControlsPtr xkb;
696f7df2e56Smrg    DeviceIntPtr dev;
69705b261ecSmrg
69805b261ecSmrg    REQUEST(xkbGetControlsReq);
69905b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetControlsReq);
70005b261ecSmrg
701f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
702f7df2e56Smrg        return BadAccess;
70305b261ecSmrg
7044642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
705f7df2e56Smrg
70605b261ecSmrg    xkb = dev->key->xkbInfo->desc->ctrls;
707f7df2e56Smrg    rep = (xkbGetControlsReply) {
708f7df2e56Smrg        .type = X_Reply,
709f7df2e56Smrg        .deviceID = ((DeviceIntPtr) dev)->id,
710f7df2e56Smrg        .sequenceNumber = client->sequence,
711f7df2e56Smrg        .length = bytes_to_int32(SIZEOF(xkbGetControlsReply) -
712f7df2e56Smrg                                 SIZEOF(xGenericReply)),
713f7df2e56Smrg        .mkDfltBtn = xkb->mk_dflt_btn,
714f7df2e56Smrg        .numGroups = xkb->num_groups,
715f7df2e56Smrg        .groupsWrap = xkb->groups_wrap,
716f7df2e56Smrg        .internalMods = xkb->internal.mask,
717f7df2e56Smrg        .ignoreLockMods = xkb->ignore_lock.mask,
718f7df2e56Smrg        .internalRealMods = xkb->internal.real_mods,
719f7df2e56Smrg        .ignoreLockRealMods = xkb->ignore_lock.real_mods,
720f7df2e56Smrg        .internalVMods = xkb->internal.vmods,
721f7df2e56Smrg        .ignoreLockVMods = xkb->ignore_lock.vmods,
722f7df2e56Smrg        .repeatDelay = xkb->repeat_delay,
723f7df2e56Smrg        .repeatInterval = xkb->repeat_interval,
724f7df2e56Smrg        .slowKeysDelay = xkb->slow_keys_delay,
725f7df2e56Smrg        .debounceDelay = xkb->debounce_delay,
726f7df2e56Smrg        .mkDelay = xkb->mk_delay,
727f7df2e56Smrg        .mkInterval = xkb->mk_interval,
728f7df2e56Smrg        .mkTimeToMax = xkb->mk_time_to_max,
729f7df2e56Smrg        .mkMaxSpeed = xkb->mk_max_speed,
730f7df2e56Smrg        .mkCurve = xkb->mk_curve,
731f7df2e56Smrg        .axOptions = xkb->ax_options,
732f7df2e56Smrg        .axTimeout = xkb->ax_timeout,
733f7df2e56Smrg        .axtOptsMask = xkb->axt_opts_mask,
734f7df2e56Smrg        .axtOptsValues = xkb->axt_opts_values,
735f7df2e56Smrg        .axtCtrlsMask = xkb->axt_ctrls_mask,
736f7df2e56Smrg        .axtCtrlsValues = xkb->axt_ctrls_values,
737f7df2e56Smrg        .enabledCtrls = xkb->enabled_ctrls,
738f7df2e56Smrg    };
739f7df2e56Smrg    memcpy(rep.perKeyRepeat, xkb->per_key_repeat, XkbPerKeyBitArraySize);
74005b261ecSmrg    if (client->swapped) {
741f7df2e56Smrg        swaps(&rep.sequenceNumber);
742f7df2e56Smrg        swapl(&rep.length);
743f7df2e56Smrg        swaps(&rep.internalVMods);
744f7df2e56Smrg        swaps(&rep.ignoreLockVMods);
745f7df2e56Smrg        swapl(&rep.enabledCtrls);
746f7df2e56Smrg        swaps(&rep.repeatDelay);
747f7df2e56Smrg        swaps(&rep.repeatInterval);
748f7df2e56Smrg        swaps(&rep.slowKeysDelay);
749f7df2e56Smrg        swaps(&rep.debounceDelay);
750f7df2e56Smrg        swaps(&rep.mkDelay);
751f7df2e56Smrg        swaps(&rep.mkInterval);
752f7df2e56Smrg        swaps(&rep.mkTimeToMax);
753f7df2e56Smrg        swaps(&rep.mkMaxSpeed);
754f7df2e56Smrg        swaps(&rep.mkCurve);
755f7df2e56Smrg        swaps(&rep.axTimeout);
756f7df2e56Smrg        swapl(&rep.axtCtrlsMask);
757f7df2e56Smrg        swapl(&rep.axtCtrlsValues);
758f7df2e56Smrg        swaps(&rep.axtOptsMask);
759f7df2e56Smrg        swaps(&rep.axtOptsValues);
760f7df2e56Smrg        swaps(&rep.axOptions);
761f7df2e56Smrg    }
762f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetControlsReply), &rep);
7636747b715Smrg    return Success;
76405b261ecSmrg}
76505b261ecSmrg
76605b261ecSmrgint
76705b261ecSmrgProcXkbSetControls(ClientPtr client)
76805b261ecSmrg{
769f7df2e56Smrg    DeviceIntPtr dev, tmpd;
770f7df2e56Smrg    XkbSrvInfoPtr xkbi;
771f7df2e56Smrg    XkbControlsPtr ctrl;
772f7df2e56Smrg    XkbControlsRec new, old;
773f7df2e56Smrg    xkbControlsNotify cn;
774f7df2e56Smrg    XkbEventCauseRec cause;
775f7df2e56Smrg    XkbSrvLedInfoPtr sli;
77605b261ecSmrg
77705b261ecSmrg    REQUEST(xkbSetControlsReq);
77805b261ecSmrg    REQUEST_SIZE_MATCH(xkbSetControlsReq);
77905b261ecSmrg
78005b261ecSmrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
781f7df2e56Smrg        return BadAccess;
78205b261ecSmrg
7834642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
78405b261ecSmrg    CHK_MASK_LEGAL(0x01, stuff->changeCtrls, XkbAllControlsMask);
78505b261ecSmrg
7866747b715Smrg    for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
7876747b715Smrg        if (!tmpd->key || !tmpd->key->xkbInfo)
7886747b715Smrg            continue;
789f7df2e56Smrg        if ((tmpd == dev) ||
790f7df2e56Smrg            (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) {
79105b261ecSmrg            xkbi = tmpd->key->xkbInfo;
79205b261ecSmrg            ctrl = xkbi->desc->ctrls;
79305b261ecSmrg            new = *ctrl;
79405b261ecSmrg            XkbSetCauseXkbReq(&cause, X_kbSetControls, client);
79505b261ecSmrg
79605b261ecSmrg            if (stuff->changeCtrls & XkbInternalModsMask) {
79705b261ecSmrg                CHK_MASK_MATCH(0x02, stuff->affectInternalMods,
79805b261ecSmrg                               stuff->internalMods);
79905b261ecSmrg                CHK_MASK_MATCH(0x03, stuff->affectInternalVMods,
80005b261ecSmrg                               stuff->internalVMods);
80105b261ecSmrg
80205b261ecSmrg                new.internal.real_mods &= ~(stuff->affectInternalMods);
80305b261ecSmrg                new.internal.real_mods |= (stuff->affectInternalMods &
80405b261ecSmrg                                           stuff->internalMods);
80505b261ecSmrg                new.internal.vmods &= ~(stuff->affectInternalVMods);
80605b261ecSmrg                new.internal.vmods |= (stuff->affectInternalVMods &
80705b261ecSmrg                                       stuff->internalVMods);
80805b261ecSmrg                new.internal.mask = new.internal.real_mods |
809f7df2e56Smrg                    XkbMaskForVMask(xkbi->desc, new.internal.vmods);
81005b261ecSmrg            }
81105b261ecSmrg
81205b261ecSmrg            if (stuff->changeCtrls & XkbIgnoreLockModsMask) {
81305b261ecSmrg                CHK_MASK_MATCH(0x4, stuff->affectIgnoreLockMods,
81405b261ecSmrg                               stuff->ignoreLockMods);
81505b261ecSmrg                CHK_MASK_MATCH(0x5, stuff->affectIgnoreLockVMods,
81605b261ecSmrg                               stuff->ignoreLockVMods);
81705b261ecSmrg
81805b261ecSmrg                new.ignore_lock.real_mods &= ~(stuff->affectIgnoreLockMods);
81905b261ecSmrg                new.ignore_lock.real_mods |= (stuff->affectIgnoreLockMods &
82005b261ecSmrg                                              stuff->ignoreLockMods);
82105b261ecSmrg                new.ignore_lock.vmods &= ~(stuff->affectIgnoreLockVMods);
82205b261ecSmrg                new.ignore_lock.vmods |= (stuff->affectIgnoreLockVMods &
82305b261ecSmrg                                          stuff->ignoreLockVMods);
82405b261ecSmrg                new.ignore_lock.mask = new.ignore_lock.real_mods |
825f7df2e56Smrg                    XkbMaskForVMask(xkbi->desc, new.ignore_lock.vmods);
82605b261ecSmrg            }
82705b261ecSmrg
82805b261ecSmrg            CHK_MASK_MATCH(0x06, stuff->affectEnabledCtrls,
82905b261ecSmrg                           stuff->enabledCtrls);
83005b261ecSmrg            if (stuff->affectEnabledCtrls) {
83105b261ecSmrg                CHK_MASK_LEGAL(0x07, stuff->affectEnabledCtrls,
83205b261ecSmrg                               XkbAllBooleanCtrlsMask);
83305b261ecSmrg
83405b261ecSmrg                new.enabled_ctrls &= ~(stuff->affectEnabledCtrls);
83505b261ecSmrg                new.enabled_ctrls |= (stuff->affectEnabledCtrls &
83605b261ecSmrg                                      stuff->enabledCtrls);
83705b261ecSmrg            }
83805b261ecSmrg
83905b261ecSmrg            if (stuff->changeCtrls & XkbRepeatKeysMask) {
84005b261ecSmrg                if (stuff->repeatDelay < 1 || stuff->repeatInterval < 1) {
84105b261ecSmrg                    client->errorValue = _XkbErrCode3(0x08, stuff->repeatDelay,
84205b261ecSmrg                                                      stuff->repeatInterval);
84305b261ecSmrg                    return BadValue;
84405b261ecSmrg                }
84505b261ecSmrg
84605b261ecSmrg                new.repeat_delay = stuff->repeatDelay;
84705b261ecSmrg                new.repeat_interval = stuff->repeatInterval;
84805b261ecSmrg            }
84905b261ecSmrg
85005b261ecSmrg            if (stuff->changeCtrls & XkbSlowKeysMask) {
85105b261ecSmrg                if (stuff->slowKeysDelay < 1) {
85205b261ecSmrg                    client->errorValue = _XkbErrCode2(0x09,
85305b261ecSmrg                                                      stuff->slowKeysDelay);
85405b261ecSmrg                    return BadValue;
85505b261ecSmrg                }
85605b261ecSmrg
85705b261ecSmrg                new.slow_keys_delay = stuff->slowKeysDelay;
85805b261ecSmrg            }
85905b261ecSmrg
86005b261ecSmrg            if (stuff->changeCtrls & XkbBounceKeysMask) {
86105b261ecSmrg                if (stuff->debounceDelay < 1) {
86205b261ecSmrg                    client->errorValue = _XkbErrCode2(0x0A,
86305b261ecSmrg                                                      stuff->debounceDelay);
86405b261ecSmrg                    return BadValue;
86505b261ecSmrg                }
86605b261ecSmrg
86705b261ecSmrg                new.debounce_delay = stuff->debounceDelay;
86805b261ecSmrg            }
86905b261ecSmrg
87005b261ecSmrg            if (stuff->changeCtrls & XkbMouseKeysMask) {
87105b261ecSmrg                if (stuff->mkDfltBtn > XkbMaxMouseKeysBtn) {
87205b261ecSmrg                    client->errorValue = _XkbErrCode2(0x0B, stuff->mkDfltBtn);
87305b261ecSmrg                    return BadValue;
87405b261ecSmrg                }
87505b261ecSmrg
87605b261ecSmrg                new.mk_dflt_btn = stuff->mkDfltBtn;
87705b261ecSmrg            }
87805b261ecSmrg
87905b261ecSmrg            if (stuff->changeCtrls & XkbMouseKeysAccelMask) {
88005b261ecSmrg                if (stuff->mkDelay < 1 || stuff->mkInterval < 1 ||
88105b261ecSmrg                    stuff->mkTimeToMax < 1 || stuff->mkMaxSpeed < 1 ||
88205b261ecSmrg                    stuff->mkCurve < -1000) {
883f7df2e56Smrg                    client->errorValue = _XkbErrCode2(0x0C, 0);
88405b261ecSmrg                    return BadValue;
88505b261ecSmrg                }
88605b261ecSmrg
88705b261ecSmrg                new.mk_delay = stuff->mkDelay;
88805b261ecSmrg                new.mk_interval = stuff->mkInterval;
88905b261ecSmrg                new.mk_time_to_max = stuff->mkTimeToMax;
89005b261ecSmrg                new.mk_max_speed = stuff->mkMaxSpeed;
89105b261ecSmrg                new.mk_curve = stuff->mkCurve;
89205b261ecSmrg                AccessXComputeCurveFactor(xkbi, &new);
89305b261ecSmrg            }
89405b261ecSmrg
89505b261ecSmrg            if (stuff->changeCtrls & XkbGroupsWrapMask) {
89605b261ecSmrg                unsigned act, num;
89705b261ecSmrg
89805b261ecSmrg                act = XkbOutOfRangeGroupAction(stuff->groupsWrap);
89905b261ecSmrg                switch (act) {
90005b261ecSmrg                case XkbRedirectIntoRange:
90105b261ecSmrg                    num = XkbOutOfRangeGroupNumber(stuff->groupsWrap);
90205b261ecSmrg                    if (num >= new.num_groups) {
90305b261ecSmrg                        client->errorValue = _XkbErrCode3(0x0D, new.num_groups,
90405b261ecSmrg                                                          num);
90505b261ecSmrg                        return BadValue;
90605b261ecSmrg                    }
90705b261ecSmrg                case XkbWrapIntoRange:
90805b261ecSmrg                case XkbClampIntoRange:
90905b261ecSmrg                    break;
91005b261ecSmrg                default:
91105b261ecSmrg                    client->errorValue = _XkbErrCode2(0x0E, act);
91205b261ecSmrg                    return BadValue;
91305b261ecSmrg                }
91405b261ecSmrg
915f7df2e56Smrg                new.groups_wrap = stuff->groupsWrap;
91605b261ecSmrg            }
91705b261ecSmrg
91805b261ecSmrg            CHK_MASK_LEGAL(0x0F, stuff->axOptions, XkbAX_AllOptionsMask);
91905b261ecSmrg            if (stuff->changeCtrls & XkbAccessXKeysMask) {
92005b261ecSmrg                new.ax_options = stuff->axOptions & XkbAX_AllOptionsMask;
92105b261ecSmrg            }
92205b261ecSmrg            else {
92305b261ecSmrg                if (stuff->changeCtrls & XkbStickyKeysMask) {
92405b261ecSmrg                    new.ax_options &= ~(XkbAX_SKOptionsMask);
92505b261ecSmrg                    new.ax_options |= (stuff->axOptions & XkbAX_SKOptionsMask);
92605b261ecSmrg                }
927f7df2e56Smrg
92805b261ecSmrg                if (stuff->changeCtrls & XkbAccessXFeedbackMask) {
92905b261ecSmrg                    new.ax_options &= ~(XkbAX_FBOptionsMask);
93005b261ecSmrg                    new.ax_options |= (stuff->axOptions & XkbAX_FBOptionsMask);
93105b261ecSmrg                }
93205b261ecSmrg            }
93305b261ecSmrg
93405b261ecSmrg            if (stuff->changeCtrls & XkbAccessXTimeoutMask) {
93505b261ecSmrg                if (stuff->axTimeout < 1) {
93605b261ecSmrg                    client->errorValue = _XkbErrCode2(0x10, stuff->axTimeout);
93705b261ecSmrg                    return BadValue;
93805b261ecSmrg                }
93905b261ecSmrg                CHK_MASK_MATCH(0x11, stuff->axtCtrlsMask,
94005b261ecSmrg                               stuff->axtCtrlsValues);
94105b261ecSmrg                CHK_MASK_LEGAL(0x12, stuff->axtCtrlsMask,
94205b261ecSmrg                               XkbAllBooleanCtrlsMask);
94305b261ecSmrg                CHK_MASK_MATCH(0x13, stuff->axtOptsMask, stuff->axtOptsValues);
94405b261ecSmrg                CHK_MASK_LEGAL(0x14, stuff->axtOptsMask, XkbAX_AllOptionsMask);
94505b261ecSmrg                new.ax_timeout = stuff->axTimeout;
94605b261ecSmrg                new.axt_ctrls_mask = stuff->axtCtrlsMask;
94705b261ecSmrg                new.axt_ctrls_values = (stuff->axtCtrlsValues &
94805b261ecSmrg                                        stuff->axtCtrlsMask);
94905b261ecSmrg                new.axt_opts_mask = stuff->axtOptsMask;
95005b261ecSmrg                new.axt_opts_values = (stuff->axtOptsValues &
95105b261ecSmrg                                       stuff->axtOptsMask);
95205b261ecSmrg            }
95305b261ecSmrg
9549ace9065Smrg            if (stuff->changeCtrls & XkbPerKeyRepeatMask) {
95505b261ecSmrg                memcpy(new.per_key_repeat, stuff->perKeyRepeat,
95605b261ecSmrg                       XkbPerKeyBitArraySize);
9579ace9065Smrg                if (xkbi->repeatKey &&
9589ace9065Smrg                    !BitIsOn(new.per_key_repeat, xkbi->repeatKey)) {
9599ace9065Smrg                    AccessXCancelRepeatKey(xkbi, xkbi->repeatKey);
9609ace9065Smrg                }
9619ace9065Smrg            }
96205b261ecSmrg
963f7df2e56Smrg            old = *ctrl;
964f7df2e56Smrg            *ctrl = new;
96505b261ecSmrg            XkbDDXChangeControls(tmpd, &old, ctrl);
96605b261ecSmrg
9676747b715Smrg            if (XkbComputeControlsNotify(tmpd, &old, ctrl, &cn, FALSE)) {
96805b261ecSmrg                cn.keycode = 0;
96905b261ecSmrg                cn.eventType = 0;
97005b261ecSmrg                cn.requestMajor = XkbReqCode;
97105b261ecSmrg                cn.requestMinor = X_kbSetControls;
97205b261ecSmrg                XkbSendControlsNotify(tmpd, &cn);
97305b261ecSmrg            }
97405b261ecSmrg
97505b261ecSmrg            sli = XkbFindSrvLedInfo(tmpd, XkbDfltXIClass, XkbDfltXIId, 0);
97605b261ecSmrg            if (sli)
9776747b715Smrg                XkbUpdateIndicators(tmpd, sli->usesControls, TRUE, NULL,
97805b261ecSmrg                                    &cause);
97905b261ecSmrg
98005b261ecSmrg            /* If sticky keys were disabled, clear all locks and latches */
98105b261ecSmrg            if ((old.enabled_ctrls & XkbStickyKeysMask) &&
98205b261ecSmrg                !(ctrl->enabled_ctrls & XkbStickyKeysMask))
9836747b715Smrg                XkbClearAllLatchesAndLocks(tmpd, xkbi, TRUE, &cause);
98405b261ecSmrg        }
98505b261ecSmrg    }
98605b261ecSmrg
9876747b715Smrg    return Success;
98805b261ecSmrg}
98905b261ecSmrg
99005b261ecSmrg/***====================================================================***/
99105b261ecSmrg
99205b261ecSmrgstatic int
993f7df2e56SmrgXkbSizeKeyTypes(XkbDescPtr xkb, xkbGetMapReply * rep)
99405b261ecSmrg{
995f7df2e56Smrg    XkbKeyTypeRec *type;
996f7df2e56Smrg    unsigned i, len;
997f7df2e56Smrg
998f7df2e56Smrg    len = 0;
999f7df2e56Smrg    if (((rep->present & XkbKeyTypesMask) == 0) || (rep->nTypes < 1) ||
1000f7df2e56Smrg        (!xkb) || (!xkb->map) || (!xkb->map->types)) {
1001f7df2e56Smrg        rep->present &= ~XkbKeyTypesMask;
1002f7df2e56Smrg        rep->firstType = rep->nTypes = 0;
1003f7df2e56Smrg        return 0;
1004f7df2e56Smrg    }
1005f7df2e56Smrg    type = &xkb->map->types[rep->firstType];
1006f7df2e56Smrg    for (i = 0; i < rep->nTypes; i++, type++) {
1007f7df2e56Smrg        len += SIZEOF(xkbKeyTypeWireDesc);
1008f7df2e56Smrg        if (type->map_count > 0) {
1009f7df2e56Smrg            len += (type->map_count * SIZEOF(xkbKTMapEntryWireDesc));
1010f7df2e56Smrg            if (type->preserve)
1011f7df2e56Smrg                len += (type->map_count * SIZEOF(xkbModsWireDesc));
1012f7df2e56Smrg        }
101305b261ecSmrg    }
101405b261ecSmrg    return len;
101505b261ecSmrg}
101605b261ecSmrg
101705b261ecSmrgstatic char *
1018f7df2e56SmrgXkbWriteKeyTypes(XkbDescPtr xkb,
1019f7df2e56Smrg                 xkbGetMapReply * rep, char *buf, ClientPtr client)
102005b261ecSmrg{
1021f7df2e56Smrg    XkbKeyTypePtr type;
1022f7df2e56Smrg    unsigned i;
102305b261ecSmrg    xkbKeyTypeWireDesc *wire;
102405b261ecSmrg
1025f7df2e56Smrg    type = &xkb->map->types[rep->firstType];
1026f7df2e56Smrg    for (i = 0; i < rep->nTypes; i++, type++) {
1027f7df2e56Smrg        register unsigned n;
1028f7df2e56Smrg
1029f7df2e56Smrg        wire = (xkbKeyTypeWireDesc *) buf;
1030f7df2e56Smrg        wire->mask = type->mods.mask;
1031f7df2e56Smrg        wire->realMods = type->mods.real_mods;
1032f7df2e56Smrg        wire->virtualMods = type->mods.vmods;
1033f7df2e56Smrg        wire->numLevels = type->num_levels;
1034f7df2e56Smrg        wire->nMapEntries = type->map_count;
1035f7df2e56Smrg        wire->preserve = (type->preserve != NULL);
1036f7df2e56Smrg        if (client->swapped) {
1037f7df2e56Smrg            swaps(&wire->virtualMods);
1038f7df2e56Smrg        }
1039f7df2e56Smrg
1040f7df2e56Smrg        buf = (char *) &wire[1];
1041f7df2e56Smrg        if (wire->nMapEntries > 0) {
1042f7df2e56Smrg            xkbKTMapEntryWireDesc *ewire;
1043f7df2e56Smrg            XkbKTMapEntryPtr entry;
1044f7df2e56Smrg
1045f7df2e56Smrg            ewire = (xkbKTMapEntryWireDesc *) buf;
1046f7df2e56Smrg            entry = type->map;
1047f7df2e56Smrg            for (n = 0; n < type->map_count; n++, ewire++, entry++) {
1048f7df2e56Smrg                ewire->active = entry->active;
1049f7df2e56Smrg                ewire->mask = entry->mods.mask;
1050f7df2e56Smrg                ewire->level = entry->level;
1051f7df2e56Smrg                ewire->realMods = entry->mods.real_mods;
1052f7df2e56Smrg                ewire->virtualMods = entry->mods.vmods;
1053f7df2e56Smrg                if (client->swapped) {
1054f7df2e56Smrg                    swaps(&ewire->virtualMods);
1055f7df2e56Smrg                }
1056f7df2e56Smrg            }
1057f7df2e56Smrg            buf = (char *) ewire;
1058f7df2e56Smrg            if (type->preserve != NULL) {
1059f7df2e56Smrg                xkbModsWireDesc *pwire;
1060f7df2e56Smrg                XkbModsPtr preserve;
1061f7df2e56Smrg
1062f7df2e56Smrg                pwire = (xkbModsWireDesc *) buf;
1063f7df2e56Smrg                preserve = type->preserve;
1064f7df2e56Smrg                for (n = 0; n < type->map_count; n++, pwire++, preserve++) {
1065f7df2e56Smrg                    pwire->mask = preserve->mask;
1066f7df2e56Smrg                    pwire->realMods = preserve->real_mods;
1067f7df2e56Smrg                    pwire->virtualMods = preserve->vmods;
1068f7df2e56Smrg                    if (client->swapped) {
1069f7df2e56Smrg                        swaps(&pwire->virtualMods);
1070f7df2e56Smrg                    }
1071f7df2e56Smrg                }
1072f7df2e56Smrg                buf = (char *) pwire;
1073f7df2e56Smrg            }
1074f7df2e56Smrg        }
107505b261ecSmrg    }
107605b261ecSmrg    return buf;
107705b261ecSmrg}
107805b261ecSmrg
107905b261ecSmrgstatic int
1080f7df2e56SmrgXkbSizeKeySyms(XkbDescPtr xkb, xkbGetMapReply * rep)
108105b261ecSmrg{
1082f7df2e56Smrg    XkbSymMapPtr symMap;
1083f7df2e56Smrg    unsigned i, len;
1084f7df2e56Smrg    unsigned nSyms, nSymsThisKey;
1085f7df2e56Smrg
1086f7df2e56Smrg    if (((rep->present & XkbKeySymsMask) == 0) || (rep->nKeySyms < 1) ||
1087f7df2e56Smrg        (!xkb) || (!xkb->map) || (!xkb->map->key_sym_map)) {
1088f7df2e56Smrg        rep->present &= ~XkbKeySymsMask;
1089f7df2e56Smrg        rep->firstKeySym = rep->nKeySyms = 0;
1090f7df2e56Smrg        rep->totalSyms = 0;
1091f7df2e56Smrg        return 0;
1092f7df2e56Smrg    }
1093f7df2e56Smrg    len = rep->nKeySyms * SIZEOF(xkbSymMapWireDesc);
109405b261ecSmrg    symMap = &xkb->map->key_sym_map[rep->firstKeySym];
1095f7df2e56Smrg    for (i = nSyms = 0; i < rep->nKeySyms; i++, symMap++) {
1096f7df2e56Smrg        if (symMap->offset != 0) {
1097f7df2e56Smrg            nSymsThisKey = XkbNumGroups(symMap->group_info) * symMap->width;
1098f7df2e56Smrg            nSyms += nSymsThisKey;
1099f7df2e56Smrg        }
1100f7df2e56Smrg    }
1101f7df2e56Smrg    len += nSyms * 4;
1102f7df2e56Smrg    rep->totalSyms = nSyms;
110305b261ecSmrg    return len;
110405b261ecSmrg}
110505b261ecSmrg
110605b261ecSmrgstatic int
1107f7df2e56SmrgXkbSizeVirtualMods(XkbDescPtr xkb, xkbGetMapReply * rep)
110805b261ecSmrg{
1109f7df2e56Smrg    register unsigned i, nMods, bit;
111005b261ecSmrg
1111f7df2e56Smrg    if (((rep->present & XkbVirtualModsMask) == 0) || (rep->virtualMods == 0) ||
1112f7df2e56Smrg        (!xkb) || (!xkb->server)) {
1113f7df2e56Smrg        rep->present &= ~XkbVirtualModsMask;
1114f7df2e56Smrg        rep->virtualMods = 0;
1115f7df2e56Smrg        return 0;
111605b261ecSmrg    }
1117f7df2e56Smrg    for (i = nMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
1118f7df2e56Smrg        if (rep->virtualMods & bit)
1119f7df2e56Smrg            nMods++;
112005b261ecSmrg    }
112105b261ecSmrg    return XkbPaddedSize(nMods);
112205b261ecSmrg}
112305b261ecSmrg
112405b261ecSmrgstatic char *
1125f7df2e56SmrgXkbWriteKeySyms(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1126f7df2e56Smrg                ClientPtr client)
112705b261ecSmrg{
1128f7df2e56Smrg    register KeySym *pSym;
1129f7df2e56Smrg    XkbSymMapPtr symMap;
1130f7df2e56Smrg    xkbSymMapWireDesc *outMap;
1131f7df2e56Smrg    register unsigned i;
113205b261ecSmrg
113305b261ecSmrg    symMap = &xkb->map->key_sym_map[rep->firstKeySym];
1134f7df2e56Smrg    for (i = 0; i < rep->nKeySyms; i++, symMap++) {
1135f7df2e56Smrg        outMap = (xkbSymMapWireDesc *) buf;
1136f7df2e56Smrg        outMap->ktIndex[0] = symMap->kt_index[0];
1137f7df2e56Smrg        outMap->ktIndex[1] = symMap->kt_index[1];
1138f7df2e56Smrg        outMap->ktIndex[2] = symMap->kt_index[2];
1139f7df2e56Smrg        outMap->ktIndex[3] = symMap->kt_index[3];
1140f7df2e56Smrg        outMap->groupInfo = symMap->group_info;
1141f7df2e56Smrg        outMap->width = symMap->width;
1142f7df2e56Smrg        outMap->nSyms = symMap->width * XkbNumGroups(symMap->group_info);
1143f7df2e56Smrg        buf = (char *) &outMap[1];
1144f7df2e56Smrg        if (outMap->nSyms == 0)
1145f7df2e56Smrg            continue;
1146f7df2e56Smrg
1147f7df2e56Smrg        pSym = &xkb->map->syms[symMap->offset];
1148f7df2e56Smrg        memcpy((char *) buf, (char *) pSym, outMap->nSyms * 4);
1149f7df2e56Smrg        if (client->swapped) {
1150f7df2e56Smrg            register int nSyms = outMap->nSyms;
1151f7df2e56Smrg
1152f7df2e56Smrg            swaps(&outMap->nSyms);
1153f7df2e56Smrg            while (nSyms-- > 0) {
1154f7df2e56Smrg                swapl((int *) buf);
1155f7df2e56Smrg                buf += 4;
1156f7df2e56Smrg            }
1157f7df2e56Smrg        }
1158f7df2e56Smrg        else
1159f7df2e56Smrg            buf += outMap->nSyms * 4;
116005b261ecSmrg    }
116105b261ecSmrg    return buf;
116205b261ecSmrg}
116305b261ecSmrg
116405b261ecSmrgstatic int
1165f7df2e56SmrgXkbSizeKeyActions(XkbDescPtr xkb, xkbGetMapReply * rep)
116605b261ecSmrg{
1167f7df2e56Smrg    unsigned i, len, nActs;
1168f7df2e56Smrg    register KeyCode firstKey;
1169f7df2e56Smrg
1170f7df2e56Smrg    if (((rep->present & XkbKeyActionsMask) == 0) || (rep->nKeyActs < 1) ||
1171f7df2e56Smrg        (!xkb) || (!xkb->server) || (!xkb->server->key_acts)) {
1172f7df2e56Smrg        rep->present &= ~XkbKeyActionsMask;
1173f7df2e56Smrg        rep->firstKeyAct = rep->nKeyActs = 0;
1174f7df2e56Smrg        rep->totalActs = 0;
1175f7df2e56Smrg        return 0;
1176f7df2e56Smrg    }
1177f7df2e56Smrg    firstKey = rep->firstKeyAct;
1178f7df2e56Smrg    for (nActs = i = 0; i < rep->nKeyActs; i++) {
1179f7df2e56Smrg        if (xkb->server->key_acts[i + firstKey] != 0)
1180f7df2e56Smrg            nActs += XkbKeyNumActions(xkb, i + firstKey);
1181f7df2e56Smrg    }
1182f7df2e56Smrg    len = XkbPaddedSize(rep->nKeyActs) + (nActs * SIZEOF(xkbActionWireDesc));
1183f7df2e56Smrg    rep->totalActs = nActs;
118405b261ecSmrg    return len;
118505b261ecSmrg}
118605b261ecSmrg
118705b261ecSmrgstatic char *
1188f7df2e56SmrgXkbWriteKeyActions(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1189f7df2e56Smrg                   ClientPtr client)
119005b261ecSmrg{
1191f7df2e56Smrg    unsigned i;
1192f7df2e56Smrg    CARD8 *numDesc;
1193f7df2e56Smrg    XkbAnyAction *actDesc;
1194f7df2e56Smrg
1195f7df2e56Smrg    numDesc = (CARD8 *) buf;
1196f7df2e56Smrg    for (i = 0; i < rep->nKeyActs; i++) {
1197f7df2e56Smrg        if (xkb->server->key_acts[i + rep->firstKeyAct] == 0)
1198f7df2e56Smrg            numDesc[i] = 0;
1199f7df2e56Smrg        else
1200f7df2e56Smrg            numDesc[i] = XkbKeyNumActions(xkb, (i + rep->firstKeyAct));
1201f7df2e56Smrg    }
1202f7df2e56Smrg    buf += XkbPaddedSize(rep->nKeyActs);
1203f7df2e56Smrg
1204f7df2e56Smrg    actDesc = (XkbAnyAction *) buf;
1205f7df2e56Smrg    for (i = 0; i < rep->nKeyActs; i++) {
1206f7df2e56Smrg        if (xkb->server->key_acts[i + rep->firstKeyAct] != 0) {
1207f7df2e56Smrg            unsigned int num;
1208f7df2e56Smrg
1209f7df2e56Smrg            num = XkbKeyNumActions(xkb, (i + rep->firstKeyAct));
1210f7df2e56Smrg            memcpy((char *) actDesc,
1211f7df2e56Smrg                   (char *) XkbKeyActionsPtr(xkb, (i + rep->firstKeyAct)),
1212f7df2e56Smrg                   num * SIZEOF(xkbActionWireDesc));
1213f7df2e56Smrg            actDesc += num;
1214f7df2e56Smrg        }
1215f7df2e56Smrg    }
1216f7df2e56Smrg    buf = (char *) actDesc;
121705b261ecSmrg    return buf;
121805b261ecSmrg}
121905b261ecSmrg
122005b261ecSmrgstatic int
1221f7df2e56SmrgXkbSizeKeyBehaviors(XkbDescPtr xkb, xkbGetMapReply * rep)
122205b261ecSmrg{
1223f7df2e56Smrg    unsigned i, len, nBhvr;
1224f7df2e56Smrg    XkbBehavior *bhv;
1225f7df2e56Smrg
1226f7df2e56Smrg    if (((rep->present & XkbKeyBehaviorsMask) == 0) || (rep->nKeyBehaviors < 1)
1227f7df2e56Smrg        || (!xkb) || (!xkb->server) || (!xkb->server->behaviors)) {
1228f7df2e56Smrg        rep->present &= ~XkbKeyBehaviorsMask;
1229f7df2e56Smrg        rep->firstKeyBehavior = rep->nKeyBehaviors = 0;
1230f7df2e56Smrg        rep->totalKeyBehaviors = 0;
1231f7df2e56Smrg        return 0;
1232f7df2e56Smrg    }
1233f7df2e56Smrg    bhv = &xkb->server->behaviors[rep->firstKeyBehavior];
1234f7df2e56Smrg    for (nBhvr = i = 0; i < rep->nKeyBehaviors; i++, bhv++) {
1235f7df2e56Smrg        if (bhv->type != XkbKB_Default)
1236f7df2e56Smrg            nBhvr++;
1237f7df2e56Smrg    }
1238f7df2e56Smrg    len = nBhvr * SIZEOF(xkbBehaviorWireDesc);
1239f7df2e56Smrg    rep->totalKeyBehaviors = nBhvr;
124005b261ecSmrg    return len;
124105b261ecSmrg}
124205b261ecSmrg
124305b261ecSmrgstatic char *
1244f7df2e56SmrgXkbWriteKeyBehaviors(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1245f7df2e56Smrg                     ClientPtr client)
124605b261ecSmrg{
1247f7df2e56Smrg    unsigned i;
1248f7df2e56Smrg    xkbBehaviorWireDesc *wire;
1249f7df2e56Smrg    XkbBehavior *pBhvr;
1250f7df2e56Smrg
1251f7df2e56Smrg    wire = (xkbBehaviorWireDesc *) buf;
1252f7df2e56Smrg    pBhvr = &xkb->server->behaviors[rep->firstKeyBehavior];
1253f7df2e56Smrg    for (i = 0; i < rep->nKeyBehaviors; i++, pBhvr++) {
1254f7df2e56Smrg        if (pBhvr->type != XkbKB_Default) {
1255f7df2e56Smrg            wire->key = i + rep->firstKeyBehavior;
1256f7df2e56Smrg            wire->type = pBhvr->type;
1257f7df2e56Smrg            wire->data = pBhvr->data;
1258f7df2e56Smrg            wire++;
1259f7df2e56Smrg        }
1260f7df2e56Smrg    }
1261f7df2e56Smrg    buf = (char *) wire;
126205b261ecSmrg    return buf;
126305b261ecSmrg}
126405b261ecSmrg
126505b261ecSmrgstatic int
1266f7df2e56SmrgXkbSizeExplicit(XkbDescPtr xkb, xkbGetMapReply * rep)
126705b261ecSmrg{
1268f7df2e56Smrg    unsigned i, len, nRtrn;
1269f7df2e56Smrg
1270f7df2e56Smrg    if (((rep->present & XkbExplicitComponentsMask) == 0) ||
1271f7df2e56Smrg        (rep->nKeyExplicit < 1) || (!xkb) || (!xkb->server) ||
1272f7df2e56Smrg        (!xkb->server->explicit)) {
1273f7df2e56Smrg        rep->present &= ~XkbExplicitComponentsMask;
1274f7df2e56Smrg        rep->firstKeyExplicit = rep->nKeyExplicit = 0;
1275f7df2e56Smrg        rep->totalKeyExplicit = 0;
1276f7df2e56Smrg        return 0;
1277f7df2e56Smrg    }
1278f7df2e56Smrg    for (nRtrn = i = 0; i < rep->nKeyExplicit; i++) {
1279f7df2e56Smrg        if (xkb->server->explicit[i + rep->firstKeyExplicit] != 0)
1280f7df2e56Smrg            nRtrn++;
1281f7df2e56Smrg    }
1282f7df2e56Smrg    rep->totalKeyExplicit = nRtrn;
1283f7df2e56Smrg    len = XkbPaddedSize(nRtrn * 2);     /* two bytes per non-zero explicit component */
128405b261ecSmrg    return len;
128505b261ecSmrg}
128605b261ecSmrg
128705b261ecSmrgstatic char *
1288f7df2e56SmrgXkbWriteExplicit(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1289f7df2e56Smrg                 ClientPtr client)
129005b261ecSmrg{
1291f7df2e56Smrg    unsigned i;
1292f7df2e56Smrg    char *start;
1293f7df2e56Smrg    unsigned char *pExp;
1294f7df2e56Smrg
1295f7df2e56Smrg    start = buf;
1296f7df2e56Smrg    pExp = &xkb->server->explicit[rep->firstKeyExplicit];
1297f7df2e56Smrg    for (i = 0; i < rep->nKeyExplicit; i++, pExp++) {
1298f7df2e56Smrg        if (*pExp != 0) {
1299f7df2e56Smrg            *buf++ = i + rep->firstKeyExplicit;
1300f7df2e56Smrg            *buf++ = *pExp;
1301f7df2e56Smrg        }
1302f7df2e56Smrg    }
1303f7df2e56Smrg    i = XkbPaddedSize(buf - start) - (buf - start);     /* pad to word boundary */
1304f7df2e56Smrg    return buf + i;
130505b261ecSmrg}
130605b261ecSmrg
130705b261ecSmrgstatic int
1308f7df2e56SmrgXkbSizeModifierMap(XkbDescPtr xkb, xkbGetMapReply * rep)
130905b261ecSmrg{
1310f7df2e56Smrg    unsigned i, len, nRtrn;
131105b261ecSmrg
1312f7df2e56Smrg    if (((rep->present & XkbModifierMapMask) == 0) || (rep->nModMapKeys < 1) ||
1313f7df2e56Smrg        (!xkb) || (!xkb->map) || (!xkb->map->modmap)) {
1314f7df2e56Smrg        rep->present &= ~XkbModifierMapMask;
1315f7df2e56Smrg        rep->firstModMapKey = rep->nModMapKeys = 0;
1316f7df2e56Smrg        rep->totalModMapKeys = 0;
1317f7df2e56Smrg        return 0;
131805b261ecSmrg    }
1319f7df2e56Smrg    for (nRtrn = i = 0; i < rep->nModMapKeys; i++) {
1320f7df2e56Smrg        if (xkb->map->modmap[i + rep->firstModMapKey] != 0)
1321f7df2e56Smrg            nRtrn++;
132205b261ecSmrg    }
1323f7df2e56Smrg    rep->totalModMapKeys = nRtrn;
1324f7df2e56Smrg    len = XkbPaddedSize(nRtrn * 2);     /* two bytes per non-zero modmap component */
132505b261ecSmrg    return len;
132605b261ecSmrg}
132705b261ecSmrg
132805b261ecSmrgstatic char *
1329f7df2e56SmrgXkbWriteModifierMap(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1330f7df2e56Smrg                    ClientPtr client)
133105b261ecSmrg{
1332f7df2e56Smrg    unsigned i;
1333f7df2e56Smrg    char *start;
1334f7df2e56Smrg    unsigned char *pMap;
1335f7df2e56Smrg
1336f7df2e56Smrg    start = buf;
1337f7df2e56Smrg    pMap = &xkb->map->modmap[rep->firstModMapKey];
1338f7df2e56Smrg    for (i = 0; i < rep->nModMapKeys; i++, pMap++) {
1339f7df2e56Smrg        if (*pMap != 0) {
1340f7df2e56Smrg            *buf++ = i + rep->firstModMapKey;
1341f7df2e56Smrg            *buf++ = *pMap;
1342f7df2e56Smrg        }
1343f7df2e56Smrg    }
1344f7df2e56Smrg    i = XkbPaddedSize(buf - start) - (buf - start);     /* pad to word boundary */
1345f7df2e56Smrg    return buf + i;
134605b261ecSmrg}
134705b261ecSmrg
134805b261ecSmrgstatic int
1349f7df2e56SmrgXkbSizeVirtualModMap(XkbDescPtr xkb, xkbGetMapReply * rep)
135005b261ecSmrg{
1351f7df2e56Smrg    unsigned i, len, nRtrn;
135205b261ecSmrg
1353f7df2e56Smrg    if (((rep->present & XkbVirtualModMapMask) == 0) || (rep->nVModMapKeys < 1)
1354f7df2e56Smrg        || (!xkb) || (!xkb->server) || (!xkb->server->vmodmap)) {
1355f7df2e56Smrg        rep->present &= ~XkbVirtualModMapMask;
1356f7df2e56Smrg        rep->firstVModMapKey = rep->nVModMapKeys = 0;
1357f7df2e56Smrg        rep->totalVModMapKeys = 0;
1358f7df2e56Smrg        return 0;
135905b261ecSmrg    }
1360f7df2e56Smrg    for (nRtrn = i = 0; i < rep->nVModMapKeys; i++) {
1361f7df2e56Smrg        if (xkb->server->vmodmap[i + rep->firstVModMapKey] != 0)
1362f7df2e56Smrg            nRtrn++;
136305b261ecSmrg    }
1364f7df2e56Smrg    rep->totalVModMapKeys = nRtrn;
1365f7df2e56Smrg    len = nRtrn * SIZEOF(xkbVModMapWireDesc);
136605b261ecSmrg    return len;
136705b261ecSmrg}
136805b261ecSmrg
136905b261ecSmrgstatic char *
1370f7df2e56SmrgXkbWriteVirtualModMap(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1371f7df2e56Smrg                      ClientPtr client)
137205b261ecSmrg{
1373f7df2e56Smrg    unsigned i;
1374f7df2e56Smrg    xkbVModMapWireDesc *wire;
1375f7df2e56Smrg    unsigned short *pMap;
1376f7df2e56Smrg
1377f7df2e56Smrg    wire = (xkbVModMapWireDesc *) buf;
1378f7df2e56Smrg    pMap = &xkb->server->vmodmap[rep->firstVModMapKey];
1379f7df2e56Smrg    for (i = 0; i < rep->nVModMapKeys; i++, pMap++) {
1380f7df2e56Smrg        if (*pMap != 0) {
1381f7df2e56Smrg            wire->key = i + rep->firstVModMapKey;
1382f7df2e56Smrg            wire->vmods = *pMap;
1383f7df2e56Smrg            wire++;
1384f7df2e56Smrg        }
1385f7df2e56Smrg    }
1386f7df2e56Smrg    return (char *) wire;
138705b261ecSmrg}
138805b261ecSmrg
138905b261ecSmrgstatic Status
1390f7df2e56SmrgXkbComputeGetMapReplySize(XkbDescPtr xkb, xkbGetMapReply * rep)
139105b261ecSmrg{
1392f7df2e56Smrg    int len;
1393f7df2e56Smrg
1394f7df2e56Smrg    rep->minKeyCode = xkb->min_key_code;
1395f7df2e56Smrg    rep->maxKeyCode = xkb->max_key_code;
1396f7df2e56Smrg    len = XkbSizeKeyTypes(xkb, rep);
1397f7df2e56Smrg    len += XkbSizeKeySyms(xkb, rep);
1398f7df2e56Smrg    len += XkbSizeKeyActions(xkb, rep);
1399f7df2e56Smrg    len += XkbSizeKeyBehaviors(xkb, rep);
1400f7df2e56Smrg    len += XkbSizeVirtualMods(xkb, rep);
1401f7df2e56Smrg    len += XkbSizeExplicit(xkb, rep);
1402f7df2e56Smrg    len += XkbSizeModifierMap(xkb, rep);
1403f7df2e56Smrg    len += XkbSizeVirtualModMap(xkb, rep);
1404f7df2e56Smrg    rep->length += (len / 4);
140505b261ecSmrg    return Success;
140605b261ecSmrg}
140705b261ecSmrg
140805b261ecSmrgstatic int
1409f7df2e56SmrgXkbSendMap(ClientPtr client, XkbDescPtr xkb, xkbGetMapReply * rep)
141005b261ecSmrg{
1411f7df2e56Smrg    unsigned i, len;
1412f7df2e56Smrg    char *desc, *start;
141305b261ecSmrg
1414f7df2e56Smrg    len = (rep->length * 4) - (SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply));
1415f7df2e56Smrg    start = desc = calloc(1, len);
141605b261ecSmrg    if (!start)
1417f7df2e56Smrg        return BadAlloc;
1418f7df2e56Smrg    if (rep->nTypes > 0)
1419f7df2e56Smrg        desc = XkbWriteKeyTypes(xkb, rep, desc, client);
1420f7df2e56Smrg    if (rep->nKeySyms > 0)
1421f7df2e56Smrg        desc = XkbWriteKeySyms(xkb, rep, desc, client);
1422f7df2e56Smrg    if (rep->nKeyActs > 0)
1423f7df2e56Smrg        desc = XkbWriteKeyActions(xkb, rep, desc, client);
1424f7df2e56Smrg    if (rep->totalKeyBehaviors > 0)
1425f7df2e56Smrg        desc = XkbWriteKeyBehaviors(xkb, rep, desc, client);
1426f7df2e56Smrg    if (rep->virtualMods) {
1427f7df2e56Smrg        register int sz, bit;
1428f7df2e56Smrg
1429f7df2e56Smrg        for (i = sz = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
1430f7df2e56Smrg            if (rep->virtualMods & bit) {
1431f7df2e56Smrg                desc[sz++] = xkb->server->vmods[i];
1432f7df2e56Smrg            }
1433f7df2e56Smrg        }
1434f7df2e56Smrg        desc += XkbPaddedSize(sz);
1435f7df2e56Smrg    }
1436f7df2e56Smrg    if (rep->totalKeyExplicit > 0)
1437f7df2e56Smrg        desc = XkbWriteExplicit(xkb, rep, desc, client);
1438f7df2e56Smrg    if (rep->totalModMapKeys > 0)
1439f7df2e56Smrg        desc = XkbWriteModifierMap(xkb, rep, desc, client);
1440f7df2e56Smrg    if (rep->totalVModMapKeys > 0)
1441f7df2e56Smrg        desc = XkbWriteVirtualModMap(xkb, rep, desc, client);
1442f7df2e56Smrg    if ((desc - start) != (len)) {
1443f7df2e56Smrg        ErrorF
1444f7df2e56Smrg            ("[xkb] BOGUS LENGTH in write keyboard desc, expected %d, got %ld\n",
1445f7df2e56Smrg             len, (unsigned long) (desc - start));
144605b261ecSmrg    }
144705b261ecSmrg    if (client->swapped) {
1448f7df2e56Smrg        swaps(&rep->sequenceNumber);
1449f7df2e56Smrg        swapl(&rep->length);
1450f7df2e56Smrg        swaps(&rep->present);
1451f7df2e56Smrg        swaps(&rep->totalSyms);
1452f7df2e56Smrg        swaps(&rep->totalActs);
1453f7df2e56Smrg    }
1454f7df2e56Smrg    WriteToClient(client, (i = SIZEOF(xkbGetMapReply)), rep);
145505b261ecSmrg    WriteToClient(client, len, start);
1456f7df2e56Smrg    free((char *) start);
14576747b715Smrg    return Success;
145805b261ecSmrg}
145905b261ecSmrg
146005b261ecSmrgint
146105b261ecSmrgProcXkbGetMap(ClientPtr client)
146205b261ecSmrg{
1463f7df2e56Smrg    DeviceIntPtr dev;
1464f7df2e56Smrg    xkbGetMapReply rep;
1465f7df2e56Smrg    XkbDescRec *xkb;
1466f7df2e56Smrg    int n, status;
146705b261ecSmrg
146805b261ecSmrg    REQUEST(xkbGetMapReq);
146905b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetMapReq);
1470f7df2e56Smrg
1471f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
1472f7df2e56Smrg        return BadAccess;
147305b261ecSmrg
14744642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
1475f7df2e56Smrg    CHK_MASK_OVERLAP(0x01, stuff->full, stuff->partial);
1476f7df2e56Smrg    CHK_MASK_LEGAL(0x02, stuff->full, XkbAllMapComponentsMask);
1477f7df2e56Smrg    CHK_MASK_LEGAL(0x03, stuff->partial, XkbAllMapComponentsMask);
1478f7df2e56Smrg
1479f7df2e56Smrg    xkb = dev->key->xkbInfo->desc;
1480f7df2e56Smrg    rep = (xkbGetMapReply) {
1481f7df2e56Smrg        .type = X_Reply,
1482f7df2e56Smrg        .deviceID = dev->id,
1483f7df2e56Smrg        .sequenceNumber = client->sequence,
1484f7df2e56Smrg        .length = (SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply)) >> 2,
1485f7df2e56Smrg        .present = stuff->partial | stuff->full,
1486f7df2e56Smrg        .minKeyCode = xkb->min_key_code,
1487f7df2e56Smrg        .maxKeyCode = xkb->max_key_code
1488f7df2e56Smrg    };
1489f7df2e56Smrg
1490f7df2e56Smrg    if (stuff->full & XkbKeyTypesMask) {
1491f7df2e56Smrg        rep.firstType = 0;
1492f7df2e56Smrg        rep.nTypes = xkb->map->num_types;
1493f7df2e56Smrg    }
1494f7df2e56Smrg    else if (stuff->partial & XkbKeyTypesMask) {
1495f7df2e56Smrg        if (((unsigned) stuff->firstType + stuff->nTypes) > xkb->map->num_types) {
1496f7df2e56Smrg            client->errorValue = _XkbErrCode4(0x04, xkb->map->num_types,
1497f7df2e56Smrg                                              stuff->firstType, stuff->nTypes);
1498f7df2e56Smrg            return BadValue;
1499f7df2e56Smrg        }
1500f7df2e56Smrg        rep.firstType = stuff->firstType;
1501f7df2e56Smrg        rep.nTypes = stuff->nTypes;
1502f7df2e56Smrg    }
1503f7df2e56Smrg    else
1504f7df2e56Smrg        rep.nTypes = 0;
150505b261ecSmrg    rep.totalTypes = xkb->map->num_types;
150605b261ecSmrg
1507f7df2e56Smrg    n = XkbNumKeys(xkb);
1508f7df2e56Smrg    if (stuff->full & XkbKeySymsMask) {
1509f7df2e56Smrg        rep.firstKeySym = xkb->min_key_code;
1510f7df2e56Smrg        rep.nKeySyms = n;
1511f7df2e56Smrg    }
1512f7df2e56Smrg    else if (stuff->partial & XkbKeySymsMask) {
1513f7df2e56Smrg        CHK_KEY_RANGE(0x05, stuff->firstKeySym, stuff->nKeySyms, xkb);
1514f7df2e56Smrg        rep.firstKeySym = stuff->firstKeySym;
1515f7df2e56Smrg        rep.nKeySyms = stuff->nKeySyms;
1516f7df2e56Smrg    }
1517f7df2e56Smrg    else
1518f7df2e56Smrg        rep.nKeySyms = 0;
1519f7df2e56Smrg    rep.totalSyms = 0;
1520f7df2e56Smrg
1521f7df2e56Smrg    if (stuff->full & XkbKeyActionsMask) {
1522f7df2e56Smrg        rep.firstKeyAct = xkb->min_key_code;
1523f7df2e56Smrg        rep.nKeyActs = n;
1524f7df2e56Smrg    }
1525f7df2e56Smrg    else if (stuff->partial & XkbKeyActionsMask) {
1526f7df2e56Smrg        CHK_KEY_RANGE(0x07, stuff->firstKeyAct, stuff->nKeyActs, xkb);
1527f7df2e56Smrg        rep.firstKeyAct = stuff->firstKeyAct;
1528f7df2e56Smrg        rep.nKeyActs = stuff->nKeyActs;
1529f7df2e56Smrg    }
1530f7df2e56Smrg    else
1531f7df2e56Smrg        rep.nKeyActs = 0;
1532f7df2e56Smrg    rep.totalActs = 0;
1533f7df2e56Smrg
1534f7df2e56Smrg    if (stuff->full & XkbKeyBehaviorsMask) {
1535f7df2e56Smrg        rep.firstKeyBehavior = xkb->min_key_code;
1536f7df2e56Smrg        rep.nKeyBehaviors = n;
1537f7df2e56Smrg    }
1538f7df2e56Smrg    else if (stuff->partial & XkbKeyBehaviorsMask) {
1539f7df2e56Smrg        CHK_KEY_RANGE(0x09, stuff->firstKeyBehavior, stuff->nKeyBehaviors, xkb);
1540f7df2e56Smrg        rep.firstKeyBehavior = stuff->firstKeyBehavior;
1541f7df2e56Smrg        rep.nKeyBehaviors = stuff->nKeyBehaviors;
1542f7df2e56Smrg    }
1543f7df2e56Smrg    else
1544f7df2e56Smrg        rep.nKeyBehaviors = 0;
1545f7df2e56Smrg    rep.totalKeyBehaviors = 0;
1546f7df2e56Smrg
1547f7df2e56Smrg    if (stuff->full & XkbVirtualModsMask)
1548f7df2e56Smrg        rep.virtualMods = ~0;
1549f7df2e56Smrg    else if (stuff->partial & XkbVirtualModsMask)
1550f7df2e56Smrg        rep.virtualMods = stuff->virtualMods;
1551f7df2e56Smrg
1552f7df2e56Smrg    if (stuff->full & XkbExplicitComponentsMask) {
1553f7df2e56Smrg        rep.firstKeyExplicit = xkb->min_key_code;
1554f7df2e56Smrg        rep.nKeyExplicit = n;
1555f7df2e56Smrg    }
1556f7df2e56Smrg    else if (stuff->partial & XkbExplicitComponentsMask) {
1557f7df2e56Smrg        CHK_KEY_RANGE(0x0B, stuff->firstKeyExplicit, stuff->nKeyExplicit, xkb);
1558f7df2e56Smrg        rep.firstKeyExplicit = stuff->firstKeyExplicit;
1559f7df2e56Smrg        rep.nKeyExplicit = stuff->nKeyExplicit;
1560f7df2e56Smrg    }
1561f7df2e56Smrg    else
1562f7df2e56Smrg        rep.nKeyExplicit = 0;
1563f7df2e56Smrg    rep.totalKeyExplicit = 0;
1564f7df2e56Smrg
1565f7df2e56Smrg    if (stuff->full & XkbModifierMapMask) {
1566f7df2e56Smrg        rep.firstModMapKey = xkb->min_key_code;
1567f7df2e56Smrg        rep.nModMapKeys = n;
1568f7df2e56Smrg    }
1569f7df2e56Smrg    else if (stuff->partial & XkbModifierMapMask) {
1570f7df2e56Smrg        CHK_KEY_RANGE(0x0D, stuff->firstModMapKey, stuff->nModMapKeys, xkb);
1571f7df2e56Smrg        rep.firstModMapKey = stuff->firstModMapKey;
1572f7df2e56Smrg        rep.nModMapKeys = stuff->nModMapKeys;
1573f7df2e56Smrg    }
1574f7df2e56Smrg    else
1575f7df2e56Smrg        rep.nModMapKeys = 0;
1576f7df2e56Smrg    rep.totalModMapKeys = 0;
1577f7df2e56Smrg
1578f7df2e56Smrg    if (stuff->full & XkbVirtualModMapMask) {
1579f7df2e56Smrg        rep.firstVModMapKey = xkb->min_key_code;
1580f7df2e56Smrg        rep.nVModMapKeys = n;
1581f7df2e56Smrg    }
1582f7df2e56Smrg    else if (stuff->partial & XkbVirtualModMapMask) {
1583f7df2e56Smrg        CHK_KEY_RANGE(0x0F, stuff->firstVModMapKey, stuff->nVModMapKeys, xkb);
1584f7df2e56Smrg        rep.firstVModMapKey = stuff->firstVModMapKey;
1585f7df2e56Smrg        rep.nVModMapKeys = stuff->nVModMapKeys;
1586f7df2e56Smrg    }
1587f7df2e56Smrg    else
1588f7df2e56Smrg        rep.nVModMapKeys = 0;
1589f7df2e56Smrg    rep.totalVModMapKeys = 0;
1590f7df2e56Smrg
1591f7df2e56Smrg    if ((status = XkbComputeGetMapReplySize(xkb, &rep)) != Success)
1592f7df2e56Smrg        return status;
1593f7df2e56Smrg    return XkbSendMap(client, xkb, &rep);
159405b261ecSmrg}
159505b261ecSmrg
159605b261ecSmrg/***====================================================================***/
159705b261ecSmrg
159805b261ecSmrgstatic int
1599f7df2e56SmrgCheckKeyTypes(ClientPtr client,
1600f7df2e56Smrg              XkbDescPtr xkb,
1601f7df2e56Smrg              xkbSetMapReq * req,
1602f7df2e56Smrg              xkbKeyTypeWireDesc ** wireRtrn,
16035a112b11Smrg              int *nMapsRtrn, CARD8 *mapWidthRtrn, Bool doswap)
160405b261ecSmrg{
1605f7df2e56Smrg    unsigned nMaps;
1606f7df2e56Smrg    register unsigned i, n;
1607f7df2e56Smrg    register CARD8 *map;
1608f7df2e56Smrg    register xkbKeyTypeWireDesc *wire = *wireRtrn;
1609f7df2e56Smrg
1610f7df2e56Smrg    if (req->firstType > ((unsigned) xkb->map->num_types)) {
1611f7df2e56Smrg        *nMapsRtrn = _XkbErrCode3(0x01, req->firstType, xkb->map->num_types);
1612f7df2e56Smrg        return 0;
1613f7df2e56Smrg    }
1614f7df2e56Smrg    if (req->flags & XkbSetMapResizeTypes) {
1615f7df2e56Smrg        nMaps = req->firstType + req->nTypes;
1616f7df2e56Smrg        if (nMaps < XkbNumRequiredTypes) {      /* canonical types must be there */
1617f7df2e56Smrg            *nMapsRtrn = _XkbErrCode4(0x02, req->firstType, req->nTypes, 4);
1618f7df2e56Smrg            return 0;
1619f7df2e56Smrg        }
1620f7df2e56Smrg    }
1621f7df2e56Smrg    else if (req->present & XkbKeyTypesMask) {
1622f7df2e56Smrg        nMaps = xkb->map->num_types;
1623f7df2e56Smrg        if ((req->firstType + req->nTypes) > nMaps) {
1624f7df2e56Smrg            *nMapsRtrn = req->firstType + req->nTypes;
1625f7df2e56Smrg            return 0;
1626f7df2e56Smrg        }
162705b261ecSmrg    }
162805b261ecSmrg    else {
1629f7df2e56Smrg        *nMapsRtrn = xkb->map->num_types;
1630f7df2e56Smrg        for (i = 0; i < xkb->map->num_types; i++) {
1631f7df2e56Smrg            mapWidthRtrn[i] = xkb->map->types[i].num_levels;
1632f7df2e56Smrg        }
1633f7df2e56Smrg        return 1;
1634f7df2e56Smrg    }
1635f7df2e56Smrg
1636f7df2e56Smrg    for (i = 0; i < req->firstType; i++) {
1637f7df2e56Smrg        mapWidthRtrn[i] = xkb->map->types[i].num_levels;
1638f7df2e56Smrg    }
1639f7df2e56Smrg    for (i = 0; i < req->nTypes; i++) {
1640f7df2e56Smrg        unsigned width;
1641f7df2e56Smrg
16425a112b11Smrg        if (client->swapped && doswap) {
1643f7df2e56Smrg            swaps(&wire->virtualMods);
1644f7df2e56Smrg        }
1645f7df2e56Smrg        n = i + req->firstType;
1646f7df2e56Smrg        width = wire->numLevels;
1647f7df2e56Smrg        if (width < 1) {
1648f7df2e56Smrg            *nMapsRtrn = _XkbErrCode3(0x04, n, width);
1649f7df2e56Smrg            return 0;
1650f7df2e56Smrg        }
1651f7df2e56Smrg        else if ((n == XkbOneLevelIndex) && (width != 1)) {     /* must be width 1 */
1652f7df2e56Smrg            *nMapsRtrn = _XkbErrCode3(0x05, n, width);
1653f7df2e56Smrg            return 0;
1654f7df2e56Smrg        }
1655f7df2e56Smrg        else if ((width != 2) &&
1656f7df2e56Smrg                 ((n == XkbTwoLevelIndex) || (n == XkbKeypadIndex) ||
1657f7df2e56Smrg                  (n == XkbAlphabeticIndex))) {
1658f7df2e56Smrg            /* TWO_LEVEL, ALPHABETIC and KEYPAD must be width 2 */
1659f7df2e56Smrg            *nMapsRtrn = _XkbErrCode3(0x05, n, width);
1660f7df2e56Smrg            return 0;
1661f7df2e56Smrg        }
1662f7df2e56Smrg        if (wire->nMapEntries > 0) {
1663f7df2e56Smrg            xkbKTSetMapEntryWireDesc *mapWire;
1664f7df2e56Smrg            xkbModsWireDesc *preWire;
1665f7df2e56Smrg
1666f7df2e56Smrg            mapWire = (xkbKTSetMapEntryWireDesc *) &wire[1];
1667f7df2e56Smrg            preWire = (xkbModsWireDesc *) &mapWire[wire->nMapEntries];
1668f7df2e56Smrg            for (n = 0; n < wire->nMapEntries; n++) {
16695a112b11Smrg                if (client->swapped && doswap) {
1670f7df2e56Smrg                    swaps(&mapWire[n].virtualMods);
1671f7df2e56Smrg                }
1672f7df2e56Smrg                if (mapWire[n].realMods & (~wire->realMods)) {
1673f7df2e56Smrg                    *nMapsRtrn = _XkbErrCode4(0x06, n, mapWire[n].realMods,
1674f7df2e56Smrg                                              wire->realMods);
1675f7df2e56Smrg                    return 0;
1676f7df2e56Smrg                }
1677f7df2e56Smrg                if (mapWire[n].virtualMods & (~wire->virtualMods)) {
1678f7df2e56Smrg                    *nMapsRtrn = _XkbErrCode3(0x07, n, mapWire[n].virtualMods);
1679f7df2e56Smrg                    return 0;
1680f7df2e56Smrg                }
1681f7df2e56Smrg                if (mapWire[n].level >= wire->numLevels) {
1682f7df2e56Smrg                    *nMapsRtrn = _XkbErrCode4(0x08, n, wire->numLevels,
1683f7df2e56Smrg                                              mapWire[n].level);
1684f7df2e56Smrg                    return 0;
1685f7df2e56Smrg                }
1686f7df2e56Smrg                if (wire->preserve) {
16875a112b11Smrg                    if (client->swapped && doswap) {
1688f7df2e56Smrg                        swaps(&preWire[n].virtualMods);
1689f7df2e56Smrg                    }
1690f7df2e56Smrg                    if (preWire[n].realMods & (~mapWire[n].realMods)) {
1691f7df2e56Smrg                        *nMapsRtrn = _XkbErrCode4(0x09, n, preWire[n].realMods,
1692f7df2e56Smrg                                                  mapWire[n].realMods);
1693f7df2e56Smrg                        return 0;
1694f7df2e56Smrg                    }
1695f7df2e56Smrg                    if (preWire[n].virtualMods & (~mapWire[n].virtualMods)) {
1696f7df2e56Smrg                        *nMapsRtrn =
1697f7df2e56Smrg                            _XkbErrCode3(0x0a, n, preWire[n].virtualMods);
1698f7df2e56Smrg                        return 0;
1699f7df2e56Smrg                    }
1700f7df2e56Smrg                }
1701f7df2e56Smrg            }
1702f7df2e56Smrg            if (wire->preserve)
1703f7df2e56Smrg                map = (CARD8 *) &preWire[wire->nMapEntries];
1704f7df2e56Smrg            else
1705f7df2e56Smrg                map = (CARD8 *) &mapWire[wire->nMapEntries];
1706f7df2e56Smrg        }
1707f7df2e56Smrg        else
1708f7df2e56Smrg            map = (CARD8 *) &wire[1];
1709f7df2e56Smrg        mapWidthRtrn[i + req->firstType] = wire->numLevels;
1710f7df2e56Smrg        wire = (xkbKeyTypeWireDesc *) map;
1711f7df2e56Smrg    }
1712f7df2e56Smrg    for (i = req->firstType + req->nTypes; i < nMaps; i++) {
1713f7df2e56Smrg        mapWidthRtrn[i] = xkb->map->types[i].num_levels;
171405b261ecSmrg    }
171505b261ecSmrg    *nMapsRtrn = nMaps;
171605b261ecSmrg    *wireRtrn = wire;
171705b261ecSmrg    return 1;
171805b261ecSmrg}
171905b261ecSmrg
172005b261ecSmrgstatic int
1721f7df2e56SmrgCheckKeySyms(ClientPtr client,
1722f7df2e56Smrg             XkbDescPtr xkb,
1723f7df2e56Smrg             xkbSetMapReq * req,
1724f7df2e56Smrg             int nTypes,
1725f7df2e56Smrg             CARD8 *mapWidths,
17265a112b11Smrg             CARD16 *symsPerKey, xkbSymMapWireDesc ** wireRtrn, int *errorRtrn, Bool doswap)
172705b261ecSmrg{
1728f7df2e56Smrg    register unsigned i;
1729f7df2e56Smrg    XkbSymMapPtr map;
1730f7df2e56Smrg    xkbSymMapWireDesc *wire = *wireRtrn;
1731f7df2e56Smrg
1732f7df2e56Smrg    if (!(XkbKeySymsMask & req->present))
1733f7df2e56Smrg        return 1;
1734f7df2e56Smrg    CHK_REQ_KEY_RANGE2(0x11, req->firstKeySym, req->nKeySyms, req, (*errorRtrn),
1735f7df2e56Smrg                       0);
1736f7df2e56Smrg    for (i = 0; i < req->nKeySyms; i++) {
1737f7df2e56Smrg        KeySym *pSyms;
1738f7df2e56Smrg        register unsigned nG;
1739f7df2e56Smrg
17405a112b11Smrg        if (client->swapped && doswap) {
1741f7df2e56Smrg            swaps(&wire->nSyms);
1742f7df2e56Smrg        }
1743f7df2e56Smrg        nG = XkbNumGroups(wire->groupInfo);
1744f7df2e56Smrg        if (nG > XkbNumKbdGroups) {
1745f7df2e56Smrg            *errorRtrn = _XkbErrCode3(0x14, i + req->firstKeySym, nG);
1746f7df2e56Smrg            return 0;
1747f7df2e56Smrg        }
1748f7df2e56Smrg        if (nG > 0) {
1749f7df2e56Smrg            register int g, w;
1750f7df2e56Smrg
1751f7df2e56Smrg            for (g = w = 0; g < nG; g++) {
1752f7df2e56Smrg                if (wire->ktIndex[g] >= (unsigned) nTypes) {
1753f7df2e56Smrg                    *errorRtrn = _XkbErrCode4(0x15, i + req->firstKeySym, g,
1754f7df2e56Smrg                                              wire->ktIndex[g]);
1755f7df2e56Smrg                    return 0;
1756f7df2e56Smrg                }
1757f7df2e56Smrg                if (mapWidths[wire->ktIndex[g]] > w)
1758f7df2e56Smrg                    w = mapWidths[wire->ktIndex[g]];
1759f7df2e56Smrg            }
1760f7df2e56Smrg            if (wire->width != w) {
1761f7df2e56Smrg                *errorRtrn =
1762f7df2e56Smrg                    _XkbErrCode3(0x16, i + req->firstKeySym, wire->width);
1763f7df2e56Smrg                return 0;
1764f7df2e56Smrg            }
1765f7df2e56Smrg            w *= nG;
1766f7df2e56Smrg            symsPerKey[i + req->firstKeySym] = w;
1767f7df2e56Smrg            if (w != wire->nSyms) {
1768f7df2e56Smrg                *errorRtrn =
1769f7df2e56Smrg                    _XkbErrCode4(0x16, i + req->firstKeySym, wire->nSyms, w);
1770f7df2e56Smrg                return 0;
1771f7df2e56Smrg            }
1772f7df2e56Smrg        }
1773f7df2e56Smrg        else if (wire->nSyms != 0) {
1774f7df2e56Smrg            *errorRtrn = _XkbErrCode3(0x17, i + req->firstKeySym, wire->nSyms);
1775f7df2e56Smrg            return 0;
1776f7df2e56Smrg        }
1777f7df2e56Smrg        pSyms = (KeySym *) &wire[1];
1778f7df2e56Smrg        wire = (xkbSymMapWireDesc *) &pSyms[wire->nSyms];
177905b261ecSmrg    }
178005b261ecSmrg
178105b261ecSmrg    map = &xkb->map->key_sym_map[i];
1782f7df2e56Smrg    for (; i <= (unsigned) xkb->max_key_code; i++, map++) {
1783f7df2e56Smrg        register int g, nG, w;
1784f7df2e56Smrg
1785f7df2e56Smrg        nG = XkbKeyNumGroups(xkb, i);
1786f7df2e56Smrg        for (w = g = 0; g < nG; g++) {
1787f7df2e56Smrg            if (map->kt_index[g] >= (unsigned) nTypes) {
1788f7df2e56Smrg                *errorRtrn = _XkbErrCode4(0x18, i, g, map->kt_index[g]);
1789f7df2e56Smrg                return 0;
1790f7df2e56Smrg            }
1791f7df2e56Smrg            if (mapWidths[map->kt_index[g]] > w)
1792f7df2e56Smrg                w = mapWidths[map->kt_index[g]];
1793f7df2e56Smrg        }
1794f7df2e56Smrg        symsPerKey[i] = w * nG;
179505b261ecSmrg    }
179605b261ecSmrg    *wireRtrn = wire;
179705b261ecSmrg    return 1;
179805b261ecSmrg}
179905b261ecSmrg
180005b261ecSmrgstatic int
1801f7df2e56SmrgCheckKeyActions(XkbDescPtr xkb,
1802f7df2e56Smrg                xkbSetMapReq * req,
1803f7df2e56Smrg                int nTypes,
1804f7df2e56Smrg                CARD8 *mapWidths,
1805f7df2e56Smrg                CARD16 *symsPerKey, CARD8 **wireRtrn, int *nActsRtrn)
180605b261ecSmrg{
1807f7df2e56Smrg    int nActs;
1808f7df2e56Smrg    CARD8 *wire = *wireRtrn;
1809f7df2e56Smrg    register unsigned i;
1810f7df2e56Smrg
1811f7df2e56Smrg    if (!(XkbKeyActionsMask & req->present))
1812f7df2e56Smrg        return 1;
1813f7df2e56Smrg    CHK_REQ_KEY_RANGE2(0x21, req->firstKeyAct, req->nKeyActs, req, (*nActsRtrn),
1814f7df2e56Smrg                       0);
1815f7df2e56Smrg    for (nActs = i = 0; i < req->nKeyActs; i++) {
1816f7df2e56Smrg        if (wire[0] != 0) {
1817f7df2e56Smrg            if (wire[0] == symsPerKey[i + req->firstKeyAct])
1818f7df2e56Smrg                nActs += wire[0];
1819f7df2e56Smrg            else {
1820f7df2e56Smrg                *nActsRtrn = _XkbErrCode3(0x23, i + req->firstKeyAct, wire[0]);
1821f7df2e56Smrg                return 0;
1822f7df2e56Smrg            }
1823f7df2e56Smrg        }
1824f7df2e56Smrg        wire++;
1825f7df2e56Smrg    }
1826f7df2e56Smrg    if (req->nKeyActs % 4)
1827f7df2e56Smrg        wire += 4 - (req->nKeyActs % 4);
1828f7df2e56Smrg    *wireRtrn = (CARD8 *) (((XkbAnyAction *) wire) + nActs);
182905b261ecSmrg    *nActsRtrn = nActs;
183005b261ecSmrg    return 1;
183105b261ecSmrg}
183205b261ecSmrg
183305b261ecSmrgstatic int
1834f7df2e56SmrgCheckKeyBehaviors(XkbDescPtr xkb,
1835f7df2e56Smrg                  xkbSetMapReq * req,
1836f7df2e56Smrg                  xkbBehaviorWireDesc ** wireRtrn, int *errorRtrn)
183705b261ecSmrg{
1838f7df2e56Smrg    register xkbBehaviorWireDesc *wire = *wireRtrn;
1839f7df2e56Smrg    register XkbServerMapPtr server = xkb->server;
1840f7df2e56Smrg    register unsigned i;
1841f7df2e56Smrg    unsigned first, last;
1842f7df2e56Smrg
1843f7df2e56Smrg    if (((req->present & XkbKeyBehaviorsMask) == 0) || (req->nKeyBehaviors < 1)) {
1844f7df2e56Smrg        req->present &= ~XkbKeyBehaviorsMask;
1845f7df2e56Smrg        req->nKeyBehaviors = 0;
1846f7df2e56Smrg        return 1;
1847f7df2e56Smrg    }
1848f7df2e56Smrg    first = req->firstKeyBehavior;
1849f7df2e56Smrg    last = req->firstKeyBehavior + req->nKeyBehaviors - 1;
1850f7df2e56Smrg    if (first < req->minKeyCode) {
1851f7df2e56Smrg        *errorRtrn = _XkbErrCode3(0x31, first, req->minKeyCode);
1852f7df2e56Smrg        return 0;
1853f7df2e56Smrg    }
1854f7df2e56Smrg    if (last > req->maxKeyCode) {
1855f7df2e56Smrg        *errorRtrn = _XkbErrCode3(0x32, last, req->maxKeyCode);
1856f7df2e56Smrg        return 0;
1857f7df2e56Smrg    }
1858f7df2e56Smrg
1859f7df2e56Smrg    for (i = 0; i < req->totalKeyBehaviors; i++, wire++) {
1860f7df2e56Smrg        if ((wire->key < first) || (wire->key > last)) {
1861f7df2e56Smrg            *errorRtrn = _XkbErrCode4(0x33, first, last, wire->key);
1862f7df2e56Smrg            return 0;
1863f7df2e56Smrg        }
1864f7df2e56Smrg        if ((wire->type & XkbKB_Permanent) &&
1865f7df2e56Smrg            ((server->behaviors[wire->key].type != wire->type) ||
1866f7df2e56Smrg             (server->behaviors[wire->key].data != wire->data))) {
1867f7df2e56Smrg            *errorRtrn = _XkbErrCode3(0x33, wire->key, wire->type);
1868f7df2e56Smrg            return 0;
1869f7df2e56Smrg        }
1870f7df2e56Smrg        if ((wire->type == XkbKB_RadioGroup) &&
1871f7df2e56Smrg            ((wire->data & (~XkbKB_RGAllowNone)) > XkbMaxRadioGroups)) {
1872f7df2e56Smrg            *errorRtrn = _XkbErrCode4(0x34, wire->key, wire->data,
1873f7df2e56Smrg                                      XkbMaxRadioGroups);
1874f7df2e56Smrg            return 0;
1875f7df2e56Smrg        }
1876f7df2e56Smrg        if ((wire->type == XkbKB_Overlay1) || (wire->type == XkbKB_Overlay2)) {
1877f7df2e56Smrg            CHK_KEY_RANGE2(0x35, wire->key, 1, xkb, *errorRtrn, 0);
1878f7df2e56Smrg        }
187905b261ecSmrg    }
188005b261ecSmrg    *wireRtrn = wire;
188105b261ecSmrg    return 1;
188205b261ecSmrg}
188305b261ecSmrg
188405b261ecSmrgstatic int
1885f7df2e56SmrgCheckVirtualMods(XkbDescRec * xkb,
1886f7df2e56Smrg                 xkbSetMapReq * req, CARD8 **wireRtrn, int *errorRtrn)
188705b261ecSmrg{
1888f7df2e56Smrg    register CARD8 *wire = *wireRtrn;
1889f7df2e56Smrg    register unsigned i, nMods, bit;
189005b261ecSmrg
1891f7df2e56Smrg    if (((req->present & XkbVirtualModsMask) == 0) || (req->virtualMods == 0))
1892f7df2e56Smrg        return 1;
1893f7df2e56Smrg    for (i = nMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
1894f7df2e56Smrg        if (req->virtualMods & bit)
1895f7df2e56Smrg            nMods++;
189605b261ecSmrg    }
1897f7df2e56Smrg    *wireRtrn = (wire + XkbPaddedSize(nMods));
189805b261ecSmrg    return 1;
189905b261ecSmrg}
190005b261ecSmrg
190105b261ecSmrgstatic int
1902f7df2e56SmrgCheckKeyExplicit(XkbDescPtr xkb,
1903f7df2e56Smrg                 xkbSetMapReq * req, CARD8 **wireRtrn, int *errorRtrn)
190405b261ecSmrg{
1905f7df2e56Smrg    register CARD8 *wire = *wireRtrn;
1906f7df2e56Smrg    CARD8 *start;
1907f7df2e56Smrg    register unsigned i;
1908f7df2e56Smrg    int first, last;
1909f7df2e56Smrg
1910f7df2e56Smrg    if (((req->present & XkbExplicitComponentsMask) == 0) ||
1911f7df2e56Smrg        (req->nKeyExplicit < 1)) {
1912f7df2e56Smrg        req->present &= ~XkbExplicitComponentsMask;
1913f7df2e56Smrg        req->nKeyExplicit = 0;
1914f7df2e56Smrg        return 1;
1915f7df2e56Smrg    }
1916f7df2e56Smrg    first = req->firstKeyExplicit;
1917f7df2e56Smrg    last = first + req->nKeyExplicit - 1;
1918f7df2e56Smrg    if (first < req->minKeyCode) {
1919f7df2e56Smrg        *errorRtrn = _XkbErrCode3(0x51, first, req->minKeyCode);
1920f7df2e56Smrg        return 0;
1921f7df2e56Smrg    }
1922f7df2e56Smrg    if (last > req->maxKeyCode) {
1923f7df2e56Smrg        *errorRtrn = _XkbErrCode3(0x52, last, req->maxKeyCode);
1924f7df2e56Smrg        return 0;
1925f7df2e56Smrg    }
1926f7df2e56Smrg    start = wire;
1927f7df2e56Smrg    for (i = 0; i < req->totalKeyExplicit; i++, wire += 2) {
1928f7df2e56Smrg        if ((wire[0] < first) || (wire[0] > last)) {
1929f7df2e56Smrg            *errorRtrn = _XkbErrCode4(0x53, first, last, wire[0]);
1930f7df2e56Smrg            return 0;
1931f7df2e56Smrg        }
1932f7df2e56Smrg        if (wire[1] & (~XkbAllExplicitMask)) {
1933f7df2e56Smrg            *errorRtrn = _XkbErrCode3(0x52, ~XkbAllExplicitMask, wire[1]);
1934f7df2e56Smrg            return 0;
1935f7df2e56Smrg        }
1936f7df2e56Smrg    }
1937f7df2e56Smrg    wire += XkbPaddedSize(wire - start) - (wire - start);
1938f7df2e56Smrg    *wireRtrn = wire;
193905b261ecSmrg    return 1;
194005b261ecSmrg}
194105b261ecSmrg
194205b261ecSmrgstatic int
1943f7df2e56SmrgCheckModifierMap(XkbDescPtr xkb, xkbSetMapReq * req, CARD8 **wireRtrn,
1944f7df2e56Smrg                 int *errRtrn)
194505b261ecSmrg{
1946f7df2e56Smrg    register CARD8 *wire = *wireRtrn;
1947f7df2e56Smrg    CARD8 *start;
1948f7df2e56Smrg    register unsigned i;
1949f7df2e56Smrg    int first, last;
1950f7df2e56Smrg
1951f7df2e56Smrg    if (((req->present & XkbModifierMapMask) == 0) || (req->nModMapKeys < 1)) {
1952f7df2e56Smrg        req->present &= ~XkbModifierMapMask;
1953f7df2e56Smrg        req->nModMapKeys = 0;
1954f7df2e56Smrg        return 1;
1955f7df2e56Smrg    }
1956f7df2e56Smrg    first = req->firstModMapKey;
1957f7df2e56Smrg    last = first + req->nModMapKeys - 1;
1958f7df2e56Smrg    if (first < req->minKeyCode) {
1959f7df2e56Smrg        *errRtrn = _XkbErrCode3(0x61, first, req->minKeyCode);
1960f7df2e56Smrg        return 0;
1961f7df2e56Smrg    }
1962f7df2e56Smrg    if (last > req->maxKeyCode) {
1963f7df2e56Smrg        *errRtrn = _XkbErrCode3(0x62, last, req->maxKeyCode);
1964f7df2e56Smrg        return 0;
1965f7df2e56Smrg    }
1966f7df2e56Smrg    start = wire;
1967f7df2e56Smrg    for (i = 0; i < req->totalModMapKeys; i++, wire += 2) {
1968f7df2e56Smrg        if ((wire[0] < first) || (wire[0] > last)) {
1969f7df2e56Smrg            *errRtrn = _XkbErrCode4(0x63, first, last, wire[0]);
1970f7df2e56Smrg            return 0;
1971f7df2e56Smrg        }
1972f7df2e56Smrg    }
1973f7df2e56Smrg    wire += XkbPaddedSize(wire - start) - (wire - start);
1974f7df2e56Smrg    *wireRtrn = wire;
197505b261ecSmrg    return 1;
197605b261ecSmrg}
197705b261ecSmrg
197805b261ecSmrgstatic int
1979f7df2e56SmrgCheckVirtualModMap(XkbDescPtr xkb,
1980f7df2e56Smrg                   xkbSetMapReq * req,
1981f7df2e56Smrg                   xkbVModMapWireDesc ** wireRtrn, int *errRtrn)
198205b261ecSmrg{
1983f7df2e56Smrg    register xkbVModMapWireDesc *wire = *wireRtrn;
1984f7df2e56Smrg    register unsigned i;
1985f7df2e56Smrg    int first, last;
1986f7df2e56Smrg
1987f7df2e56Smrg    if (((req->present & XkbVirtualModMapMask) == 0) || (req->nVModMapKeys < 1)) {
1988f7df2e56Smrg        req->present &= ~XkbVirtualModMapMask;
1989f7df2e56Smrg        req->nVModMapKeys = 0;
1990f7df2e56Smrg        return 1;
1991f7df2e56Smrg    }
1992f7df2e56Smrg    first = req->firstVModMapKey;
1993f7df2e56Smrg    last = first + req->nVModMapKeys - 1;
1994f7df2e56Smrg    if (first < req->minKeyCode) {
1995f7df2e56Smrg        *errRtrn = _XkbErrCode3(0x71, first, req->minKeyCode);
1996f7df2e56Smrg        return 0;
1997f7df2e56Smrg    }
1998f7df2e56Smrg    if (last > req->maxKeyCode) {
1999f7df2e56Smrg        *errRtrn = _XkbErrCode3(0x72, last, req->maxKeyCode);
2000f7df2e56Smrg        return 0;
2001f7df2e56Smrg    }
2002f7df2e56Smrg    for (i = 0; i < req->totalVModMapKeys; i++, wire++) {
2003f7df2e56Smrg        if ((wire->key < first) || (wire->key > last)) {
2004f7df2e56Smrg            *errRtrn = _XkbErrCode4(0x73, first, last, wire->key);
2005f7df2e56Smrg            return 0;
2006f7df2e56Smrg        }
2007f7df2e56Smrg    }
2008f7df2e56Smrg    *wireRtrn = wire;
200905b261ecSmrg    return 1;
201005b261ecSmrg}
201105b261ecSmrg
201205b261ecSmrgstatic char *
2013f7df2e56SmrgSetKeyTypes(XkbDescPtr xkb,
2014f7df2e56Smrg            xkbSetMapReq * req,
2015f7df2e56Smrg            xkbKeyTypeWireDesc * wire, XkbChangesPtr changes)
201605b261ecSmrg{
2017f7df2e56Smrg    register unsigned i;
2018f7df2e56Smrg    unsigned first, last;
2019f7df2e56Smrg    CARD8 *map;
2020f7df2e56Smrg
2021f7df2e56Smrg    if ((unsigned) (req->firstType + req->nTypes) > xkb->map->size_types) {
2022f7df2e56Smrg        i = req->firstType + req->nTypes;
2023f7df2e56Smrg        if (XkbAllocClientMap(xkb, XkbKeyTypesMask, i) != Success) {
2024f7df2e56Smrg            return NULL;
2025f7df2e56Smrg        }
2026f7df2e56Smrg    }
2027f7df2e56Smrg    if ((unsigned) (req->firstType + req->nTypes) > xkb->map->num_types)
2028f7df2e56Smrg        xkb->map->num_types = req->firstType + req->nTypes;
2029f7df2e56Smrg
2030f7df2e56Smrg    for (i = 0; i < req->nTypes; i++) {
2031f7df2e56Smrg        XkbKeyTypePtr pOld;
2032f7df2e56Smrg        register unsigned n;
2033f7df2e56Smrg
2034f7df2e56Smrg        if (XkbResizeKeyType(xkb, i + req->firstType, wire->nMapEntries,
2035f7df2e56Smrg                             wire->preserve, wire->numLevels) != Success) {
2036f7df2e56Smrg            return NULL;
2037f7df2e56Smrg        }
2038f7df2e56Smrg        pOld = &xkb->map->types[i + req->firstType];
2039f7df2e56Smrg        map = (CARD8 *) &wire[1];
2040f7df2e56Smrg
2041f7df2e56Smrg        pOld->mods.real_mods = wire->realMods;
2042f7df2e56Smrg        pOld->mods.vmods = wire->virtualMods;
2043f7df2e56Smrg        pOld->num_levels = wire->numLevels;
2044f7df2e56Smrg        pOld->map_count = wire->nMapEntries;
2045f7df2e56Smrg
2046f7df2e56Smrg        pOld->mods.mask = pOld->mods.real_mods |
2047f7df2e56Smrg            XkbMaskForVMask(xkb, pOld->mods.vmods);
2048f7df2e56Smrg
2049f7df2e56Smrg        if (wire->nMapEntries) {
2050f7df2e56Smrg            xkbKTSetMapEntryWireDesc *mapWire;
2051f7df2e56Smrg            xkbModsWireDesc *preWire;
2052f7df2e56Smrg            unsigned tmp;
2053f7df2e56Smrg
2054f7df2e56Smrg            mapWire = (xkbKTSetMapEntryWireDesc *) map;
2055f7df2e56Smrg            preWire = (xkbModsWireDesc *) &mapWire[wire->nMapEntries];
2056f7df2e56Smrg            for (n = 0; n < wire->nMapEntries; n++) {
2057f7df2e56Smrg                pOld->map[n].active = 1;
2058f7df2e56Smrg                pOld->map[n].mods.mask = mapWire[n].realMods;
2059f7df2e56Smrg                pOld->map[n].mods.real_mods = mapWire[n].realMods;
2060f7df2e56Smrg                pOld->map[n].mods.vmods = mapWire[n].virtualMods;
2061f7df2e56Smrg                pOld->map[n].level = mapWire[n].level;
2062f7df2e56Smrg                if (mapWire[n].virtualMods != 0) {
2063f7df2e56Smrg                    tmp = XkbMaskForVMask(xkb, mapWire[n].virtualMods);
2064f7df2e56Smrg                    pOld->map[n].active = (tmp != 0);
2065f7df2e56Smrg                    pOld->map[n].mods.mask |= tmp;
2066f7df2e56Smrg                }
2067f7df2e56Smrg                if (wire->preserve) {
2068f7df2e56Smrg                    pOld->preserve[n].real_mods = preWire[n].realMods;
2069f7df2e56Smrg                    pOld->preserve[n].vmods = preWire[n].virtualMods;
2070f7df2e56Smrg                    tmp = XkbMaskForVMask(xkb, preWire[n].virtualMods);
2071f7df2e56Smrg                    pOld->preserve[n].mask = preWire[n].realMods | tmp;
2072f7df2e56Smrg                }
2073f7df2e56Smrg            }
2074f7df2e56Smrg            if (wire->preserve)
2075f7df2e56Smrg                map = (CARD8 *) &preWire[wire->nMapEntries];
2076f7df2e56Smrg            else
2077f7df2e56Smrg                map = (CARD8 *) &mapWire[wire->nMapEntries];
2078f7df2e56Smrg        }
2079f7df2e56Smrg        else
2080f7df2e56Smrg            map = (CARD8 *) &wire[1];
2081f7df2e56Smrg        wire = (xkbKeyTypeWireDesc *) map;
2082f7df2e56Smrg    }
2083f7df2e56Smrg    first = req->firstType;
2084f7df2e56Smrg    last = first + req->nTypes - 1;     /* last changed type */
2085f7df2e56Smrg    if (changes->map.changed & XkbKeyTypesMask) {
2086f7df2e56Smrg        int oldLast;
2087f7df2e56Smrg
2088f7df2e56Smrg        oldLast = changes->map.first_type + changes->map.num_types - 1;
2089f7df2e56Smrg        if (changes->map.first_type < first)
2090f7df2e56Smrg            first = changes->map.first_type;
2091f7df2e56Smrg        if (oldLast > last)
2092f7df2e56Smrg            last = oldLast;
2093f7df2e56Smrg    }
2094f7df2e56Smrg    changes->map.changed |= XkbKeyTypesMask;
209505b261ecSmrg    changes->map.first_type = first;
2096f7df2e56Smrg    changes->map.num_types = (last - first) + 1;
2097f7df2e56Smrg    return (char *) wire;
209805b261ecSmrg}
209905b261ecSmrg
210005b261ecSmrgstatic char *
2101f7df2e56SmrgSetKeySyms(ClientPtr client,
2102f7df2e56Smrg           XkbDescPtr xkb,
2103f7df2e56Smrg           xkbSetMapReq * req,
2104f7df2e56Smrg           xkbSymMapWireDesc * wire, XkbChangesPtr changes, DeviceIntPtr dev)
210505b261ecSmrg{
2106f7df2e56Smrg    register unsigned i, s;
2107f7df2e56Smrg    XkbSymMapPtr oldMap;
2108f7df2e56Smrg    KeySym *newSyms;
2109f7df2e56Smrg    KeySym *pSyms;
2110f7df2e56Smrg    unsigned first, last;
211105b261ecSmrg
211205b261ecSmrg    oldMap = &xkb->map->key_sym_map[req->firstKeySym];
2113f7df2e56Smrg    for (i = 0; i < req->nKeySyms; i++, oldMap++) {
2114f7df2e56Smrg        pSyms = (KeySym *) &wire[1];
2115f7df2e56Smrg        if (wire->nSyms > 0) {
2116f7df2e56Smrg            newSyms = XkbResizeKeySyms(xkb, i + req->firstKeySym, wire->nSyms);
2117f7df2e56Smrg            for (s = 0; s < wire->nSyms; s++) {
2118f7df2e56Smrg                newSyms[s] = pSyms[s];
2119f7df2e56Smrg            }
2120f7df2e56Smrg            if (client->swapped) {
2121f7df2e56Smrg                for (s = 0; s < wire->nSyms; s++) {
2122f7df2e56Smrg                    swapl(&newSyms[s]);
2123f7df2e56Smrg                }
2124f7df2e56Smrg            }
2125f7df2e56Smrg        }
21264e185dc0Smrg        if (XkbKeyHasActions(xkb, i + req->firstKeySym))
21274e185dc0Smrg            XkbResizeKeyActions(xkb, i + req->firstKeySym,
21284e185dc0Smrg                                XkbNumGroups(wire->groupInfo) * wire->width);
2129f7df2e56Smrg        oldMap->kt_index[0] = wire->ktIndex[0];
2130f7df2e56Smrg        oldMap->kt_index[1] = wire->ktIndex[1];
2131f7df2e56Smrg        oldMap->kt_index[2] = wire->ktIndex[2];
2132f7df2e56Smrg        oldMap->kt_index[3] = wire->ktIndex[3];
2133f7df2e56Smrg        oldMap->group_info = wire->groupInfo;
2134f7df2e56Smrg        oldMap->width = wire->width;
2135f7df2e56Smrg        wire = (xkbSymMapWireDesc *) &pSyms[wire->nSyms];
2136f7df2e56Smrg    }
2137f7df2e56Smrg    first = req->firstKeySym;
2138f7df2e56Smrg    last = first + req->nKeySyms - 1;
2139f7df2e56Smrg    if (changes->map.changed & XkbKeySymsMask) {
2140f7df2e56Smrg        int oldLast =
2141f7df2e56Smrg            (changes->map.first_key_sym + changes->map.num_key_syms - 1);
2142f7df2e56Smrg        if (changes->map.first_key_sym < first)
2143f7df2e56Smrg            first = changes->map.first_key_sym;
2144f7df2e56Smrg        if (oldLast > last)
2145f7df2e56Smrg            last = oldLast;
2146f7df2e56Smrg    }
2147f7df2e56Smrg    changes->map.changed |= XkbKeySymsMask;
214805b261ecSmrg    changes->map.first_key_sym = first;
2149f7df2e56Smrg    changes->map.num_key_syms = (last - first + 1);
2150f7df2e56Smrg
2151f7df2e56Smrg    s = 0;
2152f7df2e56Smrg    for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
2153f7df2e56Smrg        if (XkbKeyNumGroups(xkb, i) > s)
2154f7df2e56Smrg            s = XkbKeyNumGroups(xkb, i);
2155f7df2e56Smrg    }
2156f7df2e56Smrg    if (s != xkb->ctrls->num_groups) {
2157f7df2e56Smrg        xkbControlsNotify cn;
2158f7df2e56Smrg        XkbControlsRec old;
2159f7df2e56Smrg
2160f7df2e56Smrg        cn.keycode = 0;
2161f7df2e56Smrg        cn.eventType = 0;
2162f7df2e56Smrg        cn.requestMajor = XkbReqCode;
2163f7df2e56Smrg        cn.requestMinor = X_kbSetMap;
2164f7df2e56Smrg        old = *xkb->ctrls;
2165f7df2e56Smrg        xkb->ctrls->num_groups = s;
2166f7df2e56Smrg        if (XkbComputeControlsNotify(dev, &old, xkb->ctrls, &cn, FALSE))
2167f7df2e56Smrg            XkbSendControlsNotify(dev, &cn);
2168f7df2e56Smrg    }
2169f7df2e56Smrg    return (char *) wire;
217005b261ecSmrg}
217105b261ecSmrg
217205b261ecSmrgstatic char *
2173f7df2e56SmrgSetKeyActions(XkbDescPtr xkb,
2174f7df2e56Smrg              xkbSetMapReq * req, CARD8 *wire, XkbChangesPtr changes)
217505b261ecSmrg{
2176f7df2e56Smrg    register unsigned i, first, last;
2177f7df2e56Smrg    CARD8 *nActs = wire;
2178f7df2e56Smrg    XkbAction *newActs;
2179f7df2e56Smrg
2180f7df2e56Smrg    wire += XkbPaddedSize(req->nKeyActs);
2181f7df2e56Smrg    for (i = 0; i < req->nKeyActs; i++) {
2182f7df2e56Smrg        if (nActs[i] == 0)
2183f7df2e56Smrg            xkb->server->key_acts[i + req->firstKeyAct] = 0;
2184f7df2e56Smrg        else {
2185f7df2e56Smrg            newActs = XkbResizeKeyActions(xkb, i + req->firstKeyAct, nActs[i]);
2186f7df2e56Smrg            memcpy((char *) newActs, (char *) wire,
2187f7df2e56Smrg                   nActs[i] * SIZEOF(xkbActionWireDesc));
2188f7df2e56Smrg            wire += nActs[i] * SIZEOF(xkbActionWireDesc);
2189f7df2e56Smrg        }
2190f7df2e56Smrg    }
2191f7df2e56Smrg    first = req->firstKeyAct;
2192f7df2e56Smrg    last = (first + req->nKeyActs - 1);
2193f7df2e56Smrg    if (changes->map.changed & XkbKeyActionsMask) {
2194f7df2e56Smrg        int oldLast;
2195f7df2e56Smrg
2196f7df2e56Smrg        oldLast = changes->map.first_key_act + changes->map.num_key_acts - 1;
2197f7df2e56Smrg        if (changes->map.first_key_act < first)
2198f7df2e56Smrg            first = changes->map.first_key_act;
2199f7df2e56Smrg        if (oldLast > last)
2200f7df2e56Smrg            last = oldLast;
2201f7df2e56Smrg    }
2202f7df2e56Smrg    changes->map.changed |= XkbKeyActionsMask;
2203f7df2e56Smrg    changes->map.first_key_act = first;
2204f7df2e56Smrg    changes->map.num_key_acts = (last - first + 1);
2205f7df2e56Smrg    return (char *) wire;
220605b261ecSmrg}
220705b261ecSmrg
220805b261ecSmrgstatic char *
2209f7df2e56SmrgSetKeyBehaviors(XkbSrvInfoPtr xkbi,
2210f7df2e56Smrg                xkbSetMapReq * req,
2211f7df2e56Smrg                xkbBehaviorWireDesc * wire, XkbChangesPtr changes)
221205b261ecSmrg{
2213f7df2e56Smrg    register unsigned i;
2214f7df2e56Smrg    int maxRG = -1;
2215f7df2e56Smrg    XkbDescPtr xkb = xkbi->desc;
2216f7df2e56Smrg    XkbServerMapPtr server = xkb->server;
2217f7df2e56Smrg    unsigned first, last;
2218f7df2e56Smrg
2219f7df2e56Smrg    first = req->firstKeyBehavior;
2220f7df2e56Smrg    last = req->firstKeyBehavior + req->nKeyBehaviors - 1;
2221f7df2e56Smrg    memset(&server->behaviors[first], 0,
2222f7df2e56Smrg           req->nKeyBehaviors * sizeof(XkbBehavior));
2223f7df2e56Smrg    for (i = 0; i < req->totalKeyBehaviors; i++) {
2224f7df2e56Smrg        if ((server->behaviors[wire->key].type & XkbKB_Permanent) == 0) {
2225f7df2e56Smrg            server->behaviors[wire->key].type = wire->type;
2226f7df2e56Smrg            server->behaviors[wire->key].data = wire->data;
2227f7df2e56Smrg            if ((wire->type == XkbKB_RadioGroup) &&
2228f7df2e56Smrg                (((int) wire->data) > maxRG))
2229f7df2e56Smrg                maxRG = wire->data + 1;
2230f7df2e56Smrg        }
2231f7df2e56Smrg        wire++;
2232f7df2e56Smrg    }
2233f7df2e56Smrg
2234f7df2e56Smrg    if (maxRG > (int) xkbi->nRadioGroups) {
223505b261ecSmrg        if (xkbi->radioGroups)
2236f7df2e56Smrg            xkbi->radioGroups = reallocarray(xkbi->radioGroups, maxRG,
2237f7df2e56Smrg                                             sizeof(XkbRadioGroupRec));
2238f7df2e56Smrg        else
2239f7df2e56Smrg            xkbi->radioGroups = calloc(maxRG, sizeof(XkbRadioGroupRec));
224005b261ecSmrg        if (xkbi->radioGroups) {
2241f7df2e56Smrg            if (xkbi->nRadioGroups)
2242f7df2e56Smrg                memset(&xkbi->radioGroups[xkbi->nRadioGroups], 0,
2243f7df2e56Smrg                       (maxRG - xkbi->nRadioGroups) * sizeof(XkbRadioGroupRec));
2244f7df2e56Smrg            xkbi->nRadioGroups = maxRG;
224505b261ecSmrg        }
2246f7df2e56Smrg        else
2247f7df2e56Smrg            xkbi->nRadioGroups = 0;
224805b261ecSmrg        /* should compute members here */
224905b261ecSmrg    }
2250f7df2e56Smrg    if (changes->map.changed & XkbKeyBehaviorsMask) {
2251f7df2e56Smrg        unsigned oldLast;
2252f7df2e56Smrg
2253f7df2e56Smrg        oldLast = changes->map.first_key_behavior +
2254f7df2e56Smrg            changes->map.num_key_behaviors - 1;
2255f7df2e56Smrg        if (changes->map.first_key_behavior < req->firstKeyBehavior)
2256f7df2e56Smrg            first = changes->map.first_key_behavior;
2257f7df2e56Smrg        if (oldLast > last)
2258f7df2e56Smrg            last = oldLast;
225905b261ecSmrg    }
2260f7df2e56Smrg    changes->map.changed |= XkbKeyBehaviorsMask;
226105b261ecSmrg    changes->map.first_key_behavior = first;
2262f7df2e56Smrg    changes->map.num_key_behaviors = (last - first + 1);
2263f7df2e56Smrg    return (char *) wire;
226405b261ecSmrg}
226505b261ecSmrg
226605b261ecSmrgstatic char *
2267f7df2e56SmrgSetVirtualMods(XkbSrvInfoPtr xkbi, xkbSetMapReq * req, CARD8 *wire,
2268f7df2e56Smrg               XkbChangesPtr changes)
226905b261ecSmrg{
2270f7df2e56Smrg    register int i, bit, nMods;
2271f7df2e56Smrg    XkbServerMapPtr srv = xkbi->desc->server;
2272f7df2e56Smrg
2273f7df2e56Smrg    if (((req->present & XkbVirtualModsMask) == 0) || (req->virtualMods == 0))
2274f7df2e56Smrg        return (char *) wire;
2275f7df2e56Smrg    for (i = nMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
2276f7df2e56Smrg        if (req->virtualMods & bit) {
2277f7df2e56Smrg            if (srv->vmods[i] != wire[nMods]) {
2278f7df2e56Smrg                changes->map.changed |= XkbVirtualModsMask;
2279f7df2e56Smrg                changes->map.vmods |= bit;
2280f7df2e56Smrg                srv->vmods[i] = wire[nMods];
2281f7df2e56Smrg            }
2282f7df2e56Smrg            nMods++;
2283f7df2e56Smrg        }
2284f7df2e56Smrg    }
2285f7df2e56Smrg    return (char *) (wire + XkbPaddedSize(nMods));
228605b261ecSmrg}
228705b261ecSmrg
228805b261ecSmrgstatic char *
2289f7df2e56SmrgSetKeyExplicit(XkbSrvInfoPtr xkbi, xkbSetMapReq * req, CARD8 *wire,
2290f7df2e56Smrg               XkbChangesPtr changes)
229105b261ecSmrg{
2292f7df2e56Smrg    register unsigned i, first, last;
2293f7df2e56Smrg    XkbServerMapPtr xkb = xkbi->desc->server;
2294f7df2e56Smrg    CARD8 *start;
229505b261ecSmrg
2296f7df2e56Smrg    start = wire;
2297f7df2e56Smrg    first = req->firstKeyExplicit;
2298f7df2e56Smrg    last = req->firstKeyExplicit + req->nKeyExplicit - 1;
22996747b715Smrg    memset(&xkb->explicit[first], 0, req->nKeyExplicit);
2300f7df2e56Smrg    for (i = 0; i < req->totalKeyExplicit; i++, wire += 2) {
2301f7df2e56Smrg        xkb->explicit[wire[0]] = wire[1];
2302f7df2e56Smrg    }
2303f7df2e56Smrg    if (first > 0) {
2304f7df2e56Smrg        if (changes->map.changed & XkbExplicitComponentsMask) {
2305f7df2e56Smrg            int oldLast;
2306f7df2e56Smrg
2307f7df2e56Smrg            oldLast = changes->map.first_key_explicit +
2308f7df2e56Smrg                changes->map.num_key_explicit - 1;
2309f7df2e56Smrg            if (changes->map.first_key_explicit < first)
2310f7df2e56Smrg                first = changes->map.first_key_explicit;
2311f7df2e56Smrg            if (oldLast > last)
2312f7df2e56Smrg                last = oldLast;
2313f7df2e56Smrg        }
2314f7df2e56Smrg        changes->map.first_key_explicit = first;
2315f7df2e56Smrg        changes->map.num_key_explicit = (last - first) + 1;
2316f7df2e56Smrg    }
2317f7df2e56Smrg    wire += XkbPaddedSize(wire - start) - (wire - start);
2318f7df2e56Smrg    return (char *) wire;
231905b261ecSmrg}
232005b261ecSmrg
232105b261ecSmrgstatic char *
2322f7df2e56SmrgSetModifierMap(XkbSrvInfoPtr xkbi,
2323f7df2e56Smrg               xkbSetMapReq * req, CARD8 *wire, XkbChangesPtr changes)
232405b261ecSmrg{
2325f7df2e56Smrg    register unsigned i, first, last;
2326f7df2e56Smrg    XkbClientMapPtr xkb = xkbi->desc->map;
2327f7df2e56Smrg    CARD8 *start;
232805b261ecSmrg
2329f7df2e56Smrg    start = wire;
2330f7df2e56Smrg    first = req->firstModMapKey;
2331f7df2e56Smrg    last = req->firstModMapKey + req->nModMapKeys - 1;
23326747b715Smrg    memset(&xkb->modmap[first], 0, req->nModMapKeys);
2333f7df2e56Smrg    for (i = 0; i < req->totalModMapKeys; i++, wire += 2) {
2334f7df2e56Smrg        xkb->modmap[wire[0]] = wire[1];
2335f7df2e56Smrg    }
2336f7df2e56Smrg    if (first > 0) {
2337f7df2e56Smrg        if (changes->map.changed & XkbModifierMapMask) {
2338f7df2e56Smrg            int oldLast;
2339f7df2e56Smrg
2340f7df2e56Smrg            oldLast = changes->map.first_modmap_key +
2341f7df2e56Smrg                changes->map.num_modmap_keys - 1;
2342f7df2e56Smrg            if (changes->map.first_modmap_key < first)
2343f7df2e56Smrg                first = changes->map.first_modmap_key;
2344f7df2e56Smrg            if (oldLast > last)
2345f7df2e56Smrg                last = oldLast;
2346f7df2e56Smrg        }
2347f7df2e56Smrg        changes->map.first_modmap_key = first;
2348f7df2e56Smrg        changes->map.num_modmap_keys = (last - first) + 1;
2349f7df2e56Smrg    }
2350f7df2e56Smrg    wire += XkbPaddedSize(wire - start) - (wire - start);
2351f7df2e56Smrg    return (char *) wire;
235205b261ecSmrg}
235305b261ecSmrg
235405b261ecSmrgstatic char *
2355f7df2e56SmrgSetVirtualModMap(XkbSrvInfoPtr xkbi,
2356f7df2e56Smrg                 xkbSetMapReq * req,
2357f7df2e56Smrg                 xkbVModMapWireDesc * wire, XkbChangesPtr changes)
235805b261ecSmrg{
2359f7df2e56Smrg    register unsigned i, first, last;
2360f7df2e56Smrg    XkbServerMapPtr srv = xkbi->desc->server;
2361f7df2e56Smrg
2362f7df2e56Smrg    first = req->firstVModMapKey;
2363f7df2e56Smrg    last = req->firstVModMapKey + req->nVModMapKeys - 1;
2364f7df2e56Smrg    memset(&srv->vmodmap[first], 0, req->nVModMapKeys * sizeof(unsigned short));
2365f7df2e56Smrg    for (i = 0; i < req->totalVModMapKeys; i++, wire++) {
2366f7df2e56Smrg        srv->vmodmap[wire->key] = wire->vmods;
2367f7df2e56Smrg    }
2368f7df2e56Smrg    if (first > 0) {
2369f7df2e56Smrg        if (changes->map.changed & XkbVirtualModMapMask) {
2370f7df2e56Smrg            int oldLast;
2371f7df2e56Smrg
2372f7df2e56Smrg            oldLast = changes->map.first_vmodmap_key +
2373f7df2e56Smrg                changes->map.num_vmodmap_keys - 1;
2374f7df2e56Smrg            if (changes->map.first_vmodmap_key < first)
2375f7df2e56Smrg                first = changes->map.first_vmodmap_key;
2376f7df2e56Smrg            if (oldLast > last)
2377f7df2e56Smrg                last = oldLast;
2378f7df2e56Smrg        }
2379f7df2e56Smrg        changes->map.first_vmodmap_key = first;
2380f7df2e56Smrg        changes->map.num_vmodmap_keys = (last - first) + 1;
2381f7df2e56Smrg    }
2382f7df2e56Smrg    return (char *) wire;
238305b261ecSmrg}
238405b261ecSmrg
2385806e81e9Smrg#define _add_check_len(new) \
2386806e81e9Smrg    if (len > UINT32_MAX - (new) || len > req_len - (new)) goto bad; \
2387806e81e9Smrg    else len += new
2388806e81e9Smrg
2389806e81e9Smrg/**
2390806e81e9Smrg * Check the length of the SetMap request
2391806e81e9Smrg */
2392806e81e9Smrgstatic int
2393806e81e9Smrg_XkbSetMapCheckLength(xkbSetMapReq *req)
2394806e81e9Smrg{
2395806e81e9Smrg    size_t len = sz_xkbSetMapReq, req_len = req->length << 2;
2396806e81e9Smrg    xkbKeyTypeWireDesc *keytype;
2397806e81e9Smrg    xkbSymMapWireDesc *symmap;
2398806e81e9Smrg    BOOL preserve;
2399806e81e9Smrg    int i, map_count, nSyms;
2400806e81e9Smrg
2401806e81e9Smrg    if (req_len < len)
2402806e81e9Smrg        goto bad;
2403806e81e9Smrg    /* types */
2404806e81e9Smrg    if (req->present & XkbKeyTypesMask) {
2405806e81e9Smrg        keytype = (xkbKeyTypeWireDesc *)(req + 1);
2406806e81e9Smrg        for (i = 0; i < req->nTypes; i++) {
2407806e81e9Smrg            _add_check_len(XkbPaddedSize(sz_xkbKeyTypeWireDesc));
24085a112b11Smrg            _add_check_len(keytype->nMapEntries
24095a112b11Smrg                           * sz_xkbKTSetMapEntryWireDesc);
24105a112b11Smrg            preserve = keytype->preserve;
24115a112b11Smrg            map_count = keytype->nMapEntries;
24125a112b11Smrg            if (preserve) {
24135a112b11Smrg                _add_check_len(map_count * sz_xkbModsWireDesc);
2414806e81e9Smrg            }
24155a112b11Smrg            keytype += 1;
24165a112b11Smrg            keytype = (xkbKeyTypeWireDesc *)
24175a112b11Smrg                      ((xkbKTSetMapEntryWireDesc *)keytype + map_count);
24185a112b11Smrg            if (preserve)
24195a112b11Smrg                keytype = (xkbKeyTypeWireDesc *)
24205a112b11Smrg                          ((xkbModsWireDesc *)keytype + map_count);
2421806e81e9Smrg        }
2422806e81e9Smrg    }
2423806e81e9Smrg    /* syms */
2424806e81e9Smrg    if (req->present & XkbKeySymsMask) {
2425806e81e9Smrg        symmap = (xkbSymMapWireDesc *)((char *)req + len);
2426806e81e9Smrg        for (i = 0; i < req->nKeySyms; i++) {
2427806e81e9Smrg            _add_check_len(sz_xkbSymMapWireDesc);
2428806e81e9Smrg            nSyms = symmap->nSyms;
2429806e81e9Smrg            _add_check_len(nSyms*sizeof(CARD32));
2430806e81e9Smrg            symmap += 1;
2431806e81e9Smrg            symmap = (xkbSymMapWireDesc *)((CARD32 *)symmap + nSyms);
2432806e81e9Smrg        }
2433806e81e9Smrg    }
2434806e81e9Smrg    /* actions */
2435806e81e9Smrg    if (req->present & XkbKeyActionsMask) {
2436806e81e9Smrg        _add_check_len(req->totalActs * sz_xkbActionWireDesc
2437806e81e9Smrg                       + XkbPaddedSize(req->nKeyActs));
2438806e81e9Smrg    }
2439806e81e9Smrg    /* behaviours */
2440806e81e9Smrg    if (req->present & XkbKeyBehaviorsMask) {
2441806e81e9Smrg        _add_check_len(req->totalKeyBehaviors * sz_xkbBehaviorWireDesc);
2442806e81e9Smrg    }
2443806e81e9Smrg    /* vmods */
2444806e81e9Smrg    if (req->present & XkbVirtualModsMask) {
2445806e81e9Smrg        _add_check_len(XkbPaddedSize(Ones(req->virtualMods)));
2446806e81e9Smrg    }
2447806e81e9Smrg    /* explicit */
2448806e81e9Smrg    if (req->present & XkbExplicitComponentsMask) {
2449806e81e9Smrg        /* two bytes per non-zero explicit componen */
2450806e81e9Smrg        _add_check_len(XkbPaddedSize(req->totalKeyExplicit * sizeof(CARD16)));
2451806e81e9Smrg    }
2452806e81e9Smrg    /* modmap */
2453806e81e9Smrg    if (req->present & XkbModifierMapMask) {
2454806e81e9Smrg         /* two bytes per non-zero modmap component */
2455806e81e9Smrg        _add_check_len(XkbPaddedSize(req->totalModMapKeys * sizeof(CARD16)));
2456806e81e9Smrg    }
2457806e81e9Smrg    /* vmodmap */
2458806e81e9Smrg    if (req->present & XkbVirtualModMapMask) {
2459806e81e9Smrg        _add_check_len(req->totalVModMapKeys * sz_xkbVModMapWireDesc);
2460806e81e9Smrg    }
2461806e81e9Smrg    if (len == req_len)
2462806e81e9Smrg        return Success;
2463806e81e9Smrgbad:
2464806e81e9Smrg    ErrorF("[xkb] BOGUS LENGTH in SetMap: expected %ld got %ld\n",
2465806e81e9Smrg           len, req_len);
2466806e81e9Smrg    return BadLength;
2467806e81e9Smrg}
2468806e81e9Smrg
2469806e81e9Smrg
24704642e01fSmrg/**
24714642e01fSmrg * Check if the given request can be applied to the given device but don't
24725a112b11Smrg * actually do anything, except swap values when client->swapped and doswap are both true.
24734642e01fSmrg */
24744642e01fSmrgstatic int
2475f7df2e56Smrg_XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq * req,
24765a112b11Smrg                 char *values, Bool doswap)
247705b261ecSmrg{
2478f7df2e56Smrg    XkbSrvInfoPtr xkbi;
2479f7df2e56Smrg    XkbDescPtr xkb;
2480f7df2e56Smrg    int error;
2481f7df2e56Smrg    int nTypes = 0, nActions;
2482f7df2e56Smrg    CARD8 mapWidths[XkbMaxLegalKeyCode + 1] = { 0 };
2483f7df2e56Smrg    CARD16 symsPerKey[XkbMaxLegalKeyCode + 1] = { 0 };
2484f7df2e56Smrg    XkbSymMapPtr map;
2485f7df2e56Smrg    int i;
2486f7df2e56Smrg
24874e185dc0Smrg    if (!dev->key)
24884e185dc0Smrg        return 0;
24894e185dc0Smrg
2490f7df2e56Smrg    xkbi = dev->key->xkbInfo;
249105b261ecSmrg    xkb = xkbi->desc;
249205b261ecSmrg
2493f7df2e56Smrg    if ((xkb->min_key_code != req->minKeyCode) ||
24944642e01fSmrg        (xkb->max_key_code != req->maxKeyCode)) {
24957e31ba66Smrg        if (client->xkbClientFlags & _XkbClientIsAncient) {
24967e31ba66Smrg            /* pre 1.0 versions of Xlib have a bug */
2497f7df2e56Smrg            req->minKeyCode = xkb->min_key_code;
2498f7df2e56Smrg            req->maxKeyCode = xkb->max_key_code;
2499f7df2e56Smrg        }
2500f7df2e56Smrg        else {
2501f7df2e56Smrg            if (!XkbIsLegalKeycode(req->minKeyCode)) {
2502f7df2e56Smrg                client->errorValue =
2503f7df2e56Smrg                    _XkbErrCode3(2, req->minKeyCode, req->maxKeyCode);
2504f7df2e56Smrg                return BadValue;
2505f7df2e56Smrg            }
2506f7df2e56Smrg            if (req->minKeyCode > req->maxKeyCode) {
2507f7df2e56Smrg                client->errorValue =
2508f7df2e56Smrg                    _XkbErrCode3(3, req->minKeyCode, req->maxKeyCode);
2509f7df2e56Smrg                return BadMatch;
2510f7df2e56Smrg            }
2511f7df2e56Smrg        }
251205b261ecSmrg    }
251305b261ecSmrg
25145a112b11Smrg    if (!(req->present & XkbKeyTypesMask)) {
25155a112b11Smrg        nTypes = xkb->map->num_types;
25165a112b11Smrg    }
25175a112b11Smrg    else if (!CheckKeyTypes(client, xkb, req, (xkbKeyTypeWireDesc **) &values,
25185a112b11Smrg			       &nTypes, mapWidths, doswap)) {
25195a112b11Smrg	    client->errorValue = nTypes;
25205a112b11Smrg	    return BadValue;
252105b261ecSmrg    }
25229ace9065Smrg
25239ace9065Smrg    /* symsPerKey/mapWidths must be filled regardless of client-side flags */
25249ace9065Smrg    map = &xkb->map->key_sym_map[xkb->min_key_code];
2525f7df2e56Smrg    for (i = xkb->min_key_code; i < xkb->max_key_code; i++, map++) {
2526f7df2e56Smrg        register int g, ng, w;
2527f7df2e56Smrg
2528f7df2e56Smrg        ng = XkbNumGroups(map->group_info);
2529f7df2e56Smrg        for (w = g = 0; g < ng; g++) {
2530f7df2e56Smrg            if (map->kt_index[g] >= (unsigned) nTypes) {
2531f7df2e56Smrg                client->errorValue = _XkbErrCode4(0x13, i, g, map->kt_index[g]);
25325a112b11Smrg                return BadValue;
2533f7df2e56Smrg            }
2534f7df2e56Smrg            if (mapWidths[map->kt_index[g]] > w)
2535f7df2e56Smrg                w = mapWidths[map->kt_index[g]];
2536f7df2e56Smrg        }
2537f7df2e56Smrg        symsPerKey[i] = w * ng;
25389ace9065Smrg    }
25399ace9065Smrg
25404642e01fSmrg    if ((req->present & XkbKeySymsMask) &&
2541f7df2e56Smrg        (!CheckKeySyms(client, xkb, req, nTypes, mapWidths, symsPerKey,
25425a112b11Smrg                       (xkbSymMapWireDesc **) &values, &error, doswap))) {
2543f7df2e56Smrg        client->errorValue = error;
2544f7df2e56Smrg        return BadValue;
254505b261ecSmrg    }
254605b261ecSmrg
25474642e01fSmrg    if ((req->present & XkbKeyActionsMask) &&
2548f7df2e56Smrg        (!CheckKeyActions(xkb, req, nTypes, mapWidths, symsPerKey,
2549f7df2e56Smrg                          (CARD8 **) &values, &nActions))) {
2550f7df2e56Smrg        client->errorValue = nActions;
2551f7df2e56Smrg        return BadValue;
255205b261ecSmrg    }
255305b261ecSmrg
25544642e01fSmrg    if ((req->present & XkbKeyBehaviorsMask) &&
2555f7df2e56Smrg        (!CheckKeyBehaviors
2556f7df2e56Smrg         (xkb, req, (xkbBehaviorWireDesc **) &values, &error))) {
2557f7df2e56Smrg        client->errorValue = error;
2558f7df2e56Smrg        return BadValue;
255905b261ecSmrg    }
256005b261ecSmrg
25614642e01fSmrg    if ((req->present & XkbVirtualModsMask) &&
2562f7df2e56Smrg        (!CheckVirtualMods(xkb, req, (CARD8 **) &values, &error))) {
2563f7df2e56Smrg        client->errorValue = error;
2564f7df2e56Smrg        return BadValue;
256505b261ecSmrg    }
2566f7df2e56Smrg    if ((req->present & XkbExplicitComponentsMask) &&
2567f7df2e56Smrg        (!CheckKeyExplicit(xkb, req, (CARD8 **) &values, &error))) {
2568f7df2e56Smrg        client->errorValue = error;
2569f7df2e56Smrg        return BadValue;
257005b261ecSmrg    }
2571f7df2e56Smrg    if ((req->present & XkbModifierMapMask) &&
2572f7df2e56Smrg        (!CheckModifierMap(xkb, req, (CARD8 **) &values, &error))) {
2573f7df2e56Smrg        client->errorValue = error;
2574f7df2e56Smrg        return BadValue;
257505b261ecSmrg    }
2576f7df2e56Smrg    if ((req->present & XkbVirtualModMapMask) &&
2577f7df2e56Smrg        (!CheckVirtualModMap
2578f7df2e56Smrg         (xkb, req, (xkbVModMapWireDesc **) &values, &error))) {
2579f7df2e56Smrg        client->errorValue = error;
2580f7df2e56Smrg        return BadValue;
258105b261ecSmrg    }
25824642e01fSmrg
2583f7df2e56Smrg    if (((values - ((char *) req)) / 4) != req->length) {
2584f7df2e56Smrg        ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after check)\n");
2585f7df2e56Smrg        client->errorValue = values - ((char *) &req[1]);
2586f7df2e56Smrg        return BadLength;
258705b261ecSmrg    }
25884642e01fSmrg
25894642e01fSmrg    return Success;
25904642e01fSmrg}
25914642e01fSmrg
25924642e01fSmrg/**
25934642e01fSmrg * Apply the given request on the given device.
25944642e01fSmrg */
25954642e01fSmrgstatic int
2596f7df2e56Smrg_XkbSetMap(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq * req, char *values)
25974642e01fSmrg{
2598f7df2e56Smrg    XkbEventCauseRec cause;
2599f7df2e56Smrg    XkbChangesRec change;
2600f7df2e56Smrg    Bool sentNKN;
2601f7df2e56Smrg    XkbSrvInfoPtr xkbi;
2602f7df2e56Smrg    XkbDescPtr xkb;
26034642e01fSmrg
26044e185dc0Smrg    if (!dev->key)
26054e185dc0Smrg        return Success;
26064e185dc0Smrg
2607f7df2e56Smrg    xkbi = dev->key->xkbInfo;
26084642e01fSmrg    xkb = xkbi->desc;
26094642e01fSmrg
2610f7df2e56Smrg    XkbSetCauseXkbReq(&cause, X_kbSetMap, client);
26116747b715Smrg    memset(&change, 0, sizeof(change));
26126747b715Smrg    sentNKN = FALSE;
2613f7df2e56Smrg    if ((xkb->min_key_code != req->minKeyCode) ||
2614f7df2e56Smrg        (xkb->max_key_code != req->maxKeyCode)) {
2615f7df2e56Smrg        Status status;
2616f7df2e56Smrg        xkbNewKeyboardNotify nkn;
2617f7df2e56Smrg
2618f7df2e56Smrg        nkn.deviceID = nkn.oldDeviceID = dev->id;
2619f7df2e56Smrg        nkn.oldMinKeyCode = xkb->min_key_code;
2620f7df2e56Smrg        nkn.oldMaxKeyCode = xkb->max_key_code;
2621f7df2e56Smrg        status = XkbChangeKeycodeRange(xkb, req->minKeyCode,
2622f7df2e56Smrg                                       req->maxKeyCode, &change);
2623f7df2e56Smrg        if (status != Success)
2624f7df2e56Smrg            return status;      /* oh-oh. what about the other keyboards? */
2625f7df2e56Smrg        nkn.minKeyCode = xkb->min_key_code;
2626f7df2e56Smrg        nkn.maxKeyCode = xkb->max_key_code;
2627f7df2e56Smrg        nkn.requestMajor = XkbReqCode;
2628f7df2e56Smrg        nkn.requestMinor = X_kbSetMap;
2629f7df2e56Smrg        nkn.changed = XkbNKN_KeycodesMask;
2630f7df2e56Smrg        XkbSendNewKeyboardNotify(dev, &nkn);
2631f7df2e56Smrg        sentNKN = TRUE;
2632f7df2e56Smrg    }
2633f7df2e56Smrg
2634f7df2e56Smrg    if (req->present & XkbKeyTypesMask) {
2635f7df2e56Smrg        values = SetKeyTypes(xkb, req, (xkbKeyTypeWireDesc *) values, &change);
2636f7df2e56Smrg        if (!values)
2637f7df2e56Smrg            goto allocFailure;
2638f7df2e56Smrg    }
2639f7df2e56Smrg    if (req->present & XkbKeySymsMask) {
2640f7df2e56Smrg        values =
2641f7df2e56Smrg            SetKeySyms(client, xkb, req, (xkbSymMapWireDesc *) values, &change,
2642f7df2e56Smrg                       dev);
2643f7df2e56Smrg        if (!values)
2644f7df2e56Smrg            goto allocFailure;
2645f7df2e56Smrg    }
2646f7df2e56Smrg    if (req->present & XkbKeyActionsMask) {
2647f7df2e56Smrg        values = SetKeyActions(xkb, req, (CARD8 *) values, &change);
2648f7df2e56Smrg        if (!values)
2649f7df2e56Smrg            goto allocFailure;
2650f7df2e56Smrg    }
2651f7df2e56Smrg    if (req->present & XkbKeyBehaviorsMask) {
2652f7df2e56Smrg        values =
2653f7df2e56Smrg            SetKeyBehaviors(xkbi, req, (xkbBehaviorWireDesc *) values, &change);
2654f7df2e56Smrg        if (!values)
2655f7df2e56Smrg            goto allocFailure;
2656f7df2e56Smrg    }
2657f7df2e56Smrg    if (req->present & XkbVirtualModsMask)
2658f7df2e56Smrg        values = SetVirtualMods(xkbi, req, (CARD8 *) values, &change);
2659f7df2e56Smrg    if (req->present & XkbExplicitComponentsMask)
2660f7df2e56Smrg        values = SetKeyExplicit(xkbi, req, (CARD8 *) values, &change);
2661f7df2e56Smrg    if (req->present & XkbModifierMapMask)
2662f7df2e56Smrg        values = SetModifierMap(xkbi, req, (CARD8 *) values, &change);
2663f7df2e56Smrg    if (req->present & XkbVirtualModMapMask)
2664f7df2e56Smrg        values =
2665f7df2e56Smrg            SetVirtualModMap(xkbi, req, (xkbVModMapWireDesc *) values, &change);
2666f7df2e56Smrg    if (((values - ((char *) req)) / 4) != req->length) {
2667f7df2e56Smrg        ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after set)\n");
2668f7df2e56Smrg        client->errorValue = values - ((char *) &req[1]);
2669f7df2e56Smrg        return BadLength;
2670f7df2e56Smrg    }
2671f7df2e56Smrg    if (req->flags & XkbSetMapRecomputeActions) {
2672f7df2e56Smrg        KeyCode first, last, firstMM, lastMM;
2673f7df2e56Smrg
2674f7df2e56Smrg        if (change.map.num_key_syms > 0) {
2675f7df2e56Smrg            first = change.map.first_key_sym;
2676f7df2e56Smrg            last = first + change.map.num_key_syms - 1;
2677f7df2e56Smrg        }
2678f7df2e56Smrg        else
2679f7df2e56Smrg            first = last = 0;
2680f7df2e56Smrg        if (change.map.num_modmap_keys > 0) {
2681f7df2e56Smrg            firstMM = change.map.first_modmap_key;
26827e31ba66Smrg            lastMM = firstMM + change.map.num_modmap_keys - 1;
2683f7df2e56Smrg        }
2684f7df2e56Smrg        else
2685f7df2e56Smrg            firstMM = lastMM = 0;
2686f7df2e56Smrg        if ((last > 0) && (lastMM > 0)) {
2687f7df2e56Smrg            if (firstMM < first)
2688f7df2e56Smrg                first = firstMM;
2689f7df2e56Smrg            if (lastMM > last)
2690f7df2e56Smrg                last = lastMM;
2691f7df2e56Smrg        }
2692f7df2e56Smrg        else if (lastMM > 0) {
2693f7df2e56Smrg            first = firstMM;
2694f7df2e56Smrg            last = lastMM;
2695f7df2e56Smrg        }
2696f7df2e56Smrg        if (last > 0) {
2697f7df2e56Smrg            unsigned check = 0;
2698f7df2e56Smrg
2699f7df2e56Smrg            XkbUpdateActions(dev, first, (last - first + 1), &change, &check,
2700f7df2e56Smrg                             &cause);
2701f7df2e56Smrg            if (check)
2702f7df2e56Smrg                XkbCheckSecondaryEffects(xkbi, check, &change, &cause);
2703f7df2e56Smrg        }
270405b261ecSmrg    }
270505b261ecSmrg    if (!sentNKN)
2706f7df2e56Smrg        XkbSendNotification(dev, &change, &cause);
270705b261ecSmrg
27084642e01fSmrg    return Success;
2709f7df2e56Smrg allocFailure:
271005b261ecSmrg    return BadAlloc;
271105b261ecSmrg}
271205b261ecSmrg
27134642e01fSmrgint
27144642e01fSmrgProcXkbSetMap(ClientPtr client)
27154642e01fSmrg{
27165a112b11Smrg    DeviceIntPtr dev, master;
2717f7df2e56Smrg    char *tmp;
2718f7df2e56Smrg    int rc;
27194642e01fSmrg
27204642e01fSmrg    REQUEST(xkbSetMapReq);
27214642e01fSmrg    REQUEST_AT_LEAST_SIZE(xkbSetMapReq);
27224642e01fSmrg
2723f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
2724f7df2e56Smrg        return BadAccess;
27254642e01fSmrg
27264642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
2727f7df2e56Smrg    CHK_MASK_LEGAL(0x01, stuff->present, XkbAllMapComponentsMask);
27284642e01fSmrg
2729806e81e9Smrg    /* first verify the request length carefully */
2730806e81e9Smrg    rc = _XkbSetMapCheckLength(stuff);
2731806e81e9Smrg    if (rc != Success)
2732806e81e9Smrg        return rc;
2733806e81e9Smrg
2734f7df2e56Smrg    tmp = (char *) &stuff[1];
27354642e01fSmrg
27364642e01fSmrg    /* Check if we can to the SetMap on the requested device. If this
27374642e01fSmrg       succeeds, do the same thing for all extension devices (if needed).
27384642e01fSmrg       If any of them fails, fail.  */
27395a112b11Smrg    rc = _XkbSetMapChecks(client, dev, stuff, tmp, TRUE);
27404642e01fSmrg
27414642e01fSmrg    if (rc != Success)
27424642e01fSmrg        return rc;
27434642e01fSmrg
27445a112b11Smrg    master = GetMaster(dev, MASTER_KEYBOARD);
27457e31ba66Smrg
2746f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
27474642e01fSmrg        DeviceIntPtr other;
2748f7df2e56Smrg
2749f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
2750f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
2751f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
2752f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
2753f7df2e56Smrg                              DixManageAccess);
2754f7df2e56Smrg                if (rc == Success) {
27555a112b11Smrg                    rc = _XkbSetMapChecks(client, other, stuff, tmp, FALSE);
27564642e01fSmrg                    if (rc != Success)
27574642e01fSmrg                        return rc;
27584642e01fSmrg                }
27594642e01fSmrg            }
27604642e01fSmrg        }
27617e31ba66Smrg    } else {
27627e31ba66Smrg        DeviceIntPtr other;
27637e31ba66Smrg
27647e31ba66Smrg        for (other = inputInfo.devices; other; other = other->next) {
27657e31ba66Smrg            if (other != dev && GetMaster(other, MASTER_KEYBOARD) != dev &&
27667e31ba66Smrg                (other != master || dev != master->lastSlave))
27677e31ba66Smrg                continue;
27687e31ba66Smrg
27695a112b11Smrg            rc = _XkbSetMapChecks(client, other, stuff, tmp, FALSE);
27707e31ba66Smrg            if (rc != Success)
27717e31ba66Smrg                return rc;
27727e31ba66Smrg        }
27734642e01fSmrg    }
27744642e01fSmrg
27757e31ba66Smrg    /* We know now that we will succeed with the SetMap. In theory anyway. */
27764642e01fSmrg    rc = _XkbSetMap(client, dev, stuff, tmp);
27774642e01fSmrg    if (rc != Success)
27784642e01fSmrg        return rc;
27794642e01fSmrg
2780f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
27814642e01fSmrg        DeviceIntPtr other;
2782f7df2e56Smrg
2783f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
2784f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
2785f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
2786f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
2787f7df2e56Smrg                              DixManageAccess);
27884642e01fSmrg                if (rc == Success)
27894642e01fSmrg                    _XkbSetMap(client, other, stuff, tmp);
27904642e01fSmrg                /* ignore rc. if the SetMap failed although the check above
27914642e01fSmrg                   reported true there isn't much we can do. we still need to
27924642e01fSmrg                   set all other devices, hoping that at least they stay in
27934642e01fSmrg                   sync. */
27944642e01fSmrg            }
27954642e01fSmrg        }
27967e31ba66Smrg    } else {
27977e31ba66Smrg        DeviceIntPtr other;
27987e31ba66Smrg
27997e31ba66Smrg        for (other = inputInfo.devices; other; other = other->next) {
28007e31ba66Smrg            if (other != dev && GetMaster(other, MASTER_KEYBOARD) != dev &&
28017e31ba66Smrg                (other != master || dev != master->lastSlave))
28027e31ba66Smrg                continue;
28037e31ba66Smrg
28047e31ba66Smrg            _XkbSetMap(client, other, stuff, tmp); //ignore rc
28057e31ba66Smrg        }
28064642e01fSmrg    }
28074642e01fSmrg
28086747b715Smrg    return Success;
28094642e01fSmrg}
28104642e01fSmrg
281105b261ecSmrg/***====================================================================***/
281205b261ecSmrg
281305b261ecSmrgstatic Status
2814f7df2e56SmrgXkbComputeGetCompatMapReplySize(XkbCompatMapPtr compat,
2815f7df2e56Smrg                                xkbGetCompatMapReply * rep)
281605b261ecSmrg{
2817f7df2e56Smrg    unsigned size, nGroups;
2818f7df2e56Smrg
2819f7df2e56Smrg    nGroups = 0;
2820f7df2e56Smrg    if (rep->groups != 0) {
2821f7df2e56Smrg        register int i, bit;
2822f7df2e56Smrg
2823f7df2e56Smrg        for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2824f7df2e56Smrg            if (rep->groups & bit)
2825f7df2e56Smrg                nGroups++;
2826f7df2e56Smrg        }
2827f7df2e56Smrg    }
2828f7df2e56Smrg    size = nGroups * SIZEOF(xkbModsWireDesc);
2829f7df2e56Smrg    size += (rep->nSI * SIZEOF(xkbSymInterpretWireDesc));
2830f7df2e56Smrg    rep->length = size / 4;
283105b261ecSmrg    return Success;
283205b261ecSmrg}
283305b261ecSmrg
283405b261ecSmrgstatic int
2835f7df2e56SmrgXkbSendCompatMap(ClientPtr client,
2836f7df2e56Smrg                 XkbCompatMapPtr compat, xkbGetCompatMapReply * rep)
283705b261ecSmrg{
2838f7df2e56Smrg    char *data;
2839f7df2e56Smrg    int size;
2840f7df2e56Smrg
2841f7df2e56Smrg    if (rep->length > 0) {
2842f7df2e56Smrg        data = xallocarray(rep->length, 4);
2843f7df2e56Smrg        if (data) {
2844f7df2e56Smrg            register unsigned i, bit;
2845f7df2e56Smrg            xkbModsWireDesc *grp;
2846f7df2e56Smrg            XkbSymInterpretPtr sym = &compat->sym_interpret[rep->firstSI];
2847f7df2e56Smrg            xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *) data;
2848f7df2e56Smrg
2849f7df2e56Smrg            size = rep->length * 4;
2850f7df2e56Smrg
2851f7df2e56Smrg            for (i = 0; i < rep->nSI; i++, sym++, wire++) {
2852f7df2e56Smrg                wire->sym = sym->sym;
2853f7df2e56Smrg                wire->mods = sym->mods;
2854f7df2e56Smrg                wire->match = sym->match;
2855f7df2e56Smrg                wire->virtualMod = sym->virtual_mod;
2856f7df2e56Smrg                wire->flags = sym->flags;
2857f7df2e56Smrg                memcpy((char *) &wire->act, (char *) &sym->act,
2858f7df2e56Smrg                       sz_xkbActionWireDesc);
2859f7df2e56Smrg                if (client->swapped) {
2860f7df2e56Smrg                    swapl(&wire->sym);
2861f7df2e56Smrg                }
2862f7df2e56Smrg            }
2863f7df2e56Smrg            if (rep->groups) {
2864f7df2e56Smrg                grp = (xkbModsWireDesc *) wire;
2865f7df2e56Smrg                for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2866f7df2e56Smrg                    if (rep->groups & bit) {
2867f7df2e56Smrg                        grp->mask = compat->groups[i].mask;
2868f7df2e56Smrg                        grp->realMods = compat->groups[i].real_mods;
2869f7df2e56Smrg                        grp->virtualMods = compat->groups[i].vmods;
2870f7df2e56Smrg                        if (client->swapped) {
2871f7df2e56Smrg                            swaps(&grp->virtualMods);
2872f7df2e56Smrg                        }
2873f7df2e56Smrg                        grp++;
2874f7df2e56Smrg                    }
2875f7df2e56Smrg                }
2876f7df2e56Smrg                wire = (xkbSymInterpretWireDesc *) grp;
2877f7df2e56Smrg            }
2878f7df2e56Smrg        }
2879f7df2e56Smrg        else
2880f7df2e56Smrg            return BadAlloc;
2881f7df2e56Smrg    }
2882f7df2e56Smrg    else
2883f7df2e56Smrg        data = NULL;
288405b261ecSmrg
288505b261ecSmrg    if (client->swapped) {
2886f7df2e56Smrg        swaps(&rep->sequenceNumber);
2887f7df2e56Smrg        swapl(&rep->length);
2888f7df2e56Smrg        swaps(&rep->firstSI);
2889f7df2e56Smrg        swaps(&rep->nSI);
2890f7df2e56Smrg        swaps(&rep->nTotalSI);
289105b261ecSmrg    }
289205b261ecSmrg
2893f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetCompatMapReply), rep);
289405b261ecSmrg    if (data) {
2895f7df2e56Smrg        WriteToClient(client, size, data);
2896f7df2e56Smrg        free((char *) data);
289705b261ecSmrg    }
28986747b715Smrg    return Success;
289905b261ecSmrg}
290005b261ecSmrg
290105b261ecSmrgint
290205b261ecSmrgProcXkbGetCompatMap(ClientPtr client)
290305b261ecSmrg{
2904f7df2e56Smrg    xkbGetCompatMapReply rep;
2905f7df2e56Smrg    DeviceIntPtr dev;
2906f7df2e56Smrg    XkbDescPtr xkb;
2907f7df2e56Smrg    XkbCompatMapPtr compat;
290805b261ecSmrg
290905b261ecSmrg    REQUEST(xkbGetCompatMapReq);
291005b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetCompatMapReq);
291105b261ecSmrg
2912f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
2913f7df2e56Smrg        return BadAccess;
291405b261ecSmrg
29154642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
291605b261ecSmrg
291705b261ecSmrg    xkb = dev->key->xkbInfo->desc;
2918f7df2e56Smrg    compat = xkb->compat;
291905b261ecSmrg
2920f7df2e56Smrg    rep = (xkbGetCompatMapReply) {
2921f7df2e56Smrg        .type = X_Reply,
2922f7df2e56Smrg        .sequenceNumber = client->sequence,
2923f7df2e56Smrg        .length = 0,
2924f7df2e56Smrg        .deviceID = dev->id,
2925f7df2e56Smrg        .firstSI = stuff->firstSI,
2926f7df2e56Smrg        .nSI = stuff->nSI
2927f7df2e56Smrg    };
292805b261ecSmrg    if (stuff->getAllSI) {
2929f7df2e56Smrg        rep.firstSI = 0;
2930f7df2e56Smrg        rep.nSI = compat->num_si;
293105b261ecSmrg    }
2932f7df2e56Smrg    else if ((((unsigned) stuff->nSI) > 0) &&
2933f7df2e56Smrg             ((unsigned) (stuff->firstSI + stuff->nSI - 1) >= compat->num_si)) {
2934f7df2e56Smrg        client->errorValue = _XkbErrCode2(0x05, compat->num_si);
2935f7df2e56Smrg        return BadValue;
293605b261ecSmrg    }
293705b261ecSmrg    rep.nTotalSI = compat->num_si;
2938f7df2e56Smrg    rep.groups = stuff->groups;
2939f7df2e56Smrg    XkbComputeGetCompatMapReplySize(compat, &rep);
2940f7df2e56Smrg    return XkbSendCompatMap(client, compat, &rep);
294105b261ecSmrg}
294205b261ecSmrg
29434642e01fSmrg/**
29444642e01fSmrg * Apply the given request on the given device.
29456747b715Smrg * If dryRun is TRUE, then value checks are performed, but the device isn't
29464642e01fSmrg * modified.
29474642e01fSmrg */
29484642e01fSmrgstatic int
29494642e01fSmrg_XkbSetCompatMap(ClientPtr client, DeviceIntPtr dev,
2950f7df2e56Smrg                 xkbSetCompatMapReq * req, char *data, BOOL dryRun)
295105b261ecSmrg{
2952f7df2e56Smrg    XkbSrvInfoPtr xkbi;
2953f7df2e56Smrg    XkbDescPtr xkb;
2954f7df2e56Smrg    XkbCompatMapPtr compat;
2955f7df2e56Smrg    int nGroups;
2956f7df2e56Smrg    unsigned i, bit;
295705b261ecSmrg
295805b261ecSmrg    xkbi = dev->key->xkbInfo;
29594642e01fSmrg    xkb = xkbi->desc;
29604642e01fSmrg    compat = xkb->compat;
29614642e01fSmrg
2962f7df2e56Smrg    if ((req->nSI > 0) || (req->truncateSI)) {
2963f7df2e56Smrg        xkbSymInterpretWireDesc *wire;
2964f7df2e56Smrg
2965f7df2e56Smrg        if (req->firstSI > compat->num_si) {
2966f7df2e56Smrg            client->errorValue = _XkbErrCode2(0x02, compat->num_si);
2967f7df2e56Smrg            return BadValue;
2968f7df2e56Smrg        }
2969f7df2e56Smrg        wire = (xkbSymInterpretWireDesc *) data;
2970f7df2e56Smrg        wire += req->nSI;
2971f7df2e56Smrg        data = (char *) wire;
297205b261ecSmrg    }
29734642e01fSmrg
2974f7df2e56Smrg    nGroups = 0;
2975f7df2e56Smrg    if (req->groups != 0) {
2976f7df2e56Smrg        for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2977f7df2e56Smrg            if (req->groups & bit)
2978f7df2e56Smrg                nGroups++;
2979f7df2e56Smrg        }
298005b261ecSmrg    }
2981f7df2e56Smrg    data += nGroups * SIZEOF(xkbModsWireDesc);
2982f7df2e56Smrg    if (((data - ((char *) req)) / 4) != req->length) {
2983f7df2e56Smrg        return BadLength;
298405b261ecSmrg    }
29854642e01fSmrg
29864642e01fSmrg    /* Done all the checks we can do */
29874642e01fSmrg    if (dryRun)
29884642e01fSmrg        return Success;
29894642e01fSmrg
2990f7df2e56Smrg    data = (char *) &req[1];
2991f7df2e56Smrg    if (req->nSI > 0) {
2992f7df2e56Smrg        xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *) data;
2993f7df2e56Smrg        XkbSymInterpretPtr sym;
2994f7df2e56Smrg        unsigned int skipped = 0;
2995f7df2e56Smrg
2996f7df2e56Smrg        if ((unsigned) (req->firstSI + req->nSI) > compat->num_si) {
2997f7df2e56Smrg            compat->num_si = req->firstSI + req->nSI;
2998f7df2e56Smrg            compat->sym_interpret = reallocarray(compat->sym_interpret,
2999f7df2e56Smrg                                                 compat->num_si,
3000f7df2e56Smrg                                                 sizeof(XkbSymInterpretRec));
3001f7df2e56Smrg            if (!compat->sym_interpret) {
3002f7df2e56Smrg                compat->num_si = 0;
3003f7df2e56Smrg                return BadAlloc;
3004f7df2e56Smrg            }
3005f7df2e56Smrg        }
3006f7df2e56Smrg        else if (req->truncateSI) {
3007f7df2e56Smrg            compat->num_si = req->firstSI + req->nSI;
3008f7df2e56Smrg        }
3009f7df2e56Smrg        sym = &compat->sym_interpret[req->firstSI];
3010f7df2e56Smrg        for (i = 0; i < req->nSI; i++, wire++) {
3011f7df2e56Smrg            if (client->swapped) {
3012f7df2e56Smrg                swapl(&wire->sym);
3013f7df2e56Smrg            }
3014f7df2e56Smrg            if (wire->sym == NoSymbol && wire->match == XkbSI_AnyOfOrNone &&
3015f7df2e56Smrg                (wire->mods & 0xff) == 0xff &&
3016f7df2e56Smrg                wire->act.type == XkbSA_XFree86Private) {
3017f7df2e56Smrg                ErrorF("XKB: Skipping broken Any+AnyOfOrNone(All) -> Private "
3018f7df2e56Smrg                       "action from client\n");
3019f7df2e56Smrg                skipped++;
3020f7df2e56Smrg                continue;
3021f7df2e56Smrg            }
3022f7df2e56Smrg            sym->sym = wire->sym;
3023f7df2e56Smrg            sym->mods = wire->mods;
3024f7df2e56Smrg            sym->match = wire->match;
3025f7df2e56Smrg            sym->flags = wire->flags;
3026f7df2e56Smrg            sym->virtual_mod = wire->virtualMod;
3027f7df2e56Smrg            memcpy((char *) &sym->act, (char *) &wire->act,
3028f7df2e56Smrg                   SIZEOF(xkbActionWireDesc));
3029f7df2e56Smrg            sym++;
3030f7df2e56Smrg        }
3031f7df2e56Smrg        if (skipped) {
3032f7df2e56Smrg            if (req->firstSI + req->nSI < compat->num_si)
3033f7df2e56Smrg                memmove(sym, sym + skipped,
3034f7df2e56Smrg                        (compat->num_si - req->firstSI - req->nSI) *
3035f7df2e56Smrg                        sizeof(*sym));
3036f7df2e56Smrg            compat->num_si -= skipped;
3037f7df2e56Smrg        }
3038f7df2e56Smrg        data = (char *) wire;
303905b261ecSmrg    }
30404642e01fSmrg    else if (req->truncateSI) {
3041f7df2e56Smrg        compat->num_si = req->firstSI;
3042f7df2e56Smrg    }
3043f7df2e56Smrg
3044f7df2e56Smrg    if (req->groups != 0) {
3045f7df2e56Smrg        xkbModsWireDesc *wire = (xkbModsWireDesc *) data;
3046f7df2e56Smrg
3047f7df2e56Smrg        for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
3048f7df2e56Smrg            if (req->groups & bit) {
3049f7df2e56Smrg                if (client->swapped) {
3050f7df2e56Smrg                    swaps(&wire->virtualMods);
3051f7df2e56Smrg                }
3052f7df2e56Smrg                compat->groups[i].mask = wire->realMods;
3053f7df2e56Smrg                compat->groups[i].real_mods = wire->realMods;
3054f7df2e56Smrg                compat->groups[i].vmods = wire->virtualMods;
3055f7df2e56Smrg                if (wire->virtualMods != 0) {
3056f7df2e56Smrg                    unsigned tmp;
3057f7df2e56Smrg
3058f7df2e56Smrg                    tmp = XkbMaskForVMask(xkb, wire->virtualMods);
3059f7df2e56Smrg                    compat->groups[i].mask |= tmp;
3060f7df2e56Smrg                }
3061f7df2e56Smrg                data += SIZEOF(xkbModsWireDesc);
3062f7df2e56Smrg                wire = (xkbModsWireDesc *) data;
3063f7df2e56Smrg            }
3064f7df2e56Smrg        }
3065f7df2e56Smrg    }
3066f7df2e56Smrg    i = XkbPaddedSize((data - ((char *) req)));
3067f7df2e56Smrg    if ((i / 4) != req->length) {
3068f7df2e56Smrg        ErrorF("[xkb] Internal length error on read in _XkbSetCompatMap\n");
3069f7df2e56Smrg        return BadLength;
307005b261ecSmrg    }
30714642e01fSmrg
307205b261ecSmrg    if (dev->xkb_interest) {
3073f7df2e56Smrg        xkbCompatMapNotify ev;
3074f7df2e56Smrg
3075f7df2e56Smrg        ev.deviceID = dev->id;
3076f7df2e56Smrg        ev.changedGroups = req->groups;
3077f7df2e56Smrg        ev.firstSI = req->firstSI;
3078f7df2e56Smrg        ev.nSI = req->nSI;
3079f7df2e56Smrg        ev.nTotalSI = compat->num_si;
3080f7df2e56Smrg        XkbSendCompatMapNotify(dev, &ev);
308105b261ecSmrg    }
308205b261ecSmrg
30834642e01fSmrg    if (req->recomputeActions) {
3084f7df2e56Smrg        XkbChangesRec change;
3085f7df2e56Smrg        unsigned check;
3086f7df2e56Smrg        XkbEventCauseRec cause;
3087f7df2e56Smrg
3088f7df2e56Smrg        XkbSetCauseXkbReq(&cause, X_kbSetCompatMap, client);
3089f7df2e56Smrg        memset(&change, 0, sizeof(XkbChangesRec));
3090f7df2e56Smrg        XkbUpdateActions(dev, xkb->min_key_code, XkbNumKeys(xkb), &change,
3091f7df2e56Smrg                         &check, &cause);
3092f7df2e56Smrg        if (check)
3093f7df2e56Smrg            XkbCheckSecondaryEffects(xkbi, check, &change, &cause);
3094f7df2e56Smrg        XkbSendNotification(dev, &change, &cause);
309505b261ecSmrg    }
30964642e01fSmrg    return Success;
30974642e01fSmrg}
30984642e01fSmrg
30994642e01fSmrgint
31004642e01fSmrgProcXkbSetCompatMap(ClientPtr client)
31014642e01fSmrg{
3102f7df2e56Smrg    DeviceIntPtr dev;
3103f7df2e56Smrg    char *data;
3104f7df2e56Smrg    int rc;
31054642e01fSmrg
31064642e01fSmrg    REQUEST(xkbSetCompatMapReq);
31074642e01fSmrg    REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq);
31084642e01fSmrg
3109f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
3110f7df2e56Smrg        return BadAccess;
31114642e01fSmrg
31124642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
31134642e01fSmrg
3114f7df2e56Smrg    data = (char *) &stuff[1];
31154642e01fSmrg
31164642e01fSmrg    /* check first using a dry-run */
31174642e01fSmrg    rc = _XkbSetCompatMap(client, dev, stuff, data, TRUE);
31184642e01fSmrg    if (rc != Success)
31194642e01fSmrg        return rc;
3120f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
31214642e01fSmrg        DeviceIntPtr other;
3122f7df2e56Smrg
3123f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
3124f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
3125f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
3126f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
3127f7df2e56Smrg                              DixManageAccess);
3128f7df2e56Smrg                if (rc == Success) {
31294642e01fSmrg                    /* dry-run */
31304642e01fSmrg                    rc = _XkbSetCompatMap(client, other, stuff, data, TRUE);
31314642e01fSmrg                    if (rc != Success)
31324642e01fSmrg                        return rc;
31334642e01fSmrg                }
31344642e01fSmrg            }
31354642e01fSmrg        }
31364642e01fSmrg    }
31374642e01fSmrg
31384642e01fSmrg    /* Yay, the dry-runs succeed. Let's apply */
31394642e01fSmrg    rc = _XkbSetCompatMap(client, dev, stuff, data, FALSE);
31404642e01fSmrg    if (rc != Success)
31414642e01fSmrg        return rc;
3142f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
31434642e01fSmrg        DeviceIntPtr other;
3144f7df2e56Smrg
3145f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
3146f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
3147f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
3148f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
3149f7df2e56Smrg                              DixManageAccess);
3150f7df2e56Smrg                if (rc == Success) {
31514642e01fSmrg                    rc = _XkbSetCompatMap(client, other, stuff, data, FALSE);
31524642e01fSmrg                    if (rc != Success)
31534642e01fSmrg                        return rc;
31544642e01fSmrg                }
31554642e01fSmrg            }
31564642e01fSmrg        }
31574642e01fSmrg    }
31584642e01fSmrg
31596747b715Smrg    return Success;
316005b261ecSmrg}
316105b261ecSmrg
316205b261ecSmrg/***====================================================================***/
316305b261ecSmrg
316405b261ecSmrgint
316505b261ecSmrgProcXkbGetIndicatorState(ClientPtr client)
316605b261ecSmrg{
3167f7df2e56Smrg    xkbGetIndicatorStateReply rep;
3168f7df2e56Smrg    XkbSrvLedInfoPtr sli;
3169f7df2e56Smrg    DeviceIntPtr dev;
317005b261ecSmrg
317105b261ecSmrg    REQUEST(xkbGetIndicatorStateReq);
317205b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq);
317305b261ecSmrg
3174f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
3175f7df2e56Smrg        return BadAccess;
317605b261ecSmrg
31774642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
317805b261ecSmrg
3179f7df2e56Smrg    sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
3180f7df2e56Smrg                            XkbXI_IndicatorStateMask);
318105b261ecSmrg    if (!sli)
3182f7df2e56Smrg        return BadAlloc;
318305b261ecSmrg
3184f7df2e56Smrg    rep = (xkbGetIndicatorStateReply) {
3185f7df2e56Smrg        .type = X_Reply,
3186f7df2e56Smrg        .deviceID = dev->id,
3187f7df2e56Smrg        .sequenceNumber = client->sequence,
3188f7df2e56Smrg        .length = 0,
3189f7df2e56Smrg        .state = sli->effectiveState
3190f7df2e56Smrg    };
319105b261ecSmrg
319205b261ecSmrg    if (client->swapped) {
3193f7df2e56Smrg        swaps(&rep.sequenceNumber);
3194f7df2e56Smrg        swapl(&rep.state);
319505b261ecSmrg    }
3196f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetIndicatorStateReply), &rep);
31976747b715Smrg    return Success;
319805b261ecSmrg}
319905b261ecSmrg
320005b261ecSmrg/***====================================================================***/
320105b261ecSmrg
320205b261ecSmrgstatic Status
3203f7df2e56SmrgXkbComputeGetIndicatorMapReplySize(XkbIndicatorPtr indicators,
3204f7df2e56Smrg                                   xkbGetIndicatorMapReply * rep)
320505b261ecSmrg{
3206f7df2e56Smrg    register int i, bit;
3207f7df2e56Smrg    int nIndicators;
320805b261ecSmrg
320905b261ecSmrg    rep->realIndicators = indicators->phys_indicators;
3210f7df2e56Smrg    for (i = nIndicators = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3211f7df2e56Smrg        if (rep->which & bit)
3212f7df2e56Smrg            nIndicators++;
321305b261ecSmrg    }
3214f7df2e56Smrg    rep->length = (nIndicators * SIZEOF(xkbIndicatorMapWireDesc)) / 4;
3215f7df2e56Smrg    rep->nIndicators = nIndicators;
321605b261ecSmrg    return Success;
321705b261ecSmrg}
321805b261ecSmrg
321905b261ecSmrgstatic int
3220f7df2e56SmrgXkbSendIndicatorMap(ClientPtr client,
3221f7df2e56Smrg                    XkbIndicatorPtr indicators, xkbGetIndicatorMapReply * rep)
322205b261ecSmrg{
3223f7df2e56Smrg    int length;
3224f7df2e56Smrg    CARD8 *map;
3225f7df2e56Smrg    register int i;
3226f7df2e56Smrg    register unsigned bit;
3227f7df2e56Smrg
3228f7df2e56Smrg    if (rep->length > 0) {
3229f7df2e56Smrg        CARD8 *to;
3230f7df2e56Smrg
3231f7df2e56Smrg        to = map = xallocarray(rep->length, 4);
3232f7df2e56Smrg        if (map) {
3233f7df2e56Smrg            xkbIndicatorMapWireDesc *wire = (xkbIndicatorMapWireDesc *) to;
3234f7df2e56Smrg
3235f7df2e56Smrg            length = rep->length * 4;
3236f7df2e56Smrg
3237f7df2e56Smrg            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3238f7df2e56Smrg                if (rep->which & bit) {
3239f7df2e56Smrg                    wire->flags = indicators->maps[i].flags;
3240f7df2e56Smrg                    wire->whichGroups = indicators->maps[i].which_groups;
3241f7df2e56Smrg                    wire->groups = indicators->maps[i].groups;
3242f7df2e56Smrg                    wire->whichMods = indicators->maps[i].which_mods;
3243f7df2e56Smrg                    wire->mods = indicators->maps[i].mods.mask;
3244f7df2e56Smrg                    wire->realMods = indicators->maps[i].mods.real_mods;
3245f7df2e56Smrg                    wire->virtualMods = indicators->maps[i].mods.vmods;
3246f7df2e56Smrg                    wire->ctrls = indicators->maps[i].ctrls;
3247f7df2e56Smrg                    if (client->swapped) {
3248f7df2e56Smrg                        swaps(&wire->virtualMods);
3249f7df2e56Smrg                        swapl(&wire->ctrls);
3250f7df2e56Smrg                    }
3251f7df2e56Smrg                    wire++;
3252f7df2e56Smrg                }
3253f7df2e56Smrg            }
3254f7df2e56Smrg            to = (CARD8 *) wire;
3255f7df2e56Smrg            if ((to - map) != length) {
3256f7df2e56Smrg                client->errorValue = _XkbErrCode2(0xff, length);
3257f7df2e56Smrg                free(map);
3258f7df2e56Smrg                return BadLength;
3259f7df2e56Smrg            }
3260f7df2e56Smrg        }
3261f7df2e56Smrg        else
3262f7df2e56Smrg            return BadAlloc;
3263f7df2e56Smrg    }
3264f7df2e56Smrg    else
3265f7df2e56Smrg        map = NULL;
326605b261ecSmrg    if (client->swapped) {
3267f7df2e56Smrg        swaps(&rep->sequenceNumber);
3268f7df2e56Smrg        swapl(&rep->length);
3269f7df2e56Smrg        swapl(&rep->which);
3270f7df2e56Smrg        swapl(&rep->realIndicators);
327105b261ecSmrg    }
3272f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetIndicatorMapReply), rep);
327305b261ecSmrg    if (map) {
3274f7df2e56Smrg        WriteToClient(client, length, map);
3275f7df2e56Smrg        free((char *) map);
327605b261ecSmrg    }
32776747b715Smrg    return Success;
327805b261ecSmrg}
327905b261ecSmrg
328005b261ecSmrgint
328105b261ecSmrgProcXkbGetIndicatorMap(ClientPtr client)
328205b261ecSmrg{
3283f7df2e56Smrg    xkbGetIndicatorMapReply rep;
3284f7df2e56Smrg    DeviceIntPtr dev;
3285f7df2e56Smrg    XkbDescPtr xkb;
3286f7df2e56Smrg    XkbIndicatorPtr leds;
328705b261ecSmrg
328805b261ecSmrg    REQUEST(xkbGetIndicatorMapReq);
328905b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq);
329005b261ecSmrg
3291f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
3292f7df2e56Smrg        return BadAccess;
329305b261ecSmrg
32944642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
329505b261ecSmrg
3296f7df2e56Smrg    xkb = dev->key->xkbInfo->desc;
3297f7df2e56Smrg    leds = xkb->indicators;
3298f7df2e56Smrg
3299f7df2e56Smrg    rep = (xkbGetIndicatorMapReply) {
3300f7df2e56Smrg        .type = X_Reply,
3301f7df2e56Smrg        .deviceID = dev->id,
3302f7df2e56Smrg        .sequenceNumber = client->sequence,
3303f7df2e56Smrg        .length = 0,
3304f7df2e56Smrg        .which = stuff->which
3305f7df2e56Smrg    };
3306f7df2e56Smrg    XkbComputeGetIndicatorMapReplySize(leds, &rep);
3307f7df2e56Smrg    return XkbSendIndicatorMap(client, leds, &rep);
330805b261ecSmrg}
330905b261ecSmrg
33104642e01fSmrg/**
33114642e01fSmrg * Apply the given map to the given device. Which specifies which components
33124642e01fSmrg * to apply.
33134642e01fSmrg */
33144642e01fSmrgstatic int
33154642e01fSmrg_XkbSetIndicatorMap(ClientPtr client, DeviceIntPtr dev,
3316f7df2e56Smrg                    int which, xkbIndicatorMapWireDesc * desc)
33174642e01fSmrg{
3318f7df2e56Smrg    XkbSrvInfoPtr xkbi;
3319f7df2e56Smrg    XkbSrvLedInfoPtr sli;
3320f7df2e56Smrg    XkbEventCauseRec cause;
3321f7df2e56Smrg    int i, bit;
33224642e01fSmrg
33234642e01fSmrg    xkbi = dev->key->xkbInfo;
33244642e01fSmrg
3325f7df2e56Smrg    sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
3326f7df2e56Smrg                            XkbXI_IndicatorMapsMask);
33274642e01fSmrg    if (!sli)
3328f7df2e56Smrg        return BadAlloc;
33294642e01fSmrg
33304642e01fSmrg    for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3331f7df2e56Smrg        if (which & bit) {
3332f7df2e56Smrg            sli->maps[i].flags = desc->flags;
3333f7df2e56Smrg            sli->maps[i].which_groups = desc->whichGroups;
3334f7df2e56Smrg            sli->maps[i].groups = desc->groups;
3335f7df2e56Smrg            sli->maps[i].which_mods = desc->whichMods;
3336f7df2e56Smrg            sli->maps[i].mods.mask = desc->mods;
3337f7df2e56Smrg            sli->maps[i].mods.real_mods = desc->mods;
3338f7df2e56Smrg            sli->maps[i].mods.vmods = desc->virtualMods;
3339f7df2e56Smrg            sli->maps[i].ctrls = desc->ctrls;
3340f7df2e56Smrg            if (desc->virtualMods != 0) {
3341f7df2e56Smrg                unsigned tmp;
3342f7df2e56Smrg
3343f7df2e56Smrg                tmp = XkbMaskForVMask(xkbi->desc, desc->virtualMods);
3344f7df2e56Smrg                sli->maps[i].mods.mask = desc->mods | tmp;
3345f7df2e56Smrg            }
3346f7df2e56Smrg            desc++;
3347f7df2e56Smrg        }
3348f7df2e56Smrg    }
3349f7df2e56Smrg
3350f7df2e56Smrg    XkbSetCauseXkbReq(&cause, X_kbSetIndicatorMap, client);
3351f7df2e56Smrg    XkbApplyLedMapChanges(dev, sli, which, NULL, NULL, &cause);
33524642e01fSmrg
33534642e01fSmrg    return Success;
33544642e01fSmrg}
33554642e01fSmrg
335605b261ecSmrgint
335705b261ecSmrgProcXkbSetIndicatorMap(ClientPtr client)
335805b261ecSmrg{
3359f7df2e56Smrg    int i, bit;
3360f7df2e56Smrg    int nIndicators;
3361f7df2e56Smrg    DeviceIntPtr dev;
3362f7df2e56Smrg    xkbIndicatorMapWireDesc *from;
3363f7df2e56Smrg    int rc;
336405b261ecSmrg
336505b261ecSmrg    REQUEST(xkbSetIndicatorMapReq);
336605b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq);
336705b261ecSmrg
3368f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
3369f7df2e56Smrg        return BadAccess;
337005b261ecSmrg
33714642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
337205b261ecSmrg
3373f7df2e56Smrg    if (stuff->which == 0)
3374f7df2e56Smrg        return Success;
337505b261ecSmrg
3376f7df2e56Smrg    for (nIndicators = i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3377f7df2e56Smrg        if (stuff->which & bit)
3378f7df2e56Smrg            nIndicators++;
337905b261ecSmrg    }
3380f7df2e56Smrg    if (stuff->length != ((SIZEOF(xkbSetIndicatorMapReq) +
3381f7df2e56Smrg                           (nIndicators * SIZEOF(xkbIndicatorMapWireDesc))) /
3382f7df2e56Smrg                          4)) {
3383f7df2e56Smrg        return BadLength;
338405b261ecSmrg    }
338505b261ecSmrg
3386f7df2e56Smrg    from = (xkbIndicatorMapWireDesc *) &stuff[1];
3387f7df2e56Smrg    for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3388f7df2e56Smrg        if (stuff->which & bit) {
3389f7df2e56Smrg            if (client->swapped) {
3390f7df2e56Smrg                swaps(&from->virtualMods);
3391f7df2e56Smrg                swapl(&from->ctrls);
3392f7df2e56Smrg            }
3393f7df2e56Smrg            CHK_MASK_LEGAL(i, from->whichGroups, XkbIM_UseAnyGroup);
3394f7df2e56Smrg            CHK_MASK_LEGAL(i, from->whichMods, XkbIM_UseAnyMods);
3395f7df2e56Smrg            from++;
3396f7df2e56Smrg        }
339705b261ecSmrg    }
339805b261ecSmrg
3399f7df2e56Smrg    from = (xkbIndicatorMapWireDesc *) &stuff[1];
34004642e01fSmrg    rc = _XkbSetIndicatorMap(client, dev, stuff->which, from);
34014642e01fSmrg    if (rc != Success)
34024642e01fSmrg        return rc;
34034642e01fSmrg
3404f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
34054642e01fSmrg        DeviceIntPtr other;
3406f7df2e56Smrg
3407f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
3408f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
3409f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
3410f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
3411f7df2e56Smrg                              DixSetAttrAccess);
34124642e01fSmrg                if (rc == Success)
34134642e01fSmrg                    _XkbSetIndicatorMap(client, other, stuff->which, from);
34144642e01fSmrg            }
34154642e01fSmrg        }
341605b261ecSmrg    }
341705b261ecSmrg
34184642e01fSmrg    return Success;
341905b261ecSmrg}
342005b261ecSmrg
342105b261ecSmrg/***====================================================================***/
342205b261ecSmrg
342305b261ecSmrgint
342405b261ecSmrgProcXkbGetNamedIndicator(ClientPtr client)
342505b261ecSmrg{
3426f7df2e56Smrg    DeviceIntPtr dev;
3427f7df2e56Smrg    xkbGetNamedIndicatorReply rep;
3428f7df2e56Smrg    register int i = 0;
3429f7df2e56Smrg    XkbSrvLedInfoPtr sli;
3430f7df2e56Smrg    XkbIndicatorMapPtr map = NULL;
343105b261ecSmrg
343205b261ecSmrg    REQUEST(xkbGetNamedIndicatorReq);
343305b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq);
343405b261ecSmrg
3435f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
3436f7df2e56Smrg        return BadAccess;
343705b261ecSmrg
34384642e01fSmrg    CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
343905b261ecSmrg    CHK_ATOM_ONLY(stuff->indicator);
344005b261ecSmrg
3441f7df2e56Smrg    sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID, 0);
344205b261ecSmrg    if (!sli)
3443f7df2e56Smrg        return BadAlloc;
3444f7df2e56Smrg
3445f7df2e56Smrg    i = 0;
3446f7df2e56Smrg    map = NULL;
3447f7df2e56Smrg    if ((sli->names) && (sli->maps)) {
3448f7df2e56Smrg        for (i = 0; i < XkbNumIndicators; i++) {
3449f7df2e56Smrg            if (stuff->indicator == sli->names[i]) {
3450f7df2e56Smrg                map = &sli->maps[i];
345105b261ecSmrg                break;
345205b261ecSmrg            }
345305b261ecSmrg        }
345405b261ecSmrg    }
345505b261ecSmrg
3456f7df2e56Smrg    rep = (xkbGetNamedIndicatorReply) {
3457f7df2e56Smrg        .type = X_Reply,
3458f7df2e56Smrg        .sequenceNumber = client->sequence,
3459f7df2e56Smrg        .length = 0,
3460f7df2e56Smrg        .deviceID = dev->id,
3461f7df2e56Smrg        .indicator = stuff->indicator
3462f7df2e56Smrg    };
3463f7df2e56Smrg    if (map != NULL) {
3464f7df2e56Smrg        rep.found = TRUE;
3465f7df2e56Smrg        rep.on = ((sli->effectiveState & (1 << i)) != 0);
3466f7df2e56Smrg        rep.realIndicator = ((sli->physIndicators & (1 << i)) != 0);
3467f7df2e56Smrg        rep.ndx = i;
3468f7df2e56Smrg        rep.flags = map->flags;
3469f7df2e56Smrg        rep.whichGroups = map->which_groups;
3470f7df2e56Smrg        rep.groups = map->groups;
3471f7df2e56Smrg        rep.whichMods = map->which_mods;
3472f7df2e56Smrg        rep.mods = map->mods.mask;
3473f7df2e56Smrg        rep.realMods = map->mods.real_mods;
3474f7df2e56Smrg        rep.virtualMods = map->mods.vmods;
3475f7df2e56Smrg        rep.ctrls = map->ctrls;
3476f7df2e56Smrg        rep.supported = TRUE;
3477f7df2e56Smrg    }
3478f7df2e56Smrg    else {
3479f7df2e56Smrg        rep.found = FALSE;
3480f7df2e56Smrg        rep.on = FALSE;
3481f7df2e56Smrg        rep.realIndicator = FALSE;
3482f7df2e56Smrg        rep.ndx = XkbNoIndicator;
3483f7df2e56Smrg        rep.flags = 0;
3484f7df2e56Smrg        rep.whichGroups = 0;
3485f7df2e56Smrg        rep.groups = 0;
3486f7df2e56Smrg        rep.whichMods = 0;
3487f7df2e56Smrg        rep.mods = 0;
3488f7df2e56Smrg        rep.realMods = 0;
3489f7df2e56Smrg        rep.virtualMods = 0;
3490f7df2e56Smrg        rep.ctrls = 0;
3491f7df2e56Smrg        rep.supported = TRUE;
3492f7df2e56Smrg    }
3493f7df2e56Smrg    if (client->swapped) {
3494f7df2e56Smrg        swapl(&rep.length);
3495f7df2e56Smrg        swaps(&rep.sequenceNumber);
3496f7df2e56Smrg        swapl(&rep.indicator);
3497f7df2e56Smrg        swaps(&rep.virtualMods);
3498f7df2e56Smrg        swapl(&rep.ctrls);
3499f7df2e56Smrg    }
3500f7df2e56Smrg
3501f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetNamedIndicatorReply), &rep);
35026747b715Smrg    return Success;
350305b261ecSmrg}
350405b261ecSmrg
35054642e01fSmrg/**
35064642e01fSmrg * Find the IM on the device.
35074642e01fSmrg * Returns the map, or NULL if the map doesn't exist.
35084642e01fSmrg * If the return value is NULL, led_return is undefined. Otherwise, led_return
35094642e01fSmrg * is set to the led index of the map.
35104642e01fSmrg */
35114642e01fSmrgstatic XkbIndicatorMapPtr
3512f7df2e56Smrg_XkbFindNamedIndicatorMap(XkbSrvLedInfoPtr sli, Atom indicator, int *led_return)
35134642e01fSmrg{
3514f7df2e56Smrg    XkbIndicatorMapPtr map;
351505b261ecSmrg
35164642e01fSmrg    /* search for the right indicator */
35174642e01fSmrg    map = NULL;
351805b261ecSmrg    if (sli->names && sli->maps) {
3519f7df2e56Smrg        int led;
35206747b715Smrg
3521f7df2e56Smrg        for (led = 0; (led < XkbNumIndicators) && (map == NULL); led++) {
3522f7df2e56Smrg            if (sli->names[led] == indicator) {
3523f7df2e56Smrg                map = &sli->maps[led];
3524f7df2e56Smrg                *led_return = led;
3525f7df2e56Smrg                break;
3526f7df2e56Smrg            }
3527f7df2e56Smrg        }
352805b261ecSmrg    }
352905b261ecSmrg
35304642e01fSmrg    return map;
35314642e01fSmrg}
35324642e01fSmrg
35334642e01fSmrg/**
35346747b715Smrg * Creates an indicator map on the device. If dryRun is TRUE, it only checks
35354642e01fSmrg * if creation is possible, but doesn't actually create it.
35364642e01fSmrg */
35374642e01fSmrgstatic int
35384642e01fSmrg_XkbCreateIndicatorMap(DeviceIntPtr dev, Atom indicator,
35394642e01fSmrg                       int ledClass, int ledID,
3540f7df2e56Smrg                       XkbIndicatorMapPtr * map_return, int *led_return,
35414642e01fSmrg                       Bool dryRun)
35424642e01fSmrg{
3543f7df2e56Smrg    XkbSrvLedInfoPtr sli;
3544f7df2e56Smrg    XkbIndicatorMapPtr map;
3545f7df2e56Smrg    int led;
35464642e01fSmrg
35474642e01fSmrg    sli = XkbFindSrvLedInfo(dev, ledClass, ledID, XkbXI_IndicatorsMask);
35484642e01fSmrg    if (!sli)
35494642e01fSmrg        return BadAlloc;
35504642e01fSmrg
35514642e01fSmrg    map = _XkbFindNamedIndicatorMap(sli, indicator, &led);
35524642e01fSmrg
3553f7df2e56Smrg    if (!map) {
35544642e01fSmrg        /* find first unused indicator maps and assign the name to it */
3555f7df2e56Smrg        for (led = 0, map = NULL; (led < XkbNumIndicators) && (map == NULL);
3556f7df2e56Smrg             led++) {
35574642e01fSmrg            if ((sli->names) && (sli->maps) && (sli->names[led] == None) &&
3558f7df2e56Smrg                (!XkbIM_InUse(&sli->maps[led]))) {
35594642e01fSmrg                map = &sli->maps[led];
35604642e01fSmrg                if (!dryRun)
35614642e01fSmrg                    sli->names[led] = indicator;
35624642e01fSmrg                break;
35634642e01fSmrg            }
35644642e01fSmrg        }
35654642e01fSmrg    }
35664642e01fSmrg
35674642e01fSmrg    if (!map)
35684642e01fSmrg        return BadAlloc;
35694642e01fSmrg
35704642e01fSmrg    *led_return = led;
35714642e01fSmrg    *map_return = map;
35724642e01fSmrg    return Success;
35734642e01fSmrg}
35744642e01fSmrg
35754642e01fSmrgstatic int
35764642e01fSmrg_XkbSetNamedIndicator(ClientPtr client, DeviceIntPtr dev,
3577f7df2e56Smrg                      xkbSetNamedIndicatorReq * stuff)
35784642e01fSmrg{
3579f7df2e56Smrg    unsigned int extDevReason;
3580f7df2e56Smrg    unsigned int statec, namec, mapc;
3581f7df2e56Smrg    XkbSrvLedInfoPtr sli;
3582f7df2e56Smrg    int led = 0;
3583f7df2e56Smrg    XkbIndicatorMapPtr map;
3584f7df2e56Smrg    DeviceIntPtr kbd;
3585f7df2e56Smrg    XkbEventCauseRec cause;
3586f7df2e56Smrg    xkbExtensionDeviceNotify ed;
3587f7df2e56Smrg    XkbChangesRec changes;
3588f7df2e56Smrg    int rc;
35894642e01fSmrg
35904642e01fSmrg    rc = _XkbCreateIndicatorMap(dev, stuff->indicator, stuff->ledClass,
35914642e01fSmrg                                stuff->ledID, &map, &led, FALSE);
3592f7df2e56Smrg    if (rc != Success || !map)  /* oh-oh */
35934642e01fSmrg        return rc;
35944642e01fSmrg
35954642e01fSmrg    sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID,
35964642e01fSmrg                            XkbXI_IndicatorsMask);
35974642e01fSmrg    if (!sli)
35984642e01fSmrg        return BadAlloc;
35994642e01fSmrg
36004642e01fSmrg    namec = mapc = statec = 0;
36014642e01fSmrg    extDevReason = 0;
36024642e01fSmrg
3603f7df2e56Smrg    namec |= (1 << led);
36044642e01fSmrg    sli->namesPresent |= ((stuff->indicator != None) ? (1 << led) : 0);
36054642e01fSmrg    extDevReason |= XkbXI_IndicatorNamesMask;
36064642e01fSmrg
36074642e01fSmrg    if (stuff->setMap) {
36084642e01fSmrg        map->flags = stuff->flags;
36094642e01fSmrg        map->which_groups = stuff->whichGroups;
36104642e01fSmrg        map->groups = stuff->groups;
36114642e01fSmrg        map->which_mods = stuff->whichMods;
36124642e01fSmrg        map->mods.mask = stuff->realMods;
36134642e01fSmrg        map->mods.real_mods = stuff->realMods;
3614f7df2e56Smrg        map->mods.vmods = stuff->virtualMods;
36154642e01fSmrg        map->ctrls = stuff->ctrls;
3616f7df2e56Smrg        mapc |= (1 << led);
36174642e01fSmrg    }
36184642e01fSmrg
3619f7df2e56Smrg    if ((stuff->setState) && ((map->flags & XkbIM_NoExplicit) == 0)) {
3620f7df2e56Smrg        if (stuff->on)
3621f7df2e56Smrg            sli->explicitState |= (1 << led);
3622f7df2e56Smrg        else
3623f7df2e56Smrg            sli->explicitState &= ~(1 << led);
36244642e01fSmrg        statec |= ((sli->effectiveState ^ sli->explicitState) & (1 << led));
362505b261ecSmrg    }
36264642e01fSmrg
3627f7df2e56Smrg    memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify));
3628f7df2e56Smrg    memset((char *) &changes, 0, sizeof(XkbChangesRec));
3629f7df2e56Smrg    XkbSetCauseXkbReq(&cause, X_kbSetNamedIndicator, client);
363005b261ecSmrg    if (namec)
3631f7df2e56Smrg        XkbApplyLedNameChanges(dev, sli, namec, &ed, &changes, &cause);
363205b261ecSmrg    if (mapc)
3633f7df2e56Smrg        XkbApplyLedMapChanges(dev, sli, mapc, &ed, &changes, &cause);
363405b261ecSmrg    if (statec)
3635f7df2e56Smrg        XkbApplyLedStateChanges(dev, sli, statec, &ed, &changes, &cause);
363605b261ecSmrg
36374642e01fSmrg    kbd = dev;
3638f7df2e56Smrg    if ((sli->flags & XkbSLI_HasOwnState) == 0)
36394642e01fSmrg        kbd = inputInfo.keyboard;
36404642e01fSmrg    XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause);
36414642e01fSmrg
36424642e01fSmrg    return Success;
36434642e01fSmrg}
36444642e01fSmrg
36454642e01fSmrgint
36464642e01fSmrgProcXkbSetNamedIndicator(ClientPtr client)
36474642e01fSmrg{
3648f7df2e56Smrg    int rc;
3649f7df2e56Smrg    DeviceIntPtr dev;
3650f7df2e56Smrg    int led = 0;
3651f7df2e56Smrg    XkbIndicatorMapPtr map;
36524642e01fSmrg
36534642e01fSmrg    REQUEST(xkbSetNamedIndicatorReq);
36544642e01fSmrg    REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq);
36554642e01fSmrg
3656f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
3657f7df2e56Smrg        return BadAccess;
36584642e01fSmrg
36594642e01fSmrg    CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
36604642e01fSmrg    CHK_ATOM_ONLY(stuff->indicator);
3661f7df2e56Smrg    CHK_MASK_LEGAL(0x10, stuff->whichGroups, XkbIM_UseAnyGroup);
3662f7df2e56Smrg    CHK_MASK_LEGAL(0x11, stuff->whichMods, XkbIM_UseAnyMods);
36634642e01fSmrg
36644642e01fSmrg    /* Dry-run for checks */
36654642e01fSmrg    rc = _XkbCreateIndicatorMap(dev, stuff->indicator,
36664642e01fSmrg                                stuff->ledClass, stuff->ledID,
36674642e01fSmrg                                &map, &led, TRUE);
3668f7df2e56Smrg    if (rc != Success || !map)  /* couldn't be created or didn't exist */
36694642e01fSmrg        return rc;
36704642e01fSmrg
36714642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd ||
3672f7df2e56Smrg        stuff->deviceSpec == XkbUseCorePtr) {
36734642e01fSmrg        DeviceIntPtr other;
3674f7df2e56Smrg
3675f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
3676f7df2e56Smrg            if ((other != dev) && !IsMaster(other) &&
3677f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev && (other->kbdfeed ||
3678f7df2e56Smrg                                                             other->leds) &&
3679f7df2e56Smrg                (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess)
3680f7df2e56Smrg                 == Success)) {
36814642e01fSmrg                rc = _XkbCreateIndicatorMap(other, stuff->indicator,
3682f7df2e56Smrg                                            stuff->ledClass, stuff->ledID, &map,
3683f7df2e56Smrg                                            &led, TRUE);
36844642e01fSmrg                if (rc != Success || !map)
36854642e01fSmrg                    return rc;
36864642e01fSmrg            }
36874642e01fSmrg        }
36884642e01fSmrg    }
36894642e01fSmrg
36904642e01fSmrg    /* All checks passed, let's do it */
36914642e01fSmrg    rc = _XkbSetNamedIndicator(client, dev, stuff);
36924642e01fSmrg    if (rc != Success)
36934642e01fSmrg        return rc;
36944642e01fSmrg
36954642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd ||
3696f7df2e56Smrg        stuff->deviceSpec == XkbUseCorePtr) {
36974642e01fSmrg        DeviceIntPtr other;
3698f7df2e56Smrg
3699f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
3700f7df2e56Smrg            if ((other != dev) && !IsMaster(other) &&
3701f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev && (other->kbdfeed ||
3702f7df2e56Smrg                                                             other->leds) &&
3703f7df2e56Smrg                (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess)
3704f7df2e56Smrg                 == Success)) {
37054642e01fSmrg                _XkbSetNamedIndicator(client, other, stuff);
37064642e01fSmrg            }
37074642e01fSmrg        }
37084642e01fSmrg    }
37094642e01fSmrg
37106747b715Smrg    return Success;
371105b261ecSmrg}
371205b261ecSmrg
371305b261ecSmrg/***====================================================================***/
371405b261ecSmrg
371505b261ecSmrgstatic CARD32
3716f7df2e56Smrg_XkbCountAtoms(Atom *atoms, int maxAtoms, int *count)
371705b261ecSmrg{
3718f7df2e56Smrg    register unsigned int i, bit, nAtoms;
3719f7df2e56Smrg    register CARD32 atomsPresent;
372005b261ecSmrg
3721f7df2e56Smrg    for (i = nAtoms = atomsPresent = 0, bit = 1; i < maxAtoms; i++, bit <<= 1) {
3722f7df2e56Smrg        if (atoms[i] != None) {
3723f7df2e56Smrg            atomsPresent |= bit;
3724f7df2e56Smrg            nAtoms++;
3725f7df2e56Smrg        }
372605b261ecSmrg    }
372705b261ecSmrg    if (count)
3728f7df2e56Smrg        *count = nAtoms;
372905b261ecSmrg    return atomsPresent;
373005b261ecSmrg}
373105b261ecSmrg
373205b261ecSmrgstatic char *
3733f7df2e56Smrg_XkbWriteAtoms(char *wire, Atom *atoms, int maxAtoms, int swap)
373405b261ecSmrg{
3735f7df2e56Smrg    register unsigned int i;
3736f7df2e56Smrg    Atom *atm;
3737f7df2e56Smrg
3738f7df2e56Smrg    atm = (Atom *) wire;
3739f7df2e56Smrg    for (i = 0; i < maxAtoms; i++) {
3740f7df2e56Smrg        if (atoms[i] != None) {
3741f7df2e56Smrg            *atm = atoms[i];
3742f7df2e56Smrg            if (swap) {
3743f7df2e56Smrg                swapl(atm);
3744f7df2e56Smrg            }
3745f7df2e56Smrg            atm++;
3746f7df2e56Smrg        }
3747f7df2e56Smrg    }
3748f7df2e56Smrg    return (char *) atm;
374905b261ecSmrg}
375005b261ecSmrg
375105b261ecSmrgstatic Status
3752f7df2e56SmrgXkbComputeGetNamesReplySize(XkbDescPtr xkb, xkbGetNamesReply * rep)
375305b261ecSmrg{
3754f7df2e56Smrg    register unsigned which, length;
3755f7df2e56Smrg    register int i;
3756f7df2e56Smrg
3757f7df2e56Smrg    rep->minKeyCode = xkb->min_key_code;
3758f7df2e56Smrg    rep->maxKeyCode = xkb->max_key_code;
3759f7df2e56Smrg    which = rep->which;
3760f7df2e56Smrg    length = 0;
3761f7df2e56Smrg    if (xkb->names != NULL) {
3762f7df2e56Smrg        if (which & XkbKeycodesNameMask)
3763f7df2e56Smrg            length++;
3764f7df2e56Smrg        if (which & XkbGeometryNameMask)
3765f7df2e56Smrg            length++;
3766f7df2e56Smrg        if (which & XkbSymbolsNameMask)
3767f7df2e56Smrg            length++;
3768f7df2e56Smrg        if (which & XkbPhysSymbolsNameMask)
3769f7df2e56Smrg            length++;
3770f7df2e56Smrg        if (which & XkbTypesNameMask)
3771f7df2e56Smrg            length++;
3772f7df2e56Smrg        if (which & XkbCompatNameMask)
3773f7df2e56Smrg            length++;
3774f7df2e56Smrg    }
3775f7df2e56Smrg    else
3776f7df2e56Smrg        which &= ~XkbComponentNamesMask;
3777f7df2e56Smrg
3778f7df2e56Smrg    if (xkb->map != NULL) {
3779f7df2e56Smrg        if (which & XkbKeyTypeNamesMask)
3780f7df2e56Smrg            length += xkb->map->num_types;
3781f7df2e56Smrg        rep->nTypes = xkb->map->num_types;
3782f7df2e56Smrg        if (which & XkbKTLevelNamesMask) {
3783f7df2e56Smrg            XkbKeyTypePtr pType = xkb->map->types;
3784f7df2e56Smrg            int nKTLevels = 0;
3785f7df2e56Smrg
3786f7df2e56Smrg            length += XkbPaddedSize(xkb->map->num_types) / 4;
3787f7df2e56Smrg            for (i = 0; i < xkb->map->num_types; i++, pType++) {
3788f7df2e56Smrg                if (pType->level_names != NULL)
3789f7df2e56Smrg                    nKTLevels += pType->num_levels;
3790f7df2e56Smrg            }
3791f7df2e56Smrg            rep->nKTLevels = nKTLevels;
3792f7df2e56Smrg            length += nKTLevels;
3793f7df2e56Smrg        }
379405b261ecSmrg    }
379505b261ecSmrg    else {
3796f7df2e56Smrg        rep->nTypes = 0;
3797f7df2e56Smrg        rep->nKTLevels = 0;
3798f7df2e56Smrg        which &= ~(XkbKeyTypeNamesMask | XkbKTLevelNamesMask);
3799f7df2e56Smrg    }
3800f7df2e56Smrg
3801f7df2e56Smrg    rep->minKeyCode = xkb->min_key_code;
3802f7df2e56Smrg    rep->maxKeyCode = xkb->max_key_code;
3803f7df2e56Smrg    rep->indicators = 0;
3804f7df2e56Smrg    rep->virtualMods = 0;
3805f7df2e56Smrg    rep->groupNames = 0;
3806f7df2e56Smrg    if (xkb->names != NULL) {
3807f7df2e56Smrg        if (which & XkbIndicatorNamesMask) {
3808f7df2e56Smrg            int nLeds;
3809f7df2e56Smrg
3810f7df2e56Smrg            rep->indicators =
3811f7df2e56Smrg                _XkbCountAtoms(xkb->names->indicators, XkbNumIndicators,
3812f7df2e56Smrg                               &nLeds);
3813f7df2e56Smrg            length += nLeds;
3814f7df2e56Smrg            if (nLeds == 0)
3815f7df2e56Smrg                which &= ~XkbIndicatorNamesMask;
3816f7df2e56Smrg        }
3817f7df2e56Smrg
3818f7df2e56Smrg        if (which & XkbVirtualModNamesMask) {
3819f7df2e56Smrg            int nVMods;
3820f7df2e56Smrg
3821f7df2e56Smrg            rep->virtualMods =
3822f7df2e56Smrg                _XkbCountAtoms(xkb->names->vmods, XkbNumVirtualMods, &nVMods);
3823f7df2e56Smrg            length += nVMods;
3824f7df2e56Smrg            if (nVMods == 0)
3825f7df2e56Smrg                which &= ~XkbVirtualModNamesMask;
3826f7df2e56Smrg        }
3827f7df2e56Smrg
3828f7df2e56Smrg        if (which & XkbGroupNamesMask) {
3829f7df2e56Smrg            int nGroups;
3830f7df2e56Smrg
3831f7df2e56Smrg            rep->groupNames =
3832f7df2e56Smrg                _XkbCountAtoms(xkb->names->groups, XkbNumKbdGroups, &nGroups);
3833f7df2e56Smrg            length += nGroups;
3834f7df2e56Smrg            if (nGroups == 0)
3835f7df2e56Smrg                which &= ~XkbGroupNamesMask;
3836f7df2e56Smrg        }
3837f7df2e56Smrg
3838f7df2e56Smrg        if ((which & XkbKeyNamesMask) && (xkb->names->keys))
3839f7df2e56Smrg            length += rep->nKeys;
3840f7df2e56Smrg        else
3841f7df2e56Smrg            which &= ~XkbKeyNamesMask;
3842f7df2e56Smrg
3843f7df2e56Smrg        if ((which & XkbKeyAliasesMask) &&
3844f7df2e56Smrg            (xkb->names->key_aliases) && (xkb->names->num_key_aliases > 0)) {
3845f7df2e56Smrg            rep->nKeyAliases = xkb->names->num_key_aliases;
3846f7df2e56Smrg            length += rep->nKeyAliases * 2;
3847f7df2e56Smrg        }
3848f7df2e56Smrg        else {
3849f7df2e56Smrg            which &= ~XkbKeyAliasesMask;
3850f7df2e56Smrg            rep->nKeyAliases = 0;
3851f7df2e56Smrg        }
3852f7df2e56Smrg
3853f7df2e56Smrg        if ((which & XkbRGNamesMask) && (xkb->names->num_rg > 0))
3854f7df2e56Smrg            length += xkb->names->num_rg;
3855f7df2e56Smrg        else
3856f7df2e56Smrg            which &= ~XkbRGNamesMask;
385705b261ecSmrg    }
385805b261ecSmrg    else {
3859f7df2e56Smrg        which &= ~(XkbIndicatorNamesMask | XkbVirtualModNamesMask);
3860f7df2e56Smrg        which &= ~(XkbGroupNamesMask | XkbKeyNamesMask | XkbKeyAliasesMask);
3861f7df2e56Smrg        which &= ~XkbRGNamesMask;
386205b261ecSmrg    }
386305b261ecSmrg
3864f7df2e56Smrg    rep->length = length;
3865f7df2e56Smrg    rep->which = which;
386605b261ecSmrg    return Success;
386705b261ecSmrg}
386805b261ecSmrg
386905b261ecSmrgstatic int
3870f7df2e56SmrgXkbSendNames(ClientPtr client, XkbDescPtr xkb, xkbGetNamesReply * rep)
387105b261ecSmrg{
3872f7df2e56Smrg    register unsigned i, length, which;
3873f7df2e56Smrg    char *start;
3874f7df2e56Smrg    char *desc;
387505b261ecSmrg
3876f7df2e56Smrg    length = rep->length * 4;
3877f7df2e56Smrg    which = rep->which;
387805b261ecSmrg    if (client->swapped) {
3879f7df2e56Smrg        swaps(&rep->sequenceNumber);
3880f7df2e56Smrg        swapl(&rep->length);
3881f7df2e56Smrg        swapl(&rep->which);
3882f7df2e56Smrg        swaps(&rep->virtualMods);
3883f7df2e56Smrg        swapl(&rep->indicators);
388405b261ecSmrg    }
388505b261ecSmrg
38869ace9065Smrg    start = desc = calloc(1, length);
3887f7df2e56Smrg    if (!start)
3888f7df2e56Smrg        return BadAlloc;
388905b261ecSmrg    if (xkb->names) {
3890f7df2e56Smrg        if (which & XkbKeycodesNameMask) {
3891f7df2e56Smrg            *((CARD32 *) desc) = xkb->names->keycodes;
389205b261ecSmrg            if (client->swapped) {
3893f7df2e56Smrg                swapl((int *) desc);
389405b261ecSmrg            }
3895f7df2e56Smrg            desc += 4;
389605b261ecSmrg        }
3897f7df2e56Smrg        if (which & XkbGeometryNameMask) {
3898f7df2e56Smrg            *((CARD32 *) desc) = xkb->names->geometry;
389905b261ecSmrg            if (client->swapped) {
3900f7df2e56Smrg                swapl((int *) desc);
390105b261ecSmrg            }
3902f7df2e56Smrg            desc += 4;
390305b261ecSmrg        }
3904f7df2e56Smrg        if (which & XkbSymbolsNameMask) {
3905f7df2e56Smrg            *((CARD32 *) desc) = xkb->names->symbols;
390605b261ecSmrg            if (client->swapped) {
3907f7df2e56Smrg                swapl((int *) desc);
390805b261ecSmrg            }
3909f7df2e56Smrg            desc += 4;
391005b261ecSmrg        }
3911f7df2e56Smrg        if (which & XkbPhysSymbolsNameMask) {
3912f7df2e56Smrg            register CARD32 *atm = (CARD32 *) desc;
3913f7df2e56Smrg
3914f7df2e56Smrg            atm[0] = (CARD32) xkb->names->phys_symbols;
391505b261ecSmrg            if (client->swapped) {
3916f7df2e56Smrg                swapl(&atm[0]);
391705b261ecSmrg            }
3918f7df2e56Smrg            desc += 4;
391905b261ecSmrg        }
3920f7df2e56Smrg        if (which & XkbTypesNameMask) {
3921f7df2e56Smrg            *((CARD32 *) desc) = (CARD32) xkb->names->types;
392205b261ecSmrg            if (client->swapped) {
3923f7df2e56Smrg                swapl((int *) desc);
392405b261ecSmrg            }
3925f7df2e56Smrg            desc += 4;
392605b261ecSmrg        }
3927f7df2e56Smrg        if (which & XkbCompatNameMask) {
3928f7df2e56Smrg            *((CARD32 *) desc) = (CARD32) xkb->names->compat;
392905b261ecSmrg            if (client->swapped) {
3930f7df2e56Smrg                swapl((int *) desc);
393105b261ecSmrg            }
3932f7df2e56Smrg            desc += 4;
393305b261ecSmrg        }
3934f7df2e56Smrg        if (which & XkbKeyTypeNamesMask) {
3935f7df2e56Smrg            register CARD32 *atm = (CARD32 *) desc;
3936f7df2e56Smrg            register XkbKeyTypePtr type = xkb->map->types;
393705b261ecSmrg
3938f7df2e56Smrg            for (i = 0; i < xkb->map->num_types; i++, atm++, type++) {
3939f7df2e56Smrg                *atm = (CARD32) type->name;
394005b261ecSmrg                if (client->swapped) {
3941f7df2e56Smrg                    swapl(atm);
394205b261ecSmrg                }
394305b261ecSmrg            }
3944f7df2e56Smrg            desc = (char *) atm;
394505b261ecSmrg        }
3946f7df2e56Smrg        if (which & XkbKTLevelNamesMask && xkb->map) {
394705b261ecSmrg            XkbKeyTypePtr type = xkb->map->types;
394805b261ecSmrg            register CARD32 *atm;
3949f7df2e56Smrg
3950f7df2e56Smrg            for (i = 0; i < rep->nTypes; i++, type++) {
395105b261ecSmrg                *desc++ = type->num_levels;
395205b261ecSmrg            }
3953f7df2e56Smrg            desc += XkbPaddedSize(rep->nTypes) - rep->nTypes;
395405b261ecSmrg
3955f7df2e56Smrg            atm = (CARD32 *) desc;
395605b261ecSmrg            type = xkb->map->types;
3957f7df2e56Smrg            for (i = 0; i < xkb->map->num_types; i++, type++) {
395805b261ecSmrg                register unsigned l;
3959f7df2e56Smrg
396005b261ecSmrg                if (type->level_names) {
3961f7df2e56Smrg                    for (l = 0; l < type->num_levels; l++, atm++) {
3962f7df2e56Smrg                        *atm = type->level_names[l];
396305b261ecSmrg                        if (client->swapped) {
3964f7df2e56Smrg                            swapl(atm);
396505b261ecSmrg                        }
396605b261ecSmrg                    }
3967f7df2e56Smrg                    desc += type->num_levels * 4;
396805b261ecSmrg                }
396905b261ecSmrg            }
397005b261ecSmrg        }
3971f7df2e56Smrg        if (which & XkbIndicatorNamesMask) {
3972f7df2e56Smrg            desc =
3973f7df2e56Smrg                _XkbWriteAtoms(desc, xkb->names->indicators, XkbNumIndicators,
3974f7df2e56Smrg                               client->swapped);
397505b261ecSmrg        }
3976f7df2e56Smrg        if (which & XkbVirtualModNamesMask) {
3977f7df2e56Smrg            desc = _XkbWriteAtoms(desc, xkb->names->vmods, XkbNumVirtualMods,
3978f7df2e56Smrg                                  client->swapped);
397905b261ecSmrg        }
3980f7df2e56Smrg        if (which & XkbGroupNamesMask) {
3981f7df2e56Smrg            desc = _XkbWriteAtoms(desc, xkb->names->groups, XkbNumKbdGroups,
3982f7df2e56Smrg                                  client->swapped);
398305b261ecSmrg        }
3984f7df2e56Smrg        if (which & XkbKeyNamesMask) {
3985f7df2e56Smrg            for (i = 0; i < rep->nKeys; i++, desc += sizeof(XkbKeyNameRec)) {
3986f7df2e56Smrg                *((XkbKeyNamePtr) desc) = xkb->names->keys[i + rep->firstKey];
398705b261ecSmrg            }
398805b261ecSmrg        }
3989f7df2e56Smrg        if (which & XkbKeyAliasesMask) {
3990f7df2e56Smrg            XkbKeyAliasPtr pAl;
3991f7df2e56Smrg
3992f7df2e56Smrg            pAl = xkb->names->key_aliases;
3993f7df2e56Smrg            for (i = 0; i < rep->nKeyAliases;
3994f7df2e56Smrg                 i++, pAl++, desc += 2 * XkbKeyNameLength) {
3995f7df2e56Smrg                *((XkbKeyAliasPtr) desc) = *pAl;
399605b261ecSmrg            }
399705b261ecSmrg        }
3998f7df2e56Smrg        if ((which & XkbRGNamesMask) && (rep->nRadioGroups > 0)) {
3999f7df2e56Smrg            register CARD32 *atm = (CARD32 *) desc;
4000f7df2e56Smrg
4001f7df2e56Smrg            for (i = 0; i < rep->nRadioGroups; i++, atm++) {
4002f7df2e56Smrg                *atm = (CARD32) xkb->names->radio_groups[i];
400305b261ecSmrg                if (client->swapped) {
4004f7df2e56Smrg                    swapl(atm);
400505b261ecSmrg                }
400605b261ecSmrg            }
4007f7df2e56Smrg            desc += rep->nRadioGroups * 4;
400805b261ecSmrg        }
400905b261ecSmrg    }
401005b261ecSmrg
4011f7df2e56Smrg    if ((desc - start) != (length)) {
4012f7df2e56Smrg        ErrorF("[xkb] BOGUS LENGTH in write names, expected %d, got %ld\n",
4013f7df2e56Smrg               length, (unsigned long) (desc - start));
401405b261ecSmrg    }
4015f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetNamesReply), rep);
401605b261ecSmrg    WriteToClient(client, length, start);
4017f7df2e56Smrg    free((char *) start);
40186747b715Smrg    return Success;
401905b261ecSmrg}
402005b261ecSmrg
402105b261ecSmrgint
402205b261ecSmrgProcXkbGetNames(ClientPtr client)
402305b261ecSmrg{
4024f7df2e56Smrg    DeviceIntPtr dev;
4025f7df2e56Smrg    XkbDescPtr xkb;
4026f7df2e56Smrg    xkbGetNamesReply rep;
402705b261ecSmrg
402805b261ecSmrg    REQUEST(xkbGetNamesReq);
402905b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetNamesReq);
403005b261ecSmrg
4031f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
4032f7df2e56Smrg        return BadAccess;
403305b261ecSmrg
40344642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
4035f7df2e56Smrg    CHK_MASK_LEGAL(0x01, stuff->which, XkbAllNamesMask);
403605b261ecSmrg
403705b261ecSmrg    xkb = dev->key->xkbInfo->desc;
4038f7df2e56Smrg    rep = (xkbGetNamesReply) {
4039f7df2e56Smrg        .type = X_Reply,
4040f7df2e56Smrg        .deviceID = dev->id,
4041f7df2e56Smrg        .sequenceNumber = client->sequence,
4042f7df2e56Smrg        .length = 0,
4043f7df2e56Smrg        .which = stuff->which,
4044f7df2e56Smrg        .nTypes = xkb->map->num_types,
4045f7df2e56Smrg        .firstKey = xkb->min_key_code,
4046f7df2e56Smrg        .nKeys = XkbNumKeys(xkb),
4047f7df2e56Smrg        .nKeyAliases = xkb->names ? xkb->names->num_key_aliases : 0,
4048f7df2e56Smrg        .nRadioGroups = xkb->names ? xkb->names->num_rg : 0
4049f7df2e56Smrg    };
4050f7df2e56Smrg    XkbComputeGetNamesReplySize(xkb, &rep);
4051f7df2e56Smrg    return XkbSendNames(client, xkb, &rep);
405205b261ecSmrg}
405305b261ecSmrg
405405b261ecSmrg/***====================================================================***/
405505b261ecSmrg
405605b261ecSmrgstatic CARD32 *
4057f7df2e56Smrg_XkbCheckAtoms(CARD32 *wire, int nAtoms, int swapped, Atom *pError)
405805b261ecSmrg{
4059f7df2e56Smrg    register int i;
4060f7df2e56Smrg
4061f7df2e56Smrg    for (i = 0; i < nAtoms; i++, wire++) {
4062f7df2e56Smrg        if (swapped) {
4063f7df2e56Smrg            swapl(wire);
4064f7df2e56Smrg        }
4065f7df2e56Smrg        if ((((Atom) *wire) != None) && (!ValidAtom((Atom) *wire))) {
4066f7df2e56Smrg            *pError = ((Atom) *wire);
4067f7df2e56Smrg            return NULL;
4068f7df2e56Smrg        }
406905b261ecSmrg    }
407005b261ecSmrg    return wire;
407105b261ecSmrg}
407205b261ecSmrg
407305b261ecSmrgstatic CARD32 *
4074f7df2e56Smrg_XkbCheckMaskedAtoms(CARD32 *wire, int nAtoms, CARD32 present, int swapped,
4075f7df2e56Smrg                     Atom *pError)
407605b261ecSmrg{
4077f7df2e56Smrg    register unsigned i, bit;
4078f7df2e56Smrg
4079f7df2e56Smrg    for (i = 0, bit = 1; (i < nAtoms) && (present); i++, bit <<= 1) {
4080f7df2e56Smrg        if ((present & bit) == 0)
4081f7df2e56Smrg            continue;
4082f7df2e56Smrg        if (swapped) {
4083f7df2e56Smrg            swapl(wire);
4084f7df2e56Smrg        }
4085f7df2e56Smrg        if ((((Atom) *wire) != None) && (!ValidAtom(((Atom) *wire)))) {
4086f7df2e56Smrg            *pError = (Atom) *wire;
4087f7df2e56Smrg            return NULL;
4088f7df2e56Smrg        }
4089f7df2e56Smrg        wire++;
409005b261ecSmrg    }
409105b261ecSmrg    return wire;
409205b261ecSmrg}
409305b261ecSmrg
409405b261ecSmrgstatic Atom *
4095f7df2e56Smrg_XkbCopyMaskedAtoms(Atom *wire, Atom *dest, int nAtoms, CARD32 present)
409605b261ecSmrg{
4097f7df2e56Smrg    register int i, bit;
409805b261ecSmrg
4099f7df2e56Smrg    for (i = 0, bit = 1; (i < nAtoms) && (present); i++, bit <<= 1) {
4100f7df2e56Smrg        if ((present & bit) == 0)
4101f7df2e56Smrg            continue;
4102f7df2e56Smrg        dest[i] = *wire++;
410305b261ecSmrg    }
410405b261ecSmrg    return wire;
410505b261ecSmrg}
410605b261ecSmrg
410705b261ecSmrgstatic Bool
4108f7df2e56Smrg_XkbCheckTypeName(Atom name, int typeNdx)
410905b261ecSmrg{
4110f7df2e56Smrg    const char *str;
411105b261ecSmrg
4112f7df2e56Smrg    str = NameForAtom(name);
4113f7df2e56Smrg    if ((strcmp(str, "ONE_LEVEL") == 0) || (strcmp(str, "TWO_LEVEL") == 0) ||
4114f7df2e56Smrg        (strcmp(str, "ALPHABETIC") == 0) || (strcmp(str, "KEYPAD") == 0))
4115f7df2e56Smrg        return FALSE;
41166747b715Smrg    return TRUE;
411705b261ecSmrg}
411805b261ecSmrg
41194642e01fSmrg/**
41204642e01fSmrg * Check the device-dependent data in the request against the device. Returns
41214642e01fSmrg * Success, or the appropriate error code.
41224642e01fSmrg */
41234642e01fSmrgstatic int
41244642e01fSmrg_XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
4125f7df2e56Smrg                  xkbSetNamesReq * stuff, CARD32 *data)
412605b261ecSmrg{
4127f7df2e56Smrg    XkbDescRec *xkb;
4128f7df2e56Smrg    CARD32 *tmp;
4129f7df2e56Smrg    Atom bad = None;
413005b261ecSmrg
41314642e01fSmrg    tmp = data;
41324642e01fSmrg    xkb = dev->key->xkbInfo->desc;
41334642e01fSmrg
41344642e01fSmrg    if (stuff->which & XkbKeyTypeNamesMask) {
41354642e01fSmrg        int i;
4136f7df2e56Smrg        CARD32 *old;
4137f7df2e56Smrg
4138f7df2e56Smrg        if (stuff->nTypes < 1) {
4139f7df2e56Smrg            client->errorValue = _XkbErrCode2(0x02, stuff->nTypes);
41404642e01fSmrg            return BadValue;
41414642e01fSmrg        }
4142f7df2e56Smrg        if ((unsigned) (stuff->firstType + stuff->nTypes - 1) >=
4143f7df2e56Smrg            xkb->map->num_types) {
4144f7df2e56Smrg            client->errorValue =
4145f7df2e56Smrg                _XkbErrCode4(0x03, stuff->firstType, stuff->nTypes,
4146f7df2e56Smrg                             xkb->map->num_types);
41474642e01fSmrg            return BadValue;
41484642e01fSmrg        }
4149f7df2e56Smrg        if (((unsigned) stuff->firstType) <= XkbLastRequiredType) {
4150f7df2e56Smrg            client->errorValue = _XkbErrCode2(0x04, stuff->firstType);
41514642e01fSmrg            return BadAccess;
41524642e01fSmrg        }
4153806e81e9Smrg        if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + stuff->nTypes))
4154806e81e9Smrg            return BadLength;
4155f7df2e56Smrg        old = tmp;
4156f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, stuff->nTypes, client->swapped, &bad);
41574642e01fSmrg        if (!tmp) {
4158f7df2e56Smrg            client->errorValue = bad;
41594642e01fSmrg            return BadAtom;
41604642e01fSmrg        }
4161f7df2e56Smrg        for (i = 0; i < stuff->nTypes; i++, old++) {
4162f7df2e56Smrg            if (!_XkbCheckTypeName((Atom) *old, stuff->firstType + i))
4163f7df2e56Smrg                client->errorValue = _XkbErrCode2(0x05, i);
41644642e01fSmrg        }
41654642e01fSmrg    }
4166f7df2e56Smrg    if (stuff->which & XkbKTLevelNamesMask) {
41674642e01fSmrg        unsigned i;
4168f7df2e56Smrg        XkbKeyTypePtr type;
4169f7df2e56Smrg        CARD8 *width;
4170f7df2e56Smrg
4171f7df2e56Smrg        if (stuff->nKTLevels < 1) {
4172f7df2e56Smrg            client->errorValue = _XkbErrCode2(0x05, stuff->nKTLevels);
41734642e01fSmrg            return BadValue;
41744642e01fSmrg        }
4175f7df2e56Smrg        if ((unsigned) (stuff->firstKTLevel + stuff->nKTLevels - 1) >=
4176f7df2e56Smrg            xkb->map->num_types) {
4177f7df2e56Smrg            client->errorValue = _XkbErrCode4(0x06, stuff->firstKTLevel,
4178f7df2e56Smrg                                              stuff->nKTLevels,
4179f7df2e56Smrg                                              xkb->map->num_types);
41804642e01fSmrg            return BadValue;
41814642e01fSmrg        }
4182f7df2e56Smrg        width = (CARD8 *) tmp;
4183f7df2e56Smrg        tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels));
4184806e81e9Smrg        if (!_XkbCheckRequestBounds(client, stuff, width, tmp))
4185806e81e9Smrg            return BadLength;
41864642e01fSmrg        type = &xkb->map->types[stuff->firstKTLevel];
4187f7df2e56Smrg        for (i = 0; i < stuff->nKTLevels; i++, type++) {
4188f7df2e56Smrg            if (width[i] == 0)
41894642e01fSmrg                continue;
4190f7df2e56Smrg            else if (width[i] != type->num_levels) {
4191f7df2e56Smrg                client->errorValue = _XkbErrCode4(0x07, i + stuff->firstKTLevel,
4192f7df2e56Smrg                                                  type->num_levels, width[i]);
41934642e01fSmrg                return BadMatch;
41944642e01fSmrg            }
4195806e81e9Smrg            if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + width[i]))
4196806e81e9Smrg                return BadLength;
4197f7df2e56Smrg            tmp = _XkbCheckAtoms(tmp, width[i], client->swapped, &bad);
41984642e01fSmrg            if (!tmp) {
4199f7df2e56Smrg                client->errorValue = bad;
42004642e01fSmrg                return BadAtom;
42014642e01fSmrg            }
42024642e01fSmrg        }
42034642e01fSmrg    }
4204f7df2e56Smrg    if (stuff->which & XkbIndicatorNamesMask) {
4205f7df2e56Smrg        if (stuff->indicators == 0) {
4206f7df2e56Smrg            client->errorValue = 0x08;
42074642e01fSmrg            return BadMatch;
42084642e01fSmrg        }
4209806e81e9Smrg        if (!_XkbCheckRequestBounds(client, stuff, tmp,
4210806e81e9Smrg                                    tmp + Ones(stuff->indicators)))
4211806e81e9Smrg            return BadLength;
4212f7df2e56Smrg        tmp = _XkbCheckMaskedAtoms(tmp, XkbNumIndicators, stuff->indicators,
4213f7df2e56Smrg                                   client->swapped, &bad);
42144642e01fSmrg        if (!tmp) {
4215f7df2e56Smrg            client->errorValue = bad;
42164642e01fSmrg            return BadAtom;
42174642e01fSmrg        }
42184642e01fSmrg    }
4219f7df2e56Smrg    if (stuff->which & XkbVirtualModNamesMask) {
4220f7df2e56Smrg        if (stuff->virtualMods == 0) {
4221f7df2e56Smrg            client->errorValue = 0x09;
42224642e01fSmrg            return BadMatch;
42234642e01fSmrg        }
4224806e81e9Smrg        if (!_XkbCheckRequestBounds(client, stuff, tmp,
4225806e81e9Smrg                                    tmp + Ones(stuff->virtualMods)))
4226806e81e9Smrg            return BadLength;
4227f7df2e56Smrg        tmp = _XkbCheckMaskedAtoms(tmp, XkbNumVirtualMods,
4228f7df2e56Smrg                                   (CARD32) stuff->virtualMods,
4229f7df2e56Smrg                                   client->swapped, &bad);
42304642e01fSmrg        if (!tmp) {
42314642e01fSmrg            client->errorValue = bad;
42324642e01fSmrg            return BadAtom;
42334642e01fSmrg        }
42344642e01fSmrg    }
4235f7df2e56Smrg    if (stuff->which & XkbGroupNamesMask) {
4236f7df2e56Smrg        if (stuff->groupNames == 0) {
4237f7df2e56Smrg            client->errorValue = 0x0a;
42384642e01fSmrg            return BadMatch;
42394642e01fSmrg        }
4240806e81e9Smrg        if (!_XkbCheckRequestBounds(client, stuff, tmp,
4241806e81e9Smrg                                    tmp + Ones(stuff->groupNames)))
4242806e81e9Smrg            return BadLength;
4243f7df2e56Smrg        tmp = _XkbCheckMaskedAtoms(tmp, XkbNumKbdGroups,
4244f7df2e56Smrg                                   (CARD32) stuff->groupNames,
4245f7df2e56Smrg                                   client->swapped, &bad);
42464642e01fSmrg        if (!tmp) {
42474642e01fSmrg            client->errorValue = bad;
42484642e01fSmrg            return BadAtom;
42494642e01fSmrg        }
42504642e01fSmrg    }
4251f7df2e56Smrg    if (stuff->which & XkbKeyNamesMask) {
4252f7df2e56Smrg        if (stuff->firstKey < (unsigned) xkb->min_key_code) {
4253f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x0b, xkb->min_key_code,
4254f7df2e56Smrg                                              stuff->firstKey);
42554642e01fSmrg            return BadValue;
42564642e01fSmrg        }
4257f7df2e56Smrg        if (((unsigned) (stuff->firstKey + stuff->nKeys - 1) >
4258f7df2e56Smrg             xkb->max_key_code) || (stuff->nKeys < 1)) {
4259f7df2e56Smrg            client->errorValue =
4260f7df2e56Smrg                _XkbErrCode4(0x0c, xkb->max_key_code, stuff->firstKey,
4261f7df2e56Smrg                             stuff->nKeys);
42624642e01fSmrg            return BadValue;
42634642e01fSmrg        }
4264806e81e9Smrg        if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + stuff->nKeys))
4265806e81e9Smrg            return BadLength;
4266f7df2e56Smrg        tmp += stuff->nKeys;
42674642e01fSmrg    }
4268f7df2e56Smrg    if ((stuff->which & XkbKeyAliasesMask) && (stuff->nKeyAliases > 0)) {
4269806e81e9Smrg        if (!_XkbCheckRequestBounds(client, stuff, tmp,
4270806e81e9Smrg                                    tmp + (stuff->nKeyAliases * 2)))
4271806e81e9Smrg            return BadLength;
4272f7df2e56Smrg        tmp += stuff->nKeyAliases * 2;
42734642e01fSmrg    }
4274f7df2e56Smrg    if (stuff->which & XkbRGNamesMask) {
4275f7df2e56Smrg        if (stuff->nRadioGroups < 1) {
4276f7df2e56Smrg            client->errorValue = _XkbErrCode2(0x0d, stuff->nRadioGroups);
42774642e01fSmrg            return BadValue;
42784642e01fSmrg        }
4279806e81e9Smrg        if (!_XkbCheckRequestBounds(client, stuff, tmp,
4280806e81e9Smrg                                    tmp + stuff->nRadioGroups))
4281806e81e9Smrg            return BadLength;
4282f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, stuff->nRadioGroups, client->swapped, &bad);
42834642e01fSmrg        if (!tmp) {
4284f7df2e56Smrg            client->errorValue = bad;
42854642e01fSmrg            return BadAtom;
42864642e01fSmrg        }
42874642e01fSmrg    }
4288f7df2e56Smrg    if ((tmp - ((CARD32 *) stuff)) != stuff->length) {
42894642e01fSmrg        client->errorValue = stuff->length;
42904642e01fSmrg        return BadLength;
42914642e01fSmrg    }
42924642e01fSmrg
42934642e01fSmrg    return Success;
42944642e01fSmrg}
42954642e01fSmrg
42964642e01fSmrgstatic int
4297f7df2e56Smrg_XkbSetNames(ClientPtr client, DeviceIntPtr dev, xkbSetNamesReq * stuff)
42984642e01fSmrg{
4299f7df2e56Smrg    XkbDescRec *xkb;
4300f7df2e56Smrg    XkbNamesRec *names;
4301f7df2e56Smrg    CARD32 *tmp;
4302f7df2e56Smrg    xkbNamesNotify nn;
43034642e01fSmrg
4304f7df2e56Smrg    tmp = (CARD32 *) &stuff[1];
43054642e01fSmrg    xkb = dev->key->xkbInfo->desc;
43064642e01fSmrg    names = xkb->names;
43074642e01fSmrg
4308f7df2e56Smrg    if (XkbAllocNames(xkb, stuff->which, stuff->nRadioGroups,
4309f7df2e56Smrg                      stuff->nKeyAliases) != Success) {
43104642e01fSmrg        return BadAlloc;
43114642e01fSmrg    }
43124642e01fSmrg
43136747b715Smrg    memset(&nn, 0, sizeof(xkbNamesNotify));
4314f7df2e56Smrg    nn.changed = stuff->which;
4315f7df2e56Smrg    tmp = (CARD32 *) &stuff[1];
4316f7df2e56Smrg    if (stuff->which & XkbKeycodesNameMask)
4317f7df2e56Smrg        names->keycodes = *tmp++;
4318f7df2e56Smrg    if (stuff->which & XkbGeometryNameMask)
4319f7df2e56Smrg        names->geometry = *tmp++;
4320f7df2e56Smrg    if (stuff->which & XkbSymbolsNameMask)
4321f7df2e56Smrg        names->symbols = *tmp++;
4322f7df2e56Smrg    if (stuff->which & XkbPhysSymbolsNameMask)
4323f7df2e56Smrg        names->phys_symbols = *tmp++;
4324f7df2e56Smrg    if (stuff->which & XkbTypesNameMask)
4325f7df2e56Smrg        names->types = *tmp++;
4326f7df2e56Smrg    if (stuff->which & XkbCompatNameMask)
4327f7df2e56Smrg        names->compat = *tmp++;
4328f7df2e56Smrg    if ((stuff->which & XkbKeyTypeNamesMask) && (stuff->nTypes > 0)) {
43294642e01fSmrg        register unsigned i;
43304642e01fSmrg        register XkbKeyTypePtr type;
43314642e01fSmrg
4332f7df2e56Smrg        type = &xkb->map->types[stuff->firstType];
4333f7df2e56Smrg        for (i = 0; i < stuff->nTypes; i++, type++) {
4334f7df2e56Smrg            type->name = *tmp++;
43354642e01fSmrg        }
4336f7df2e56Smrg        nn.firstType = stuff->firstType;
4337f7df2e56Smrg        nn.nTypes = stuff->nTypes;
43384642e01fSmrg    }
4339f7df2e56Smrg    if (stuff->which & XkbKTLevelNamesMask) {
4340f7df2e56Smrg        register XkbKeyTypePtr type;
43414642e01fSmrg        register unsigned i;
43424642e01fSmrg        CARD8 *width;
43434642e01fSmrg
4344f7df2e56Smrg        width = (CARD8 *) tmp;
4345f7df2e56Smrg        tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels));
4346f7df2e56Smrg        type = &xkb->map->types[stuff->firstKTLevel];
4347f7df2e56Smrg        for (i = 0; i < stuff->nKTLevels; i++, type++) {
4348f7df2e56Smrg            if (width[i] > 0) {
43494642e01fSmrg                if (type->level_names) {
43504642e01fSmrg                    register unsigned n;
4351f7df2e56Smrg
4352f7df2e56Smrg                    for (n = 0; n < width[i]; n++) {
4353f7df2e56Smrg                        type->level_names[n] = tmp[n];
43544642e01fSmrg                    }
43554642e01fSmrg                }
4356f7df2e56Smrg                tmp += width[i];
43574642e01fSmrg            }
43584642e01fSmrg        }
4359f7df2e56Smrg        nn.firstLevelName = 0;
4360f7df2e56Smrg        nn.nLevelNames = stuff->nTypes;
4361f7df2e56Smrg    }
4362f7df2e56Smrg    if (stuff->which & XkbIndicatorNamesMask) {
4363f7df2e56Smrg        tmp = _XkbCopyMaskedAtoms(tmp, names->indicators, XkbNumIndicators,
4364f7df2e56Smrg                                  stuff->indicators);
4365f7df2e56Smrg        nn.changedIndicators = stuff->indicators;
4366f7df2e56Smrg    }
4367f7df2e56Smrg    if (stuff->which & XkbVirtualModNamesMask) {
4368f7df2e56Smrg        tmp = _XkbCopyMaskedAtoms(tmp, names->vmods, XkbNumVirtualMods,
4369f7df2e56Smrg                                  stuff->virtualMods);
4370f7df2e56Smrg        nn.changedVirtualMods = stuff->virtualMods;
4371f7df2e56Smrg    }
4372f7df2e56Smrg    if (stuff->which & XkbGroupNamesMask) {
4373f7df2e56Smrg        tmp = _XkbCopyMaskedAtoms(tmp, names->groups, XkbNumKbdGroups,
4374f7df2e56Smrg                                  stuff->groupNames);
4375f7df2e56Smrg        nn.changedVirtualMods = stuff->groupNames;
4376f7df2e56Smrg    }
4377f7df2e56Smrg    if (stuff->which & XkbKeyNamesMask) {
4378f7df2e56Smrg        memcpy((char *) &names->keys[stuff->firstKey], (char *) tmp,
4379f7df2e56Smrg               stuff->nKeys * XkbKeyNameLength);
4380f7df2e56Smrg        tmp += stuff->nKeys;
4381f7df2e56Smrg        nn.firstKey = stuff->firstKey;
4382f7df2e56Smrg        nn.nKeys = stuff->nKeys;
4383f7df2e56Smrg    }
4384f7df2e56Smrg    if (stuff->which & XkbKeyAliasesMask) {
4385f7df2e56Smrg        if (stuff->nKeyAliases > 0) {
4386f7df2e56Smrg            register int na = stuff->nKeyAliases;
4387f7df2e56Smrg
4388f7df2e56Smrg            if (XkbAllocNames(xkb, XkbKeyAliasesMask, 0, na) != Success)
43894642e01fSmrg                return BadAlloc;
4390f7df2e56Smrg            memcpy((char *) names->key_aliases, (char *) tmp,
4391f7df2e56Smrg                   stuff->nKeyAliases * sizeof(XkbKeyAliasRec));
4392f7df2e56Smrg            tmp += stuff->nKeyAliases * 2;
43934642e01fSmrg        }
4394f7df2e56Smrg        else if (names->key_aliases != NULL) {
43956747b715Smrg            free(names->key_aliases);
4396f7df2e56Smrg            names->key_aliases = NULL;
4397f7df2e56Smrg            names->num_key_aliases = 0;
43984642e01fSmrg        }
4399f7df2e56Smrg        nn.nAliases = names->num_key_aliases;
44004642e01fSmrg    }
4401f7df2e56Smrg    if (stuff->which & XkbRGNamesMask) {
4402f7df2e56Smrg        if (stuff->nRadioGroups > 0) {
4403f7df2e56Smrg            register unsigned i, nrg;
4404f7df2e56Smrg
4405f7df2e56Smrg            nrg = stuff->nRadioGroups;
4406f7df2e56Smrg            if (XkbAllocNames(xkb, XkbRGNamesMask, nrg, 0) != Success)
44074642e01fSmrg                return BadAlloc;
44084642e01fSmrg
4409f7df2e56Smrg            for (i = 0; i < stuff->nRadioGroups; i++) {
4410f7df2e56Smrg                names->radio_groups[i] = tmp[i];
44114642e01fSmrg            }
4412f7df2e56Smrg            tmp += stuff->nRadioGroups;
44134642e01fSmrg        }
44144642e01fSmrg        else if (names->radio_groups) {
44156747b715Smrg            free(names->radio_groups);
4416f7df2e56Smrg            names->radio_groups = NULL;
4417f7df2e56Smrg            names->num_rg = 0;
44184642e01fSmrg        }
4419f7df2e56Smrg        nn.nRadioGroups = names->num_rg;
44204642e01fSmrg    }
44214642e01fSmrg    if (nn.changed) {
44224642e01fSmrg        Bool needExtEvent;
4423f7df2e56Smrg
4424f7df2e56Smrg        needExtEvent = (nn.changed & XkbIndicatorNamesMask) != 0;
4425f7df2e56Smrg        XkbSendNamesNotify(dev, &nn);
44264642e01fSmrg        if (needExtEvent) {
4427f7df2e56Smrg            XkbSrvLedInfoPtr sli;
4428f7df2e56Smrg            xkbExtensionDeviceNotify edev;
4429f7df2e56Smrg            register int i;
4430f7df2e56Smrg            register unsigned bit;
4431f7df2e56Smrg
4432f7df2e56Smrg            sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
4433f7df2e56Smrg                                    XkbXI_IndicatorsMask);
4434f7df2e56Smrg            sli->namesPresent = 0;
4435f7df2e56Smrg            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
4436f7df2e56Smrg                if (names->indicators[i] != None)
4437f7df2e56Smrg                    sli->namesPresent |= bit;
44384642e01fSmrg            }
44396747b715Smrg            memset(&edev, 0, sizeof(xkbExtensionDeviceNotify));
4440f7df2e56Smrg            edev.reason = XkbXI_IndicatorNamesMask;
4441f7df2e56Smrg            edev.ledClass = KbdFeedbackClass;
4442f7df2e56Smrg            edev.ledID = dev->kbdfeed->ctrl.id;
4443f7df2e56Smrg            edev.ledsDefined = sli->namesPresent | sli->mapsPresent;
4444f7df2e56Smrg            edev.ledState = sli->effectiveState;
4445f7df2e56Smrg            edev.firstBtn = 0;
4446f7df2e56Smrg            edev.nBtns = 0;
4447f7df2e56Smrg            edev.supported = XkbXI_AllFeaturesMask;
4448f7df2e56Smrg            edev.unsupported = 0;
4449f7df2e56Smrg            XkbSendExtensionDeviceNotify(dev, client, &edev);
44504642e01fSmrg        }
44514642e01fSmrg    }
44524642e01fSmrg    return Success;
44534642e01fSmrg}
44544642e01fSmrg
44554642e01fSmrgint
44564642e01fSmrgProcXkbSetNames(ClientPtr client)
44574642e01fSmrg{
4458f7df2e56Smrg    DeviceIntPtr dev;
4459f7df2e56Smrg    CARD32 *tmp;
4460f7df2e56Smrg    Atom bad;
4461f7df2e56Smrg    int rc;
44624642e01fSmrg
446305b261ecSmrg    REQUEST(xkbSetNamesReq);
446405b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetNamesReq);
446505b261ecSmrg
4466f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
4467f7df2e56Smrg        return BadAccess;
446805b261ecSmrg
44694642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
4470f7df2e56Smrg    CHK_MASK_LEGAL(0x01, stuff->which, XkbAllNamesMask);
447105b261ecSmrg
44724642e01fSmrg    /* check device-independent stuff */
4473f7df2e56Smrg    tmp = (CARD32 *) &stuff[1];
4474f7df2e56Smrg
4475806e81e9Smrg    if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
4476806e81e9Smrg        return BadLength;
4477f7df2e56Smrg    if (stuff->which & XkbKeycodesNameMask) {
4478f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4479f7df2e56Smrg        if (!tmp) {
4480f7df2e56Smrg            client->errorValue = bad;
4481f7df2e56Smrg            return BadAtom;
4482f7df2e56Smrg        }
4483f7df2e56Smrg    }
4484806e81e9Smrg    if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
4485806e81e9Smrg        return BadLength;
4486f7df2e56Smrg    if (stuff->which & XkbGeometryNameMask) {
4487f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4488f7df2e56Smrg        if (!tmp) {
4489f7df2e56Smrg            client->errorValue = bad;
4490f7df2e56Smrg            return BadAtom;
4491f7df2e56Smrg        }
4492f7df2e56Smrg    }
4493806e81e9Smrg    if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
4494806e81e9Smrg        return BadLength;
4495f7df2e56Smrg    if (stuff->which & XkbSymbolsNameMask) {
4496f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4497f7df2e56Smrg        if (!tmp) {
4498f7df2e56Smrg            client->errorValue = bad;
4499f7df2e56Smrg            return BadAtom;
4500f7df2e56Smrg        }
4501f7df2e56Smrg    }
4502806e81e9Smrg    if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
4503806e81e9Smrg        return BadLength;
4504f7df2e56Smrg    if (stuff->which & XkbPhysSymbolsNameMask) {
4505f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4506f7df2e56Smrg        if (!tmp) {
4507f7df2e56Smrg            client->errorValue = bad;
4508f7df2e56Smrg            return BadAtom;
4509f7df2e56Smrg        }
4510f7df2e56Smrg    }
4511806e81e9Smrg    if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
4512806e81e9Smrg        return BadLength;
4513f7df2e56Smrg    if (stuff->which & XkbTypesNameMask) {
4514f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4515f7df2e56Smrg        if (!tmp) {
4516f7df2e56Smrg            client->errorValue = bad;
4517f7df2e56Smrg            return BadAtom;
4518f7df2e56Smrg        }
4519f7df2e56Smrg    }
4520806e81e9Smrg    if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
4521806e81e9Smrg        return BadLength;
4522f7df2e56Smrg    if (stuff->which & XkbCompatNameMask) {
4523f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4524f7df2e56Smrg        if (!tmp) {
4525f7df2e56Smrg            client->errorValue = bad;
4526f7df2e56Smrg            return BadAtom;
4527f7df2e56Smrg        }
452805b261ecSmrg    }
45294642e01fSmrg
45304642e01fSmrg    /* start of device-dependent tests */
45314642e01fSmrg    rc = _XkbSetNamesCheck(client, dev, stuff, tmp);
45324642e01fSmrg    if (rc != Success)
45334642e01fSmrg        return rc;
45344642e01fSmrg
4535f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
45364642e01fSmrg        DeviceIntPtr other;
45374642e01fSmrg
4538f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
4539f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
4540f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
4541f7df2e56Smrg
4542f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
4543f7df2e56Smrg                              DixManageAccess);
4544f7df2e56Smrg                if (rc == Success) {
45454642e01fSmrg                    rc = _XkbSetNamesCheck(client, other, stuff, tmp);
45464642e01fSmrg                    if (rc != Success)
45474642e01fSmrg                        return rc;
45484642e01fSmrg                }
45494642e01fSmrg            }
45504642e01fSmrg        }
455105b261ecSmrg    }
455205b261ecSmrg
455305b261ecSmrg    /* everything is okay -- update names */
455405b261ecSmrg
45554642e01fSmrg    rc = _XkbSetNames(client, dev, stuff);
45564642e01fSmrg    if (rc != Success)
45574642e01fSmrg        return rc;
455805b261ecSmrg
4559f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
45604642e01fSmrg        DeviceIntPtr other;
45614642e01fSmrg
4562f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
4563f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
4564f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
4565f7df2e56Smrg
4566f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
4567f7df2e56Smrg                              DixManageAccess);
45684642e01fSmrg                if (rc == Success)
45694642e01fSmrg                    _XkbSetNames(client, other, stuff);
45704642e01fSmrg            }
45714642e01fSmrg        }
457205b261ecSmrg    }
45734642e01fSmrg
45744642e01fSmrg    /* everything is okay -- update names */
45754642e01fSmrg
45766747b715Smrg    return Success;
457705b261ecSmrg}
457805b261ecSmrg
457905b261ecSmrg/***====================================================================***/
458005b261ecSmrg
45814642e01fSmrg#include "xkbgeom.h"
458205b261ecSmrg
458305b261ecSmrg#define	XkbSizeCountedString(s)  ((s)?((((2+strlen(s))+3)/4)*4):4)
458405b261ecSmrg
4585f7df2e56Smrg/**
4586f7df2e56Smrg * Write the zero-terminated string str into wire as a pascal string with a
4587f7df2e56Smrg * 16-bit length field prefixed before the actual string.
4588f7df2e56Smrg *
4589f7df2e56Smrg * @param wire The destination array, usually the wire struct
4590f7df2e56Smrg * @param str The source string as zero-terminated C string
4591f7df2e56Smrg * @param swap If TRUE, the length field is swapped.
4592f7df2e56Smrg *
4593f7df2e56Smrg * @return The input string in the format <string length><string> with a
4594f7df2e56Smrg * (swapped) 16 bit string length, non-zero terminated.
4595f7df2e56Smrg */
459605b261ecSmrgstatic char *
4597f7df2e56SmrgXkbWriteCountedString(char *wire, const char *str, Bool swap)
459805b261ecSmrg{
4599f7df2e56Smrg    CARD16 len, *pLen, paddedLen;
460005b261ecSmrg
46016747b715Smrg    if (!str)
46026747b715Smrg        return wire;
46036747b715Smrg
4604f7df2e56Smrg    len = strlen(str);
4605f7df2e56Smrg    pLen = (CARD16 *) wire;
4606f7df2e56Smrg    *pLen = len;
460705b261ecSmrg    if (swap) {
4608f7df2e56Smrg        swaps(pLen);
460905b261ecSmrg    }
4610f7df2e56Smrg    paddedLen = pad_to_int32(sizeof(len) + len) - sizeof(len);
4611f7df2e56Smrg    strncpy(&wire[sizeof(len)], str, paddedLen);
4612f7df2e56Smrg    wire += sizeof(len) + paddedLen;
461305b261ecSmrg    return wire;
461405b261ecSmrg}
461505b261ecSmrg
461605b261ecSmrgstatic int
461705b261ecSmrgXkbSizeGeomProperties(XkbGeometryPtr geom)
461805b261ecSmrg{
4619f7df2e56Smrg    register int i, size;
4620f7df2e56Smrg    XkbPropertyPtr prop;
4621f7df2e56Smrg
4622f7df2e56Smrg    for (size = i = 0, prop = geom->properties; i < geom->num_properties;
4623f7df2e56Smrg         i++, prop++) {
4624f7df2e56Smrg        size += XkbSizeCountedString(prop->name);
4625f7df2e56Smrg        size += XkbSizeCountedString(prop->value);
462605b261ecSmrg    }
462705b261ecSmrg    return size;
462805b261ecSmrg}
462905b261ecSmrg
463005b261ecSmrgstatic char *
4631f7df2e56SmrgXkbWriteGeomProperties(char *wire, XkbGeometryPtr geom, Bool swap)
463205b261ecSmrg{
4633f7df2e56Smrg    register int i;
4634f7df2e56Smrg    register XkbPropertyPtr prop;
4635f7df2e56Smrg
4636f7df2e56Smrg    for (i = 0, prop = geom->properties; i < geom->num_properties; i++, prop++) {
4637f7df2e56Smrg        wire = XkbWriteCountedString(wire, prop->name, swap);
4638f7df2e56Smrg        wire = XkbWriteCountedString(wire, prop->value, swap);
463905b261ecSmrg    }
464005b261ecSmrg    return wire;
464105b261ecSmrg}
464205b261ecSmrg
464305b261ecSmrgstatic int
464405b261ecSmrgXkbSizeGeomKeyAliases(XkbGeometryPtr geom)
464505b261ecSmrg{
4646f7df2e56Smrg    return geom->num_key_aliases * (2 * XkbKeyNameLength);
464705b261ecSmrg}
464805b261ecSmrg
464905b261ecSmrgstatic char *
4650f7df2e56SmrgXkbWriteGeomKeyAliases(char *wire, XkbGeometryPtr geom, Bool swap)
465105b261ecSmrg{
4652f7df2e56Smrg    register int sz;
4653f7df2e56Smrg
4654f7df2e56Smrg    sz = geom->num_key_aliases * (XkbKeyNameLength * 2);
4655f7df2e56Smrg    if (sz > 0) {
4656f7df2e56Smrg        memcpy(wire, (char *) geom->key_aliases, sz);
4657f7df2e56Smrg        wire += sz;
465805b261ecSmrg    }
465905b261ecSmrg    return wire;
466005b261ecSmrg}
466105b261ecSmrg
466205b261ecSmrgstatic int
466305b261ecSmrgXkbSizeGeomColors(XkbGeometryPtr geom)
466405b261ecSmrg{
4665f7df2e56Smrg    register int i, size;
4666f7df2e56Smrg    register XkbColorPtr color;
466705b261ecSmrg
4668f7df2e56Smrg    for (i = size = 0, color = geom->colors; i < geom->num_colors; i++, color++) {
4669f7df2e56Smrg        size += XkbSizeCountedString(color->spec);
467005b261ecSmrg    }
467105b261ecSmrg    return size;
467205b261ecSmrg}
467305b261ecSmrg
467405b261ecSmrgstatic char *
4675f7df2e56SmrgXkbWriteGeomColors(char *wire, XkbGeometryPtr geom, Bool swap)
467605b261ecSmrg{
4677f7df2e56Smrg    register int i;
4678f7df2e56Smrg    register XkbColorPtr color;
467905b261ecSmrg
4680f7df2e56Smrg    for (i = 0, color = geom->colors; i < geom->num_colors; i++, color++) {
4681f7df2e56Smrg        wire = XkbWriteCountedString(wire, color->spec, swap);
468205b261ecSmrg    }
468305b261ecSmrg    return wire;
468405b261ecSmrg}
468505b261ecSmrg
468605b261ecSmrgstatic int
468705b261ecSmrgXkbSizeGeomShapes(XkbGeometryPtr geom)
468805b261ecSmrg{
4689f7df2e56Smrg    register int i, size;
4690f7df2e56Smrg    register XkbShapePtr shape;
4691f7df2e56Smrg
4692f7df2e56Smrg    for (i = size = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) {
4693f7df2e56Smrg        register int n;
4694f7df2e56Smrg        register XkbOutlinePtr ol;
4695f7df2e56Smrg
4696f7df2e56Smrg        size += SIZEOF(xkbShapeWireDesc);
4697f7df2e56Smrg        for (n = 0, ol = shape->outlines; n < shape->num_outlines; n++, ol++) {
4698f7df2e56Smrg            size += SIZEOF(xkbOutlineWireDesc);
4699f7df2e56Smrg            size += ol->num_points * SIZEOF(xkbPointWireDesc);
4700f7df2e56Smrg        }
470105b261ecSmrg    }
470205b261ecSmrg    return size;
470305b261ecSmrg}
470405b261ecSmrg
470505b261ecSmrgstatic char *
4706f7df2e56SmrgXkbWriteGeomShapes(char *wire, XkbGeometryPtr geom, Bool swap)
470705b261ecSmrg{
4708f7df2e56Smrg    int i;
4709f7df2e56Smrg    XkbShapePtr shape;
4710f7df2e56Smrg    xkbShapeWireDesc *shapeWire;
4711f7df2e56Smrg
4712f7df2e56Smrg    for (i = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) {
4713f7df2e56Smrg        register int o;
4714f7df2e56Smrg        XkbOutlinePtr ol;
4715f7df2e56Smrg        xkbOutlineWireDesc *olWire;
4716f7df2e56Smrg
4717f7df2e56Smrg        shapeWire = (xkbShapeWireDesc *) wire;
4718f7df2e56Smrg        shapeWire->name = shape->name;
4719f7df2e56Smrg        shapeWire->nOutlines = shape->num_outlines;
4720f7df2e56Smrg        if (shape->primary != NULL)
4721f7df2e56Smrg            shapeWire->primaryNdx = XkbOutlineIndex(shape, shape->primary);
4722f7df2e56Smrg        else
4723f7df2e56Smrg            shapeWire->primaryNdx = XkbNoShape;
4724f7df2e56Smrg        if (shape->approx != NULL)
4725f7df2e56Smrg            shapeWire->approxNdx = XkbOutlineIndex(shape, shape->approx);
4726f7df2e56Smrg        else
4727f7df2e56Smrg            shapeWire->approxNdx = XkbNoShape;
4728f7df2e56Smrg        shapeWire->pad = 0;
4729f7df2e56Smrg        if (swap) {
4730f7df2e56Smrg            swapl(&shapeWire->name);
4731f7df2e56Smrg        }
4732f7df2e56Smrg        wire = (char *) &shapeWire[1];
4733f7df2e56Smrg        for (o = 0, ol = shape->outlines; o < shape->num_outlines; o++, ol++) {
4734f7df2e56Smrg            register int p;
4735f7df2e56Smrg            XkbPointPtr pt;
4736f7df2e56Smrg            xkbPointWireDesc *ptWire;
4737f7df2e56Smrg
4738f7df2e56Smrg            olWire = (xkbOutlineWireDesc *) wire;
4739f7df2e56Smrg            olWire->nPoints = ol->num_points;
4740f7df2e56Smrg            olWire->cornerRadius = ol->corner_radius;
4741f7df2e56Smrg            olWire->pad = 0;
4742f7df2e56Smrg            wire = (char *) &olWire[1];
4743f7df2e56Smrg            ptWire = (xkbPointWireDesc *) wire;
4744f7df2e56Smrg            for (p = 0, pt = ol->points; p < ol->num_points; p++, pt++) {
4745f7df2e56Smrg                ptWire[p].x = pt->x;
4746f7df2e56Smrg                ptWire[p].y = pt->y;
4747f7df2e56Smrg                if (swap) {
4748f7df2e56Smrg                    swaps(&ptWire[p].x);
4749f7df2e56Smrg                    swaps(&ptWire[p].y);
4750f7df2e56Smrg                }
4751f7df2e56Smrg            }
4752f7df2e56Smrg            wire = (char *) &ptWire[ol->num_points];
4753f7df2e56Smrg        }
475405b261ecSmrg    }
475505b261ecSmrg    return wire;
475605b261ecSmrg}
475705b261ecSmrg
475805b261ecSmrgstatic int
4759f7df2e56SmrgXkbSizeGeomDoodads(int num_doodads, XkbDoodadPtr doodad)
476005b261ecSmrg{
4761f7df2e56Smrg    register int i, size;
4762f7df2e56Smrg
4763f7df2e56Smrg    for (i = size = 0; i < num_doodads; i++, doodad++) {
4764f7df2e56Smrg        size += SIZEOF(xkbAnyDoodadWireDesc);
4765f7df2e56Smrg        if (doodad->any.type == XkbTextDoodad) {
4766f7df2e56Smrg            size += XkbSizeCountedString(doodad->text.text);
4767f7df2e56Smrg            size += XkbSizeCountedString(doodad->text.font);
4768f7df2e56Smrg        }
4769f7df2e56Smrg        else if (doodad->any.type == XkbLogoDoodad) {
4770f7df2e56Smrg            size += XkbSizeCountedString(doodad->logo.logo_name);
4771f7df2e56Smrg        }
477205b261ecSmrg    }
477305b261ecSmrg    return size;
477405b261ecSmrg}
477505b261ecSmrg
477605b261ecSmrgstatic char *
4777f7df2e56SmrgXkbWriteGeomDoodads(char *wire, int num_doodads, XkbDoodadPtr doodad, Bool swap)
477805b261ecSmrg{
4779f7df2e56Smrg    register int i;
4780f7df2e56Smrg    xkbDoodadWireDesc *doodadWire;
4781f7df2e56Smrg
4782f7df2e56Smrg    for (i = 0; i < num_doodads; i++, doodad++) {
4783f7df2e56Smrg        doodadWire = (xkbDoodadWireDesc *) wire;
4784f7df2e56Smrg        wire = (char *) &doodadWire[1];
4785f7df2e56Smrg        memset(doodadWire, 0, SIZEOF(xkbDoodadWireDesc));
4786f7df2e56Smrg        doodadWire->any.name = doodad->any.name;
4787f7df2e56Smrg        doodadWire->any.type = doodad->any.type;
4788f7df2e56Smrg        doodadWire->any.priority = doodad->any.priority;
4789f7df2e56Smrg        doodadWire->any.top = doodad->any.top;
4790f7df2e56Smrg        doodadWire->any.left = doodad->any.left;
4791f7df2e56Smrg        if (swap) {
4792f7df2e56Smrg            swapl(&doodadWire->any.name);
4793f7df2e56Smrg            swaps(&doodadWire->any.top);
4794f7df2e56Smrg            swaps(&doodadWire->any.left);
4795f7df2e56Smrg        }
4796f7df2e56Smrg        switch (doodad->any.type) {
4797f7df2e56Smrg        case XkbOutlineDoodad:
4798f7df2e56Smrg        case XkbSolidDoodad:
4799f7df2e56Smrg            doodadWire->shape.angle = doodad->shape.angle;
4800f7df2e56Smrg            doodadWire->shape.colorNdx = doodad->shape.color_ndx;
4801f7df2e56Smrg            doodadWire->shape.shapeNdx = doodad->shape.shape_ndx;
4802f7df2e56Smrg            if (swap) {
4803f7df2e56Smrg                swaps(&doodadWire->shape.angle);
4804f7df2e56Smrg            }
4805f7df2e56Smrg            break;
4806f7df2e56Smrg        case XkbTextDoodad:
4807f7df2e56Smrg            doodadWire->text.angle = doodad->text.angle;
4808f7df2e56Smrg            doodadWire->text.width = doodad->text.width;
4809f7df2e56Smrg            doodadWire->text.height = doodad->text.height;
4810f7df2e56Smrg            doodadWire->text.colorNdx = doodad->text.color_ndx;
4811f7df2e56Smrg            if (swap) {
4812f7df2e56Smrg                swaps(&doodadWire->text.angle);
4813f7df2e56Smrg                swaps(&doodadWire->text.width);
4814f7df2e56Smrg                swaps(&doodadWire->text.height);
4815f7df2e56Smrg            }
4816f7df2e56Smrg            wire = XkbWriteCountedString(wire, doodad->text.text, swap);
4817f7df2e56Smrg            wire = XkbWriteCountedString(wire, doodad->text.font, swap);
4818f7df2e56Smrg            break;
4819f7df2e56Smrg        case XkbIndicatorDoodad:
4820f7df2e56Smrg            doodadWire->indicator.shapeNdx = doodad->indicator.shape_ndx;
4821f7df2e56Smrg            doodadWire->indicator.onColorNdx = doodad->indicator.on_color_ndx;
4822f7df2e56Smrg            doodadWire->indicator.offColorNdx = doodad->indicator.off_color_ndx;
4823f7df2e56Smrg            break;
4824f7df2e56Smrg        case XkbLogoDoodad:
4825f7df2e56Smrg            doodadWire->logo.angle = doodad->logo.angle;
4826f7df2e56Smrg            doodadWire->logo.colorNdx = doodad->logo.color_ndx;
4827f7df2e56Smrg            doodadWire->logo.shapeNdx = doodad->logo.shape_ndx;
4828f7df2e56Smrg            wire = XkbWriteCountedString(wire, doodad->logo.logo_name, swap);
4829f7df2e56Smrg            break;
4830f7df2e56Smrg        default:
4831f7df2e56Smrg            ErrorF("[xkb] Unknown doodad type %d in XkbWriteGeomDoodads\n",
4832f7df2e56Smrg                   doodad->any.type);
4833f7df2e56Smrg            ErrorF("[xkb] Ignored\n");
4834f7df2e56Smrg            break;
4835f7df2e56Smrg        }
483605b261ecSmrg    }
483705b261ecSmrg    return wire;
483805b261ecSmrg}
483905b261ecSmrg
484005b261ecSmrgstatic char *
4841f7df2e56SmrgXkbWriteGeomOverlay(char *wire, XkbOverlayPtr ol, Bool swap)
484205b261ecSmrg{
4843f7df2e56Smrg    register int r;
4844f7df2e56Smrg    XkbOverlayRowPtr row;
4845f7df2e56Smrg    xkbOverlayWireDesc *olWire;
4846f7df2e56Smrg
4847f7df2e56Smrg    olWire = (xkbOverlayWireDesc *) wire;
4848f7df2e56Smrg    olWire->name = ol->name;
4849f7df2e56Smrg    olWire->nRows = ol->num_rows;
4850f7df2e56Smrg    olWire->pad1 = 0;
4851f7df2e56Smrg    olWire->pad2 = 0;
4852f7df2e56Smrg    if (swap) {
4853f7df2e56Smrg        swapl(&olWire->name);
4854f7df2e56Smrg    }
4855f7df2e56Smrg    wire = (char *) &olWire[1];
4856f7df2e56Smrg    for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) {
4857f7df2e56Smrg        unsigned int k;
4858f7df2e56Smrg        XkbOverlayKeyPtr key;
4859f7df2e56Smrg        xkbOverlayRowWireDesc *rowWire;
4860f7df2e56Smrg
4861f7df2e56Smrg        rowWire = (xkbOverlayRowWireDesc *) wire;
4862f7df2e56Smrg        rowWire->rowUnder = row->row_under;
4863f7df2e56Smrg        rowWire->nKeys = row->num_keys;
4864f7df2e56Smrg        rowWire->pad1 = 0;
4865f7df2e56Smrg        wire = (char *) &rowWire[1];
4866f7df2e56Smrg        for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
4867f7df2e56Smrg            xkbOverlayKeyWireDesc *keyWire;
4868f7df2e56Smrg
4869f7df2e56Smrg            keyWire = (xkbOverlayKeyWireDesc *) wire;
4870f7df2e56Smrg            memcpy(keyWire->over, key->over.name, XkbKeyNameLength);
4871f7df2e56Smrg            memcpy(keyWire->under, key->under.name, XkbKeyNameLength);
4872f7df2e56Smrg            wire = (char *) &keyWire[1];
4873f7df2e56Smrg        }
4874f7df2e56Smrg    }
4875f7df2e56Smrg    return wire;
487605b261ecSmrg}
487705b261ecSmrg
487805b261ecSmrgstatic int
487905b261ecSmrgXkbSizeGeomSections(XkbGeometryPtr geom)
488005b261ecSmrg{
4881f7df2e56Smrg    register int i, size;
4882f7df2e56Smrg    XkbSectionPtr section;
4883f7df2e56Smrg
4884f7df2e56Smrg    for (i = size = 0, section = geom->sections; i < geom->num_sections;
4885f7df2e56Smrg         i++, section++) {
4886f7df2e56Smrg        size += SIZEOF(xkbSectionWireDesc);
4887f7df2e56Smrg        if (section->rows) {
4888f7df2e56Smrg            int r;
4889f7df2e56Smrg            XkbRowPtr row;
4890f7df2e56Smrg
4891f7df2e56Smrg            for (r = 0, row = section->rows; r < section->num_rows; row++, r++) {
4892f7df2e56Smrg                size += SIZEOF(xkbRowWireDesc);
4893f7df2e56Smrg                size += row->num_keys * SIZEOF(xkbKeyWireDesc);
4894f7df2e56Smrg            }
4895f7df2e56Smrg        }
4896f7df2e56Smrg        if (section->doodads)
4897f7df2e56Smrg            size += XkbSizeGeomDoodads(section->num_doodads, section->doodads);
4898f7df2e56Smrg        if (section->overlays) {
4899f7df2e56Smrg            int o;
4900f7df2e56Smrg            XkbOverlayPtr ol;
4901f7df2e56Smrg
4902f7df2e56Smrg            for (o = 0, ol = section->overlays; o < section->num_overlays;
4903f7df2e56Smrg                 o++, ol++) {
4904f7df2e56Smrg                int r;
4905f7df2e56Smrg                XkbOverlayRowPtr row;
4906f7df2e56Smrg
4907f7df2e56Smrg                size += SIZEOF(xkbOverlayWireDesc);
4908f7df2e56Smrg                for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) {
4909f7df2e56Smrg                    size += SIZEOF(xkbOverlayRowWireDesc);
4910f7df2e56Smrg                    size += row->num_keys * SIZEOF(xkbOverlayKeyWireDesc);
4911f7df2e56Smrg                }
4912f7df2e56Smrg            }
4913f7df2e56Smrg        }
491405b261ecSmrg    }
491505b261ecSmrg    return size;
491605b261ecSmrg}
491705b261ecSmrg
491805b261ecSmrgstatic char *
4919f7df2e56SmrgXkbWriteGeomSections(char *wire, XkbGeometryPtr geom, Bool swap)
492005b261ecSmrg{
4921f7df2e56Smrg    register int i;
4922f7df2e56Smrg    XkbSectionPtr section;
4923f7df2e56Smrg    xkbSectionWireDesc *sectionWire;
4924f7df2e56Smrg
4925f7df2e56Smrg    for (i = 0, section = geom->sections; i < geom->num_sections;
4926f7df2e56Smrg         i++, section++) {
4927f7df2e56Smrg        sectionWire = (xkbSectionWireDesc *) wire;
4928f7df2e56Smrg        sectionWire->name = section->name;
4929f7df2e56Smrg        sectionWire->top = section->top;
4930f7df2e56Smrg        sectionWire->left = section->left;
4931f7df2e56Smrg        sectionWire->width = section->width;
4932f7df2e56Smrg        sectionWire->height = section->height;
4933f7df2e56Smrg        sectionWire->angle = section->angle;
4934f7df2e56Smrg        sectionWire->priority = section->priority;
4935f7df2e56Smrg        sectionWire->nRows = section->num_rows;
4936f7df2e56Smrg        sectionWire->nDoodads = section->num_doodads;
4937f7df2e56Smrg        sectionWire->nOverlays = section->num_overlays;
4938f7df2e56Smrg        sectionWire->pad = 0;
4939f7df2e56Smrg        if (swap) {
4940f7df2e56Smrg            swapl(&sectionWire->name);
4941f7df2e56Smrg            swaps(&sectionWire->top);
4942f7df2e56Smrg            swaps(&sectionWire->left);
4943f7df2e56Smrg            swaps(&sectionWire->width);
4944f7df2e56Smrg            swaps(&sectionWire->height);
4945f7df2e56Smrg            swaps(&sectionWire->angle);
4946f7df2e56Smrg        }
4947f7df2e56Smrg        wire = (char *) &sectionWire[1];
4948f7df2e56Smrg        if (section->rows) {
4949f7df2e56Smrg            int r;
4950f7df2e56Smrg            XkbRowPtr row;
4951f7df2e56Smrg            xkbRowWireDesc *rowWire;
4952f7df2e56Smrg
4953f7df2e56Smrg            for (r = 0, row = section->rows; r < section->num_rows; r++, row++) {
4954f7df2e56Smrg                rowWire = (xkbRowWireDesc *) wire;
4955f7df2e56Smrg                rowWire->top = row->top;
4956f7df2e56Smrg                rowWire->left = row->left;
4957f7df2e56Smrg                rowWire->nKeys = row->num_keys;
4958f7df2e56Smrg                rowWire->vertical = row->vertical;
4959f7df2e56Smrg                rowWire->pad = 0;
4960f7df2e56Smrg                if (swap) {
4961f7df2e56Smrg                    swaps(&rowWire->top);
4962f7df2e56Smrg                    swaps(&rowWire->left);
4963f7df2e56Smrg                }
4964f7df2e56Smrg                wire = (char *) &rowWire[1];
4965f7df2e56Smrg                if (row->keys) {
4966f7df2e56Smrg                    int k;
4967f7df2e56Smrg                    XkbKeyPtr key;
4968f7df2e56Smrg                    xkbKeyWireDesc *keyWire;
4969f7df2e56Smrg
4970f7df2e56Smrg                    keyWire = (xkbKeyWireDesc *) wire;
4971f7df2e56Smrg                    for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
4972f7df2e56Smrg                        memcpy(keyWire[k].name, key->name.name,
4973f7df2e56Smrg                               XkbKeyNameLength);
4974f7df2e56Smrg                        keyWire[k].gap = key->gap;
4975f7df2e56Smrg                        keyWire[k].shapeNdx = key->shape_ndx;
4976f7df2e56Smrg                        keyWire[k].colorNdx = key->color_ndx;
4977f7df2e56Smrg                        if (swap) {
4978f7df2e56Smrg                            swaps(&keyWire[k].gap);
4979f7df2e56Smrg                        }
4980f7df2e56Smrg                    }
4981f7df2e56Smrg                    wire = (char *) &keyWire[row->num_keys];
4982f7df2e56Smrg                }
4983f7df2e56Smrg            }
4984f7df2e56Smrg        }
4985f7df2e56Smrg        if (section->doodads) {
4986f7df2e56Smrg            wire = XkbWriteGeomDoodads(wire,
4987f7df2e56Smrg                                       section->num_doodads, section->doodads,
4988f7df2e56Smrg                                       swap);
4989f7df2e56Smrg        }
4990f7df2e56Smrg        if (section->overlays) {
4991f7df2e56Smrg            register int o;
4992f7df2e56Smrg
4993f7df2e56Smrg            for (o = 0; o < section->num_overlays; o++) {
4994f7df2e56Smrg                wire = XkbWriteGeomOverlay(wire, &section->overlays[o], swap);
4995f7df2e56Smrg            }
4996f7df2e56Smrg        }
499705b261ecSmrg    }
499805b261ecSmrg    return wire;
499905b261ecSmrg}
500005b261ecSmrg
500105b261ecSmrgstatic Status
5002f7df2e56SmrgXkbComputeGetGeometryReplySize(XkbGeometryPtr geom,
5003f7df2e56Smrg                               xkbGetGeometryReply * rep, Atom name)
500405b261ecSmrg{
5005f7df2e56Smrg    int len;
5006f7df2e56Smrg
5007f7df2e56Smrg    if (geom != NULL) {
5008f7df2e56Smrg        len = XkbSizeCountedString(geom->label_font);
5009f7df2e56Smrg        len += XkbSizeGeomProperties(geom);
5010f7df2e56Smrg        len += XkbSizeGeomColors(geom);
5011f7df2e56Smrg        len += XkbSizeGeomShapes(geom);
5012f7df2e56Smrg        len += XkbSizeGeomSections(geom);
5013f7df2e56Smrg        len += XkbSizeGeomDoodads(geom->num_doodads, geom->doodads);
5014f7df2e56Smrg        len += XkbSizeGeomKeyAliases(geom);
5015f7df2e56Smrg        rep->length = len / 4;
5016f7df2e56Smrg        rep->found = TRUE;
5017f7df2e56Smrg        rep->name = geom->name;
5018f7df2e56Smrg        rep->widthMM = geom->width_mm;
5019f7df2e56Smrg        rep->heightMM = geom->height_mm;
5020f7df2e56Smrg        rep->nProperties = geom->num_properties;
5021f7df2e56Smrg        rep->nColors = geom->num_colors;
5022f7df2e56Smrg        rep->nShapes = geom->num_shapes;
5023f7df2e56Smrg        rep->nSections = geom->num_sections;
5024f7df2e56Smrg        rep->nDoodads = geom->num_doodads;
5025f7df2e56Smrg        rep->nKeyAliases = geom->num_key_aliases;
5026f7df2e56Smrg        rep->baseColorNdx = XkbGeomColorIndex(geom, geom->base_color);
5027f7df2e56Smrg        rep->labelColorNdx = XkbGeomColorIndex(geom, geom->label_color);
502805b261ecSmrg    }
502905b261ecSmrg    else {
5030f7df2e56Smrg        rep->length = 0;
5031f7df2e56Smrg        rep->found = FALSE;
5032f7df2e56Smrg        rep->name = name;
5033f7df2e56Smrg        rep->widthMM = rep->heightMM = 0;
5034f7df2e56Smrg        rep->nProperties = rep->nColors = rep->nShapes = 0;
5035f7df2e56Smrg        rep->nSections = rep->nDoodads = 0;
5036f7df2e56Smrg        rep->nKeyAliases = 0;
5037f7df2e56Smrg        rep->labelColorNdx = rep->baseColorNdx = 0;
503805b261ecSmrg    }
503905b261ecSmrg    return Success;
504005b261ecSmrg}
504105b261ecSmrgstatic int
5042f7df2e56SmrgXkbSendGeometry(ClientPtr client,
5043f7df2e56Smrg                XkbGeometryPtr geom, xkbGetGeometryReply * rep, Bool freeGeom)
504405b261ecSmrg{
5045f7df2e56Smrg    char *desc, *start;
5046f7df2e56Smrg    int len;
5047f7df2e56Smrg
5048f7df2e56Smrg    if (geom != NULL) {
5049f7df2e56Smrg        start = desc = xallocarray(rep->length, 4);
5050f7df2e56Smrg        if (!start)
5051f7df2e56Smrg            return BadAlloc;
5052f7df2e56Smrg        len = rep->length * 4;
5053f7df2e56Smrg        desc = XkbWriteCountedString(desc, geom->label_font, client->swapped);
5054f7df2e56Smrg        if (rep->nProperties > 0)
5055f7df2e56Smrg            desc = XkbWriteGeomProperties(desc, geom, client->swapped);
5056f7df2e56Smrg        if (rep->nColors > 0)
5057f7df2e56Smrg            desc = XkbWriteGeomColors(desc, geom, client->swapped);
5058f7df2e56Smrg        if (rep->nShapes > 0)
5059f7df2e56Smrg            desc = XkbWriteGeomShapes(desc, geom, client->swapped);
5060f7df2e56Smrg        if (rep->nSections > 0)
5061f7df2e56Smrg            desc = XkbWriteGeomSections(desc, geom, client->swapped);
5062f7df2e56Smrg        if (rep->nDoodads > 0)
5063f7df2e56Smrg            desc = XkbWriteGeomDoodads(desc, geom->num_doodads, geom->doodads,
5064f7df2e56Smrg                                       client->swapped);
5065f7df2e56Smrg        if (rep->nKeyAliases > 0)
5066f7df2e56Smrg            desc = XkbWriteGeomKeyAliases(desc, geom, client->swapped);
5067f7df2e56Smrg        if ((desc - start) != (len)) {
5068f7df2e56Smrg            ErrorF
5069f7df2e56Smrg                ("[xkb] BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n",
5070f7df2e56Smrg                 len, (unsigned long) (desc - start));
5071f7df2e56Smrg        }
507205b261ecSmrg    }
507305b261ecSmrg    else {
5074f7df2e56Smrg        len = 0;
5075f7df2e56Smrg        start = NULL;
507605b261ecSmrg    }
507705b261ecSmrg    if (client->swapped) {
5078f7df2e56Smrg        swaps(&rep->sequenceNumber);
5079f7df2e56Smrg        swapl(&rep->length);
5080f7df2e56Smrg        swapl(&rep->name);
5081f7df2e56Smrg        swaps(&rep->widthMM);
5082f7df2e56Smrg        swaps(&rep->heightMM);
5083f7df2e56Smrg        swaps(&rep->nProperties);
5084f7df2e56Smrg        swaps(&rep->nColors);
5085f7df2e56Smrg        swaps(&rep->nShapes);
5086f7df2e56Smrg        swaps(&rep->nSections);
5087f7df2e56Smrg        swaps(&rep->nDoodads);
5088f7df2e56Smrg        swaps(&rep->nKeyAliases);
5089f7df2e56Smrg    }
5090f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetGeometryReply), rep);
5091f7df2e56Smrg    if (len > 0)
5092f7df2e56Smrg        WriteToClient(client, len, start);
5093f7df2e56Smrg    if (start != NULL)
5094f7df2e56Smrg        free((char *) start);
509505b261ecSmrg    if (freeGeom)
5096f7df2e56Smrg        XkbFreeGeometry(geom, XkbGeomAllMask, TRUE);
50976747b715Smrg    return Success;
509805b261ecSmrg}
509905b261ecSmrg
510005b261ecSmrgint
510105b261ecSmrgProcXkbGetGeometry(ClientPtr client)
510205b261ecSmrg{
5103f7df2e56Smrg    DeviceIntPtr dev;
510405b261ecSmrg    xkbGetGeometryReply rep;
5105f7df2e56Smrg    XkbGeometryPtr geom;
5106f7df2e56Smrg    Bool shouldFree;
5107f7df2e56Smrg    Status status;
510805b261ecSmrg
510905b261ecSmrg    REQUEST(xkbGetGeometryReq);
511005b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetGeometryReq);
511105b261ecSmrg
5112f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
5113f7df2e56Smrg        return BadAccess;
511405b261ecSmrg
51154642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
511605b261ecSmrg    CHK_ATOM_OR_NONE(stuff->name);
511705b261ecSmrg
5118f7df2e56Smrg    geom = XkbLookupNamedGeometry(dev, stuff->name, &shouldFree);
5119f7df2e56Smrg    rep = (xkbGetGeometryReply) {
5120f7df2e56Smrg        .type = X_Reply,
5121f7df2e56Smrg        .deviceID = dev->id,
5122f7df2e56Smrg        .sequenceNumber = client->sequence,
5123f7df2e56Smrg        .length = 0
5124f7df2e56Smrg    };
5125f7df2e56Smrg    status = XkbComputeGetGeometryReplySize(geom, &rep, stuff->name);
5126f7df2e56Smrg    if (status != Success)
5127f7df2e56Smrg        return status;
5128f7df2e56Smrg    else
5129f7df2e56Smrg        return XkbSendGeometry(client, geom, &rep, shouldFree);
513005b261ecSmrg}
513105b261ecSmrg
513205b261ecSmrg/***====================================================================***/
513305b261ecSmrg
51341e26616aSmrgstatic Status
51351e26616aSmrg_GetCountedString(char **wire_inout, ClientPtr client, char **str)
513605b261ecSmrg{
51371e26616aSmrg    char *wire, *next;
51381e26616aSmrg    CARD16 len;
513905b261ecSmrg
51401e26616aSmrg    wire = *wire_inout;
51411e26616aSmrg    len = *(CARD16 *) wire;
51421e26616aSmrg    if (client->swapped) {
5143f7df2e56Smrg        swaps(&len);
514405b261ecSmrg    }
51451e26616aSmrg    next = wire + XkbPaddedSize(len + 2);
51461e26616aSmrg    /* Check we're still within the size of the request */
51471e26616aSmrg    if (client->req_len <
51481e26616aSmrg        bytes_to_int32(next - (char *) client->requestBuffer))
51491e26616aSmrg        return BadValue;
51501e26616aSmrg    *str = malloc(len + 1);
51511e26616aSmrg    if (!*str)
51521e26616aSmrg        return BadAlloc;
51531e26616aSmrg    memcpy(*str, &wire[2], len);
51541e26616aSmrg    *(*str + len) = '\0';
51551e26616aSmrg    *wire_inout = next;
51561e26616aSmrg    return Success;
515705b261ecSmrg}
515805b261ecSmrg
515905b261ecSmrgstatic Status
5160f7df2e56Smrg_CheckSetDoodad(char **wire_inout,
5161f7df2e56Smrg                XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client)
516205b261ecSmrg{
5163f7df2e56Smrg    char *wire;
5164f7df2e56Smrg    xkbDoodadWireDesc *dWire;
5165f7df2e56Smrg    xkbAnyDoodadWireDesc any;
5166f7df2e56Smrg    xkbTextDoodadWireDesc text;
5167f7df2e56Smrg    XkbDoodadPtr doodad;
51681e26616aSmrg    Status status;
516905b261ecSmrg
5170f7df2e56Smrg    dWire = (xkbDoodadWireDesc *) (*wire_inout);
5171f7df2e56Smrg    any = dWire->any;
5172f7df2e56Smrg    wire = (char *) &dWire[1];
517305b261ecSmrg    if (client->swapped) {
5174f7df2e56Smrg        swapl(&any.name);
5175f7df2e56Smrg        swaps(&any.top);
5176f7df2e56Smrg        swaps(&any.left);
5177f7df2e56Smrg        swaps(&any.angle);
517805b261ecSmrg    }
517905b261ecSmrg    CHK_ATOM_ONLY(dWire->any.name);
5180f7df2e56Smrg    doodad = XkbAddGeomDoodad(geom, section, any.name);
518105b261ecSmrg    if (!doodad)
5182f7df2e56Smrg        return BadAlloc;
5183f7df2e56Smrg    doodad->any.type = dWire->any.type;
5184f7df2e56Smrg    doodad->any.priority = dWire->any.priority;
5185f7df2e56Smrg    doodad->any.top = any.top;
5186f7df2e56Smrg    doodad->any.left = any.left;
5187f7df2e56Smrg    doodad->any.angle = any.angle;
518805b261ecSmrg    switch (doodad->any.type) {
5189f7df2e56Smrg    case XkbOutlineDoodad:
5190f7df2e56Smrg    case XkbSolidDoodad:
5191f7df2e56Smrg        if (dWire->shape.colorNdx >= geom->num_colors) {
5192f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x40, geom->num_colors,
5193f7df2e56Smrg                                              dWire->shape.colorNdx);
5194f7df2e56Smrg            return BadMatch;
5195f7df2e56Smrg        }
5196f7df2e56Smrg        if (dWire->shape.shapeNdx >= geom->num_shapes) {
5197f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x41, geom->num_shapes,
5198f7df2e56Smrg                                              dWire->shape.shapeNdx);
5199f7df2e56Smrg            return BadMatch;
5200f7df2e56Smrg        }
5201f7df2e56Smrg        doodad->shape.color_ndx = dWire->shape.colorNdx;
5202f7df2e56Smrg        doodad->shape.shape_ndx = dWire->shape.shapeNdx;
5203f7df2e56Smrg        break;
5204f7df2e56Smrg    case XkbTextDoodad:
5205f7df2e56Smrg        if (dWire->text.colorNdx >= geom->num_colors) {
5206f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x42, geom->num_colors,
5207f7df2e56Smrg                                              dWire->text.colorNdx);
5208f7df2e56Smrg            return BadMatch;
5209f7df2e56Smrg        }
5210f7df2e56Smrg        text = dWire->text;
5211f7df2e56Smrg        if (client->swapped) {
5212f7df2e56Smrg            swaps(&text.width);
5213f7df2e56Smrg            swaps(&text.height);
5214f7df2e56Smrg        }
5215f7df2e56Smrg        doodad->text.width = text.width;
5216f7df2e56Smrg        doodad->text.height = text.height;
5217f7df2e56Smrg        doodad->text.color_ndx = dWire->text.colorNdx;
5218f7df2e56Smrg        status = _GetCountedString(&wire, client, &doodad->text.text);
5219f7df2e56Smrg        if (status != Success)
5220f7df2e56Smrg            return status;
5221f7df2e56Smrg        status = _GetCountedString(&wire, client, &doodad->text.font);
5222f7df2e56Smrg        if (status != Success) {
5223f7df2e56Smrg            free (doodad->text.text);
5224f7df2e56Smrg            return status;
5225f7df2e56Smrg        }
5226f7df2e56Smrg        break;
5227f7df2e56Smrg    case XkbIndicatorDoodad:
5228f7df2e56Smrg        if (dWire->indicator.onColorNdx >= geom->num_colors) {
5229f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x43, geom->num_colors,
5230f7df2e56Smrg                                              dWire->indicator.onColorNdx);
5231f7df2e56Smrg            return BadMatch;
5232f7df2e56Smrg        }
5233f7df2e56Smrg        if (dWire->indicator.offColorNdx >= geom->num_colors) {
5234f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x44, geom->num_colors,
5235f7df2e56Smrg                                              dWire->indicator.offColorNdx);
5236f7df2e56Smrg            return BadMatch;
5237f7df2e56Smrg        }
5238f7df2e56Smrg        if (dWire->indicator.shapeNdx >= geom->num_shapes) {
5239f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x45, geom->num_shapes,
5240f7df2e56Smrg                                              dWire->indicator.shapeNdx);
5241f7df2e56Smrg            return BadMatch;
5242f7df2e56Smrg        }
5243f7df2e56Smrg        doodad->indicator.shape_ndx = dWire->indicator.shapeNdx;
5244f7df2e56Smrg        doodad->indicator.on_color_ndx = dWire->indicator.onColorNdx;
5245f7df2e56Smrg        doodad->indicator.off_color_ndx = dWire->indicator.offColorNdx;
5246f7df2e56Smrg        break;
5247f7df2e56Smrg    case XkbLogoDoodad:
5248f7df2e56Smrg        if (dWire->logo.colorNdx >= geom->num_colors) {
5249f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x46, geom->num_colors,
5250f7df2e56Smrg                                              dWire->logo.colorNdx);
5251f7df2e56Smrg            return BadMatch;
5252f7df2e56Smrg        }
5253f7df2e56Smrg        if (dWire->logo.shapeNdx >= geom->num_shapes) {
5254f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x47, geom->num_shapes,
5255f7df2e56Smrg                                              dWire->logo.shapeNdx);
5256f7df2e56Smrg            return BadMatch;
5257f7df2e56Smrg        }
5258f7df2e56Smrg        doodad->logo.color_ndx = dWire->logo.colorNdx;
5259f7df2e56Smrg        doodad->logo.shape_ndx = dWire->logo.shapeNdx;
5260f7df2e56Smrg        status = _GetCountedString(&wire, client, &doodad->logo.logo_name);
5261f7df2e56Smrg        if (status != Success)
5262f7df2e56Smrg            return status;
5263f7df2e56Smrg        break;
5264f7df2e56Smrg    default:
5265f7df2e56Smrg        client->errorValue = _XkbErrCode2(0x4F, dWire->any.type);
5266f7df2e56Smrg        return BadValue;
5267f7df2e56Smrg    }
5268f7df2e56Smrg    *wire_inout = wire;
5269f7df2e56Smrg    return Success;
5270f7df2e56Smrg}
5271f7df2e56Smrg
5272f7df2e56Smrgstatic Status
5273f7df2e56Smrg_CheckSetOverlay(char **wire_inout,
5274f7df2e56Smrg                 XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client)
527505b261ecSmrg{
5276f7df2e56Smrg    register int r;
5277f7df2e56Smrg    char *wire;
5278f7df2e56Smrg    XkbOverlayPtr ol;
5279f7df2e56Smrg    xkbOverlayWireDesc *olWire;
5280f7df2e56Smrg    xkbOverlayRowWireDesc *rWire;
528105b261ecSmrg
5282f7df2e56Smrg    wire = *wire_inout;
5283f7df2e56Smrg    olWire = (xkbOverlayWireDesc *) wire;
5284f7df2e56Smrg    if (client->swapped) {
5285f7df2e56Smrg        swapl(&olWire->name);
5286f7df2e56Smrg    }
5287f7df2e56Smrg    CHK_ATOM_ONLY(olWire->name);
5288f7df2e56Smrg    ol = XkbAddGeomOverlay(section, olWire->name, olWire->nRows);
5289f7df2e56Smrg    rWire = (xkbOverlayRowWireDesc *) &olWire[1];
5290f7df2e56Smrg    for (r = 0; r < olWire->nRows; r++) {
5291f7df2e56Smrg        register int k;
5292f7df2e56Smrg        xkbOverlayKeyWireDesc *kWire;
5293f7df2e56Smrg        XkbOverlayRowPtr row;
5294f7df2e56Smrg
5295f7df2e56Smrg        if (rWire->rowUnder > section->num_rows) {
5296f7df2e56Smrg            client->errorValue = _XkbErrCode4(0x20, r, section->num_rows,
5297f7df2e56Smrg                                              rWire->rowUnder);
5298f7df2e56Smrg            return BadMatch;
5299f7df2e56Smrg        }
5300f7df2e56Smrg        row = XkbAddGeomOverlayRow(ol, rWire->rowUnder, rWire->nKeys);
5301f7df2e56Smrg        kWire = (xkbOverlayKeyWireDesc *) &rWire[1];
5302f7df2e56Smrg        for (k = 0; k < rWire->nKeys; k++, kWire++) {
5303f7df2e56Smrg            if (XkbAddGeomOverlayKey(ol, row,
5304f7df2e56Smrg                                     (char *) kWire->over,
5305f7df2e56Smrg                                     (char *) kWire->under) == NULL) {
5306f7df2e56Smrg                client->errorValue = _XkbErrCode3(0x21, r, k);
5307f7df2e56Smrg                return BadMatch;
5308f7df2e56Smrg            }
5309f7df2e56Smrg        }
5310f7df2e56Smrg        rWire = (xkbOverlayRowWireDesc *) kWire;
5311f7df2e56Smrg    }
5312f7df2e56Smrg    olWire = (xkbOverlayWireDesc *) rWire;
5313f7df2e56Smrg    wire = (char *) olWire;
5314f7df2e56Smrg    *wire_inout = wire;
5315f7df2e56Smrg    return Success;
5316f7df2e56Smrg}
5317f7df2e56Smrg
5318f7df2e56Smrgstatic Status
5319f7df2e56Smrg_CheckSetSections(XkbGeometryPtr geom,
5320f7df2e56Smrg                  xkbSetGeometryReq * req, char **wire_inout, ClientPtr client)
5321f7df2e56Smrg{
5322f7df2e56Smrg    Status status;
5323f7df2e56Smrg    register int s;
5324f7df2e56Smrg    char *wire;
5325f7df2e56Smrg    xkbSectionWireDesc *sWire;
5326f7df2e56Smrg    XkbSectionPtr section;
5327f7df2e56Smrg
5328f7df2e56Smrg    wire = *wire_inout;
5329f7df2e56Smrg    if (req->nSections < 1)
5330f7df2e56Smrg        return Success;
5331f7df2e56Smrg    sWire = (xkbSectionWireDesc *) wire;
5332f7df2e56Smrg    for (s = 0; s < req->nSections; s++) {
5333f7df2e56Smrg        register int r;
5334f7df2e56Smrg        xkbRowWireDesc *rWire;
5335f7df2e56Smrg
5336f7df2e56Smrg        if (client->swapped) {
5337f7df2e56Smrg            swapl(&sWire->name);
5338f7df2e56Smrg            swaps(&sWire->top);
5339f7df2e56Smrg            swaps(&sWire->left);
5340f7df2e56Smrg            swaps(&sWire->width);
5341f7df2e56Smrg            swaps(&sWire->height);
5342f7df2e56Smrg            swaps(&sWire->angle);
5343f7df2e56Smrg        }
5344f7df2e56Smrg        CHK_ATOM_ONLY(sWire->name);
5345f7df2e56Smrg        section = XkbAddGeomSection(geom, sWire->name, sWire->nRows,
5346f7df2e56Smrg                                    sWire->nDoodads, sWire->nOverlays);
5347f7df2e56Smrg        if (!section)
5348f7df2e56Smrg            return BadAlloc;
5349f7df2e56Smrg        section->priority = sWire->priority;
5350f7df2e56Smrg        section->top = sWire->top;
5351f7df2e56Smrg        section->left = sWire->left;
5352f7df2e56Smrg        section->width = sWire->width;
5353f7df2e56Smrg        section->height = sWire->height;
5354f7df2e56Smrg        section->angle = sWire->angle;
5355f7df2e56Smrg        rWire = (xkbRowWireDesc *) &sWire[1];
5356f7df2e56Smrg        for (r = 0; r < sWire->nRows; r++) {
5357f7df2e56Smrg            register int k;
5358f7df2e56Smrg            XkbRowPtr row;
5359f7df2e56Smrg            xkbKeyWireDesc *kWire;
5360f7df2e56Smrg
5361f7df2e56Smrg            if (client->swapped) {
5362f7df2e56Smrg                swaps(&rWire->top);
5363f7df2e56Smrg                swaps(&rWire->left);
5364f7df2e56Smrg            }
5365f7df2e56Smrg            row = XkbAddGeomRow(section, rWire->nKeys);
5366f7df2e56Smrg            if (!row)
5367f7df2e56Smrg                return BadAlloc;
5368f7df2e56Smrg            row->top = rWire->top;
5369f7df2e56Smrg            row->left = rWire->left;
5370f7df2e56Smrg            row->vertical = rWire->vertical;
5371f7df2e56Smrg            kWire = (xkbKeyWireDesc *) &rWire[1];
5372f7df2e56Smrg            for (k = 0; k < rWire->nKeys; k++) {
5373f7df2e56Smrg                XkbKeyPtr key;
5374f7df2e56Smrg
5375f7df2e56Smrg                key = XkbAddGeomKey(row);
5376f7df2e56Smrg                if (!key)
5377f7df2e56Smrg                    return BadAlloc;
5378f7df2e56Smrg                memcpy(key->name.name, kWire[k].name, XkbKeyNameLength);
5379f7df2e56Smrg                key->gap = kWire[k].gap;
5380f7df2e56Smrg                key->shape_ndx = kWire[k].shapeNdx;
5381f7df2e56Smrg                key->color_ndx = kWire[k].colorNdx;
5382f7df2e56Smrg                if (key->shape_ndx >= geom->num_shapes) {
5383f7df2e56Smrg                    client->errorValue = _XkbErrCode3(0x10, key->shape_ndx,
5384f7df2e56Smrg                                                      geom->num_shapes);
5385f7df2e56Smrg                    return BadMatch;
5386f7df2e56Smrg                }
5387f7df2e56Smrg                if (key->color_ndx >= geom->num_colors) {
5388f7df2e56Smrg                    client->errorValue = _XkbErrCode3(0x11, key->color_ndx,
5389f7df2e56Smrg                                                      geom->num_colors);
5390f7df2e56Smrg                    return BadMatch;
5391f7df2e56Smrg                }
5392f7df2e56Smrg            }
5393f7df2e56Smrg            rWire = (xkbRowWireDesc *) &kWire[rWire->nKeys];
5394f7df2e56Smrg        }
5395f7df2e56Smrg        wire = (char *) rWire;
5396f7df2e56Smrg        if (sWire->nDoodads > 0) {
5397f7df2e56Smrg            register int d;
5398f7df2e56Smrg
5399f7df2e56Smrg            for (d = 0; d < sWire->nDoodads; d++) {
5400f7df2e56Smrg                status = _CheckSetDoodad(&wire, geom, section, client);
5401f7df2e56Smrg                if (status != Success)
5402f7df2e56Smrg                    return status;
5403f7df2e56Smrg            }
5404f7df2e56Smrg        }
5405f7df2e56Smrg        if (sWire->nOverlays > 0) {
5406f7df2e56Smrg            register int o;
5407f7df2e56Smrg
5408f7df2e56Smrg            for (o = 0; o < sWire->nOverlays; o++) {
5409f7df2e56Smrg                status = _CheckSetOverlay(&wire, geom, section, client);
5410f7df2e56Smrg                if (status != Success)
5411f7df2e56Smrg                    return status;
5412f7df2e56Smrg            }
5413f7df2e56Smrg        }
5414f7df2e56Smrg        sWire = (xkbSectionWireDesc *) wire;
5415f7df2e56Smrg    }
5416f7df2e56Smrg    wire = (char *) sWire;
5417f7df2e56Smrg    *wire_inout = wire;
5418f7df2e56Smrg    return Success;
5419f7df2e56Smrg}
5420f7df2e56Smrg
5421f7df2e56Smrgstatic Status
5422f7df2e56Smrg_CheckSetShapes(XkbGeometryPtr geom,
5423f7df2e56Smrg                xkbSetGeometryReq * req, char **wire_inout, ClientPtr client)
5424f7df2e56Smrg{
5425f7df2e56Smrg    register int i;
5426f7df2e56Smrg    char *wire;
5427f7df2e56Smrg
5428f7df2e56Smrg    wire = *wire_inout;
5429f7df2e56Smrg    if (req->nShapes < 1) {
5430f7df2e56Smrg        client->errorValue = _XkbErrCode2(0x06, req->nShapes);
5431f7df2e56Smrg        return BadValue;
543205b261ecSmrg    }
543305b261ecSmrg    else {
5434f7df2e56Smrg        xkbShapeWireDesc *shapeWire;
5435f7df2e56Smrg        XkbShapePtr shape;
5436f7df2e56Smrg        register int o;
5437f7df2e56Smrg
5438f7df2e56Smrg        shapeWire = (xkbShapeWireDesc *) wire;
5439f7df2e56Smrg        for (i = 0; i < req->nShapes; i++) {
5440f7df2e56Smrg            xkbOutlineWireDesc *olWire;
5441f7df2e56Smrg            XkbOutlinePtr ol;
5442f7df2e56Smrg
5443f7df2e56Smrg            shape =
5444f7df2e56Smrg                XkbAddGeomShape(geom, shapeWire->name, shapeWire->nOutlines);
5445f7df2e56Smrg            if (!shape)
5446f7df2e56Smrg                return BadAlloc;
5447f7df2e56Smrg            olWire = (xkbOutlineWireDesc *) (&shapeWire[1]);
5448f7df2e56Smrg            for (o = 0; o < shapeWire->nOutlines; o++) {
5449f7df2e56Smrg                register int p;
5450f7df2e56Smrg                XkbPointPtr pt;
5451f7df2e56Smrg                xkbPointWireDesc *ptWire;
5452f7df2e56Smrg
5453f7df2e56Smrg                ol = XkbAddGeomOutline(shape, olWire->nPoints);
5454f7df2e56Smrg                if (!ol)
5455f7df2e56Smrg                    return BadAlloc;
5456f7df2e56Smrg                ol->corner_radius = olWire->cornerRadius;
5457f7df2e56Smrg                ptWire = (xkbPointWireDesc *) &olWire[1];
5458f7df2e56Smrg                for (p = 0, pt = ol->points; p < olWire->nPoints; p++, pt++) {
5459f7df2e56Smrg                    pt->x = ptWire[p].x;
5460f7df2e56Smrg                    pt->y = ptWire[p].y;
5461f7df2e56Smrg                    if (client->swapped) {
5462f7df2e56Smrg                        swaps(&pt->x);
5463f7df2e56Smrg                        swaps(&pt->y);
5464f7df2e56Smrg                    }
5465f7df2e56Smrg                }
5466f7df2e56Smrg                ol->num_points = olWire->nPoints;
5467f7df2e56Smrg                olWire = (xkbOutlineWireDesc *) (&ptWire[olWire->nPoints]);
5468f7df2e56Smrg            }
5469f7df2e56Smrg            if (shapeWire->primaryNdx != XkbNoShape)
5470f7df2e56Smrg                shape->primary = &shape->outlines[shapeWire->primaryNdx];
5471f7df2e56Smrg            if (shapeWire->approxNdx != XkbNoShape)
5472f7df2e56Smrg                shape->approx = &shape->outlines[shapeWire->approxNdx];
5473f7df2e56Smrg            shapeWire = (xkbShapeWireDesc *) olWire;
5474f7df2e56Smrg        }
5475f7df2e56Smrg        wire = (char *) shapeWire;
5476f7df2e56Smrg    }
5477f7df2e56Smrg    if (geom->num_shapes != req->nShapes) {
5478f7df2e56Smrg        client->errorValue = _XkbErrCode3(0x07, geom->num_shapes, req->nShapes);
5479f7df2e56Smrg        return BadMatch;
5480f7df2e56Smrg    }
5481f7df2e56Smrg
5482f7df2e56Smrg    *wire_inout = wire;
548305b261ecSmrg    return Success;
548405b261ecSmrg}
548505b261ecSmrg
548605b261ecSmrgstatic Status
5487f7df2e56Smrg_CheckSetGeom(XkbGeometryPtr geom, xkbSetGeometryReq * req, ClientPtr client)
548805b261ecSmrg{
5489f7df2e56Smrg    register int i;
5490f7df2e56Smrg    Status status;
5491f7df2e56Smrg    char *wire;
549205b261ecSmrg
5493f7df2e56Smrg    wire = (char *) &req[1];
54941e26616aSmrg    status = _GetCountedString(&wire, client, &geom->label_font);
54951e26616aSmrg    if (status != Success)
54961e26616aSmrg        return status;
54971e26616aSmrg
54981e26616aSmrg    for (i = 0; i < req->nProperties; i++) {
5499f7df2e56Smrg        char *name, *val;
55001e26616aSmrg
55011e26616aSmrg        status = _GetCountedString(&wire, client, &name);
55021e26616aSmrg        if (status != Success)
55031e26616aSmrg            return status;
55041e26616aSmrg        status = _GetCountedString(&wire, client, &val);
55051e26616aSmrg        if (status != Success) {
55066747b715Smrg            free(name);
55071e26616aSmrg            return status;
550805b261ecSmrg        }
5509f7df2e56Smrg        if (XkbAddGeomProperty(geom, name, val) == NULL) {
55106747b715Smrg            free(name);
55116747b715Smrg            free(val);
5512f7df2e56Smrg            return BadAlloc;
551305b261ecSmrg        }
55146747b715Smrg        free(name);
55156747b715Smrg        free(val);
551605b261ecSmrg    }
551705b261ecSmrg
5518f7df2e56Smrg    if (req->nColors < 2) {
5519f7df2e56Smrg        client->errorValue = _XkbErrCode3(0x01, 2, req->nColors);
5520f7df2e56Smrg        return BadValue;
552105b261ecSmrg    }
5522f7df2e56Smrg    if (req->baseColorNdx > req->nColors) {
5523f7df2e56Smrg        client->errorValue =
5524f7df2e56Smrg            _XkbErrCode3(0x03, req->nColors, req->baseColorNdx);
5525f7df2e56Smrg        return BadMatch;
552605b261ecSmrg    }
5527f7df2e56Smrg    if (req->labelColorNdx > req->nColors) {
5528f7df2e56Smrg        client->errorValue =
5529f7df2e56Smrg            _XkbErrCode3(0x03, req->nColors, req->labelColorNdx);
5530f7df2e56Smrg        return BadMatch;
553105b261ecSmrg    }
5532f7df2e56Smrg    if (req->labelColorNdx == req->baseColorNdx) {
5533f7df2e56Smrg        client->errorValue = _XkbErrCode3(0x04, req->baseColorNdx,
5534f7df2e56Smrg                                          req->labelColorNdx);
5535f7df2e56Smrg        return BadMatch;
553605b261ecSmrg    }
553705b261ecSmrg
55381e26616aSmrg    for (i = 0; i < req->nColors; i++) {
5539f7df2e56Smrg        char *name;
5540f7df2e56Smrg
55411e26616aSmrg        status = _GetCountedString(&wire, client, &name);
55421e26616aSmrg        if (status != Success)
55431e26616aSmrg            return status;
5544f7df2e56Smrg        if (!XkbAddGeomColor(geom, name, geom->num_colors)) {
55456747b715Smrg            free(name);
5546f7df2e56Smrg            return BadAlloc;
554705b261ecSmrg        }
55486747b715Smrg        free(name);
554905b261ecSmrg    }
5550f7df2e56Smrg    if (req->nColors != geom->num_colors) {
5551f7df2e56Smrg        client->errorValue = _XkbErrCode3(0x05, req->nColors, geom->num_colors);
5552f7df2e56Smrg        return BadMatch;
555305b261ecSmrg    }
5554f7df2e56Smrg    geom->label_color = &geom->colors[req->labelColorNdx];
5555f7df2e56Smrg    geom->base_color = &geom->colors[req->baseColorNdx];
555605b261ecSmrg
5557f7df2e56Smrg    if ((status = _CheckSetShapes(geom, req, &wire, client)) != Success)
5558f7df2e56Smrg        return status;
555905b261ecSmrg
5560f7df2e56Smrg    if ((status = _CheckSetSections(geom, req, &wire, client)) != Success)
5561f7df2e56Smrg        return status;
556205b261ecSmrg
5563f7df2e56Smrg    for (i = 0; i < req->nDoodads; i++) {
5564f7df2e56Smrg        status = _CheckSetDoodad(&wire, geom, NULL, client);
5565f7df2e56Smrg        if (status != Success)
5566f7df2e56Smrg            return status;
556705b261ecSmrg    }
556805b261ecSmrg
5569f7df2e56Smrg    for (i = 0; i < req->nKeyAliases; i++) {
5570f7df2e56Smrg        if (XkbAddGeomKeyAlias(geom, &wire[XkbKeyNameLength], wire) == NULL)
5571f7df2e56Smrg            return BadAlloc;
5572f7df2e56Smrg        wire += 2 * XkbKeyNameLength;
557305b261ecSmrg    }
557405b261ecSmrg    return Success;
557505b261ecSmrg}
557605b261ecSmrg
55774642e01fSmrgstatic int
5578f7df2e56Smrg_XkbSetGeometry(ClientPtr client, DeviceIntPtr dev, xkbSetGeometryReq * stuff)
557905b261ecSmrg{
5580f7df2e56Smrg    XkbDescPtr xkb;
5581f7df2e56Smrg    Bool new_name;
5582f7df2e56Smrg    xkbNewKeyboardNotify nkn;
5583f7df2e56Smrg    XkbGeometryPtr geom, old;
5584f7df2e56Smrg    XkbGeometrySizesRec sizes;
5585f7df2e56Smrg    Status status;
5586f7df2e56Smrg
5587f7df2e56Smrg    xkb = dev->key->xkbInfo->desc;
5588f7df2e56Smrg    old = xkb->geom;
5589f7df2e56Smrg    xkb->geom = NULL;
5590f7df2e56Smrg
5591f7df2e56Smrg    sizes.which = XkbGeomAllMask;
5592f7df2e56Smrg    sizes.num_properties = stuff->nProperties;
5593f7df2e56Smrg    sizes.num_colors = stuff->nColors;
5594f7df2e56Smrg    sizes.num_shapes = stuff->nShapes;
5595f7df2e56Smrg    sizes.num_sections = stuff->nSections;
5596f7df2e56Smrg    sizes.num_doodads = stuff->nDoodads;
5597f7df2e56Smrg    sizes.num_key_aliases = stuff->nKeyAliases;
5598f7df2e56Smrg    if ((status = XkbAllocGeometry(xkb, &sizes)) != Success) {
5599f7df2e56Smrg        xkb->geom = old;
56004642e01fSmrg        return status;
560105b261ecSmrg    }
5602f7df2e56Smrg    geom = xkb->geom;
5603f7df2e56Smrg    geom->name = stuff->name;
5604f7df2e56Smrg    geom->width_mm = stuff->widthMM;
5605f7df2e56Smrg    geom->height_mm = stuff->heightMM;
5606f7df2e56Smrg    if ((status = _CheckSetGeom(geom, stuff, client)) != Success) {
5607f7df2e56Smrg        XkbFreeGeometry(geom, XkbGeomAllMask, TRUE);
5608f7df2e56Smrg        xkb->geom = old;
56094642e01fSmrg        return status;
561005b261ecSmrg    }
5611f7df2e56Smrg    new_name = (xkb->names->geometry != geom->name);
5612f7df2e56Smrg    xkb->names->geometry = geom->name;
561305b261ecSmrg    if (old)
5614f7df2e56Smrg        XkbFreeGeometry(old, XkbGeomAllMask, TRUE);
561505b261ecSmrg    if (new_name) {
5616f7df2e56Smrg        xkbNamesNotify nn;
5617f7df2e56Smrg
56186747b715Smrg        memset(&nn, 0, sizeof(xkbNamesNotify));
5619f7df2e56Smrg        nn.changed = XkbGeometryNameMask;
5620f7df2e56Smrg        XkbSendNamesNotify(dev, &nn);
5621f7df2e56Smrg    }
5622f7df2e56Smrg    nkn.deviceID = nkn.oldDeviceID = dev->id;
5623f7df2e56Smrg    nkn.minKeyCode = nkn.oldMinKeyCode = xkb->min_key_code;
5624f7df2e56Smrg    nkn.maxKeyCode = nkn.oldMaxKeyCode = xkb->max_key_code;
5625f7df2e56Smrg    nkn.requestMajor = XkbReqCode;
5626f7df2e56Smrg    nkn.requestMinor = X_kbSetGeometry;
5627f7df2e56Smrg    nkn.changed = XkbNKN_GeometryMask;
5628f7df2e56Smrg    XkbSendNewKeyboardNotify(dev, &nkn);
562905b261ecSmrg    return Success;
563005b261ecSmrg}
563105b261ecSmrg
56324642e01fSmrgint
56334642e01fSmrgProcXkbSetGeometry(ClientPtr client)
56344642e01fSmrg{
5635f7df2e56Smrg    DeviceIntPtr dev;
5636f7df2e56Smrg    int rc;
56374642e01fSmrg
56384642e01fSmrg    REQUEST(xkbSetGeometryReq);
56394642e01fSmrg    REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq);
56404642e01fSmrg
5641f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
5642f7df2e56Smrg        return BadAccess;
56434642e01fSmrg
56444642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
56454642e01fSmrg    CHK_ATOM_OR_NONE(stuff->name);
56464642e01fSmrg
56474642e01fSmrg    rc = _XkbSetGeometry(client, dev, stuff);
56484642e01fSmrg    if (rc != Success)
56494642e01fSmrg        return rc;
56504642e01fSmrg
5651f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
56524642e01fSmrg        DeviceIntPtr other;
5653f7df2e56Smrg
5654f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
5655f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
5656f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
5657f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
5658f7df2e56Smrg                              DixManageAccess);
56594642e01fSmrg                if (rc == Success)
56604642e01fSmrg                    _XkbSetGeometry(client, other, stuff);
56614642e01fSmrg            }
56624642e01fSmrg        }
56634642e01fSmrg    }
56644642e01fSmrg
56654642e01fSmrg    return Success;
56664642e01fSmrg}
56674642e01fSmrg
566805b261ecSmrg/***====================================================================***/
566905b261ecSmrg
567005b261ecSmrgint
567105b261ecSmrgProcXkbPerClientFlags(ClientPtr client)
567205b261ecSmrg{
5673f7df2e56Smrg    DeviceIntPtr dev;
5674f7df2e56Smrg    xkbPerClientFlagsReply rep;
5675f7df2e56Smrg    XkbInterestPtr interest;
56764642e01fSmrg    Mask access_mode = DixGetAttrAccess | DixSetAttrAccess;
567705b261ecSmrg
567805b261ecSmrg    REQUEST(xkbPerClientFlagsReq);
567905b261ecSmrg    REQUEST_SIZE_MATCH(xkbPerClientFlagsReq);
568005b261ecSmrg
5681f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
5682f7df2e56Smrg        return BadAccess;
568305b261ecSmrg
56844642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
5685f7df2e56Smrg    CHK_MASK_LEGAL(0x01, stuff->change, XkbPCF_AllFlagsMask);
5686f7df2e56Smrg    CHK_MASK_MATCH(0x02, stuff->change, stuff->value);
568705b261ecSmrg
5688f7df2e56Smrg    interest = XkbFindClientResource((DevicePtr) dev, client);
568905b261ecSmrg    if (stuff->change) {
5690f7df2e56Smrg        client->xkbClientFlags &= ~stuff->change;
5691f7df2e56Smrg        client->xkbClientFlags |= stuff->value;
569205b261ecSmrg    }
5693f7df2e56Smrg    if (stuff->change & XkbPCF_AutoResetControlsMask) {
5694f7df2e56Smrg        Bool want;
5695f7df2e56Smrg
5696f7df2e56Smrg        want = stuff->value & XkbPCF_AutoResetControlsMask;
5697f7df2e56Smrg        if (interest && !want) {
5698f7df2e56Smrg            interest->autoCtrls = interest->autoCtrlValues = 0;
5699f7df2e56Smrg        }
5700f7df2e56Smrg        else if (want && (!interest)) {
5701f7df2e56Smrg            XID id = FakeClientID(client->index);
5702f7df2e56Smrg
5703f7df2e56Smrg            if (!AddResource(id, RT_XKBCLIENT, dev))
5704f7df2e56Smrg                return BadAlloc;
5705f7df2e56Smrg            interest = XkbAddClientResource((DevicePtr) dev, client, id);
5706f7df2e56Smrg            if (!interest)
5707f7df2e56Smrg                return BadAlloc;
5708f7df2e56Smrg        }
5709f7df2e56Smrg        if (interest && want) {
5710f7df2e56Smrg            register unsigned affect;
5711f7df2e56Smrg
5712f7df2e56Smrg            affect = stuff->ctrlsToChange;
5713f7df2e56Smrg
5714f7df2e56Smrg            CHK_MASK_LEGAL(0x03, affect, XkbAllBooleanCtrlsMask);
5715f7df2e56Smrg            CHK_MASK_MATCH(0x04, affect, stuff->autoCtrls);
5716f7df2e56Smrg            CHK_MASK_MATCH(0x05, stuff->autoCtrls, stuff->autoCtrlValues);
5717f7df2e56Smrg
5718f7df2e56Smrg            interest->autoCtrls &= ~affect;
5719f7df2e56Smrg            interest->autoCtrlValues &= ~affect;
5720f7df2e56Smrg            interest->autoCtrls |= stuff->autoCtrls & affect;
5721f7df2e56Smrg            interest->autoCtrlValues |= stuff->autoCtrlValues & affect;
5722f7df2e56Smrg        }
572305b261ecSmrg    }
5724f7df2e56Smrg
5725f7df2e56Smrg    rep = (xkbPerClientFlagsReply) {
5726f7df2e56Smrg        .type = X_Reply,
5727f7df2e56Smrg        .sequenceNumber = client->sequence,
5728f7df2e56Smrg        .length = 0,
5729f7df2e56Smrg        .supported = XkbPCF_AllFlagsMask,
5730f7df2e56Smrg        .value = client->xkbClientFlags & XkbPCF_AllFlagsMask,
5731f7df2e56Smrg        .autoCtrls = interest ? interest->autoCtrls : 0,
5732f7df2e56Smrg        .autoCtrlValues =  interest ? interest->autoCtrlValues : 0,
5733f7df2e56Smrg    };
5734f7df2e56Smrg    if (client->swapped) {
5735f7df2e56Smrg        swaps(&rep.sequenceNumber);
5736f7df2e56Smrg        swapl(&rep.supported);
5737f7df2e56Smrg        swapl(&rep.value);
5738f7df2e56Smrg        swapl(&rep.autoCtrls);
5739f7df2e56Smrg        swapl(&rep.autoCtrlValues);
574005b261ecSmrg    }
5741f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbPerClientFlagsReply), &rep);
57426747b715Smrg    return Success;
574305b261ecSmrg}
574405b261ecSmrg
574505b261ecSmrg/***====================================================================***/
574605b261ecSmrg
574705b261ecSmrg/* all latin-1 alphanumerics, plus parens, minus, underscore, slash */
574805b261ecSmrg/* and wildcards */
574905b261ecSmrgstatic unsigned char componentSpecLegal[] = {
5750f7df2e56Smrg    0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x87,
5751f7df2e56Smrg    0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07,
5752f7df2e56Smrg    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5753f7df2e56Smrg    0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
575405b261ecSmrg};
575505b261ecSmrg
575605b261ecSmrg/* same as above but accepts percent, plus and bar too */
575705b261ecSmrgstatic unsigned char componentExprLegal[] = {
5758f7df2e56Smrg    0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0xff, 0x87,
5759f7df2e56Smrg    0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x17,
5760f7df2e56Smrg    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5761f7df2e56Smrg    0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
576205b261ecSmrg};
576305b261ecSmrg
576405b261ecSmrgstatic char *
5765f7df2e56SmrgGetComponentSpec(unsigned char **pWire, Bool allowExpr, int *errRtrn)
576605b261ecSmrg{
5767f7df2e56Smrg    int len;
5768f7df2e56Smrg    register int i;
5769f7df2e56Smrg    unsigned char *wire, *str, *tmp, *legal;
5770f7df2e56Smrg
5771f7df2e56Smrg    if (allowExpr)
5772f7df2e56Smrg        legal = &componentExprLegal[0];
5773f7df2e56Smrg    else
5774f7df2e56Smrg        legal = &componentSpecLegal[0];
5775f7df2e56Smrg
5776f7df2e56Smrg    wire = *pWire;
5777f7df2e56Smrg    len = (*(unsigned char *) wire++);
5778f7df2e56Smrg    if (len > 0) {
5779f7df2e56Smrg        str = calloc(1, len + 1);
5780f7df2e56Smrg        if (str) {
5781f7df2e56Smrg            tmp = str;
5782f7df2e56Smrg            for (i = 0; i < len; i++) {
5783f7df2e56Smrg                if (legal[(*wire) / 8] & (1 << ((*wire) % 8)))
5784f7df2e56Smrg                    *tmp++ = *wire++;
5785f7df2e56Smrg                else
5786f7df2e56Smrg                    wire++;
5787f7df2e56Smrg            }
5788f7df2e56Smrg            if (tmp != str)
5789f7df2e56Smrg                *tmp++ = '\0';
5790f7df2e56Smrg            else {
5791f7df2e56Smrg                free(str);
5792f7df2e56Smrg                str = NULL;
5793f7df2e56Smrg            }
5794f7df2e56Smrg        }
5795f7df2e56Smrg        else {
5796f7df2e56Smrg            *errRtrn = BadAlloc;
5797f7df2e56Smrg        }
579805b261ecSmrg    }
579905b261ecSmrg    else {
5800f7df2e56Smrg        str = NULL;
580105b261ecSmrg    }
5802f7df2e56Smrg    *pWire = wire;
5803f7df2e56Smrg    return (char *) str;
580405b261ecSmrg}
580505b261ecSmrg
580605b261ecSmrg/***====================================================================***/
580705b261ecSmrg
580805b261ecSmrgint
580905b261ecSmrgProcXkbListComponents(ClientPtr client)
581005b261ecSmrg{
5811f7df2e56Smrg    DeviceIntPtr dev;
5812f7df2e56Smrg    xkbListComponentsReply rep;
5813f7df2e56Smrg    unsigned len;
5814f7df2e56Smrg    unsigned char *str;
5815f7df2e56Smrg    uint8_t size;
5816f7df2e56Smrg    int i;
581705b261ecSmrg
581805b261ecSmrg    REQUEST(xkbListComponentsReq);
581905b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbListComponentsReq);
582005b261ecSmrg
5821f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
5822f7df2e56Smrg        return BadAccess;
582305b261ecSmrg
58244642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
582505b261ecSmrg
5826f7df2e56Smrg    /* The request is followed by six Pascal strings (i.e. size in characters
5827f7df2e56Smrg     * followed by a string pattern) describing what the client wants us to
5828f7df2e56Smrg     * list.  We don't care, but might as well check they haven't got the
5829f7df2e56Smrg     * length wrong. */
5830f7df2e56Smrg    str = (unsigned char *) &stuff[1];
5831f7df2e56Smrg    for (i = 0; i < 6; i++) {
5832f7df2e56Smrg        size = *((uint8_t *)str);
5833f7df2e56Smrg        len = (str + size + 1) - ((unsigned char *) stuff);
5834f7df2e56Smrg        if ((XkbPaddedSize(len) / 4) > stuff->length)
5835f7df2e56Smrg            return BadLength;
5836f7df2e56Smrg        str += (size + 1);
5837f7df2e56Smrg    }
5838f7df2e56Smrg    if ((XkbPaddedSize(len) / 4) != stuff->length)
5839f7df2e56Smrg        return BadLength;
5840f7df2e56Smrg    rep = (xkbListComponentsReply) {
5841f7df2e56Smrg        .type = X_Reply,
5842f7df2e56Smrg        .deviceID = dev->id,
5843f7df2e56Smrg        .sequenceNumber = client->sequence,
5844f7df2e56Smrg        .length = 0,
5845f7df2e56Smrg        .nKeymaps = 0,
5846f7df2e56Smrg        .nKeycodes = 0,
5847f7df2e56Smrg        .nTypes = 0,
5848f7df2e56Smrg        .nCompatMaps = 0,
5849f7df2e56Smrg        .nSymbols = 0,
5850f7df2e56Smrg        .nGeometries = 0,
5851f7df2e56Smrg        .extra = 0
5852f7df2e56Smrg    };
585305b261ecSmrg    if (client->swapped) {
5854f7df2e56Smrg        swaps(&rep.sequenceNumber);
5855f7df2e56Smrg        swapl(&rep.length);
5856f7df2e56Smrg        swaps(&rep.nKeymaps);
5857f7df2e56Smrg        swaps(&rep.nKeycodes);
5858f7df2e56Smrg        swaps(&rep.nTypes);
5859f7df2e56Smrg        swaps(&rep.nCompatMaps);
5860f7df2e56Smrg        swaps(&rep.nSymbols);
5861f7df2e56Smrg        swaps(&rep.nGeometries);
5862f7df2e56Smrg        swaps(&rep.extra);
5863f7df2e56Smrg    }
5864f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbListComponentsReply), &rep);
58656747b715Smrg    return Success;
586605b261ecSmrg}
586705b261ecSmrg
586805b261ecSmrg/***====================================================================***/
586905b261ecSmrgint
587005b261ecSmrgProcXkbGetKbdByName(ClientPtr client)
587105b261ecSmrg{
5872f7df2e56Smrg    DeviceIntPtr dev;
5873f7df2e56Smrg    DeviceIntPtr tmpd;
5874f7df2e56Smrg    DeviceIntPtr master;
5875f7df2e56Smrg    xkbGetKbdByNameReply rep = { 0 };
5876f7df2e56Smrg    xkbGetMapReply mrep = { 0 };
5877f7df2e56Smrg    xkbGetCompatMapReply crep = { 0 };
5878f7df2e56Smrg    xkbGetIndicatorMapReply irep = { 0 };
5879f7df2e56Smrg    xkbGetNamesReply nrep = { 0 };
5880f7df2e56Smrg    xkbGetGeometryReply grep = { 0 };
5881f7df2e56Smrg    XkbComponentNamesRec names = { 0 };
5882f7df2e56Smrg    XkbDescPtr xkb, new;
5883f7df2e56Smrg    XkbEventCauseRec cause;
5884f7df2e56Smrg    unsigned char *str;
5885f7df2e56Smrg    char mapFile[PATH_MAX];
5886f7df2e56Smrg    unsigned len;
5887f7df2e56Smrg    unsigned fwant, fneed, reported;
5888f7df2e56Smrg    int status;
5889f7df2e56Smrg    Bool geom_changed;
5890f7df2e56Smrg    XkbSrvLedInfoPtr old_sli;
5891f7df2e56Smrg    XkbSrvLedInfoPtr sli;
58924642e01fSmrg    Mask access_mode = DixGetAttrAccess | DixManageAccess;
589305b261ecSmrg
589405b261ecSmrg    REQUEST(xkbGetKbdByNameReq);
589505b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq);
589605b261ecSmrg
5897f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
5898f7df2e56Smrg        return BadAccess;
589905b261ecSmrg
59004642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
5901f7df2e56Smrg    master = GetMaster(dev, MASTER_KEYBOARD);
590205b261ecSmrg
590305b261ecSmrg    xkb = dev->key->xkbInfo->desc;
5904f7df2e56Smrg    status = Success;
5905f7df2e56Smrg    str = (unsigned char *) &stuff[1];
5906f7df2e56Smrg    if (GetComponentSpec(&str, TRUE, &status))  /* keymap, unsupported */
59076747b715Smrg        return BadMatch;
5908f7df2e56Smrg    names.keycodes = GetComponentSpec(&str, TRUE, &status);
5909f7df2e56Smrg    names.types = GetComponentSpec(&str, TRUE, &status);
5910f7df2e56Smrg    names.compat = GetComponentSpec(&str, TRUE, &status);
5911f7df2e56Smrg    names.symbols = GetComponentSpec(&str, TRUE, &status);
5912f7df2e56Smrg    names.geometry = GetComponentSpec(&str, TRUE, &status);
5913f7df2e56Smrg    if (status != Success)
5914f7df2e56Smrg        return status;
5915f7df2e56Smrg    len = str - ((unsigned char *) stuff);
5916f7df2e56Smrg    if ((XkbPaddedSize(len) / 4) != stuff->length)
5917f7df2e56Smrg        return BadLength;
5918f7df2e56Smrg
5919f7df2e56Smrg    CHK_MASK_LEGAL(0x01, stuff->want, XkbGBN_AllComponentsMask);
5920f7df2e56Smrg    CHK_MASK_LEGAL(0x02, stuff->need, XkbGBN_AllComponentsMask);
5921f7df2e56Smrg
592205b261ecSmrg    if (stuff->load)
5923f7df2e56Smrg        fwant = XkbGBN_AllComponentsMask;
5924f7df2e56Smrg    else
5925f7df2e56Smrg        fwant = stuff->want | stuff->need;
5926f7df2e56Smrg    if ((!names.compat) &&
5927f7df2e56Smrg        (fwant & (XkbGBN_CompatMapMask | XkbGBN_IndicatorMapMask))) {
5928f7df2e56Smrg        names.compat = Xstrdup("%");
592905b261ecSmrg    }
5930f7df2e56Smrg    if ((!names.types) && (fwant & (XkbGBN_TypesMask))) {
5931f7df2e56Smrg        names.types = Xstrdup("%");
59324642e01fSmrg    }
5933f7df2e56Smrg    if ((!names.symbols) && (fwant & XkbGBN_SymbolsMask)) {
5934f7df2e56Smrg        names.symbols = Xstrdup("%");
59354642e01fSmrg    }
5936f7df2e56Smrg    geom_changed = ((names.geometry != NULL) &&
5937f7df2e56Smrg                    (strcmp(names.geometry, "%") != 0));
5938f7df2e56Smrg    if ((!names.geometry) && (fwant & XkbGBN_GeometryMask)) {
5939f7df2e56Smrg        names.geometry = Xstrdup("%");
5940f7df2e56Smrg        geom_changed = FALSE;
594105b261ecSmrg    }
594205b261ecSmrg
59436747b715Smrg    memset(mapFile, 0, PATH_MAX);
5944f7df2e56Smrg    rep.type = X_Reply;
594505b261ecSmrg    rep.deviceID = dev->id;
594605b261ecSmrg    rep.sequenceNumber = client->sequence;
594705b261ecSmrg    rep.length = 0;
594805b261ecSmrg    rep.minKeyCode = xkb->min_key_code;
594905b261ecSmrg    rep.maxKeyCode = xkb->max_key_code;
5950f7df2e56Smrg    rep.loaded = FALSE;
5951f7df2e56Smrg    fwant =
5952f7df2e56Smrg        XkbConvertGetByNameComponents(TRUE, stuff->want) | XkmVirtualModsMask;
5953f7df2e56Smrg    fneed = XkbConvertGetByNameComponents(TRUE, stuff->need);
5954f7df2e56Smrg    rep.reported = XkbConvertGetByNameComponents(FALSE, fwant | fneed);
595505b261ecSmrg    if (stuff->load) {
5956f7df2e56Smrg        fneed |= XkmKeymapRequired;
5957f7df2e56Smrg        fwant |= XkmKeymapLegal;
595805b261ecSmrg    }
5959f7df2e56Smrg    if ((fwant | fneed) & XkmSymbolsMask) {
5960f7df2e56Smrg        fneed |= XkmKeyNamesIndex | XkmTypesIndex;
5961f7df2e56Smrg        fwant |= XkmIndicatorsIndex;
596205b261ecSmrg    }
596305b261ecSmrg
596405b261ecSmrg    /* We pass dev in here so we can get the old names out if needed. */
5965f7df2e56Smrg    rep.found = XkbDDXLoadKeymapByNames(dev, &names, fwant, fneed, &new,
5966f7df2e56Smrg                                        mapFile, PATH_MAX);
5967f7df2e56Smrg    rep.newKeyboard = FALSE;
5968f7df2e56Smrg    rep.pad1 = rep.pad2 = rep.pad3 = rep.pad4 = 0;
5969f7df2e56Smrg
5970f7df2e56Smrg    stuff->want |= stuff->need;
5971f7df2e56Smrg    if (new == NULL)
5972f7df2e56Smrg        rep.reported = 0;
597305b261ecSmrg    else {
5974f7df2e56Smrg        if (stuff->load)
5975f7df2e56Smrg            rep.loaded = TRUE;
5976f7df2e56Smrg        if (stuff->load ||
5977f7df2e56Smrg            ((rep.reported & XkbGBN_SymbolsMask) && (new->compat))) {
5978f7df2e56Smrg            XkbChangesRec changes;
5979f7df2e56Smrg
5980f7df2e56Smrg            memset(&changes, 0, sizeof(changes));
5981f7df2e56Smrg            XkbUpdateDescActions(new,
5982f7df2e56Smrg                                 new->min_key_code, XkbNumKeys(new), &changes);
5983f7df2e56Smrg        }
598405b261ecSmrg
5985f7df2e56Smrg        if (new->map == NULL)
5986f7df2e56Smrg            rep.reported &= ~(XkbGBN_SymbolsMask | XkbGBN_TypesMask);
5987f7df2e56Smrg        else if (rep.reported & (XkbGBN_SymbolsMask | XkbGBN_TypesMask)) {
5988f7df2e56Smrg            mrep.type = X_Reply;
5989f7df2e56Smrg            mrep.deviceID = dev->id;
5990f7df2e56Smrg            mrep.sequenceNumber = client->sequence;
5991f7df2e56Smrg            mrep.length =
5992f7df2e56Smrg                ((SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply)) >> 2);
5993f7df2e56Smrg            mrep.minKeyCode = new->min_key_code;
5994f7df2e56Smrg            mrep.maxKeyCode = new->max_key_code;
5995f7df2e56Smrg            mrep.present = 0;
5996f7df2e56Smrg            mrep.totalSyms = mrep.totalActs =
5997f7df2e56Smrg                mrep.totalKeyBehaviors = mrep.totalKeyExplicit =
5998f7df2e56Smrg                mrep.totalModMapKeys = mrep.totalVModMapKeys = 0;
5999f7df2e56Smrg            if (rep.reported & (XkbGBN_TypesMask | XkbGBN_ClientSymbolsMask)) {
6000f7df2e56Smrg                mrep.present |= XkbKeyTypesMask;
6001f7df2e56Smrg                mrep.firstType = 0;
6002f7df2e56Smrg                mrep.nTypes = mrep.totalTypes = new->map->num_types;
6003f7df2e56Smrg            }
6004f7df2e56Smrg            else {
6005f7df2e56Smrg                mrep.firstType = mrep.nTypes = 0;
6006f7df2e56Smrg                mrep.totalTypes = 0;
6007f7df2e56Smrg            }
6008f7df2e56Smrg            if (rep.reported & XkbGBN_ClientSymbolsMask) {
6009f7df2e56Smrg                mrep.present |= (XkbKeySymsMask | XkbModifierMapMask);
6010f7df2e56Smrg                mrep.firstKeySym = mrep.firstModMapKey = new->min_key_code;
6011f7df2e56Smrg                mrep.nKeySyms = mrep.nModMapKeys = XkbNumKeys(new);
6012f7df2e56Smrg            }
6013f7df2e56Smrg            else {
6014f7df2e56Smrg                mrep.firstKeySym = mrep.firstModMapKey = 0;
6015f7df2e56Smrg                mrep.nKeySyms = mrep.nModMapKeys = 0;
6016f7df2e56Smrg            }
6017f7df2e56Smrg            if (rep.reported & XkbGBN_ServerSymbolsMask) {
6018f7df2e56Smrg                mrep.present |= XkbAllServerInfoMask;
6019f7df2e56Smrg                mrep.virtualMods = ~0;
6020f7df2e56Smrg                mrep.firstKeyAct = mrep.firstKeyBehavior =
6021f7df2e56Smrg                    mrep.firstKeyExplicit = new->min_key_code;
6022f7df2e56Smrg                mrep.nKeyActs = mrep.nKeyBehaviors =
6023f7df2e56Smrg                    mrep.nKeyExplicit = XkbNumKeys(new);
6024f7df2e56Smrg                mrep.firstVModMapKey = new->min_key_code;
6025f7df2e56Smrg                mrep.nVModMapKeys = XkbNumKeys(new);
6026f7df2e56Smrg            }
6027f7df2e56Smrg            else {
6028f7df2e56Smrg                mrep.virtualMods = 0;
6029f7df2e56Smrg                mrep.firstKeyAct = mrep.firstKeyBehavior =
6030f7df2e56Smrg                    mrep.firstKeyExplicit = 0;
6031f7df2e56Smrg                mrep.nKeyActs = mrep.nKeyBehaviors = mrep.nKeyExplicit = 0;
6032f7df2e56Smrg            }
6033f7df2e56Smrg            XkbComputeGetMapReplySize(new, &mrep);
6034f7df2e56Smrg            rep.length += SIZEOF(xGenericReply) / 4 + mrep.length;
6035f7df2e56Smrg        }
6036f7df2e56Smrg        if (new->compat == NULL)
6037f7df2e56Smrg            rep.reported &= ~XkbGBN_CompatMapMask;
6038f7df2e56Smrg        else if (rep.reported & XkbGBN_CompatMapMask) {
6039f7df2e56Smrg            crep.type = X_Reply;
6040f7df2e56Smrg            crep.deviceID = dev->id;
6041f7df2e56Smrg            crep.sequenceNumber = client->sequence;
6042f7df2e56Smrg            crep.length = 0;
6043f7df2e56Smrg            crep.groups = XkbAllGroupsMask;
6044f7df2e56Smrg            crep.firstSI = 0;
6045f7df2e56Smrg            crep.nSI = crep.nTotalSI = new->compat->num_si;
6046f7df2e56Smrg            XkbComputeGetCompatMapReplySize(new->compat, &crep);
6047f7df2e56Smrg            rep.length += SIZEOF(xGenericReply) / 4 + crep.length;
6048f7df2e56Smrg        }
6049f7df2e56Smrg        if (new->indicators == NULL)
6050f7df2e56Smrg            rep.reported &= ~XkbGBN_IndicatorMapMask;
6051f7df2e56Smrg        else if (rep.reported & XkbGBN_IndicatorMapMask) {
6052f7df2e56Smrg            irep.type = X_Reply;
6053f7df2e56Smrg            irep.deviceID = dev->id;
6054f7df2e56Smrg            irep.sequenceNumber = client->sequence;
6055f7df2e56Smrg            irep.length = 0;
6056f7df2e56Smrg            irep.which = XkbAllIndicatorsMask;
6057f7df2e56Smrg            XkbComputeGetIndicatorMapReplySize(new->indicators, &irep);
6058f7df2e56Smrg            rep.length += SIZEOF(xGenericReply) / 4 + irep.length;
6059f7df2e56Smrg        }
6060f7df2e56Smrg        if (new->names == NULL)
6061f7df2e56Smrg            rep.reported &= ~(XkbGBN_OtherNamesMask | XkbGBN_KeyNamesMask);
6062f7df2e56Smrg        else if (rep.reported & (XkbGBN_OtherNamesMask | XkbGBN_KeyNamesMask)) {
6063f7df2e56Smrg            nrep.type = X_Reply;
6064f7df2e56Smrg            nrep.deviceID = dev->id;
6065f7df2e56Smrg            nrep.sequenceNumber = client->sequence;
6066f7df2e56Smrg            nrep.length = 0;
6067f7df2e56Smrg            nrep.minKeyCode = new->min_key_code;
6068f7df2e56Smrg            nrep.maxKeyCode = new->max_key_code;
6069f7df2e56Smrg            if (rep.reported & XkbGBN_OtherNamesMask) {
6070f7df2e56Smrg                nrep.which = XkbAllNamesMask;
6071f7df2e56Smrg                if (new->map != NULL)
6072f7df2e56Smrg                    nrep.nTypes = new->map->num_types;
6073f7df2e56Smrg                else
6074f7df2e56Smrg                    nrep.nTypes = 0;
6075f7df2e56Smrg                nrep.nKTLevels = 0;
6076f7df2e56Smrg                nrep.groupNames = XkbAllGroupsMask;
6077f7df2e56Smrg                nrep.virtualMods = XkbAllVirtualModsMask;
6078f7df2e56Smrg                nrep.indicators = XkbAllIndicatorsMask;
6079f7df2e56Smrg                nrep.nRadioGroups = new->names->num_rg;
6080f7df2e56Smrg            }
6081f7df2e56Smrg            else {
6082f7df2e56Smrg                nrep.which = 0;
6083f7df2e56Smrg                nrep.nTypes = 0;
6084f7df2e56Smrg                nrep.nKTLevels = 0;
6085f7df2e56Smrg                nrep.groupNames = 0;
6086f7df2e56Smrg                nrep.virtualMods = 0;
6087f7df2e56Smrg                nrep.indicators = 0;
6088f7df2e56Smrg                nrep.nRadioGroups = 0;
6089f7df2e56Smrg            }
6090f7df2e56Smrg            if (rep.reported & XkbGBN_KeyNamesMask) {
6091f7df2e56Smrg                nrep.which |= XkbKeyNamesMask;
6092f7df2e56Smrg                nrep.firstKey = new->min_key_code;
6093f7df2e56Smrg                nrep.nKeys = XkbNumKeys(new);
6094f7df2e56Smrg                nrep.nKeyAliases = new->names->num_key_aliases;
6095f7df2e56Smrg                if (nrep.nKeyAliases)
6096f7df2e56Smrg                    nrep.which |= XkbKeyAliasesMask;
6097f7df2e56Smrg            }
6098f7df2e56Smrg            else {
6099f7df2e56Smrg                nrep.which &= ~(XkbKeyNamesMask | XkbKeyAliasesMask);
6100f7df2e56Smrg                nrep.firstKey = nrep.nKeys = 0;
6101f7df2e56Smrg                nrep.nKeyAliases = 0;
6102f7df2e56Smrg            }
6103f7df2e56Smrg            XkbComputeGetNamesReplySize(new, &nrep);
6104f7df2e56Smrg            rep.length += SIZEOF(xGenericReply) / 4 + nrep.length;
6105f7df2e56Smrg        }
6106f7df2e56Smrg        if (new->geom == NULL)
6107f7df2e56Smrg            rep.reported &= ~XkbGBN_GeometryMask;
6108f7df2e56Smrg        else if (rep.reported & XkbGBN_GeometryMask) {
6109f7df2e56Smrg            grep.type = X_Reply;
6110f7df2e56Smrg            grep.deviceID = dev->id;
6111f7df2e56Smrg            grep.sequenceNumber = client->sequence;
6112f7df2e56Smrg            grep.length = 0;
6113f7df2e56Smrg            grep.found = TRUE;
6114f7df2e56Smrg            grep.pad = 0;
6115f7df2e56Smrg            grep.widthMM = grep.heightMM = 0;
6116f7df2e56Smrg            grep.nProperties = grep.nColors = grep.nShapes = 0;
6117f7df2e56Smrg            grep.nSections = grep.nDoodads = 0;
6118f7df2e56Smrg            grep.baseColorNdx = grep.labelColorNdx = 0;
6119f7df2e56Smrg            XkbComputeGetGeometryReplySize(new->geom, &grep, None);
6120f7df2e56Smrg            rep.length += SIZEOF(xGenericReply) / 4 + grep.length;
6121f7df2e56Smrg        }
6122f7df2e56Smrg    }
6123f7df2e56Smrg
6124f7df2e56Smrg    reported = rep.reported;
6125f7df2e56Smrg    if (client->swapped) {
6126f7df2e56Smrg        swaps(&rep.sequenceNumber);
6127f7df2e56Smrg        swapl(&rep.length);
6128f7df2e56Smrg        swaps(&rep.found);
6129f7df2e56Smrg        swaps(&rep.reported);
6130f7df2e56Smrg    }
6131f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetKbdByNameReply), &rep);
6132f7df2e56Smrg    if (reported & (XkbGBN_SymbolsMask | XkbGBN_TypesMask))
6133f7df2e56Smrg        XkbSendMap(client, new, &mrep);
6134f7df2e56Smrg    if (reported & XkbGBN_CompatMapMask)
6135f7df2e56Smrg        XkbSendCompatMap(client, new->compat, &crep);
6136f7df2e56Smrg    if (reported & XkbGBN_IndicatorMapMask)
6137f7df2e56Smrg        XkbSendIndicatorMap(client, new->indicators, &irep);
6138f7df2e56Smrg    if (reported & (XkbGBN_KeyNamesMask | XkbGBN_OtherNamesMask))
6139f7df2e56Smrg        XkbSendNames(client, new, &nrep);
6140f7df2e56Smrg    if (reported & XkbGBN_GeometryMask)
6141f7df2e56Smrg        XkbSendGeometry(client, new->geom, &grep, FALSE);
6142f7df2e56Smrg    if (rep.loaded) {
6143f7df2e56Smrg        XkbDescPtr old_xkb;
6144f7df2e56Smrg        xkbNewKeyboardNotify nkn;
6145f7df2e56Smrg
6146f7df2e56Smrg        old_xkb = xkb;
6147f7df2e56Smrg        xkb = new;
6148f7df2e56Smrg        dev->key->xkbInfo->desc = xkb;
6149f7df2e56Smrg        new = old_xkb;          /* so it'll get freed automatically */
6150f7df2e56Smrg
6151f7df2e56Smrg        XkbCopyControls(xkb, old_xkb);
6152f7df2e56Smrg
6153f7df2e56Smrg        nkn.deviceID = nkn.oldDeviceID = dev->id;
6154f7df2e56Smrg        nkn.minKeyCode = new->min_key_code;
6155f7df2e56Smrg        nkn.maxKeyCode = new->max_key_code;
6156f7df2e56Smrg        nkn.oldMinKeyCode = xkb->min_key_code;
6157f7df2e56Smrg        nkn.oldMaxKeyCode = xkb->max_key_code;
6158f7df2e56Smrg        nkn.requestMajor = XkbReqCode;
6159f7df2e56Smrg        nkn.requestMinor = X_kbGetKbdByName;
6160f7df2e56Smrg        nkn.changed = XkbNKN_KeycodesMask;
6161f7df2e56Smrg        if (geom_changed)
6162f7df2e56Smrg            nkn.changed |= XkbNKN_GeometryMask;
6163f7df2e56Smrg        XkbSendNewKeyboardNotify(dev, &nkn);
6164f7df2e56Smrg
6165f7df2e56Smrg        /* Update the map and LED info on the device itself, as well as
6166f7df2e56Smrg         * any slaves if it's an MD, or its MD if it's an SD and was the
6167f7df2e56Smrg         * last device used on that MD. */
616805b261ecSmrg        for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
6169f7df2e56Smrg            if (tmpd != dev && GetMaster(tmpd, MASTER_KEYBOARD) != dev &&
6170f7df2e56Smrg                (tmpd != master || dev != master->lastSlave))
6171f7df2e56Smrg                continue;
6172f7df2e56Smrg
6173f7df2e56Smrg            if (tmpd != dev)
6174f7df2e56Smrg                XkbDeviceApplyKeymap(tmpd, xkb);
6175f7df2e56Smrg
6176f7df2e56Smrg            if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) {
6177f7df2e56Smrg                old_sli = tmpd->kbdfeed->xkb_sli;
6178f7df2e56Smrg                tmpd->kbdfeed->xkb_sli = NULL;
6179f7df2e56Smrg                sli = XkbAllocSrvLedInfo(tmpd, tmpd->kbdfeed, NULL, 0);
6180f7df2e56Smrg                if (sli) {
6181f7df2e56Smrg                    sli->explicitState = old_sli->explicitState;
6182f7df2e56Smrg                    sli->effectiveState = old_sli->effectiveState;
618305b261ecSmrg                }
6184f7df2e56Smrg                tmpd->kbdfeed->xkb_sli = sli;
6185f7df2e56Smrg                XkbFreeSrvLedInfo(old_sli);
618605b261ecSmrg            }
618705b261ecSmrg        }
6188f7df2e56Smrg    }
6189f7df2e56Smrg    if ((new != NULL) && (new != xkb)) {
6190f7df2e56Smrg        XkbFreeKeyboard(new, XkbAllComponentsMask, TRUE);
6191f7df2e56Smrg        new = NULL;
619205b261ecSmrg    }
61939ace9065Smrg    XkbFreeComponentNames(&names, FALSE);
6194f7df2e56Smrg    XkbSetCauseXkbReq(&cause, X_kbGetKbdByName, client);
6195f7df2e56Smrg    XkbUpdateAllDeviceIndicators(NULL, &cause);
6196f7df2e56Smrg
61976747b715Smrg    return Success;
619805b261ecSmrg}
619905b261ecSmrg
620005b261ecSmrg/***====================================================================***/
620105b261ecSmrg
620205b261ecSmrgstatic int
6203f7df2e56SmrgComputeDeviceLedInfoSize(DeviceIntPtr dev,
6204f7df2e56Smrg                         unsigned int what, XkbSrvLedInfoPtr sli)
620505b261ecSmrg{
6206f7df2e56Smrg    int nNames, nMaps;
6207f7df2e56Smrg    register unsigned n, bit;
6208f7df2e56Smrg
6209f7df2e56Smrg    if (sli == NULL)
6210f7df2e56Smrg        return 0;
6211f7df2e56Smrg    nNames = nMaps = 0;
6212f7df2e56Smrg    if ((what & XkbXI_IndicatorNamesMask) == 0)
6213f7df2e56Smrg        sli->namesPresent = 0;
6214f7df2e56Smrg    if ((what & XkbXI_IndicatorMapsMask) == 0)
6215f7df2e56Smrg        sli->mapsPresent = 0;
6216f7df2e56Smrg
6217f7df2e56Smrg    for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6218f7df2e56Smrg        if (sli->names && sli->names[n] != None) {
6219f7df2e56Smrg            sli->namesPresent |= bit;
6220f7df2e56Smrg            nNames++;
6221f7df2e56Smrg        }
6222f7df2e56Smrg        if (sli->maps && XkbIM_InUse(&sli->maps[n])) {
6223f7df2e56Smrg            sli->mapsPresent |= bit;
6224f7df2e56Smrg            nMaps++;
6225f7df2e56Smrg        }
6226f7df2e56Smrg    }
6227f7df2e56Smrg    return (nNames * 4) + (nMaps * SIZEOF(xkbIndicatorMapWireDesc));
622805b261ecSmrg}
622905b261ecSmrg
6230f7df2e56Smrgstatic int
6231f7df2e56SmrgCheckDeviceLedFBs(DeviceIntPtr dev,
6232f7df2e56Smrg                  int class,
6233f7df2e56Smrg                  int id, xkbGetDeviceInfoReply * rep, ClientPtr client)
623405b261ecSmrg{
6235f7df2e56Smrg    int nFBs = 0;
6236f7df2e56Smrg    int length = 0;
6237f7df2e56Smrg    Bool classOk;
6238f7df2e56Smrg
6239f7df2e56Smrg    if (class == XkbDfltXIClass) {
6240f7df2e56Smrg        if (dev->kbdfeed)
6241f7df2e56Smrg            class = KbdFeedbackClass;
6242f7df2e56Smrg        else if (dev->leds)
6243f7df2e56Smrg            class = LedFeedbackClass;
6244f7df2e56Smrg        else {
6245f7df2e56Smrg            client->errorValue = _XkbErrCode2(XkbErr_BadClass, class);
6246f7df2e56Smrg            return XkbKeyboardErrorCode;
6247f7df2e56Smrg        }
6248f7df2e56Smrg    }
6249f7df2e56Smrg    classOk = FALSE;
6250f7df2e56Smrg    if ((dev->kbdfeed) &&
6251f7df2e56Smrg        ((class == KbdFeedbackClass) || (class == XkbAllXIClasses))) {
6252f7df2e56Smrg        KbdFeedbackPtr kf;
6253f7df2e56Smrg
6254f7df2e56Smrg        classOk = TRUE;
6255f7df2e56Smrg        for (kf = dev->kbdfeed; (kf); kf = kf->next) {
6256f7df2e56Smrg            if ((id != XkbAllXIIds) && (id != XkbDfltXIId) &&
6257f7df2e56Smrg                (id != kf->ctrl.id))
6258f7df2e56Smrg                continue;
6259f7df2e56Smrg            nFBs++;
6260f7df2e56Smrg            length += SIZEOF(xkbDeviceLedsWireDesc);
6261f7df2e56Smrg            if (!kf->xkb_sli)
6262f7df2e56Smrg                kf->xkb_sli = XkbAllocSrvLedInfo(dev, kf, NULL, 0);
6263f7df2e56Smrg            length += ComputeDeviceLedInfoSize(dev, rep->present, kf->xkb_sli);
6264f7df2e56Smrg            if (id != XkbAllXIIds)
6265f7df2e56Smrg                break;
6266f7df2e56Smrg        }
6267f7df2e56Smrg    }
6268f7df2e56Smrg    if ((dev->leds) &&
6269f7df2e56Smrg        ((class == LedFeedbackClass) || (class == XkbAllXIClasses))) {
6270f7df2e56Smrg        LedFeedbackPtr lf;
6271f7df2e56Smrg
6272f7df2e56Smrg        classOk = TRUE;
6273f7df2e56Smrg        for (lf = dev->leds; (lf); lf = lf->next) {
6274f7df2e56Smrg            if ((id != XkbAllXIIds) && (id != XkbDfltXIId) &&
6275f7df2e56Smrg                (id != lf->ctrl.id))
6276f7df2e56Smrg                continue;
6277f7df2e56Smrg            nFBs++;
6278f7df2e56Smrg            length += SIZEOF(xkbDeviceLedsWireDesc);
6279f7df2e56Smrg            if (!lf->xkb_sli)
6280f7df2e56Smrg                lf->xkb_sli = XkbAllocSrvLedInfo(dev, NULL, lf, 0);
6281f7df2e56Smrg            length += ComputeDeviceLedInfoSize(dev, rep->present, lf->xkb_sli);
6282f7df2e56Smrg            if (id != XkbAllXIIds)
6283f7df2e56Smrg                break;
6284f7df2e56Smrg        }
6285f7df2e56Smrg    }
6286f7df2e56Smrg    if (nFBs > 0) {
6287f7df2e56Smrg        rep->nDeviceLedFBs = nFBs;
6288f7df2e56Smrg        rep->length += (length / 4);
6289f7df2e56Smrg        return Success;
6290f7df2e56Smrg    }
6291f7df2e56Smrg    if (classOk)
6292f7df2e56Smrg        client->errorValue = _XkbErrCode2(XkbErr_BadId, id);
6293f7df2e56Smrg    else
6294f7df2e56Smrg        client->errorValue = _XkbErrCode2(XkbErr_BadClass, class);
629505b261ecSmrg    return XkbKeyboardErrorCode;
629605b261ecSmrg}
629705b261ecSmrg
629805b261ecSmrgstatic int
6299f7df2e56SmrgSendDeviceLedInfo(XkbSrvLedInfoPtr sli, ClientPtr client)
630005b261ecSmrg{
6301f7df2e56Smrg    xkbDeviceLedsWireDesc wire;
6302f7df2e56Smrg    int length;
6303f7df2e56Smrg
6304f7df2e56Smrg    length = 0;
6305f7df2e56Smrg    wire.ledClass = sli->class;
6306f7df2e56Smrg    wire.ledID = sli->id;
6307f7df2e56Smrg    wire.namesPresent = sli->namesPresent;
6308f7df2e56Smrg    wire.mapsPresent = sli->mapsPresent;
6309f7df2e56Smrg    wire.physIndicators = sli->physIndicators;
6310f7df2e56Smrg    wire.state = sli->effectiveState;
631105b261ecSmrg    if (client->swapped) {
6312f7df2e56Smrg        swaps(&wire.ledClass);
6313f7df2e56Smrg        swaps(&wire.ledID);
6314f7df2e56Smrg        swapl(&wire.namesPresent);
6315f7df2e56Smrg        swapl(&wire.mapsPresent);
6316f7df2e56Smrg        swapl(&wire.physIndicators);
6317f7df2e56Smrg        swapl(&wire.state);
6318f7df2e56Smrg    }
6319f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbDeviceLedsWireDesc), &wire);
6320f7df2e56Smrg    length += SIZEOF(xkbDeviceLedsWireDesc);
6321f7df2e56Smrg    if (sli->namesPresent | sli->mapsPresent) {
6322f7df2e56Smrg        register unsigned i, bit;
6323f7df2e56Smrg
6324f7df2e56Smrg        if (sli->namesPresent) {
6325f7df2e56Smrg            CARD32 awire;
6326f7df2e56Smrg
6327f7df2e56Smrg            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
6328f7df2e56Smrg                if (sli->namesPresent & bit) {
6329f7df2e56Smrg                    awire = (CARD32) sli->names[i];
6330f7df2e56Smrg                    if (client->swapped) {
6331f7df2e56Smrg                        swapl(&awire);
6332f7df2e56Smrg                    }
6333f7df2e56Smrg                    WriteToClient(client, 4, &awire);
6334f7df2e56Smrg                    length += 4;
6335f7df2e56Smrg                }
6336f7df2e56Smrg            }
6337f7df2e56Smrg        }
6338f7df2e56Smrg        if (sli->mapsPresent) {
6339f7df2e56Smrg            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
6340f7df2e56Smrg                xkbIndicatorMapWireDesc iwire;
6341f7df2e56Smrg
6342f7df2e56Smrg                if (sli->mapsPresent & bit) {
6343f7df2e56Smrg                    iwire.flags = sli->maps[i].flags;
6344f7df2e56Smrg                    iwire.whichGroups = sli->maps[i].which_groups;
6345f7df2e56Smrg                    iwire.groups = sli->maps[i].groups;
6346f7df2e56Smrg                    iwire.whichMods = sli->maps[i].which_mods;
6347f7df2e56Smrg                    iwire.mods = sli->maps[i].mods.mask;
6348f7df2e56Smrg                    iwire.realMods = sli->maps[i].mods.real_mods;
6349f7df2e56Smrg                    iwire.virtualMods = sli->maps[i].mods.vmods;
6350f7df2e56Smrg                    iwire.ctrls = sli->maps[i].ctrls;
6351f7df2e56Smrg                    if (client->swapped) {
6352f7df2e56Smrg                        swaps(&iwire.virtualMods);
6353f7df2e56Smrg                        swapl(&iwire.ctrls);
6354f7df2e56Smrg                    }
6355f7df2e56Smrg                    WriteToClient(client, SIZEOF(xkbIndicatorMapWireDesc),
6356f7df2e56Smrg                                  &iwire);
6357f7df2e56Smrg                    length += SIZEOF(xkbIndicatorMapWireDesc);
6358f7df2e56Smrg                }
6359f7df2e56Smrg            }
6360f7df2e56Smrg        }
636105b261ecSmrg    }
636205b261ecSmrg    return length;
636305b261ecSmrg}
636405b261ecSmrg
636505b261ecSmrgstatic int
6366f7df2e56SmrgSendDeviceLedFBs(DeviceIntPtr dev,
6367f7df2e56Smrg                 int class, int id, unsigned wantLength, ClientPtr client)
636805b261ecSmrg{
6369f7df2e56Smrg    int length = 0;
6370f7df2e56Smrg
6371f7df2e56Smrg    if (class == XkbDfltXIClass) {
6372f7df2e56Smrg        if (dev->kbdfeed)
6373f7df2e56Smrg            class = KbdFeedbackClass;
6374f7df2e56Smrg        else if (dev->leds)
6375f7df2e56Smrg            class = LedFeedbackClass;
6376f7df2e56Smrg    }
6377f7df2e56Smrg    if ((dev->kbdfeed) &&
6378f7df2e56Smrg        ((class == KbdFeedbackClass) || (class == XkbAllXIClasses))) {
6379f7df2e56Smrg        KbdFeedbackPtr kf;
6380f7df2e56Smrg
6381f7df2e56Smrg        for (kf = dev->kbdfeed; (kf); kf = kf->next) {
6382f7df2e56Smrg            if ((id == XkbAllXIIds) || (id == XkbDfltXIId) ||
6383f7df2e56Smrg                (id == kf->ctrl.id)) {
6384f7df2e56Smrg                length += SendDeviceLedInfo(kf->xkb_sli, client);
6385f7df2e56Smrg                if (id != XkbAllXIIds)
6386f7df2e56Smrg                    break;
6387f7df2e56Smrg            }
6388f7df2e56Smrg        }
6389f7df2e56Smrg    }
6390f7df2e56Smrg    if ((dev->leds) &&
6391f7df2e56Smrg        ((class == LedFeedbackClass) || (class == XkbAllXIClasses))) {
6392f7df2e56Smrg        LedFeedbackPtr lf;
6393f7df2e56Smrg
6394f7df2e56Smrg        for (lf = dev->leds; (lf); lf = lf->next) {
6395f7df2e56Smrg            if ((id == XkbAllXIIds) || (id == XkbDfltXIId) ||
6396f7df2e56Smrg                (id == lf->ctrl.id)) {
6397f7df2e56Smrg                length += SendDeviceLedInfo(lf->xkb_sli, client);
6398f7df2e56Smrg                if (id != XkbAllXIIds)
6399f7df2e56Smrg                    break;
6400f7df2e56Smrg            }
6401f7df2e56Smrg        }
6402f7df2e56Smrg    }
6403f7df2e56Smrg    if (length == wantLength)
6404f7df2e56Smrg        return Success;
6405f7df2e56Smrg    else
6406f7df2e56Smrg        return BadLength;
640705b261ecSmrg}
640805b261ecSmrg
640905b261ecSmrgint
641005b261ecSmrgProcXkbGetDeviceInfo(ClientPtr client)
641105b261ecSmrg{
6412f7df2e56Smrg    DeviceIntPtr dev;
6413f7df2e56Smrg    xkbGetDeviceInfoReply rep;
6414f7df2e56Smrg    int status, nDeviceLedFBs;
6415f7df2e56Smrg    unsigned length, nameLen;
6416f7df2e56Smrg    CARD16 ledClass, ledID;
6417f7df2e56Smrg    unsigned wanted;
6418f7df2e56Smrg    char *str;
641905b261ecSmrg
642005b261ecSmrg    REQUEST(xkbGetDeviceInfoReq);
642105b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq);
642205b261ecSmrg
6423f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
6424f7df2e56Smrg        return BadAccess;
642505b261ecSmrg
6426f7df2e56Smrg    wanted = stuff->wanted;
642705b261ecSmrg
64284642e01fSmrg    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
6429f7df2e56Smrg    CHK_MASK_LEGAL(0x01, wanted, XkbXI_AllDeviceFeaturesMask);
6430f7df2e56Smrg
6431f7df2e56Smrg    if ((!dev->button) || ((stuff->nBtns < 1) && (!stuff->allBtns)))
6432f7df2e56Smrg        wanted &= ~XkbXI_ButtonActionsMask;
6433f7df2e56Smrg    if ((!dev->kbdfeed) && (!dev->leds))
6434f7df2e56Smrg        wanted &= ~XkbXI_IndicatorsMask;
6435f7df2e56Smrg
6436f7df2e56Smrg    nameLen = XkbSizeCountedString(dev->name);
6437f7df2e56Smrg    rep = (xkbGetDeviceInfoReply) {
6438f7df2e56Smrg        .type = X_Reply,
6439f7df2e56Smrg        .deviceID = dev->id,
6440f7df2e56Smrg        .sequenceNumber = client->sequence,
6441f7df2e56Smrg        .length = nameLen / 4,
6442f7df2e56Smrg        .present = wanted,
6443f7df2e56Smrg        .supported = XkbXI_AllDeviceFeaturesMask,
6444f7df2e56Smrg        .unsupported = 0,
6445f7df2e56Smrg        .nDeviceLedFBs = 0,
6446f7df2e56Smrg        .firstBtnWanted = 0,
6447f7df2e56Smrg        .nBtnsWanted = 0,
6448f7df2e56Smrg        .firstBtnRtrn = 0,
6449f7df2e56Smrg        .nBtnsRtrn = 0,
6450f7df2e56Smrg        .totalBtns = dev->button ? dev->button->numButtons : 0,
6451f7df2e56Smrg        .hasOwnState = (dev->key && dev->key->xkbInfo),
6452f7df2e56Smrg        .dfltKbdFB = dev->kbdfeed ? dev->kbdfeed->ctrl.id : XkbXINone,
6453f7df2e56Smrg        .dfltLedFB = dev->leds ? dev->leds->ctrl.id : XkbXINone,
6454f7df2e56Smrg        .devType = dev->xinput_type
6455f7df2e56Smrg    };
6456f7df2e56Smrg
6457f7df2e56Smrg    ledClass = stuff->ledClass;
6458f7df2e56Smrg    ledID = stuff->ledID;
6459f7df2e56Smrg
6460f7df2e56Smrg    if (wanted & XkbXI_ButtonActionsMask) {
6461f7df2e56Smrg        if (stuff->allBtns) {
6462f7df2e56Smrg            stuff->firstBtn = 0;
6463f7df2e56Smrg            stuff->nBtns = dev->button->numButtons;
6464f7df2e56Smrg        }
646505b261ecSmrg
6466f7df2e56Smrg        if ((stuff->firstBtn + stuff->nBtns) > dev->button->numButtons) {
6467f7df2e56Smrg            client->errorValue = _XkbErrCode4(0x02, dev->button->numButtons,
6468f7df2e56Smrg                                              stuff->firstBtn, stuff->nBtns);
6469f7df2e56Smrg            return BadValue;
6470f7df2e56Smrg        }
6471f7df2e56Smrg        else {
6472f7df2e56Smrg            rep.firstBtnWanted = stuff->firstBtn;
6473f7df2e56Smrg            rep.nBtnsWanted = stuff->nBtns;
6474f7df2e56Smrg            if (dev->button->xkb_acts != NULL) {
6475f7df2e56Smrg                XkbAction *act;
6476f7df2e56Smrg                register int i;
6477f7df2e56Smrg
6478f7df2e56Smrg                rep.firstBtnRtrn = stuff->firstBtn;
6479f7df2e56Smrg                rep.nBtnsRtrn = stuff->nBtns;
6480f7df2e56Smrg                act = &dev->button->xkb_acts[rep.firstBtnWanted];
6481f7df2e56Smrg                for (i = 0; i < rep.nBtnsRtrn; i++, act++) {
6482f7df2e56Smrg                    if (act->type != XkbSA_NoAction)
6483f7df2e56Smrg                        break;
6484f7df2e56Smrg                }
6485f7df2e56Smrg                rep.firstBtnRtrn += i;
6486f7df2e56Smrg                rep.nBtnsRtrn -= i;
6487f7df2e56Smrg                act =
6488f7df2e56Smrg                    &dev->button->xkb_acts[rep.firstBtnRtrn + rep.nBtnsRtrn -
6489f7df2e56Smrg                                           1];
6490f7df2e56Smrg                for (i = 0; i < rep.nBtnsRtrn; i++, act--) {
6491f7df2e56Smrg                    if (act->type != XkbSA_NoAction)
6492f7df2e56Smrg                        break;
6493f7df2e56Smrg                }
6494f7df2e56Smrg                rep.nBtnsRtrn -= i;
6495f7df2e56Smrg            }
6496f7df2e56Smrg            rep.length += (rep.nBtnsRtrn * SIZEOF(xkbActionWireDesc)) / 4;
6497f7df2e56Smrg        }
6498f7df2e56Smrg    }
649905b261ecSmrg
6500f7df2e56Smrg    if (wanted & XkbXI_IndicatorsMask) {
6501f7df2e56Smrg        status = CheckDeviceLedFBs(dev, ledClass, ledID, &rep, client);
6502f7df2e56Smrg        if (status != Success)
6503f7df2e56Smrg            return status;
6504f7df2e56Smrg    }
6505f7df2e56Smrg    length = rep.length * 4;
650605b261ecSmrg    nDeviceLedFBs = rep.nDeviceLedFBs;
650705b261ecSmrg    if (client->swapped) {
6508f7df2e56Smrg        swaps(&rep.sequenceNumber);
6509f7df2e56Smrg        swapl(&rep.length);
6510f7df2e56Smrg        swaps(&rep.present);
6511f7df2e56Smrg        swaps(&rep.supported);
6512f7df2e56Smrg        swaps(&rep.unsupported);
6513f7df2e56Smrg        swaps(&rep.nDeviceLedFBs);
6514f7df2e56Smrg        swaps(&rep.dfltKbdFB);
6515f7df2e56Smrg        swaps(&rep.dfltLedFB);
6516f7df2e56Smrg        swapl(&rep.devType);
6517f7df2e56Smrg    }
6518f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetDeviceInfoReply), &rep);
6519f7df2e56Smrg
6520f7df2e56Smrg    str = malloc(nameLen);
6521f7df2e56Smrg    if (!str)
6522f7df2e56Smrg        return BadAlloc;
6523f7df2e56Smrg    XkbWriteCountedString(str, dev->name, client->swapped);
6524f7df2e56Smrg    WriteToClient(client, nameLen, str);
65256747b715Smrg    free(str);
6526f7df2e56Smrg    length -= nameLen;
6527f7df2e56Smrg
6528f7df2e56Smrg    if (rep.nBtnsRtrn > 0) {
6529f7df2e56Smrg        int sz;
6530f7df2e56Smrg        xkbActionWireDesc *awire;
6531f7df2e56Smrg
6532f7df2e56Smrg        sz = rep.nBtnsRtrn * SIZEOF(xkbActionWireDesc);
6533f7df2e56Smrg        awire = (xkbActionWireDesc *) &dev->button->xkb_acts[rep.firstBtnRtrn];
6534f7df2e56Smrg        WriteToClient(client, sz, awire);
6535f7df2e56Smrg        length -= sz;
6536f7df2e56Smrg    }
6537f7df2e56Smrg    if (nDeviceLedFBs > 0) {
6538f7df2e56Smrg        status = SendDeviceLedFBs(dev, ledClass, ledID, length, client);
6539f7df2e56Smrg        if (status != Success)
6540f7df2e56Smrg            return status;
6541f7df2e56Smrg    }
6542f7df2e56Smrg    else if (length != 0) {
6543f7df2e56Smrg        ErrorF("[xkb] Internal Error!  BadLength in ProcXkbGetDeviceInfo\n");
6544f7df2e56Smrg        ErrorF("[xkb]                  Wrote %d fewer bytes than expected\n",
6545f7df2e56Smrg               length);
6546f7df2e56Smrg        return BadLength;
654705b261ecSmrg    }
65486747b715Smrg    return Success;
654905b261ecSmrg}
655005b261ecSmrg
655105b261ecSmrgstatic char *
6552f7df2e56SmrgCheckSetDeviceIndicators(char *wire,
6553f7df2e56Smrg                         DeviceIntPtr dev,
6554f7df2e56Smrg                         int num, int *status_rtrn, ClientPtr client)
655505b261ecSmrg{
6556f7df2e56Smrg    xkbDeviceLedsWireDesc *ledWire;
6557f7df2e56Smrg    int i;
6558f7df2e56Smrg    XkbSrvLedInfoPtr sli;
6559f7df2e56Smrg
6560f7df2e56Smrg    ledWire = (xkbDeviceLedsWireDesc *) wire;
6561f7df2e56Smrg    for (i = 0; i < num; i++) {
6562f7df2e56Smrg        if (client->swapped) {
6563f7df2e56Smrg            swaps(&ledWire->ledClass);
6564f7df2e56Smrg            swaps(&ledWire->ledID);
6565f7df2e56Smrg            swapl(&ledWire->namesPresent);
6566f7df2e56Smrg            swapl(&ledWire->mapsPresent);
6567f7df2e56Smrg            swapl(&ledWire->physIndicators);
6568f7df2e56Smrg        }
6569f7df2e56Smrg
6570f7df2e56Smrg        sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID,
6571f7df2e56Smrg                                XkbXI_IndicatorsMask);
6572f7df2e56Smrg        if (sli != NULL) {
6573f7df2e56Smrg            register int n;
6574f7df2e56Smrg            register unsigned bit;
6575f7df2e56Smrg            int nMaps, nNames;
6576f7df2e56Smrg            CARD32 *atomWire;
6577f7df2e56Smrg            xkbIndicatorMapWireDesc *mapWire;
6578f7df2e56Smrg
6579f7df2e56Smrg            nMaps = nNames = 0;
6580f7df2e56Smrg            for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6581f7df2e56Smrg                if (ledWire->namesPresent & bit)
6582f7df2e56Smrg                    nNames++;
6583f7df2e56Smrg                if (ledWire->mapsPresent & bit)
6584f7df2e56Smrg                    nMaps++;
6585f7df2e56Smrg            }
6586f7df2e56Smrg            atomWire = (CARD32 *) &ledWire[1];
6587f7df2e56Smrg            if (nNames > 0) {
6588f7df2e56Smrg                for (n = 0; n < nNames; n++) {
6589f7df2e56Smrg                    if (client->swapped) {
6590f7df2e56Smrg                        swapl(atomWire);
6591f7df2e56Smrg                    }
6592f7df2e56Smrg                    CHK_ATOM_OR_NONE3(((Atom) (*atomWire)), client->errorValue,
6593f7df2e56Smrg                                      *status_rtrn, NULL);
6594f7df2e56Smrg                    atomWire++;
6595f7df2e56Smrg                }
6596f7df2e56Smrg            }
6597f7df2e56Smrg            mapWire = (xkbIndicatorMapWireDesc *) atomWire;
6598f7df2e56Smrg            if (nMaps > 0) {
6599f7df2e56Smrg                for (n = 0; n < nMaps; n++) {
6600f7df2e56Smrg                    if (client->swapped) {
6601f7df2e56Smrg                        swaps(&mapWire->virtualMods);
6602f7df2e56Smrg                        swapl(&mapWire->ctrls);
6603f7df2e56Smrg                    }
6604f7df2e56Smrg                    CHK_MASK_LEGAL3(0x21, mapWire->whichGroups,
6605f7df2e56Smrg                                    XkbIM_UseAnyGroup,
6606f7df2e56Smrg                                    client->errorValue, *status_rtrn, NULL);
6607f7df2e56Smrg                    CHK_MASK_LEGAL3(0x22, mapWire->whichMods, XkbIM_UseAnyMods,
6608f7df2e56Smrg                                    client->errorValue, *status_rtrn, NULL);
6609f7df2e56Smrg                    mapWire++;
6610f7df2e56Smrg                }
6611f7df2e56Smrg            }
6612f7df2e56Smrg            ledWire = (xkbDeviceLedsWireDesc *) mapWire;
6613f7df2e56Smrg        }
6614f7df2e56Smrg        else {
6615f7df2e56Smrg            /* SHOULD NEVER HAPPEN */
6616f7df2e56Smrg            return (char *) ledWire;
6617f7df2e56Smrg        }
6618f7df2e56Smrg    }
6619f7df2e56Smrg    return (char *) ledWire;
662005b261ecSmrg}
662105b261ecSmrg
662205b261ecSmrgstatic char *
6623f7df2e56SmrgSetDeviceIndicators(char *wire,
6624f7df2e56Smrg                    DeviceIntPtr dev,
6625f7df2e56Smrg                    unsigned changed,
6626f7df2e56Smrg                    int num,
6627f7df2e56Smrg                    int *status_rtrn,
6628806e81e9Smrg                    ClientPtr client,
6629806e81e9Smrg                    xkbExtensionDeviceNotify * ev,
6630806e81e9Smrg                    xkbSetDeviceInfoReq * stuff)
663105b261ecSmrg{
6632f7df2e56Smrg    xkbDeviceLedsWireDesc *ledWire;
6633f7df2e56Smrg    int i;
6634f7df2e56Smrg    XkbEventCauseRec cause;
6635f7df2e56Smrg    unsigned namec, mapc, statec;
6636f7df2e56Smrg    xkbExtensionDeviceNotify ed;
6637f7df2e56Smrg    XkbChangesRec changes;
6638f7df2e56Smrg    DeviceIntPtr kbd;
6639f7df2e56Smrg
6640f7df2e56Smrg    memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify));
6641f7df2e56Smrg    memset((char *) &changes, 0, sizeof(XkbChangesRec));
6642f7df2e56Smrg    XkbSetCauseXkbReq(&cause, X_kbSetDeviceInfo, client);
6643f7df2e56Smrg    ledWire = (xkbDeviceLedsWireDesc *) wire;
6644f7df2e56Smrg    for (i = 0; i < num; i++) {
6645f7df2e56Smrg        register int n;
6646f7df2e56Smrg        register unsigned bit;
6647f7df2e56Smrg        CARD32 *atomWire;
6648f7df2e56Smrg        xkbIndicatorMapWireDesc *mapWire;
6649f7df2e56Smrg        XkbSrvLedInfoPtr sli;
6650f7df2e56Smrg
6651806e81e9Smrg        if (!_XkbCheckRequestBounds(client, stuff, ledWire, ledWire + 1)) {
6652806e81e9Smrg            *status_rtrn = BadLength;
6653806e81e9Smrg            return (char *) ledWire;
6654806e81e9Smrg        }
6655806e81e9Smrg
6656f7df2e56Smrg        namec = mapc = statec = 0;
6657f7df2e56Smrg        sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID,
6658f7df2e56Smrg                                XkbXI_IndicatorMapsMask);
6659f7df2e56Smrg        if (!sli) {
6660f7df2e56Smrg            /* SHOULD NEVER HAPPEN!! */
6661f7df2e56Smrg            return (char *) ledWire;
6662f7df2e56Smrg        }
666305b261ecSmrg
6664f7df2e56Smrg        atomWire = (CARD32 *) &ledWire[1];
6665f7df2e56Smrg        if (changed & XkbXI_IndicatorNamesMask) {
6666f7df2e56Smrg            namec = sli->namesPresent | ledWire->namesPresent;
6667f7df2e56Smrg            memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom));
6668f7df2e56Smrg        }
6669f7df2e56Smrg        if (ledWire->namesPresent) {
6670f7df2e56Smrg            sli->namesPresent = ledWire->namesPresent;
6671f7df2e56Smrg            memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom));
6672f7df2e56Smrg            for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6673f7df2e56Smrg                if (ledWire->namesPresent & bit) {
6674806e81e9Smrg                    if (!_XkbCheckRequestBounds(client, stuff, atomWire, atomWire + 1)) {
6675806e81e9Smrg                        *status_rtrn = BadLength;
6676806e81e9Smrg                        return (char *) atomWire;
6677806e81e9Smrg                    }
6678f7df2e56Smrg                    sli->names[n] = (Atom) *atomWire;
6679f7df2e56Smrg                    if (sli->names[n] == None)
6680f7df2e56Smrg                        ledWire->namesPresent &= ~bit;
6681f7df2e56Smrg                    atomWire++;
6682f7df2e56Smrg                }
6683f7df2e56Smrg            }
6684f7df2e56Smrg        }
6685f7df2e56Smrg        mapWire = (xkbIndicatorMapWireDesc *) atomWire;
6686f7df2e56Smrg        if (changed & XkbXI_IndicatorMapsMask) {
6687f7df2e56Smrg            mapc = sli->mapsPresent | ledWire->mapsPresent;
6688f7df2e56Smrg            sli->mapsPresent = ledWire->mapsPresent;
6689f7df2e56Smrg            memset((char *) sli->maps, 0,
6690f7df2e56Smrg                   XkbNumIndicators * sizeof(XkbIndicatorMapRec));
6691f7df2e56Smrg        }
6692f7df2e56Smrg        if (ledWire->mapsPresent) {
6693f7df2e56Smrg            for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6694f7df2e56Smrg                if (ledWire->mapsPresent & bit) {
6695806e81e9Smrg                    if (!_XkbCheckRequestBounds(client, stuff, mapWire, mapWire + 1)) {
6696806e81e9Smrg                        *status_rtrn = BadLength;
6697806e81e9Smrg                        return (char *) mapWire;
6698806e81e9Smrg                    }
6699f7df2e56Smrg                    sli->maps[n].flags = mapWire->flags;
6700f7df2e56Smrg                    sli->maps[n].which_groups = mapWire->whichGroups;
6701f7df2e56Smrg                    sli->maps[n].groups = mapWire->groups;
6702f7df2e56Smrg                    sli->maps[n].which_mods = mapWire->whichMods;
6703f7df2e56Smrg                    sli->maps[n].mods.mask = mapWire->mods;
6704f7df2e56Smrg                    sli->maps[n].mods.real_mods = mapWire->realMods;
6705f7df2e56Smrg                    sli->maps[n].mods.vmods = mapWire->virtualMods;
6706f7df2e56Smrg                    sli->maps[n].ctrls = mapWire->ctrls;
6707f7df2e56Smrg                    mapWire++;
6708f7df2e56Smrg                }
6709f7df2e56Smrg            }
6710f7df2e56Smrg        }
6711f7df2e56Smrg        if (changed & XkbXI_IndicatorStateMask) {
6712f7df2e56Smrg            statec = sli->effectiveState ^ ledWire->state;
6713f7df2e56Smrg            sli->explicitState &= ~statec;
6714f7df2e56Smrg            sli->explicitState |= (ledWire->state & statec);
6715f7df2e56Smrg        }
6716f7df2e56Smrg        if (namec)
6717f7df2e56Smrg            XkbApplyLedNameChanges(dev, sli, namec, &ed, &changes, &cause);
6718f7df2e56Smrg        if (mapc)
6719f7df2e56Smrg            XkbApplyLedMapChanges(dev, sli, mapc, &ed, &changes, &cause);
6720f7df2e56Smrg        if (statec)
6721f7df2e56Smrg            XkbApplyLedStateChanges(dev, sli, statec, &ed, &changes, &cause);
6722f7df2e56Smrg
6723f7df2e56Smrg        kbd = dev;
6724f7df2e56Smrg        if ((sli->flags & XkbSLI_HasOwnState) == 0)
6725f7df2e56Smrg            kbd = inputInfo.keyboard;
6726f7df2e56Smrg
6727f7df2e56Smrg        XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause);
6728f7df2e56Smrg        ledWire = (xkbDeviceLedsWireDesc *) mapWire;
6729f7df2e56Smrg    }
6730f7df2e56Smrg    return (char *) ledWire;
6731f7df2e56Smrg}
673205b261ecSmrg
67334642e01fSmrgstatic int
67344642e01fSmrg_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev,
6735f7df2e56Smrg                  xkbSetDeviceInfoReq * stuff)
67364642e01fSmrg{
6737f7df2e56Smrg    char *wire;
6738f7df2e56Smrg
6739f7df2e56Smrg    wire = (char *) &stuff[1];
6740f7df2e56Smrg    if (stuff->change & XkbXI_ButtonActionsMask) {
6741f7df2e56Smrg        if (!dev->button) {
6742f7df2e56Smrg            client->errorValue = _XkbErrCode2(XkbErr_BadClass, ButtonClass);
6743f7df2e56Smrg            return XkbKeyboardErrorCode;
6744f7df2e56Smrg        }
6745f7df2e56Smrg        if ((stuff->firstBtn + stuff->nBtns) > dev->button->numButtons) {
6746f7df2e56Smrg            client->errorValue =
6747f7df2e56Smrg                _XkbErrCode4(0x02, stuff->firstBtn, stuff->nBtns,
6748f7df2e56Smrg                             dev->button->numButtons);
6749f7df2e56Smrg            return BadMatch;
6750f7df2e56Smrg        }
6751f7df2e56Smrg        wire += (stuff->nBtns * SIZEOF(xkbActionWireDesc));
6752f7df2e56Smrg    }
6753f7df2e56Smrg    if (stuff->change & XkbXI_IndicatorsMask) {
6754f7df2e56Smrg        int status = Success;
6755f7df2e56Smrg
6756f7df2e56Smrg        wire = CheckSetDeviceIndicators(wire, dev, stuff->nDeviceLedFBs,
6757f7df2e56Smrg                                        &status, client);
6758f7df2e56Smrg        if (status != Success)
6759f7df2e56Smrg            return status;
6760f7df2e56Smrg    }
6761f7df2e56Smrg    if (((wire - ((char *) stuff)) / 4) != stuff->length)
6762f7df2e56Smrg        return BadLength;
676305b261ecSmrg
67644642e01fSmrg    return Success;
67654642e01fSmrg}
67664642e01fSmrg
67674642e01fSmrgstatic int
67684642e01fSmrg_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev,
6769f7df2e56Smrg                       xkbSetDeviceInfoReq * stuff)
67704642e01fSmrg{
6771f7df2e56Smrg    char *wire;
6772f7df2e56Smrg    xkbExtensionDeviceNotify ed;
6773f7df2e56Smrg
6774f7df2e56Smrg    memset((char *) &ed, 0, SIZEOF(xkbExtensionDeviceNotify));
6775f7df2e56Smrg    ed.deviceID = dev->id;
6776f7df2e56Smrg    wire = (char *) &stuff[1];
6777f7df2e56Smrg    if (stuff->change & XkbXI_ButtonActionsMask) {
6778806e81e9Smrg	int nBtns, sz, i;
6779f7df2e56Smrg        XkbAction *acts;
6780f7df2e56Smrg        DeviceIntPtr kbd;
6781f7df2e56Smrg
6782f7df2e56Smrg        nBtns = dev->button->numButtons;
6783f7df2e56Smrg        acts = dev->button->xkb_acts;
6784f7df2e56Smrg        if (acts == NULL) {
6785f7df2e56Smrg            acts = calloc(nBtns, sizeof(XkbAction));
6786f7df2e56Smrg            if (!acts)
6787f7df2e56Smrg                return BadAlloc;
6788f7df2e56Smrg            dev->button->xkb_acts = acts;
6789f7df2e56Smrg        }
6790806e81e9Smrg        if (stuff->firstBtn + stuff->nBtns > nBtns)
6791806e81e9Smrg            return BadValue;
6792f7df2e56Smrg        sz = stuff->nBtns * SIZEOF(xkbActionWireDesc);
6793806e81e9Smrg        if (!_XkbCheckRequestBounds(client, stuff, wire, (char *) wire + sz))
6794806e81e9Smrg            return BadLength;
6795f7df2e56Smrg        memcpy((char *) &acts[stuff->firstBtn], (char *) wire, sz);
6796f7df2e56Smrg        wire += sz;
6797f7df2e56Smrg        ed.reason |= XkbXI_ButtonActionsMask;
6798f7df2e56Smrg        ed.firstBtn = stuff->firstBtn;
6799f7df2e56Smrg        ed.nBtns = stuff->nBtns;
6800f7df2e56Smrg
6801f7df2e56Smrg        if (dev->key)
6802f7df2e56Smrg            kbd = dev;
6803f7df2e56Smrg        else
6804f7df2e56Smrg            kbd = inputInfo.keyboard;
6805f7df2e56Smrg        acts = &dev->button->xkb_acts[stuff->firstBtn];
6806f7df2e56Smrg        for (i = 0; i < stuff->nBtns; i++, acts++) {
6807f7df2e56Smrg            if (acts->type != XkbSA_NoAction)
6808f7df2e56Smrg                XkbSetActionKeyMods(kbd->key->xkbInfo->desc, acts, 0);
6809f7df2e56Smrg        }
6810f7df2e56Smrg    }
6811f7df2e56Smrg    if (stuff->change & XkbXI_IndicatorsMask) {
6812f7df2e56Smrg        int status = Success;
6813f7df2e56Smrg
6814f7df2e56Smrg        wire = SetDeviceIndicators(wire, dev, stuff->change,
6815806e81e9Smrg                                   stuff->nDeviceLedFBs, &status, client, &ed,
6816806e81e9Smrg                                   stuff);
6817f7df2e56Smrg        if (status != Success)
6818f7df2e56Smrg            return status;
6819f7df2e56Smrg    }
6820f7df2e56Smrg    if ((stuff->change) && (ed.reason))
6821f7df2e56Smrg        XkbSendExtensionDeviceNotify(dev, client, &ed);
68224642e01fSmrg    return Success;
68234642e01fSmrg}
68244642e01fSmrg
68254642e01fSmrgint
68264642e01fSmrgProcXkbSetDeviceInfo(ClientPtr client)
68274642e01fSmrg{
6828f7df2e56Smrg    DeviceIntPtr dev;
6829f7df2e56Smrg    int rc;
68304642e01fSmrg
68314642e01fSmrg    REQUEST(xkbSetDeviceInfoReq);
68324642e01fSmrg    REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq);
68334642e01fSmrg
6834f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
6835f7df2e56Smrg        return BadAccess;
68364642e01fSmrg
68374642e01fSmrg    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
6838f7df2e56Smrg    CHK_MASK_LEGAL(0x01, stuff->change, XkbXI_AllFeaturesMask);
68394642e01fSmrg
68404642e01fSmrg    rc = _XkbSetDeviceInfoCheck(client, dev, stuff);
68414642e01fSmrg
68424642e01fSmrg    if (rc != Success)
68434642e01fSmrg        return rc;
68444642e01fSmrg
6845f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd ||
6846f7df2e56Smrg        stuff->deviceSpec == XkbUseCorePtr) {
68474642e01fSmrg        DeviceIntPtr other;
6848f7df2e56Smrg
6849f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
6850f7df2e56Smrg            if (((other != dev) && !IsMaster(other) &&
6851f7df2e56Smrg                 GetMaster(other, MASTER_KEYBOARD) == dev) &&
68524642e01fSmrg                ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
6853f7df2e56Smrg                 (stuff->deviceSpec == XkbUseCorePtr && other->button))) {
6854f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
6855f7df2e56Smrg                              DixManageAccess);
6856f7df2e56Smrg                if (rc == Success) {
68574642e01fSmrg                    rc = _XkbSetDeviceInfoCheck(client, other, stuff);
68584642e01fSmrg                    if (rc != Success)
68594642e01fSmrg                        return rc;
68604642e01fSmrg                }
68614642e01fSmrg            }
68624642e01fSmrg        }
68634642e01fSmrg    }
68644642e01fSmrg
68654642e01fSmrg    /* checks done, apply */
68664642e01fSmrg    rc = _XkbSetDeviceInfo(client, dev, stuff);
68674642e01fSmrg    if (rc != Success)
68684642e01fSmrg        return rc;
68694642e01fSmrg
6870f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd ||
6871f7df2e56Smrg        stuff->deviceSpec == XkbUseCorePtr) {
68724642e01fSmrg        DeviceIntPtr other;
6873f7df2e56Smrg
6874f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
6875f7df2e56Smrg            if (((other != dev) && !IsMaster(other) &&
6876f7df2e56Smrg                 GetMaster(other, MASTER_KEYBOARD) == dev) &&
68774642e01fSmrg                ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
6878f7df2e56Smrg                 (stuff->deviceSpec == XkbUseCorePtr && other->button))) {
6879f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
6880f7df2e56Smrg                              DixManageAccess);
6881f7df2e56Smrg                if (rc == Success) {
68824642e01fSmrg                    rc = _XkbSetDeviceInfo(client, other, stuff);
68834642e01fSmrg                    if (rc != Success)
68844642e01fSmrg                        return rc;
68854642e01fSmrg                }
68864642e01fSmrg            }
68874642e01fSmrg        }
68884642e01fSmrg    }
68894642e01fSmrg
68906747b715Smrg    return Success;
689105b261ecSmrg}
689205b261ecSmrg
689305b261ecSmrg/***====================================================================***/
689405b261ecSmrg
689505b261ecSmrgint
689605b261ecSmrgProcXkbSetDebuggingFlags(ClientPtr client)
689705b261ecSmrg{
6898f7df2e56Smrg    CARD32 newFlags, newCtrls, extraLength;
6899f7df2e56Smrg    xkbSetDebuggingFlagsReply rep;
6900f7df2e56Smrg    int rc;
690105b261ecSmrg
690205b261ecSmrg    REQUEST(xkbSetDebuggingFlagsReq);
690305b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq);
690405b261ecSmrg
69054642e01fSmrg    rc = XaceHook(XACE_SERVER_ACCESS, client, DixDebugAccess);
69064642e01fSmrg    if (rc != Success)
6907f7df2e56Smrg        return rc;
69084642e01fSmrg
6909f7df2e56Smrg    newFlags = xkbDebugFlags & (~stuff->affectFlags);
6910f7df2e56Smrg    newFlags |= (stuff->flags & stuff->affectFlags);
6911f7df2e56Smrg    newCtrls = xkbDebugCtrls & (~stuff->affectCtrls);
6912f7df2e56Smrg    newCtrls |= (stuff->ctrls & stuff->affectCtrls);
691305b261ecSmrg    if (xkbDebugFlags || newFlags || stuff->msgLength) {
6914f7df2e56Smrg        ErrorF("[xkb] XkbDebug: Setting debug flags to 0x%lx\n",
6915f7df2e56Smrg               (long) newFlags);
6916f7df2e56Smrg        if (newCtrls != xkbDebugCtrls)
6917f7df2e56Smrg            ErrorF("[xkb] XkbDebug: Setting debug controls to 0x%lx\n",
6918f7df2e56Smrg                   (long) newCtrls);
6919f7df2e56Smrg    }
6920f7df2e56Smrg    extraLength = (stuff->length << 2) - sz_xkbSetDebuggingFlagsReq;
6921f7df2e56Smrg    if (stuff->msgLength > 0) {
6922f7df2e56Smrg        char *msg;
6923f7df2e56Smrg
6924f7df2e56Smrg        if (extraLength < XkbPaddedSize(stuff->msgLength)) {
6925f7df2e56Smrg            ErrorF
6926f7df2e56Smrg                ("[xkb] XkbDebug: msgLength= %d, length= %ld (should be %d)\n",
6927f7df2e56Smrg                 stuff->msgLength, (long) extraLength,
6928f7df2e56Smrg                 XkbPaddedSize(stuff->msgLength));
6929f7df2e56Smrg            return BadLength;
6930f7df2e56Smrg        }
6931f7df2e56Smrg        msg = (char *) &stuff[1];
6932f7df2e56Smrg        if (msg[stuff->msgLength - 1] != '\0') {
6933f7df2e56Smrg            ErrorF("[xkb] XkbDebug: message not null-terminated\n");
6934f7df2e56Smrg            return BadValue;
6935f7df2e56Smrg        }
6936f7df2e56Smrg        ErrorF("[xkb] XkbDebug: %s\n", msg);
693705b261ecSmrg    }
693805b261ecSmrg    xkbDebugFlags = newFlags;
693905b261ecSmrg    xkbDebugCtrls = newCtrls;
694005b261ecSmrg
6941f7df2e56Smrg    rep = (xkbSetDebuggingFlagsReply) {
6942f7df2e56Smrg        .type = X_Reply,
6943f7df2e56Smrg        .sequenceNumber = client->sequence,
6944f7df2e56Smrg        .length = 0,
6945f7df2e56Smrg        .currentFlags = newFlags,
6946f7df2e56Smrg        .currentCtrls = newCtrls,
6947f7df2e56Smrg        .supportedFlags = ~0,
6948f7df2e56Smrg        .supportedCtrls = ~0
6949f7df2e56Smrg    };
6950f7df2e56Smrg    if (client->swapped) {
6951f7df2e56Smrg        swaps(&rep.sequenceNumber);
6952f7df2e56Smrg        swapl(&rep.currentFlags);
6953f7df2e56Smrg        swapl(&rep.currentCtrls);
6954f7df2e56Smrg        swapl(&rep.supportedFlags);
6955f7df2e56Smrg        swapl(&rep.supportedCtrls);
6956f7df2e56Smrg    }
6957f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbSetDebuggingFlagsReply), &rep);
69586747b715Smrg    return Success;
695905b261ecSmrg}
696005b261ecSmrg
696105b261ecSmrg/***====================================================================***/
696205b261ecSmrg
696305b261ecSmrgstatic int
6964f7df2e56SmrgProcXkbDispatch(ClientPtr client)
696505b261ecSmrg{
696605b261ecSmrg    REQUEST(xReq);
6967f7df2e56Smrg    switch (stuff->data) {
696805b261ecSmrg    case X_kbUseExtension:
6969f7df2e56Smrg        return ProcXkbUseExtension(client);
697005b261ecSmrg    case X_kbSelectEvents:
6971f7df2e56Smrg        return ProcXkbSelectEvents(client);
697205b261ecSmrg    case X_kbBell:
6973f7df2e56Smrg        return ProcXkbBell(client);
697405b261ecSmrg    case X_kbGetState:
6975f7df2e56Smrg        return ProcXkbGetState(client);
697605b261ecSmrg    case X_kbLatchLockState:
6977f7df2e56Smrg        return ProcXkbLatchLockState(client);
697805b261ecSmrg    case X_kbGetControls:
6979f7df2e56Smrg        return ProcXkbGetControls(client);
698005b261ecSmrg    case X_kbSetControls:
6981f7df2e56Smrg        return ProcXkbSetControls(client);
698205b261ecSmrg    case X_kbGetMap:
6983f7df2e56Smrg        return ProcXkbGetMap(client);
698405b261ecSmrg    case X_kbSetMap:
6985f7df2e56Smrg        return ProcXkbSetMap(client);
698605b261ecSmrg    case X_kbGetCompatMap:
6987f7df2e56Smrg        return ProcXkbGetCompatMap(client);
698805b261ecSmrg    case X_kbSetCompatMap:
6989f7df2e56Smrg        return ProcXkbSetCompatMap(client);
699005b261ecSmrg    case X_kbGetIndicatorState:
6991f7df2e56Smrg        return ProcXkbGetIndicatorState(client);
699205b261ecSmrg    case X_kbGetIndicatorMap:
6993f7df2e56Smrg        return ProcXkbGetIndicatorMap(client);
699405b261ecSmrg    case X_kbSetIndicatorMap:
6995f7df2e56Smrg        return ProcXkbSetIndicatorMap(client);
699605b261ecSmrg    case X_kbGetNamedIndicator:
6997f7df2e56Smrg        return ProcXkbGetNamedIndicator(client);
699805b261ecSmrg    case X_kbSetNamedIndicator:
6999f7df2e56Smrg        return ProcXkbSetNamedIndicator(client);
700005b261ecSmrg    case X_kbGetNames:
7001f7df2e56Smrg        return ProcXkbGetNames(client);
700205b261ecSmrg    case X_kbSetNames:
7003f7df2e56Smrg        return ProcXkbSetNames(client);
700405b261ecSmrg    case X_kbGetGeometry:
7005f7df2e56Smrg        return ProcXkbGetGeometry(client);
700605b261ecSmrg    case X_kbSetGeometry:
7007f7df2e56Smrg        return ProcXkbSetGeometry(client);
700805b261ecSmrg    case X_kbPerClientFlags:
7009f7df2e56Smrg        return ProcXkbPerClientFlags(client);
701005b261ecSmrg    case X_kbListComponents:
7011f7df2e56Smrg        return ProcXkbListComponents(client);
701205b261ecSmrg    case X_kbGetKbdByName:
7013f7df2e56Smrg        return ProcXkbGetKbdByName(client);
701405b261ecSmrg    case X_kbGetDeviceInfo:
7015f7df2e56Smrg        return ProcXkbGetDeviceInfo(client);
701605b261ecSmrg    case X_kbSetDeviceInfo:
7017f7df2e56Smrg        return ProcXkbSetDeviceInfo(client);
701805b261ecSmrg    case X_kbSetDebuggingFlags:
7019f7df2e56Smrg        return ProcXkbSetDebuggingFlags(client);
702005b261ecSmrg    default:
7021f7df2e56Smrg        return BadRequest;
702205b261ecSmrg    }
702305b261ecSmrg}
702405b261ecSmrg
702505b261ecSmrgstatic int
7026f7df2e56SmrgXkbClientGone(void *data, XID id)
702705b261ecSmrg{
7028f7df2e56Smrg    DevicePtr pXDev = (DevicePtr) data;
702905b261ecSmrg
7030f7df2e56Smrg    if (!XkbRemoveResourceClient(pXDev, id)) {
7031f7df2e56Smrg        ErrorF
7032f7df2e56Smrg            ("[xkb] Internal Error! bad RemoveResourceClient in XkbClientGone\n");
703305b261ecSmrg    }
703405b261ecSmrg    return 1;
703505b261ecSmrg}
703605b261ecSmrg
703705b261ecSmrgvoid
703805b261ecSmrgXkbExtensionInit(void)
703905b261ecSmrg{
704005b261ecSmrg    ExtensionEntry *extEntry;
704105b261ecSmrg
70426747b715Smrg    RT_XKBCLIENT = CreateNewResourceType(XkbClientGone, "XkbClient");
70436747b715Smrg    if (!RT_XKBCLIENT)
7044f7df2e56Smrg        return;
70456747b715Smrg
70466747b715Smrg    if (!XkbInitPrivates())
7047f7df2e56Smrg        return;
70486747b715Smrg
704905b261ecSmrg    if ((extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors,
7050f7df2e56Smrg                                 ProcXkbDispatch, SProcXkbDispatch,
7051f7df2e56Smrg                                 NULL, StandardMinorOpcode))) {
7052f7df2e56Smrg        XkbReqCode = (unsigned char) extEntry->base;
7053f7df2e56Smrg        XkbEventBase = (unsigned char) extEntry->eventBase;
7054f7df2e56Smrg        XkbErrorBase = (unsigned char) extEntry->errorBase;
7055f7df2e56Smrg        XkbKeyboardErrorCode = XkbErrorBase + XkbKeyboard;
705605b261ecSmrg    }
705705b261ecSmrg    return;
705805b261ecSmrg}
7059