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++) {
1096d566a54bSmrg        nSymsThisKey = XkbNumGroups(symMap->group_info) * symMap->width;
1097d566a54bSmrg        if (nSymsThisKey == 0)
1098d566a54bSmrg            continue;
1099d566a54bSmrg        nSyms += nSymsThisKey;
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
251490bea6a0Smrg    /* nTypes/mapWidths/symsPerKey must be filled for further tests below,
251590bea6a0Smrg     * regardless of client-side flags */
251690bea6a0Smrg
251790bea6a0Smrg    if (!CheckKeyTypes(client, xkb, req, (xkbKeyTypeWireDesc **) &values,
251890bea6a0Smrg		       &nTypes, mapWidths, doswap)) {
25195a112b11Smrg	    client->errorValue = nTypes;
25205a112b11Smrg	    return BadValue;
252105b261ecSmrg    }
25229ace9065Smrg
25239ace9065Smrg    map = &xkb->map->key_sym_map[xkb->min_key_code];
2524f7df2e56Smrg    for (i = xkb->min_key_code; i < xkb->max_key_code; i++, map++) {
2525f7df2e56Smrg        register int g, ng, w;
2526f7df2e56Smrg
2527f7df2e56Smrg        ng = XkbNumGroups(map->group_info);
2528f7df2e56Smrg        for (w = g = 0; g < ng; g++) {
2529f7df2e56Smrg            if (map->kt_index[g] >= (unsigned) nTypes) {
2530f7df2e56Smrg                client->errorValue = _XkbErrCode4(0x13, i, g, map->kt_index[g]);
25315a112b11Smrg                return BadValue;
2532f7df2e56Smrg            }
2533f7df2e56Smrg            if (mapWidths[map->kt_index[g]] > w)
2534f7df2e56Smrg                w = mapWidths[map->kt_index[g]];
2535f7df2e56Smrg        }
2536f7df2e56Smrg        symsPerKey[i] = w * ng;
25379ace9065Smrg    }
25389ace9065Smrg
25394642e01fSmrg    if ((req->present & XkbKeySymsMask) &&
2540f7df2e56Smrg        (!CheckKeySyms(client, xkb, req, nTypes, mapWidths, symsPerKey,
25415a112b11Smrg                       (xkbSymMapWireDesc **) &values, &error, doswap))) {
2542f7df2e56Smrg        client->errorValue = error;
2543f7df2e56Smrg        return BadValue;
254405b261ecSmrg    }
254505b261ecSmrg
25464642e01fSmrg    if ((req->present & XkbKeyActionsMask) &&
2547f7df2e56Smrg        (!CheckKeyActions(xkb, req, nTypes, mapWidths, symsPerKey,
2548f7df2e56Smrg                          (CARD8 **) &values, &nActions))) {
2549f7df2e56Smrg        client->errorValue = nActions;
2550f7df2e56Smrg        return BadValue;
255105b261ecSmrg    }
255205b261ecSmrg
25534642e01fSmrg    if ((req->present & XkbKeyBehaviorsMask) &&
2554f7df2e56Smrg        (!CheckKeyBehaviors
2555f7df2e56Smrg         (xkb, req, (xkbBehaviorWireDesc **) &values, &error))) {
2556f7df2e56Smrg        client->errorValue = error;
2557f7df2e56Smrg        return BadValue;
255805b261ecSmrg    }
255905b261ecSmrg
25604642e01fSmrg    if ((req->present & XkbVirtualModsMask) &&
2561f7df2e56Smrg        (!CheckVirtualMods(xkb, req, (CARD8 **) &values, &error))) {
2562f7df2e56Smrg        client->errorValue = error;
2563f7df2e56Smrg        return BadValue;
256405b261ecSmrg    }
2565f7df2e56Smrg    if ((req->present & XkbExplicitComponentsMask) &&
2566f7df2e56Smrg        (!CheckKeyExplicit(xkb, req, (CARD8 **) &values, &error))) {
2567f7df2e56Smrg        client->errorValue = error;
2568f7df2e56Smrg        return BadValue;
256905b261ecSmrg    }
2570f7df2e56Smrg    if ((req->present & XkbModifierMapMask) &&
2571f7df2e56Smrg        (!CheckModifierMap(xkb, req, (CARD8 **) &values, &error))) {
2572f7df2e56Smrg        client->errorValue = error;
2573f7df2e56Smrg        return BadValue;
257405b261ecSmrg    }
2575f7df2e56Smrg    if ((req->present & XkbVirtualModMapMask) &&
2576f7df2e56Smrg        (!CheckVirtualModMap
2577f7df2e56Smrg         (xkb, req, (xkbVModMapWireDesc **) &values, &error))) {
2578f7df2e56Smrg        client->errorValue = error;
2579f7df2e56Smrg        return BadValue;
258005b261ecSmrg    }
25814642e01fSmrg
2582f7df2e56Smrg    if (((values - ((char *) req)) / 4) != req->length) {
2583f7df2e56Smrg        ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after check)\n");
2584f7df2e56Smrg        client->errorValue = values - ((char *) &req[1]);
2585f7df2e56Smrg        return BadLength;
258605b261ecSmrg    }
25874642e01fSmrg
25884642e01fSmrg    return Success;
25894642e01fSmrg}
25904642e01fSmrg
25914642e01fSmrg/**
25924642e01fSmrg * Apply the given request on the given device.
25934642e01fSmrg */
25944642e01fSmrgstatic int
2595f7df2e56Smrg_XkbSetMap(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq * req, char *values)
25964642e01fSmrg{
2597f7df2e56Smrg    XkbEventCauseRec cause;
2598f7df2e56Smrg    XkbChangesRec change;
2599f7df2e56Smrg    Bool sentNKN;
2600f7df2e56Smrg    XkbSrvInfoPtr xkbi;
2601f7df2e56Smrg    XkbDescPtr xkb;
26024642e01fSmrg
26034e185dc0Smrg    if (!dev->key)
26044e185dc0Smrg        return Success;
26054e185dc0Smrg
2606f7df2e56Smrg    xkbi = dev->key->xkbInfo;
26074642e01fSmrg    xkb = xkbi->desc;
26084642e01fSmrg
2609f7df2e56Smrg    XkbSetCauseXkbReq(&cause, X_kbSetMap, client);
26106747b715Smrg    memset(&change, 0, sizeof(change));
26116747b715Smrg    sentNKN = FALSE;
2612f7df2e56Smrg    if ((xkb->min_key_code != req->minKeyCode) ||
2613f7df2e56Smrg        (xkb->max_key_code != req->maxKeyCode)) {
2614f7df2e56Smrg        Status status;
2615f7df2e56Smrg        xkbNewKeyboardNotify nkn;
2616f7df2e56Smrg
2617f7df2e56Smrg        nkn.deviceID = nkn.oldDeviceID = dev->id;
2618f7df2e56Smrg        nkn.oldMinKeyCode = xkb->min_key_code;
2619f7df2e56Smrg        nkn.oldMaxKeyCode = xkb->max_key_code;
2620f7df2e56Smrg        status = XkbChangeKeycodeRange(xkb, req->minKeyCode,
2621f7df2e56Smrg                                       req->maxKeyCode, &change);
2622f7df2e56Smrg        if (status != Success)
2623f7df2e56Smrg            return status;      /* oh-oh. what about the other keyboards? */
2624f7df2e56Smrg        nkn.minKeyCode = xkb->min_key_code;
2625f7df2e56Smrg        nkn.maxKeyCode = xkb->max_key_code;
2626f7df2e56Smrg        nkn.requestMajor = XkbReqCode;
2627f7df2e56Smrg        nkn.requestMinor = X_kbSetMap;
2628f7df2e56Smrg        nkn.changed = XkbNKN_KeycodesMask;
2629f7df2e56Smrg        XkbSendNewKeyboardNotify(dev, &nkn);
2630f7df2e56Smrg        sentNKN = TRUE;
2631f7df2e56Smrg    }
2632f7df2e56Smrg
2633f7df2e56Smrg    if (req->present & XkbKeyTypesMask) {
2634f7df2e56Smrg        values = SetKeyTypes(xkb, req, (xkbKeyTypeWireDesc *) values, &change);
2635f7df2e56Smrg        if (!values)
2636f7df2e56Smrg            goto allocFailure;
2637f7df2e56Smrg    }
2638f7df2e56Smrg    if (req->present & XkbKeySymsMask) {
2639f7df2e56Smrg        values =
2640f7df2e56Smrg            SetKeySyms(client, xkb, req, (xkbSymMapWireDesc *) values, &change,
2641f7df2e56Smrg                       dev);
2642f7df2e56Smrg        if (!values)
2643f7df2e56Smrg            goto allocFailure;
2644f7df2e56Smrg    }
2645f7df2e56Smrg    if (req->present & XkbKeyActionsMask) {
2646f7df2e56Smrg        values = SetKeyActions(xkb, req, (CARD8 *) values, &change);
2647f7df2e56Smrg        if (!values)
2648f7df2e56Smrg            goto allocFailure;
2649f7df2e56Smrg    }
2650f7df2e56Smrg    if (req->present & XkbKeyBehaviorsMask) {
2651f7df2e56Smrg        values =
2652f7df2e56Smrg            SetKeyBehaviors(xkbi, req, (xkbBehaviorWireDesc *) values, &change);
2653f7df2e56Smrg        if (!values)
2654f7df2e56Smrg            goto allocFailure;
2655f7df2e56Smrg    }
2656f7df2e56Smrg    if (req->present & XkbVirtualModsMask)
2657f7df2e56Smrg        values = SetVirtualMods(xkbi, req, (CARD8 *) values, &change);
2658f7df2e56Smrg    if (req->present & XkbExplicitComponentsMask)
2659f7df2e56Smrg        values = SetKeyExplicit(xkbi, req, (CARD8 *) values, &change);
2660f7df2e56Smrg    if (req->present & XkbModifierMapMask)
2661f7df2e56Smrg        values = SetModifierMap(xkbi, req, (CARD8 *) values, &change);
2662f7df2e56Smrg    if (req->present & XkbVirtualModMapMask)
2663f7df2e56Smrg        values =
2664f7df2e56Smrg            SetVirtualModMap(xkbi, req, (xkbVModMapWireDesc *) values, &change);
2665f7df2e56Smrg    if (((values - ((char *) req)) / 4) != req->length) {
2666f7df2e56Smrg        ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after set)\n");
2667f7df2e56Smrg        client->errorValue = values - ((char *) &req[1]);
2668f7df2e56Smrg        return BadLength;
2669f7df2e56Smrg    }
2670f7df2e56Smrg    if (req->flags & XkbSetMapRecomputeActions) {
2671f7df2e56Smrg        KeyCode first, last, firstMM, lastMM;
2672f7df2e56Smrg
2673f7df2e56Smrg        if (change.map.num_key_syms > 0) {
2674f7df2e56Smrg            first = change.map.first_key_sym;
2675f7df2e56Smrg            last = first + change.map.num_key_syms - 1;
2676f7df2e56Smrg        }
2677f7df2e56Smrg        else
2678f7df2e56Smrg            first = last = 0;
2679f7df2e56Smrg        if (change.map.num_modmap_keys > 0) {
2680f7df2e56Smrg            firstMM = change.map.first_modmap_key;
26817e31ba66Smrg            lastMM = firstMM + change.map.num_modmap_keys - 1;
2682f7df2e56Smrg        }
2683f7df2e56Smrg        else
2684f7df2e56Smrg            firstMM = lastMM = 0;
2685f7df2e56Smrg        if ((last > 0) && (lastMM > 0)) {
2686f7df2e56Smrg            if (firstMM < first)
2687f7df2e56Smrg                first = firstMM;
2688f7df2e56Smrg            if (lastMM > last)
2689f7df2e56Smrg                last = lastMM;
2690f7df2e56Smrg        }
2691f7df2e56Smrg        else if (lastMM > 0) {
2692f7df2e56Smrg            first = firstMM;
2693f7df2e56Smrg            last = lastMM;
2694f7df2e56Smrg        }
2695f7df2e56Smrg        if (last > 0) {
2696f7df2e56Smrg            unsigned check = 0;
2697f7df2e56Smrg
2698f7df2e56Smrg            XkbUpdateActions(dev, first, (last - first + 1), &change, &check,
2699f7df2e56Smrg                             &cause);
2700f7df2e56Smrg            if (check)
2701f7df2e56Smrg                XkbCheckSecondaryEffects(xkbi, check, &change, &cause);
2702f7df2e56Smrg        }
270305b261ecSmrg    }
270405b261ecSmrg    if (!sentNKN)
2705f7df2e56Smrg        XkbSendNotification(dev, &change, &cause);
270605b261ecSmrg
27074642e01fSmrg    return Success;
2708f7df2e56Smrg allocFailure:
270905b261ecSmrg    return BadAlloc;
271005b261ecSmrg}
271105b261ecSmrg
27124642e01fSmrgint
27134642e01fSmrgProcXkbSetMap(ClientPtr client)
27144642e01fSmrg{
27155a112b11Smrg    DeviceIntPtr dev, master;
2716f7df2e56Smrg    char *tmp;
2717f7df2e56Smrg    int rc;
27184642e01fSmrg
27194642e01fSmrg    REQUEST(xkbSetMapReq);
27204642e01fSmrg    REQUEST_AT_LEAST_SIZE(xkbSetMapReq);
27214642e01fSmrg
2722f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
2723f7df2e56Smrg        return BadAccess;
27244642e01fSmrg
27254642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
2726f7df2e56Smrg    CHK_MASK_LEGAL(0x01, stuff->present, XkbAllMapComponentsMask);
27274642e01fSmrg
2728806e81e9Smrg    /* first verify the request length carefully */
2729806e81e9Smrg    rc = _XkbSetMapCheckLength(stuff);
2730806e81e9Smrg    if (rc != Success)
2731806e81e9Smrg        return rc;
2732806e81e9Smrg
2733f7df2e56Smrg    tmp = (char *) &stuff[1];
27344642e01fSmrg
27354642e01fSmrg    /* Check if we can to the SetMap on the requested device. If this
27364642e01fSmrg       succeeds, do the same thing for all extension devices (if needed).
27374642e01fSmrg       If any of them fails, fail.  */
27385a112b11Smrg    rc = _XkbSetMapChecks(client, dev, stuff, tmp, TRUE);
27394642e01fSmrg
27404642e01fSmrg    if (rc != Success)
27414642e01fSmrg        return rc;
27424642e01fSmrg
27435a112b11Smrg    master = GetMaster(dev, MASTER_KEYBOARD);
27447e31ba66Smrg
2745f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
27464642e01fSmrg        DeviceIntPtr other;
2747f7df2e56Smrg
2748f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
2749f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
2750f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
2751f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
2752f7df2e56Smrg                              DixManageAccess);
2753f7df2e56Smrg                if (rc == Success) {
27545a112b11Smrg                    rc = _XkbSetMapChecks(client, other, stuff, tmp, FALSE);
27554642e01fSmrg                    if (rc != Success)
27564642e01fSmrg                        return rc;
27574642e01fSmrg                }
27584642e01fSmrg            }
27594642e01fSmrg        }
27607e31ba66Smrg    } else {
27617e31ba66Smrg        DeviceIntPtr other;
27627e31ba66Smrg
27637e31ba66Smrg        for (other = inputInfo.devices; other; other = other->next) {
27647e31ba66Smrg            if (other != dev && GetMaster(other, MASTER_KEYBOARD) != dev &&
27657e31ba66Smrg                (other != master || dev != master->lastSlave))
27667e31ba66Smrg                continue;
27677e31ba66Smrg
27685a112b11Smrg            rc = _XkbSetMapChecks(client, other, stuff, tmp, FALSE);
27697e31ba66Smrg            if (rc != Success)
27707e31ba66Smrg                return rc;
27717e31ba66Smrg        }
27724642e01fSmrg    }
27734642e01fSmrg
27747e31ba66Smrg    /* We know now that we will succeed with the SetMap. In theory anyway. */
27754642e01fSmrg    rc = _XkbSetMap(client, dev, stuff, tmp);
27764642e01fSmrg    if (rc != Success)
27774642e01fSmrg        return rc;
27784642e01fSmrg
2779f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
27804642e01fSmrg        DeviceIntPtr other;
2781f7df2e56Smrg
2782f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
2783f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
2784f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
2785f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
2786f7df2e56Smrg                              DixManageAccess);
27874642e01fSmrg                if (rc == Success)
27884642e01fSmrg                    _XkbSetMap(client, other, stuff, tmp);
27894642e01fSmrg                /* ignore rc. if the SetMap failed although the check above
27904642e01fSmrg                   reported true there isn't much we can do. we still need to
27914642e01fSmrg                   set all other devices, hoping that at least they stay in
27924642e01fSmrg                   sync. */
27934642e01fSmrg            }
27944642e01fSmrg        }
27957e31ba66Smrg    } else {
27967e31ba66Smrg        DeviceIntPtr other;
27977e31ba66Smrg
27987e31ba66Smrg        for (other = inputInfo.devices; other; other = other->next) {
27997e31ba66Smrg            if (other != dev && GetMaster(other, MASTER_KEYBOARD) != dev &&
28007e31ba66Smrg                (other != master || dev != master->lastSlave))
28017e31ba66Smrg                continue;
28027e31ba66Smrg
28037e31ba66Smrg            _XkbSetMap(client, other, stuff, tmp); //ignore rc
28047e31ba66Smrg        }
28054642e01fSmrg    }
28064642e01fSmrg
28076747b715Smrg    return Success;
28084642e01fSmrg}
28094642e01fSmrg
281005b261ecSmrg/***====================================================================***/
281105b261ecSmrg
281205b261ecSmrgstatic Status
2813f7df2e56SmrgXkbComputeGetCompatMapReplySize(XkbCompatMapPtr compat,
2814f7df2e56Smrg                                xkbGetCompatMapReply * rep)
281505b261ecSmrg{
2816f7df2e56Smrg    unsigned size, nGroups;
2817f7df2e56Smrg
2818f7df2e56Smrg    nGroups = 0;
2819f7df2e56Smrg    if (rep->groups != 0) {
2820f7df2e56Smrg        register int i, bit;
2821f7df2e56Smrg
2822f7df2e56Smrg        for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2823f7df2e56Smrg            if (rep->groups & bit)
2824f7df2e56Smrg                nGroups++;
2825f7df2e56Smrg        }
2826f7df2e56Smrg    }
2827f7df2e56Smrg    size = nGroups * SIZEOF(xkbModsWireDesc);
2828f7df2e56Smrg    size += (rep->nSI * SIZEOF(xkbSymInterpretWireDesc));
2829f7df2e56Smrg    rep->length = size / 4;
283005b261ecSmrg    return Success;
283105b261ecSmrg}
283205b261ecSmrg
283305b261ecSmrgstatic int
2834f7df2e56SmrgXkbSendCompatMap(ClientPtr client,
2835f7df2e56Smrg                 XkbCompatMapPtr compat, xkbGetCompatMapReply * rep)
283605b261ecSmrg{
2837f7df2e56Smrg    char *data;
2838f7df2e56Smrg    int size;
2839f7df2e56Smrg
2840f7df2e56Smrg    if (rep->length > 0) {
2841f7df2e56Smrg        data = xallocarray(rep->length, 4);
2842f7df2e56Smrg        if (data) {
2843f7df2e56Smrg            register unsigned i, bit;
2844f7df2e56Smrg            xkbModsWireDesc *grp;
2845f7df2e56Smrg            XkbSymInterpretPtr sym = &compat->sym_interpret[rep->firstSI];
2846f7df2e56Smrg            xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *) data;
2847f7df2e56Smrg
2848f7df2e56Smrg            size = rep->length * 4;
2849f7df2e56Smrg
2850f7df2e56Smrg            for (i = 0; i < rep->nSI; i++, sym++, wire++) {
2851f7df2e56Smrg                wire->sym = sym->sym;
2852f7df2e56Smrg                wire->mods = sym->mods;
2853f7df2e56Smrg                wire->match = sym->match;
2854f7df2e56Smrg                wire->virtualMod = sym->virtual_mod;
2855f7df2e56Smrg                wire->flags = sym->flags;
2856f7df2e56Smrg                memcpy((char *) &wire->act, (char *) &sym->act,
2857f7df2e56Smrg                       sz_xkbActionWireDesc);
2858f7df2e56Smrg                if (client->swapped) {
2859f7df2e56Smrg                    swapl(&wire->sym);
2860f7df2e56Smrg                }
2861f7df2e56Smrg            }
2862f7df2e56Smrg            if (rep->groups) {
2863f7df2e56Smrg                grp = (xkbModsWireDesc *) wire;
2864f7df2e56Smrg                for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2865f7df2e56Smrg                    if (rep->groups & bit) {
2866f7df2e56Smrg                        grp->mask = compat->groups[i].mask;
2867f7df2e56Smrg                        grp->realMods = compat->groups[i].real_mods;
2868f7df2e56Smrg                        grp->virtualMods = compat->groups[i].vmods;
2869f7df2e56Smrg                        if (client->swapped) {
2870f7df2e56Smrg                            swaps(&grp->virtualMods);
2871f7df2e56Smrg                        }
2872f7df2e56Smrg                        grp++;
2873f7df2e56Smrg                    }
2874f7df2e56Smrg                }
2875f7df2e56Smrg                wire = (xkbSymInterpretWireDesc *) grp;
2876f7df2e56Smrg            }
2877f7df2e56Smrg        }
2878f7df2e56Smrg        else
2879f7df2e56Smrg            return BadAlloc;
2880f7df2e56Smrg    }
2881f7df2e56Smrg    else
2882f7df2e56Smrg        data = NULL;
288305b261ecSmrg
288405b261ecSmrg    if (client->swapped) {
2885f7df2e56Smrg        swaps(&rep->sequenceNumber);
2886f7df2e56Smrg        swapl(&rep->length);
2887f7df2e56Smrg        swaps(&rep->firstSI);
2888f7df2e56Smrg        swaps(&rep->nSI);
2889f7df2e56Smrg        swaps(&rep->nTotalSI);
289005b261ecSmrg    }
289105b261ecSmrg
2892f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetCompatMapReply), rep);
289305b261ecSmrg    if (data) {
2894f7df2e56Smrg        WriteToClient(client, size, data);
2895f7df2e56Smrg        free((char *) data);
289605b261ecSmrg    }
28976747b715Smrg    return Success;
289805b261ecSmrg}
289905b261ecSmrg
290005b261ecSmrgint
290105b261ecSmrgProcXkbGetCompatMap(ClientPtr client)
290205b261ecSmrg{
2903f7df2e56Smrg    xkbGetCompatMapReply rep;
2904f7df2e56Smrg    DeviceIntPtr dev;
2905f7df2e56Smrg    XkbDescPtr xkb;
2906f7df2e56Smrg    XkbCompatMapPtr compat;
290705b261ecSmrg
290805b261ecSmrg    REQUEST(xkbGetCompatMapReq);
290905b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetCompatMapReq);
291005b261ecSmrg
2911f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
2912f7df2e56Smrg        return BadAccess;
291305b261ecSmrg
29144642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
291505b261ecSmrg
291605b261ecSmrg    xkb = dev->key->xkbInfo->desc;
2917f7df2e56Smrg    compat = xkb->compat;
291805b261ecSmrg
2919f7df2e56Smrg    rep = (xkbGetCompatMapReply) {
2920f7df2e56Smrg        .type = X_Reply,
2921f7df2e56Smrg        .sequenceNumber = client->sequence,
2922f7df2e56Smrg        .length = 0,
2923f7df2e56Smrg        .deviceID = dev->id,
2924f7df2e56Smrg        .firstSI = stuff->firstSI,
2925f7df2e56Smrg        .nSI = stuff->nSI
2926f7df2e56Smrg    };
292705b261ecSmrg    if (stuff->getAllSI) {
2928f7df2e56Smrg        rep.firstSI = 0;
2929f7df2e56Smrg        rep.nSI = compat->num_si;
293005b261ecSmrg    }
2931f7df2e56Smrg    else if ((((unsigned) stuff->nSI) > 0) &&
2932f7df2e56Smrg             ((unsigned) (stuff->firstSI + stuff->nSI - 1) >= compat->num_si)) {
2933f7df2e56Smrg        client->errorValue = _XkbErrCode2(0x05, compat->num_si);
2934f7df2e56Smrg        return BadValue;
293505b261ecSmrg    }
293605b261ecSmrg    rep.nTotalSI = compat->num_si;
2937f7df2e56Smrg    rep.groups = stuff->groups;
2938f7df2e56Smrg    XkbComputeGetCompatMapReplySize(compat, &rep);
2939f7df2e56Smrg    return XkbSendCompatMap(client, compat, &rep);
294005b261ecSmrg}
294105b261ecSmrg
29424642e01fSmrg/**
29434642e01fSmrg * Apply the given request on the given device.
29446747b715Smrg * If dryRun is TRUE, then value checks are performed, but the device isn't
29454642e01fSmrg * modified.
29464642e01fSmrg */
29474642e01fSmrgstatic int
29484642e01fSmrg_XkbSetCompatMap(ClientPtr client, DeviceIntPtr dev,
2949f7df2e56Smrg                 xkbSetCompatMapReq * req, char *data, BOOL dryRun)
295005b261ecSmrg{
2951f7df2e56Smrg    XkbSrvInfoPtr xkbi;
2952f7df2e56Smrg    XkbDescPtr xkb;
2953f7df2e56Smrg    XkbCompatMapPtr compat;
2954f7df2e56Smrg    int nGroups;
2955f7df2e56Smrg    unsigned i, bit;
295605b261ecSmrg
295705b261ecSmrg    xkbi = dev->key->xkbInfo;
29584642e01fSmrg    xkb = xkbi->desc;
29594642e01fSmrg    compat = xkb->compat;
29604642e01fSmrg
2961f7df2e56Smrg    if ((req->nSI > 0) || (req->truncateSI)) {
2962f7df2e56Smrg        xkbSymInterpretWireDesc *wire;
2963f7df2e56Smrg
2964f7df2e56Smrg        if (req->firstSI > compat->num_si) {
2965f7df2e56Smrg            client->errorValue = _XkbErrCode2(0x02, compat->num_si);
2966f7df2e56Smrg            return BadValue;
2967f7df2e56Smrg        }
2968f7df2e56Smrg        wire = (xkbSymInterpretWireDesc *) data;
2969f7df2e56Smrg        wire += req->nSI;
2970f7df2e56Smrg        data = (char *) wire;
297105b261ecSmrg    }
29724642e01fSmrg
2973f7df2e56Smrg    nGroups = 0;
2974f7df2e56Smrg    if (req->groups != 0) {
2975f7df2e56Smrg        for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2976f7df2e56Smrg            if (req->groups & bit)
2977f7df2e56Smrg                nGroups++;
2978f7df2e56Smrg        }
297905b261ecSmrg    }
2980f7df2e56Smrg    data += nGroups * SIZEOF(xkbModsWireDesc);
2981f7df2e56Smrg    if (((data - ((char *) req)) / 4) != req->length) {
2982f7df2e56Smrg        return BadLength;
298305b261ecSmrg    }
29844642e01fSmrg
29854642e01fSmrg    /* Done all the checks we can do */
29864642e01fSmrg    if (dryRun)
29874642e01fSmrg        return Success;
29884642e01fSmrg
2989f7df2e56Smrg    data = (char *) &req[1];
2990f7df2e56Smrg    if (req->nSI > 0) {
2991f7df2e56Smrg        xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *) data;
2992f7df2e56Smrg        XkbSymInterpretPtr sym;
2993f7df2e56Smrg        unsigned int skipped = 0;
2994f7df2e56Smrg
299559ca590cSmrg        if ((unsigned) (req->firstSI + req->nSI) > compat->size_si) {
299659ca590cSmrg            compat->num_si = compat->size_si = req->firstSI + req->nSI;
2997f7df2e56Smrg            compat->sym_interpret = reallocarray(compat->sym_interpret,
299859ca590cSmrg                                                 compat->size_si,
2999f7df2e56Smrg                                                 sizeof(XkbSymInterpretRec));
3000f7df2e56Smrg            if (!compat->sym_interpret) {
300159ca590cSmrg                compat->num_si = compat->size_si = 0;
3002f7df2e56Smrg                return BadAlloc;
3003f7df2e56Smrg            }
3004f7df2e56Smrg        }
3005f7df2e56Smrg        else if (req->truncateSI) {
3006f7df2e56Smrg            compat->num_si = req->firstSI + req->nSI;
3007f7df2e56Smrg        }
3008f7df2e56Smrg        sym = &compat->sym_interpret[req->firstSI];
3009f7df2e56Smrg        for (i = 0; i < req->nSI; i++, wire++) {
3010f7df2e56Smrg            if (client->swapped) {
3011f7df2e56Smrg                swapl(&wire->sym);
3012f7df2e56Smrg            }
3013f7df2e56Smrg            if (wire->sym == NoSymbol && wire->match == XkbSI_AnyOfOrNone &&
3014f7df2e56Smrg                (wire->mods & 0xff) == 0xff &&
3015f7df2e56Smrg                wire->act.type == XkbSA_XFree86Private) {
3016f7df2e56Smrg                ErrorF("XKB: Skipping broken Any+AnyOfOrNone(All) -> Private "
3017f7df2e56Smrg                       "action from client\n");
3018f7df2e56Smrg                skipped++;
3019f7df2e56Smrg                continue;
3020f7df2e56Smrg            }
3021f7df2e56Smrg            sym->sym = wire->sym;
3022f7df2e56Smrg            sym->mods = wire->mods;
3023f7df2e56Smrg            sym->match = wire->match;
3024f7df2e56Smrg            sym->flags = wire->flags;
3025f7df2e56Smrg            sym->virtual_mod = wire->virtualMod;
3026f7df2e56Smrg            memcpy((char *) &sym->act, (char *) &wire->act,
3027f7df2e56Smrg                   SIZEOF(xkbActionWireDesc));
3028f7df2e56Smrg            sym++;
3029f7df2e56Smrg        }
3030f7df2e56Smrg        if (skipped) {
3031f7df2e56Smrg            if (req->firstSI + req->nSI < compat->num_si)
3032f7df2e56Smrg                memmove(sym, sym + skipped,
3033f7df2e56Smrg                        (compat->num_si - req->firstSI - req->nSI) *
3034f7df2e56Smrg                        sizeof(*sym));
3035f7df2e56Smrg            compat->num_si -= skipped;
3036f7df2e56Smrg        }
3037f7df2e56Smrg        data = (char *) wire;
303805b261ecSmrg    }
30394642e01fSmrg    else if (req->truncateSI) {
3040f7df2e56Smrg        compat->num_si = req->firstSI;
3041f7df2e56Smrg    }
3042f7df2e56Smrg
3043f7df2e56Smrg    if (req->groups != 0) {
3044f7df2e56Smrg        xkbModsWireDesc *wire = (xkbModsWireDesc *) data;
3045f7df2e56Smrg
3046f7df2e56Smrg        for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
3047f7df2e56Smrg            if (req->groups & bit) {
3048f7df2e56Smrg                if (client->swapped) {
3049f7df2e56Smrg                    swaps(&wire->virtualMods);
3050f7df2e56Smrg                }
3051f7df2e56Smrg                compat->groups[i].mask = wire->realMods;
3052f7df2e56Smrg                compat->groups[i].real_mods = wire->realMods;
3053f7df2e56Smrg                compat->groups[i].vmods = wire->virtualMods;
3054f7df2e56Smrg                if (wire->virtualMods != 0) {
3055f7df2e56Smrg                    unsigned tmp;
3056f7df2e56Smrg
3057f7df2e56Smrg                    tmp = XkbMaskForVMask(xkb, wire->virtualMods);
3058f7df2e56Smrg                    compat->groups[i].mask |= tmp;
3059f7df2e56Smrg                }
3060f7df2e56Smrg                data += SIZEOF(xkbModsWireDesc);
3061f7df2e56Smrg                wire = (xkbModsWireDesc *) data;
3062f7df2e56Smrg            }
3063f7df2e56Smrg        }
3064f7df2e56Smrg    }
3065f7df2e56Smrg    i = XkbPaddedSize((data - ((char *) req)));
3066f7df2e56Smrg    if ((i / 4) != req->length) {
3067f7df2e56Smrg        ErrorF("[xkb] Internal length error on read in _XkbSetCompatMap\n");
3068f7df2e56Smrg        return BadLength;
306905b261ecSmrg    }
30704642e01fSmrg
307105b261ecSmrg    if (dev->xkb_interest) {
3072f7df2e56Smrg        xkbCompatMapNotify ev;
3073f7df2e56Smrg
3074f7df2e56Smrg        ev.deviceID = dev->id;
3075f7df2e56Smrg        ev.changedGroups = req->groups;
3076f7df2e56Smrg        ev.firstSI = req->firstSI;
3077f7df2e56Smrg        ev.nSI = req->nSI;
3078f7df2e56Smrg        ev.nTotalSI = compat->num_si;
3079f7df2e56Smrg        XkbSendCompatMapNotify(dev, &ev);
308005b261ecSmrg    }
308105b261ecSmrg
30824642e01fSmrg    if (req->recomputeActions) {
3083f7df2e56Smrg        XkbChangesRec change;
3084f7df2e56Smrg        unsigned check;
3085f7df2e56Smrg        XkbEventCauseRec cause;
3086f7df2e56Smrg
3087f7df2e56Smrg        XkbSetCauseXkbReq(&cause, X_kbSetCompatMap, client);
3088f7df2e56Smrg        memset(&change, 0, sizeof(XkbChangesRec));
3089f7df2e56Smrg        XkbUpdateActions(dev, xkb->min_key_code, XkbNumKeys(xkb), &change,
3090f7df2e56Smrg                         &check, &cause);
3091f7df2e56Smrg        if (check)
3092f7df2e56Smrg            XkbCheckSecondaryEffects(xkbi, check, &change, &cause);
3093f7df2e56Smrg        XkbSendNotification(dev, &change, &cause);
309405b261ecSmrg    }
30954642e01fSmrg    return Success;
30964642e01fSmrg}
30974642e01fSmrg
30984642e01fSmrgint
30994642e01fSmrgProcXkbSetCompatMap(ClientPtr client)
31004642e01fSmrg{
3101f7df2e56Smrg    DeviceIntPtr dev;
3102f7df2e56Smrg    char *data;
3103f7df2e56Smrg    int rc;
31044642e01fSmrg
31054642e01fSmrg    REQUEST(xkbSetCompatMapReq);
31064642e01fSmrg    REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq);
31074642e01fSmrg
3108f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
3109f7df2e56Smrg        return BadAccess;
31104642e01fSmrg
31114642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
31124642e01fSmrg
3113f7df2e56Smrg    data = (char *) &stuff[1];
31144642e01fSmrg
31154642e01fSmrg    /* check first using a dry-run */
31164642e01fSmrg    rc = _XkbSetCompatMap(client, dev, stuff, data, TRUE);
31174642e01fSmrg    if (rc != Success)
31184642e01fSmrg        return rc;
3119f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
31204642e01fSmrg        DeviceIntPtr other;
3121f7df2e56Smrg
3122f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
3123f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
3124f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
3125f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
3126f7df2e56Smrg                              DixManageAccess);
3127f7df2e56Smrg                if (rc == Success) {
31284642e01fSmrg                    /* dry-run */
31294642e01fSmrg                    rc = _XkbSetCompatMap(client, other, stuff, data, TRUE);
31304642e01fSmrg                    if (rc != Success)
31314642e01fSmrg                        return rc;
31324642e01fSmrg                }
31334642e01fSmrg            }
31344642e01fSmrg        }
31354642e01fSmrg    }
31364642e01fSmrg
31374642e01fSmrg    /* Yay, the dry-runs succeed. Let's apply */
31384642e01fSmrg    rc = _XkbSetCompatMap(client, dev, stuff, data, FALSE);
31394642e01fSmrg    if (rc != Success)
31404642e01fSmrg        return rc;
3141f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
31424642e01fSmrg        DeviceIntPtr other;
3143f7df2e56Smrg
3144f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
3145f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
3146f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
3147f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
3148f7df2e56Smrg                              DixManageAccess);
3149f7df2e56Smrg                if (rc == Success) {
31504642e01fSmrg                    rc = _XkbSetCompatMap(client, other, stuff, data, FALSE);
31514642e01fSmrg                    if (rc != Success)
31524642e01fSmrg                        return rc;
31534642e01fSmrg                }
31544642e01fSmrg            }
31554642e01fSmrg        }
31564642e01fSmrg    }
31574642e01fSmrg
31586747b715Smrg    return Success;
315905b261ecSmrg}
316005b261ecSmrg
316105b261ecSmrg/***====================================================================***/
316205b261ecSmrg
316305b261ecSmrgint
316405b261ecSmrgProcXkbGetIndicatorState(ClientPtr client)
316505b261ecSmrg{
3166f7df2e56Smrg    xkbGetIndicatorStateReply rep;
3167f7df2e56Smrg    XkbSrvLedInfoPtr sli;
3168f7df2e56Smrg    DeviceIntPtr dev;
316905b261ecSmrg
317005b261ecSmrg    REQUEST(xkbGetIndicatorStateReq);
317105b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq);
317205b261ecSmrg
3173f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
3174f7df2e56Smrg        return BadAccess;
317505b261ecSmrg
31764642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
317705b261ecSmrg
3178f7df2e56Smrg    sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
3179f7df2e56Smrg                            XkbXI_IndicatorStateMask);
318005b261ecSmrg    if (!sli)
3181f7df2e56Smrg        return BadAlloc;
318205b261ecSmrg
3183f7df2e56Smrg    rep = (xkbGetIndicatorStateReply) {
3184f7df2e56Smrg        .type = X_Reply,
3185f7df2e56Smrg        .deviceID = dev->id,
3186f7df2e56Smrg        .sequenceNumber = client->sequence,
3187f7df2e56Smrg        .length = 0,
3188f7df2e56Smrg        .state = sli->effectiveState
3189f7df2e56Smrg    };
319005b261ecSmrg
319105b261ecSmrg    if (client->swapped) {
3192f7df2e56Smrg        swaps(&rep.sequenceNumber);
3193f7df2e56Smrg        swapl(&rep.state);
319405b261ecSmrg    }
3195f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetIndicatorStateReply), &rep);
31966747b715Smrg    return Success;
319705b261ecSmrg}
319805b261ecSmrg
319905b261ecSmrg/***====================================================================***/
320005b261ecSmrg
320105b261ecSmrgstatic Status
3202f7df2e56SmrgXkbComputeGetIndicatorMapReplySize(XkbIndicatorPtr indicators,
3203f7df2e56Smrg                                   xkbGetIndicatorMapReply * rep)
320405b261ecSmrg{
3205f7df2e56Smrg    register int i, bit;
3206f7df2e56Smrg    int nIndicators;
320705b261ecSmrg
320805b261ecSmrg    rep->realIndicators = indicators->phys_indicators;
3209f7df2e56Smrg    for (i = nIndicators = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3210f7df2e56Smrg        if (rep->which & bit)
3211f7df2e56Smrg            nIndicators++;
321205b261ecSmrg    }
3213f7df2e56Smrg    rep->length = (nIndicators * SIZEOF(xkbIndicatorMapWireDesc)) / 4;
3214f7df2e56Smrg    rep->nIndicators = nIndicators;
321505b261ecSmrg    return Success;
321605b261ecSmrg}
321705b261ecSmrg
321805b261ecSmrgstatic int
3219f7df2e56SmrgXkbSendIndicatorMap(ClientPtr client,
3220f7df2e56Smrg                    XkbIndicatorPtr indicators, xkbGetIndicatorMapReply * rep)
322105b261ecSmrg{
3222f7df2e56Smrg    int length;
3223f7df2e56Smrg    CARD8 *map;
3224f7df2e56Smrg    register int i;
3225f7df2e56Smrg    register unsigned bit;
3226f7df2e56Smrg
3227f7df2e56Smrg    if (rep->length > 0) {
3228f7df2e56Smrg        CARD8 *to;
3229f7df2e56Smrg
3230f7df2e56Smrg        to = map = xallocarray(rep->length, 4);
3231f7df2e56Smrg        if (map) {
3232f7df2e56Smrg            xkbIndicatorMapWireDesc *wire = (xkbIndicatorMapWireDesc *) to;
3233f7df2e56Smrg
3234f7df2e56Smrg            length = rep->length * 4;
3235f7df2e56Smrg
3236f7df2e56Smrg            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3237f7df2e56Smrg                if (rep->which & bit) {
3238f7df2e56Smrg                    wire->flags = indicators->maps[i].flags;
3239f7df2e56Smrg                    wire->whichGroups = indicators->maps[i].which_groups;
3240f7df2e56Smrg                    wire->groups = indicators->maps[i].groups;
3241f7df2e56Smrg                    wire->whichMods = indicators->maps[i].which_mods;
3242f7df2e56Smrg                    wire->mods = indicators->maps[i].mods.mask;
3243f7df2e56Smrg                    wire->realMods = indicators->maps[i].mods.real_mods;
3244f7df2e56Smrg                    wire->virtualMods = indicators->maps[i].mods.vmods;
3245f7df2e56Smrg                    wire->ctrls = indicators->maps[i].ctrls;
3246f7df2e56Smrg                    if (client->swapped) {
3247f7df2e56Smrg                        swaps(&wire->virtualMods);
3248f7df2e56Smrg                        swapl(&wire->ctrls);
3249f7df2e56Smrg                    }
3250f7df2e56Smrg                    wire++;
3251f7df2e56Smrg                }
3252f7df2e56Smrg            }
3253f7df2e56Smrg            to = (CARD8 *) wire;
3254f7df2e56Smrg            if ((to - map) != length) {
3255f7df2e56Smrg                client->errorValue = _XkbErrCode2(0xff, length);
3256f7df2e56Smrg                free(map);
3257f7df2e56Smrg                return BadLength;
3258f7df2e56Smrg            }
3259f7df2e56Smrg        }
3260f7df2e56Smrg        else
3261f7df2e56Smrg            return BadAlloc;
3262f7df2e56Smrg    }
3263f7df2e56Smrg    else
3264f7df2e56Smrg        map = NULL;
326505b261ecSmrg    if (client->swapped) {
3266f7df2e56Smrg        swaps(&rep->sequenceNumber);
3267f7df2e56Smrg        swapl(&rep->length);
3268f7df2e56Smrg        swapl(&rep->which);
3269f7df2e56Smrg        swapl(&rep->realIndicators);
327005b261ecSmrg    }
3271f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetIndicatorMapReply), rep);
327205b261ecSmrg    if (map) {
3273f7df2e56Smrg        WriteToClient(client, length, map);
3274f7df2e56Smrg        free((char *) map);
327505b261ecSmrg    }
32766747b715Smrg    return Success;
327705b261ecSmrg}
327805b261ecSmrg
327905b261ecSmrgint
328005b261ecSmrgProcXkbGetIndicatorMap(ClientPtr client)
328105b261ecSmrg{
3282f7df2e56Smrg    xkbGetIndicatorMapReply rep;
3283f7df2e56Smrg    DeviceIntPtr dev;
3284f7df2e56Smrg    XkbDescPtr xkb;
3285f7df2e56Smrg    XkbIndicatorPtr leds;
328605b261ecSmrg
328705b261ecSmrg    REQUEST(xkbGetIndicatorMapReq);
328805b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq);
328905b261ecSmrg
3290f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
3291f7df2e56Smrg        return BadAccess;
329205b261ecSmrg
32934642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
329405b261ecSmrg
3295f7df2e56Smrg    xkb = dev->key->xkbInfo->desc;
3296f7df2e56Smrg    leds = xkb->indicators;
3297f7df2e56Smrg
3298f7df2e56Smrg    rep = (xkbGetIndicatorMapReply) {
3299f7df2e56Smrg        .type = X_Reply,
3300f7df2e56Smrg        .deviceID = dev->id,
3301f7df2e56Smrg        .sequenceNumber = client->sequence,
3302f7df2e56Smrg        .length = 0,
3303f7df2e56Smrg        .which = stuff->which
3304f7df2e56Smrg    };
3305f7df2e56Smrg    XkbComputeGetIndicatorMapReplySize(leds, &rep);
3306f7df2e56Smrg    return XkbSendIndicatorMap(client, leds, &rep);
330705b261ecSmrg}
330805b261ecSmrg
33094642e01fSmrg/**
33104642e01fSmrg * Apply the given map to the given device. Which specifies which components
33114642e01fSmrg * to apply.
33124642e01fSmrg */
33134642e01fSmrgstatic int
33144642e01fSmrg_XkbSetIndicatorMap(ClientPtr client, DeviceIntPtr dev,
3315f7df2e56Smrg                    int which, xkbIndicatorMapWireDesc * desc)
33164642e01fSmrg{
3317f7df2e56Smrg    XkbSrvInfoPtr xkbi;
3318f7df2e56Smrg    XkbSrvLedInfoPtr sli;
3319f7df2e56Smrg    XkbEventCauseRec cause;
3320f7df2e56Smrg    int i, bit;
33214642e01fSmrg
33224642e01fSmrg    xkbi = dev->key->xkbInfo;
33234642e01fSmrg
3324f7df2e56Smrg    sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
3325f7df2e56Smrg                            XkbXI_IndicatorMapsMask);
33264642e01fSmrg    if (!sli)
3327f7df2e56Smrg        return BadAlloc;
33284642e01fSmrg
33294642e01fSmrg    for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3330f7df2e56Smrg        if (which & bit) {
3331f7df2e56Smrg            sli->maps[i].flags = desc->flags;
3332f7df2e56Smrg            sli->maps[i].which_groups = desc->whichGroups;
3333f7df2e56Smrg            sli->maps[i].groups = desc->groups;
3334f7df2e56Smrg            sli->maps[i].which_mods = desc->whichMods;
3335f7df2e56Smrg            sli->maps[i].mods.mask = desc->mods;
3336f7df2e56Smrg            sli->maps[i].mods.real_mods = desc->mods;
3337f7df2e56Smrg            sli->maps[i].mods.vmods = desc->virtualMods;
3338f7df2e56Smrg            sli->maps[i].ctrls = desc->ctrls;
3339f7df2e56Smrg            if (desc->virtualMods != 0) {
3340f7df2e56Smrg                unsigned tmp;
3341f7df2e56Smrg
3342f7df2e56Smrg                tmp = XkbMaskForVMask(xkbi->desc, desc->virtualMods);
3343f7df2e56Smrg                sli->maps[i].mods.mask = desc->mods | tmp;
3344f7df2e56Smrg            }
3345f7df2e56Smrg            desc++;
3346f7df2e56Smrg        }
3347f7df2e56Smrg    }
3348f7df2e56Smrg
3349f7df2e56Smrg    XkbSetCauseXkbReq(&cause, X_kbSetIndicatorMap, client);
3350f7df2e56Smrg    XkbApplyLedMapChanges(dev, sli, which, NULL, NULL, &cause);
33514642e01fSmrg
33524642e01fSmrg    return Success;
33534642e01fSmrg}
33544642e01fSmrg
335505b261ecSmrgint
335605b261ecSmrgProcXkbSetIndicatorMap(ClientPtr client)
335705b261ecSmrg{
3358f7df2e56Smrg    int i, bit;
3359f7df2e56Smrg    int nIndicators;
3360f7df2e56Smrg    DeviceIntPtr dev;
3361f7df2e56Smrg    xkbIndicatorMapWireDesc *from;
3362f7df2e56Smrg    int rc;
336305b261ecSmrg
336405b261ecSmrg    REQUEST(xkbSetIndicatorMapReq);
336505b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq);
336605b261ecSmrg
3367f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
3368f7df2e56Smrg        return BadAccess;
336905b261ecSmrg
33704642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
337105b261ecSmrg
3372f7df2e56Smrg    if (stuff->which == 0)
3373f7df2e56Smrg        return Success;
337405b261ecSmrg
3375f7df2e56Smrg    for (nIndicators = i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3376f7df2e56Smrg        if (stuff->which & bit)
3377f7df2e56Smrg            nIndicators++;
337805b261ecSmrg    }
3379f7df2e56Smrg    if (stuff->length != ((SIZEOF(xkbSetIndicatorMapReq) +
3380f7df2e56Smrg                           (nIndicators * SIZEOF(xkbIndicatorMapWireDesc))) /
3381f7df2e56Smrg                          4)) {
3382f7df2e56Smrg        return BadLength;
338305b261ecSmrg    }
338405b261ecSmrg
3385f7df2e56Smrg    from = (xkbIndicatorMapWireDesc *) &stuff[1];
3386f7df2e56Smrg    for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3387f7df2e56Smrg        if (stuff->which & bit) {
3388f7df2e56Smrg            if (client->swapped) {
3389f7df2e56Smrg                swaps(&from->virtualMods);
3390f7df2e56Smrg                swapl(&from->ctrls);
3391f7df2e56Smrg            }
3392f7df2e56Smrg            CHK_MASK_LEGAL(i, from->whichGroups, XkbIM_UseAnyGroup);
3393f7df2e56Smrg            CHK_MASK_LEGAL(i, from->whichMods, XkbIM_UseAnyMods);
3394f7df2e56Smrg            from++;
3395f7df2e56Smrg        }
339605b261ecSmrg    }
339705b261ecSmrg
3398f7df2e56Smrg    from = (xkbIndicatorMapWireDesc *) &stuff[1];
33994642e01fSmrg    rc = _XkbSetIndicatorMap(client, dev, stuff->which, from);
34004642e01fSmrg    if (rc != Success)
34014642e01fSmrg        return rc;
34024642e01fSmrg
3403f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
34044642e01fSmrg        DeviceIntPtr other;
3405f7df2e56Smrg
3406f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
3407f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
3408f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
3409f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
3410f7df2e56Smrg                              DixSetAttrAccess);
34114642e01fSmrg                if (rc == Success)
34124642e01fSmrg                    _XkbSetIndicatorMap(client, other, stuff->which, from);
34134642e01fSmrg            }
34144642e01fSmrg        }
341505b261ecSmrg    }
341605b261ecSmrg
34174642e01fSmrg    return Success;
341805b261ecSmrg}
341905b261ecSmrg
342005b261ecSmrg/***====================================================================***/
342105b261ecSmrg
342205b261ecSmrgint
342305b261ecSmrgProcXkbGetNamedIndicator(ClientPtr client)
342405b261ecSmrg{
3425f7df2e56Smrg    DeviceIntPtr dev;
3426f7df2e56Smrg    xkbGetNamedIndicatorReply rep;
3427f7df2e56Smrg    register int i = 0;
3428f7df2e56Smrg    XkbSrvLedInfoPtr sli;
3429f7df2e56Smrg    XkbIndicatorMapPtr map = NULL;
343005b261ecSmrg
343105b261ecSmrg    REQUEST(xkbGetNamedIndicatorReq);
343205b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq);
343305b261ecSmrg
3434f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
3435f7df2e56Smrg        return BadAccess;
343605b261ecSmrg
34374642e01fSmrg    CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
343805b261ecSmrg    CHK_ATOM_ONLY(stuff->indicator);
343905b261ecSmrg
3440f7df2e56Smrg    sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID, 0);
344105b261ecSmrg    if (!sli)
3442f7df2e56Smrg        return BadAlloc;
3443f7df2e56Smrg
3444f7df2e56Smrg    i = 0;
3445f7df2e56Smrg    map = NULL;
3446f7df2e56Smrg    if ((sli->names) && (sli->maps)) {
3447f7df2e56Smrg        for (i = 0; i < XkbNumIndicators; i++) {
3448f7df2e56Smrg            if (stuff->indicator == sli->names[i]) {
3449f7df2e56Smrg                map = &sli->maps[i];
345005b261ecSmrg                break;
345105b261ecSmrg            }
345205b261ecSmrg        }
345305b261ecSmrg    }
345405b261ecSmrg
3455f7df2e56Smrg    rep = (xkbGetNamedIndicatorReply) {
3456f7df2e56Smrg        .type = X_Reply,
3457f7df2e56Smrg        .sequenceNumber = client->sequence,
3458f7df2e56Smrg        .length = 0,
3459f7df2e56Smrg        .deviceID = dev->id,
3460f7df2e56Smrg        .indicator = stuff->indicator
3461f7df2e56Smrg    };
3462f7df2e56Smrg    if (map != NULL) {
3463f7df2e56Smrg        rep.found = TRUE;
3464f7df2e56Smrg        rep.on = ((sli->effectiveState & (1 << i)) != 0);
3465f7df2e56Smrg        rep.realIndicator = ((sli->physIndicators & (1 << i)) != 0);
3466f7df2e56Smrg        rep.ndx = i;
3467f7df2e56Smrg        rep.flags = map->flags;
3468f7df2e56Smrg        rep.whichGroups = map->which_groups;
3469f7df2e56Smrg        rep.groups = map->groups;
3470f7df2e56Smrg        rep.whichMods = map->which_mods;
3471f7df2e56Smrg        rep.mods = map->mods.mask;
3472f7df2e56Smrg        rep.realMods = map->mods.real_mods;
3473f7df2e56Smrg        rep.virtualMods = map->mods.vmods;
3474f7df2e56Smrg        rep.ctrls = map->ctrls;
3475f7df2e56Smrg        rep.supported = TRUE;
3476f7df2e56Smrg    }
3477f7df2e56Smrg    else {
3478f7df2e56Smrg        rep.found = FALSE;
3479f7df2e56Smrg        rep.on = FALSE;
3480f7df2e56Smrg        rep.realIndicator = FALSE;
3481f7df2e56Smrg        rep.ndx = XkbNoIndicator;
3482f7df2e56Smrg        rep.flags = 0;
3483f7df2e56Smrg        rep.whichGroups = 0;
3484f7df2e56Smrg        rep.groups = 0;
3485f7df2e56Smrg        rep.whichMods = 0;
3486f7df2e56Smrg        rep.mods = 0;
3487f7df2e56Smrg        rep.realMods = 0;
3488f7df2e56Smrg        rep.virtualMods = 0;
3489f7df2e56Smrg        rep.ctrls = 0;
3490f7df2e56Smrg        rep.supported = TRUE;
3491f7df2e56Smrg    }
3492f7df2e56Smrg    if (client->swapped) {
3493f7df2e56Smrg        swapl(&rep.length);
3494f7df2e56Smrg        swaps(&rep.sequenceNumber);
3495f7df2e56Smrg        swapl(&rep.indicator);
3496f7df2e56Smrg        swaps(&rep.virtualMods);
3497f7df2e56Smrg        swapl(&rep.ctrls);
3498f7df2e56Smrg    }
3499f7df2e56Smrg
3500f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetNamedIndicatorReply), &rep);
35016747b715Smrg    return Success;
350205b261ecSmrg}
350305b261ecSmrg
35044642e01fSmrg/**
35054642e01fSmrg * Find the IM on the device.
35064642e01fSmrg * Returns the map, or NULL if the map doesn't exist.
35074642e01fSmrg * If the return value is NULL, led_return is undefined. Otherwise, led_return
35084642e01fSmrg * is set to the led index of the map.
35094642e01fSmrg */
35104642e01fSmrgstatic XkbIndicatorMapPtr
3511f7df2e56Smrg_XkbFindNamedIndicatorMap(XkbSrvLedInfoPtr sli, Atom indicator, int *led_return)
35124642e01fSmrg{
3513f7df2e56Smrg    XkbIndicatorMapPtr map;
351405b261ecSmrg
35154642e01fSmrg    /* search for the right indicator */
35164642e01fSmrg    map = NULL;
351705b261ecSmrg    if (sli->names && sli->maps) {
3518f7df2e56Smrg        int led;
35196747b715Smrg
3520f7df2e56Smrg        for (led = 0; (led < XkbNumIndicators) && (map == NULL); led++) {
3521f7df2e56Smrg            if (sli->names[led] == indicator) {
3522f7df2e56Smrg                map = &sli->maps[led];
3523f7df2e56Smrg                *led_return = led;
3524f7df2e56Smrg                break;
3525f7df2e56Smrg            }
3526f7df2e56Smrg        }
352705b261ecSmrg    }
352805b261ecSmrg
35294642e01fSmrg    return map;
35304642e01fSmrg}
35314642e01fSmrg
35324642e01fSmrg/**
35336747b715Smrg * Creates an indicator map on the device. If dryRun is TRUE, it only checks
35344642e01fSmrg * if creation is possible, but doesn't actually create it.
35354642e01fSmrg */
35364642e01fSmrgstatic int
35374642e01fSmrg_XkbCreateIndicatorMap(DeviceIntPtr dev, Atom indicator,
35384642e01fSmrg                       int ledClass, int ledID,
3539f7df2e56Smrg                       XkbIndicatorMapPtr * map_return, int *led_return,
35404642e01fSmrg                       Bool dryRun)
35414642e01fSmrg{
3542f7df2e56Smrg    XkbSrvLedInfoPtr sli;
3543f7df2e56Smrg    XkbIndicatorMapPtr map;
3544f7df2e56Smrg    int led;
35454642e01fSmrg
35464642e01fSmrg    sli = XkbFindSrvLedInfo(dev, ledClass, ledID, XkbXI_IndicatorsMask);
35474642e01fSmrg    if (!sli)
35484642e01fSmrg        return BadAlloc;
35494642e01fSmrg
35504642e01fSmrg    map = _XkbFindNamedIndicatorMap(sli, indicator, &led);
35514642e01fSmrg
3552f7df2e56Smrg    if (!map) {
35534642e01fSmrg        /* find first unused indicator maps and assign the name to it */
3554f7df2e56Smrg        for (led = 0, map = NULL; (led < XkbNumIndicators) && (map == NULL);
3555f7df2e56Smrg             led++) {
35564642e01fSmrg            if ((sli->names) && (sli->maps) && (sli->names[led] == None) &&
3557f7df2e56Smrg                (!XkbIM_InUse(&sli->maps[led]))) {
35584642e01fSmrg                map = &sli->maps[led];
35594642e01fSmrg                if (!dryRun)
35604642e01fSmrg                    sli->names[led] = indicator;
35614642e01fSmrg                break;
35624642e01fSmrg            }
35634642e01fSmrg        }
35644642e01fSmrg    }
35654642e01fSmrg
35664642e01fSmrg    if (!map)
35674642e01fSmrg        return BadAlloc;
35684642e01fSmrg
35694642e01fSmrg    *led_return = led;
35704642e01fSmrg    *map_return = map;
35714642e01fSmrg    return Success;
35724642e01fSmrg}
35734642e01fSmrg
35744642e01fSmrgstatic int
35754642e01fSmrg_XkbSetNamedIndicator(ClientPtr client, DeviceIntPtr dev,
3576f7df2e56Smrg                      xkbSetNamedIndicatorReq * stuff)
35774642e01fSmrg{
3578f7df2e56Smrg    unsigned int extDevReason;
3579f7df2e56Smrg    unsigned int statec, namec, mapc;
3580f7df2e56Smrg    XkbSrvLedInfoPtr sli;
3581f7df2e56Smrg    int led = 0;
3582f7df2e56Smrg    XkbIndicatorMapPtr map;
3583f7df2e56Smrg    DeviceIntPtr kbd;
3584f7df2e56Smrg    XkbEventCauseRec cause;
3585f7df2e56Smrg    xkbExtensionDeviceNotify ed;
3586f7df2e56Smrg    XkbChangesRec changes;
3587f7df2e56Smrg    int rc;
35884642e01fSmrg
35894642e01fSmrg    rc = _XkbCreateIndicatorMap(dev, stuff->indicator, stuff->ledClass,
35904642e01fSmrg                                stuff->ledID, &map, &led, FALSE);
3591f7df2e56Smrg    if (rc != Success || !map)  /* oh-oh */
35924642e01fSmrg        return rc;
35934642e01fSmrg
35944642e01fSmrg    sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID,
35954642e01fSmrg                            XkbXI_IndicatorsMask);
35964642e01fSmrg    if (!sli)
35974642e01fSmrg        return BadAlloc;
35984642e01fSmrg
35994642e01fSmrg    namec = mapc = statec = 0;
36004642e01fSmrg    extDevReason = 0;
36014642e01fSmrg
3602f7df2e56Smrg    namec |= (1 << led);
36034642e01fSmrg    sli->namesPresent |= ((stuff->indicator != None) ? (1 << led) : 0);
36044642e01fSmrg    extDevReason |= XkbXI_IndicatorNamesMask;
36054642e01fSmrg
36064642e01fSmrg    if (stuff->setMap) {
36074642e01fSmrg        map->flags = stuff->flags;
36084642e01fSmrg        map->which_groups = stuff->whichGroups;
36094642e01fSmrg        map->groups = stuff->groups;
36104642e01fSmrg        map->which_mods = stuff->whichMods;
36114642e01fSmrg        map->mods.mask = stuff->realMods;
36124642e01fSmrg        map->mods.real_mods = stuff->realMods;
3613f7df2e56Smrg        map->mods.vmods = stuff->virtualMods;
36144642e01fSmrg        map->ctrls = stuff->ctrls;
3615f7df2e56Smrg        mapc |= (1 << led);
36164642e01fSmrg    }
36174642e01fSmrg
3618f7df2e56Smrg    if ((stuff->setState) && ((map->flags & XkbIM_NoExplicit) == 0)) {
3619f7df2e56Smrg        if (stuff->on)
3620f7df2e56Smrg            sli->explicitState |= (1 << led);
3621f7df2e56Smrg        else
3622f7df2e56Smrg            sli->explicitState &= ~(1 << led);
36234642e01fSmrg        statec |= ((sli->effectiveState ^ sli->explicitState) & (1 << led));
362405b261ecSmrg    }
36254642e01fSmrg
3626f7df2e56Smrg    memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify));
3627f7df2e56Smrg    memset((char *) &changes, 0, sizeof(XkbChangesRec));
3628f7df2e56Smrg    XkbSetCauseXkbReq(&cause, X_kbSetNamedIndicator, client);
362905b261ecSmrg    if (namec)
3630f7df2e56Smrg        XkbApplyLedNameChanges(dev, sli, namec, &ed, &changes, &cause);
363105b261ecSmrg    if (mapc)
3632f7df2e56Smrg        XkbApplyLedMapChanges(dev, sli, mapc, &ed, &changes, &cause);
363305b261ecSmrg    if (statec)
3634f7df2e56Smrg        XkbApplyLedStateChanges(dev, sli, statec, &ed, &changes, &cause);
363505b261ecSmrg
36364642e01fSmrg    kbd = dev;
3637f7df2e56Smrg    if ((sli->flags & XkbSLI_HasOwnState) == 0)
36384642e01fSmrg        kbd = inputInfo.keyboard;
36394642e01fSmrg    XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause);
36404642e01fSmrg
36414642e01fSmrg    return Success;
36424642e01fSmrg}
36434642e01fSmrg
36444642e01fSmrgint
36454642e01fSmrgProcXkbSetNamedIndicator(ClientPtr client)
36464642e01fSmrg{
3647f7df2e56Smrg    int rc;
3648f7df2e56Smrg    DeviceIntPtr dev;
3649f7df2e56Smrg    int led = 0;
3650f7df2e56Smrg    XkbIndicatorMapPtr map;
36514642e01fSmrg
36524642e01fSmrg    REQUEST(xkbSetNamedIndicatorReq);
36534642e01fSmrg    REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq);
36544642e01fSmrg
3655f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
3656f7df2e56Smrg        return BadAccess;
36574642e01fSmrg
36584642e01fSmrg    CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
36594642e01fSmrg    CHK_ATOM_ONLY(stuff->indicator);
3660f7df2e56Smrg    CHK_MASK_LEGAL(0x10, stuff->whichGroups, XkbIM_UseAnyGroup);
3661f7df2e56Smrg    CHK_MASK_LEGAL(0x11, stuff->whichMods, XkbIM_UseAnyMods);
36624642e01fSmrg
36634642e01fSmrg    /* Dry-run for checks */
36644642e01fSmrg    rc = _XkbCreateIndicatorMap(dev, stuff->indicator,
36654642e01fSmrg                                stuff->ledClass, stuff->ledID,
36664642e01fSmrg                                &map, &led, TRUE);
3667f7df2e56Smrg    if (rc != Success || !map)  /* couldn't be created or didn't exist */
36684642e01fSmrg        return rc;
36694642e01fSmrg
36704642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd ||
3671f7df2e56Smrg        stuff->deviceSpec == XkbUseCorePtr) {
36724642e01fSmrg        DeviceIntPtr other;
3673f7df2e56Smrg
3674f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
3675f7df2e56Smrg            if ((other != dev) && !IsMaster(other) &&
3676f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev && (other->kbdfeed ||
3677f7df2e56Smrg                                                             other->leds) &&
3678f7df2e56Smrg                (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess)
3679f7df2e56Smrg                 == Success)) {
36804642e01fSmrg                rc = _XkbCreateIndicatorMap(other, stuff->indicator,
3681f7df2e56Smrg                                            stuff->ledClass, stuff->ledID, &map,
3682f7df2e56Smrg                                            &led, TRUE);
36834642e01fSmrg                if (rc != Success || !map)
36844642e01fSmrg                    return rc;
36854642e01fSmrg            }
36864642e01fSmrg        }
36874642e01fSmrg    }
36884642e01fSmrg
36894642e01fSmrg    /* All checks passed, let's do it */
36904642e01fSmrg    rc = _XkbSetNamedIndicator(client, dev, stuff);
36914642e01fSmrg    if (rc != Success)
36924642e01fSmrg        return rc;
36934642e01fSmrg
36944642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd ||
3695f7df2e56Smrg        stuff->deviceSpec == XkbUseCorePtr) {
36964642e01fSmrg        DeviceIntPtr other;
3697f7df2e56Smrg
3698f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
3699f7df2e56Smrg            if ((other != dev) && !IsMaster(other) &&
3700f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev && (other->kbdfeed ||
3701f7df2e56Smrg                                                             other->leds) &&
3702f7df2e56Smrg                (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess)
3703f7df2e56Smrg                 == Success)) {
37044642e01fSmrg                _XkbSetNamedIndicator(client, other, stuff);
37054642e01fSmrg            }
37064642e01fSmrg        }
37074642e01fSmrg    }
37084642e01fSmrg
37096747b715Smrg    return Success;
371005b261ecSmrg}
371105b261ecSmrg
371205b261ecSmrg/***====================================================================***/
371305b261ecSmrg
371405b261ecSmrgstatic CARD32
3715f7df2e56Smrg_XkbCountAtoms(Atom *atoms, int maxAtoms, int *count)
371605b261ecSmrg{
3717f7df2e56Smrg    register unsigned int i, bit, nAtoms;
3718f7df2e56Smrg    register CARD32 atomsPresent;
371905b261ecSmrg
3720f7df2e56Smrg    for (i = nAtoms = atomsPresent = 0, bit = 1; i < maxAtoms; i++, bit <<= 1) {
3721f7df2e56Smrg        if (atoms[i] != None) {
3722f7df2e56Smrg            atomsPresent |= bit;
3723f7df2e56Smrg            nAtoms++;
3724f7df2e56Smrg        }
372505b261ecSmrg    }
372605b261ecSmrg    if (count)
3727f7df2e56Smrg        *count = nAtoms;
372805b261ecSmrg    return atomsPresent;
372905b261ecSmrg}
373005b261ecSmrg
373105b261ecSmrgstatic char *
3732f7df2e56Smrg_XkbWriteAtoms(char *wire, Atom *atoms, int maxAtoms, int swap)
373305b261ecSmrg{
3734f7df2e56Smrg    register unsigned int i;
3735f7df2e56Smrg    Atom *atm;
3736f7df2e56Smrg
3737f7df2e56Smrg    atm = (Atom *) wire;
3738f7df2e56Smrg    for (i = 0; i < maxAtoms; i++) {
3739f7df2e56Smrg        if (atoms[i] != None) {
3740f7df2e56Smrg            *atm = atoms[i];
3741f7df2e56Smrg            if (swap) {
3742f7df2e56Smrg                swapl(atm);
3743f7df2e56Smrg            }
3744f7df2e56Smrg            atm++;
3745f7df2e56Smrg        }
3746f7df2e56Smrg    }
3747f7df2e56Smrg    return (char *) atm;
374805b261ecSmrg}
374905b261ecSmrg
375005b261ecSmrgstatic Status
3751f7df2e56SmrgXkbComputeGetNamesReplySize(XkbDescPtr xkb, xkbGetNamesReply * rep)
375205b261ecSmrg{
3753f7df2e56Smrg    register unsigned which, length;
3754f7df2e56Smrg    register int i;
3755f7df2e56Smrg
3756f7df2e56Smrg    rep->minKeyCode = xkb->min_key_code;
3757f7df2e56Smrg    rep->maxKeyCode = xkb->max_key_code;
3758f7df2e56Smrg    which = rep->which;
3759f7df2e56Smrg    length = 0;
3760f7df2e56Smrg    if (xkb->names != NULL) {
3761f7df2e56Smrg        if (which & XkbKeycodesNameMask)
3762f7df2e56Smrg            length++;
3763f7df2e56Smrg        if (which & XkbGeometryNameMask)
3764f7df2e56Smrg            length++;
3765f7df2e56Smrg        if (which & XkbSymbolsNameMask)
3766f7df2e56Smrg            length++;
3767f7df2e56Smrg        if (which & XkbPhysSymbolsNameMask)
3768f7df2e56Smrg            length++;
3769f7df2e56Smrg        if (which & XkbTypesNameMask)
3770f7df2e56Smrg            length++;
3771f7df2e56Smrg        if (which & XkbCompatNameMask)
3772f7df2e56Smrg            length++;
3773f7df2e56Smrg    }
3774f7df2e56Smrg    else
3775f7df2e56Smrg        which &= ~XkbComponentNamesMask;
3776f7df2e56Smrg
3777f7df2e56Smrg    if (xkb->map != NULL) {
3778f7df2e56Smrg        if (which & XkbKeyTypeNamesMask)
3779f7df2e56Smrg            length += xkb->map->num_types;
3780f7df2e56Smrg        rep->nTypes = xkb->map->num_types;
3781f7df2e56Smrg        if (which & XkbKTLevelNamesMask) {
3782f7df2e56Smrg            XkbKeyTypePtr pType = xkb->map->types;
3783f7df2e56Smrg            int nKTLevels = 0;
3784f7df2e56Smrg
3785f7df2e56Smrg            length += XkbPaddedSize(xkb->map->num_types) / 4;
3786f7df2e56Smrg            for (i = 0; i < xkb->map->num_types; i++, pType++) {
3787f7df2e56Smrg                if (pType->level_names != NULL)
3788f7df2e56Smrg                    nKTLevels += pType->num_levels;
3789f7df2e56Smrg            }
3790f7df2e56Smrg            rep->nKTLevels = nKTLevels;
3791f7df2e56Smrg            length += nKTLevels;
3792f7df2e56Smrg        }
379305b261ecSmrg    }
379405b261ecSmrg    else {
3795f7df2e56Smrg        rep->nTypes = 0;
3796f7df2e56Smrg        rep->nKTLevels = 0;
3797f7df2e56Smrg        which &= ~(XkbKeyTypeNamesMask | XkbKTLevelNamesMask);
3798f7df2e56Smrg    }
3799f7df2e56Smrg
3800f7df2e56Smrg    rep->minKeyCode = xkb->min_key_code;
3801f7df2e56Smrg    rep->maxKeyCode = xkb->max_key_code;
3802f7df2e56Smrg    rep->indicators = 0;
3803f7df2e56Smrg    rep->virtualMods = 0;
3804f7df2e56Smrg    rep->groupNames = 0;
3805f7df2e56Smrg    if (xkb->names != NULL) {
3806f7df2e56Smrg        if (which & XkbIndicatorNamesMask) {
3807f7df2e56Smrg            int nLeds;
3808f7df2e56Smrg
3809f7df2e56Smrg            rep->indicators =
3810f7df2e56Smrg                _XkbCountAtoms(xkb->names->indicators, XkbNumIndicators,
3811f7df2e56Smrg                               &nLeds);
3812f7df2e56Smrg            length += nLeds;
3813f7df2e56Smrg            if (nLeds == 0)
3814f7df2e56Smrg                which &= ~XkbIndicatorNamesMask;
3815f7df2e56Smrg        }
3816f7df2e56Smrg
3817f7df2e56Smrg        if (which & XkbVirtualModNamesMask) {
3818f7df2e56Smrg            int nVMods;
3819f7df2e56Smrg
3820f7df2e56Smrg            rep->virtualMods =
3821f7df2e56Smrg                _XkbCountAtoms(xkb->names->vmods, XkbNumVirtualMods, &nVMods);
3822f7df2e56Smrg            length += nVMods;
3823f7df2e56Smrg            if (nVMods == 0)
3824f7df2e56Smrg                which &= ~XkbVirtualModNamesMask;
3825f7df2e56Smrg        }
3826f7df2e56Smrg
3827f7df2e56Smrg        if (which & XkbGroupNamesMask) {
3828f7df2e56Smrg            int nGroups;
3829f7df2e56Smrg
3830f7df2e56Smrg            rep->groupNames =
3831f7df2e56Smrg                _XkbCountAtoms(xkb->names->groups, XkbNumKbdGroups, &nGroups);
3832f7df2e56Smrg            length += nGroups;
3833f7df2e56Smrg            if (nGroups == 0)
3834f7df2e56Smrg                which &= ~XkbGroupNamesMask;
3835f7df2e56Smrg        }
3836f7df2e56Smrg
3837f7df2e56Smrg        if ((which & XkbKeyNamesMask) && (xkb->names->keys))
3838f7df2e56Smrg            length += rep->nKeys;
3839f7df2e56Smrg        else
3840f7df2e56Smrg            which &= ~XkbKeyNamesMask;
3841f7df2e56Smrg
3842f7df2e56Smrg        if ((which & XkbKeyAliasesMask) &&
3843f7df2e56Smrg            (xkb->names->key_aliases) && (xkb->names->num_key_aliases > 0)) {
3844f7df2e56Smrg            rep->nKeyAliases = xkb->names->num_key_aliases;
3845f7df2e56Smrg            length += rep->nKeyAliases * 2;
3846f7df2e56Smrg        }
3847f7df2e56Smrg        else {
3848f7df2e56Smrg            which &= ~XkbKeyAliasesMask;
3849f7df2e56Smrg            rep->nKeyAliases = 0;
3850f7df2e56Smrg        }
3851f7df2e56Smrg
3852f7df2e56Smrg        if ((which & XkbRGNamesMask) && (xkb->names->num_rg > 0))
3853f7df2e56Smrg            length += xkb->names->num_rg;
3854f7df2e56Smrg        else
3855f7df2e56Smrg            which &= ~XkbRGNamesMask;
385605b261ecSmrg    }
385705b261ecSmrg    else {
3858f7df2e56Smrg        which &= ~(XkbIndicatorNamesMask | XkbVirtualModNamesMask);
3859f7df2e56Smrg        which &= ~(XkbGroupNamesMask | XkbKeyNamesMask | XkbKeyAliasesMask);
3860f7df2e56Smrg        which &= ~XkbRGNamesMask;
386105b261ecSmrg    }
386205b261ecSmrg
3863f7df2e56Smrg    rep->length = length;
3864f7df2e56Smrg    rep->which = which;
386505b261ecSmrg    return Success;
386605b261ecSmrg}
386705b261ecSmrg
386805b261ecSmrgstatic int
3869f7df2e56SmrgXkbSendNames(ClientPtr client, XkbDescPtr xkb, xkbGetNamesReply * rep)
387005b261ecSmrg{
3871f7df2e56Smrg    register unsigned i, length, which;
3872f7df2e56Smrg    char *start;
3873f7df2e56Smrg    char *desc;
387405b261ecSmrg
3875f7df2e56Smrg    length = rep->length * 4;
3876f7df2e56Smrg    which = rep->which;
387705b261ecSmrg    if (client->swapped) {
3878f7df2e56Smrg        swaps(&rep->sequenceNumber);
3879f7df2e56Smrg        swapl(&rep->length);
3880f7df2e56Smrg        swapl(&rep->which);
3881f7df2e56Smrg        swaps(&rep->virtualMods);
3882f7df2e56Smrg        swapl(&rep->indicators);
388305b261ecSmrg    }
388405b261ecSmrg
38859ace9065Smrg    start = desc = calloc(1, length);
3886f7df2e56Smrg    if (!start)
3887f7df2e56Smrg        return BadAlloc;
388805b261ecSmrg    if (xkb->names) {
3889f7df2e56Smrg        if (which & XkbKeycodesNameMask) {
3890f7df2e56Smrg            *((CARD32 *) desc) = xkb->names->keycodes;
389105b261ecSmrg            if (client->swapped) {
3892f7df2e56Smrg                swapl((int *) desc);
389305b261ecSmrg            }
3894f7df2e56Smrg            desc += 4;
389505b261ecSmrg        }
3896f7df2e56Smrg        if (which & XkbGeometryNameMask) {
3897f7df2e56Smrg            *((CARD32 *) desc) = xkb->names->geometry;
389805b261ecSmrg            if (client->swapped) {
3899f7df2e56Smrg                swapl((int *) desc);
390005b261ecSmrg            }
3901f7df2e56Smrg            desc += 4;
390205b261ecSmrg        }
3903f7df2e56Smrg        if (which & XkbSymbolsNameMask) {
3904f7df2e56Smrg            *((CARD32 *) desc) = xkb->names->symbols;
390505b261ecSmrg            if (client->swapped) {
3906f7df2e56Smrg                swapl((int *) desc);
390705b261ecSmrg            }
3908f7df2e56Smrg            desc += 4;
390905b261ecSmrg        }
3910f7df2e56Smrg        if (which & XkbPhysSymbolsNameMask) {
3911f7df2e56Smrg            register CARD32 *atm = (CARD32 *) desc;
3912f7df2e56Smrg
3913f7df2e56Smrg            atm[0] = (CARD32) xkb->names->phys_symbols;
391405b261ecSmrg            if (client->swapped) {
3915f7df2e56Smrg                swapl(&atm[0]);
391605b261ecSmrg            }
3917f7df2e56Smrg            desc += 4;
391805b261ecSmrg        }
3919f7df2e56Smrg        if (which & XkbTypesNameMask) {
3920f7df2e56Smrg            *((CARD32 *) desc) = (CARD32) xkb->names->types;
392105b261ecSmrg            if (client->swapped) {
3922f7df2e56Smrg                swapl((int *) desc);
392305b261ecSmrg            }
3924f7df2e56Smrg            desc += 4;
392505b261ecSmrg        }
3926f7df2e56Smrg        if (which & XkbCompatNameMask) {
3927f7df2e56Smrg            *((CARD32 *) desc) = (CARD32) xkb->names->compat;
392805b261ecSmrg            if (client->swapped) {
3929f7df2e56Smrg                swapl((int *) desc);
393005b261ecSmrg            }
3931f7df2e56Smrg            desc += 4;
393205b261ecSmrg        }
3933f7df2e56Smrg        if (which & XkbKeyTypeNamesMask) {
3934f7df2e56Smrg            register CARD32 *atm = (CARD32 *) desc;
3935f7df2e56Smrg            register XkbKeyTypePtr type = xkb->map->types;
393605b261ecSmrg
3937f7df2e56Smrg            for (i = 0; i < xkb->map->num_types; i++, atm++, type++) {
3938f7df2e56Smrg                *atm = (CARD32) type->name;
393905b261ecSmrg                if (client->swapped) {
3940f7df2e56Smrg                    swapl(atm);
394105b261ecSmrg                }
394205b261ecSmrg            }
3943f7df2e56Smrg            desc = (char *) atm;
394405b261ecSmrg        }
3945f7df2e56Smrg        if (which & XkbKTLevelNamesMask && xkb->map) {
394605b261ecSmrg            XkbKeyTypePtr type = xkb->map->types;
394705b261ecSmrg            register CARD32 *atm;
3948f7df2e56Smrg
3949f7df2e56Smrg            for (i = 0; i < rep->nTypes; i++, type++) {
395005b261ecSmrg                *desc++ = type->num_levels;
395105b261ecSmrg            }
3952f7df2e56Smrg            desc += XkbPaddedSize(rep->nTypes) - rep->nTypes;
395305b261ecSmrg
3954f7df2e56Smrg            atm = (CARD32 *) desc;
395505b261ecSmrg            type = xkb->map->types;
3956f7df2e56Smrg            for (i = 0; i < xkb->map->num_types; i++, type++) {
395705b261ecSmrg                register unsigned l;
3958f7df2e56Smrg
395905b261ecSmrg                if (type->level_names) {
3960f7df2e56Smrg                    for (l = 0; l < type->num_levels; l++, atm++) {
3961f7df2e56Smrg                        *atm = type->level_names[l];
396205b261ecSmrg                        if (client->swapped) {
3963f7df2e56Smrg                            swapl(atm);
396405b261ecSmrg                        }
396505b261ecSmrg                    }
3966f7df2e56Smrg                    desc += type->num_levels * 4;
396705b261ecSmrg                }
396805b261ecSmrg            }
396905b261ecSmrg        }
3970f7df2e56Smrg        if (which & XkbIndicatorNamesMask) {
3971f7df2e56Smrg            desc =
3972f7df2e56Smrg                _XkbWriteAtoms(desc, xkb->names->indicators, XkbNumIndicators,
3973f7df2e56Smrg                               client->swapped);
397405b261ecSmrg        }
3975f7df2e56Smrg        if (which & XkbVirtualModNamesMask) {
3976f7df2e56Smrg            desc = _XkbWriteAtoms(desc, xkb->names->vmods, XkbNumVirtualMods,
3977f7df2e56Smrg                                  client->swapped);
397805b261ecSmrg        }
3979f7df2e56Smrg        if (which & XkbGroupNamesMask) {
3980f7df2e56Smrg            desc = _XkbWriteAtoms(desc, xkb->names->groups, XkbNumKbdGroups,
3981f7df2e56Smrg                                  client->swapped);
398205b261ecSmrg        }
3983f7df2e56Smrg        if (which & XkbKeyNamesMask) {
3984f7df2e56Smrg            for (i = 0; i < rep->nKeys; i++, desc += sizeof(XkbKeyNameRec)) {
3985f7df2e56Smrg                *((XkbKeyNamePtr) desc) = xkb->names->keys[i + rep->firstKey];
398605b261ecSmrg            }
398705b261ecSmrg        }
3988f7df2e56Smrg        if (which & XkbKeyAliasesMask) {
3989f7df2e56Smrg            XkbKeyAliasPtr pAl;
3990f7df2e56Smrg
3991f7df2e56Smrg            pAl = xkb->names->key_aliases;
3992f7df2e56Smrg            for (i = 0; i < rep->nKeyAliases;
3993f7df2e56Smrg                 i++, pAl++, desc += 2 * XkbKeyNameLength) {
3994f7df2e56Smrg                *((XkbKeyAliasPtr) desc) = *pAl;
399505b261ecSmrg            }
399605b261ecSmrg        }
3997f7df2e56Smrg        if ((which & XkbRGNamesMask) && (rep->nRadioGroups > 0)) {
3998f7df2e56Smrg            register CARD32 *atm = (CARD32 *) desc;
3999f7df2e56Smrg
4000f7df2e56Smrg            for (i = 0; i < rep->nRadioGroups; i++, atm++) {
4001f7df2e56Smrg                *atm = (CARD32) xkb->names->radio_groups[i];
400205b261ecSmrg                if (client->swapped) {
4003f7df2e56Smrg                    swapl(atm);
400405b261ecSmrg                }
400505b261ecSmrg            }
4006f7df2e56Smrg            desc += rep->nRadioGroups * 4;
400705b261ecSmrg        }
400805b261ecSmrg    }
400905b261ecSmrg
4010f7df2e56Smrg    if ((desc - start) != (length)) {
4011f7df2e56Smrg        ErrorF("[xkb] BOGUS LENGTH in write names, expected %d, got %ld\n",
4012f7df2e56Smrg               length, (unsigned long) (desc - start));
401305b261ecSmrg    }
4014f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetNamesReply), rep);
401505b261ecSmrg    WriteToClient(client, length, start);
4016f7df2e56Smrg    free((char *) start);
40176747b715Smrg    return Success;
401805b261ecSmrg}
401905b261ecSmrg
402005b261ecSmrgint
402105b261ecSmrgProcXkbGetNames(ClientPtr client)
402205b261ecSmrg{
4023f7df2e56Smrg    DeviceIntPtr dev;
4024f7df2e56Smrg    XkbDescPtr xkb;
4025f7df2e56Smrg    xkbGetNamesReply rep;
402605b261ecSmrg
402705b261ecSmrg    REQUEST(xkbGetNamesReq);
402805b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetNamesReq);
402905b261ecSmrg
4030f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
4031f7df2e56Smrg        return BadAccess;
403205b261ecSmrg
40334642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
4034f7df2e56Smrg    CHK_MASK_LEGAL(0x01, stuff->which, XkbAllNamesMask);
403505b261ecSmrg
403605b261ecSmrg    xkb = dev->key->xkbInfo->desc;
4037f7df2e56Smrg    rep = (xkbGetNamesReply) {
4038f7df2e56Smrg        .type = X_Reply,
4039f7df2e56Smrg        .deviceID = dev->id,
4040f7df2e56Smrg        .sequenceNumber = client->sequence,
4041f7df2e56Smrg        .length = 0,
4042f7df2e56Smrg        .which = stuff->which,
4043f7df2e56Smrg        .nTypes = xkb->map->num_types,
4044f7df2e56Smrg        .firstKey = xkb->min_key_code,
4045f7df2e56Smrg        .nKeys = XkbNumKeys(xkb),
4046f7df2e56Smrg        .nKeyAliases = xkb->names ? xkb->names->num_key_aliases : 0,
4047f7df2e56Smrg        .nRadioGroups = xkb->names ? xkb->names->num_rg : 0
4048f7df2e56Smrg    };
4049f7df2e56Smrg    XkbComputeGetNamesReplySize(xkb, &rep);
4050f7df2e56Smrg    return XkbSendNames(client, xkb, &rep);
405105b261ecSmrg}
405205b261ecSmrg
405305b261ecSmrg/***====================================================================***/
405405b261ecSmrg
405505b261ecSmrgstatic CARD32 *
4056f7df2e56Smrg_XkbCheckAtoms(CARD32 *wire, int nAtoms, int swapped, Atom *pError)
405705b261ecSmrg{
4058f7df2e56Smrg    register int i;
4059f7df2e56Smrg
4060f7df2e56Smrg    for (i = 0; i < nAtoms; i++, wire++) {
4061f7df2e56Smrg        if (swapped) {
4062f7df2e56Smrg            swapl(wire);
4063f7df2e56Smrg        }
4064f7df2e56Smrg        if ((((Atom) *wire) != None) && (!ValidAtom((Atom) *wire))) {
4065f7df2e56Smrg            *pError = ((Atom) *wire);
4066f7df2e56Smrg            return NULL;
4067f7df2e56Smrg        }
406805b261ecSmrg    }
406905b261ecSmrg    return wire;
407005b261ecSmrg}
407105b261ecSmrg
407205b261ecSmrgstatic CARD32 *
4073f7df2e56Smrg_XkbCheckMaskedAtoms(CARD32 *wire, int nAtoms, CARD32 present, int swapped,
4074f7df2e56Smrg                     Atom *pError)
407505b261ecSmrg{
4076f7df2e56Smrg    register unsigned i, bit;
4077f7df2e56Smrg
4078f7df2e56Smrg    for (i = 0, bit = 1; (i < nAtoms) && (present); i++, bit <<= 1) {
4079f7df2e56Smrg        if ((present & bit) == 0)
4080f7df2e56Smrg            continue;
4081f7df2e56Smrg        if (swapped) {
4082f7df2e56Smrg            swapl(wire);
4083f7df2e56Smrg        }
4084f7df2e56Smrg        if ((((Atom) *wire) != None) && (!ValidAtom(((Atom) *wire)))) {
4085f7df2e56Smrg            *pError = (Atom) *wire;
4086f7df2e56Smrg            return NULL;
4087f7df2e56Smrg        }
4088f7df2e56Smrg        wire++;
408905b261ecSmrg    }
409005b261ecSmrg    return wire;
409105b261ecSmrg}
409205b261ecSmrg
409305b261ecSmrgstatic Atom *
4094f7df2e56Smrg_XkbCopyMaskedAtoms(Atom *wire, Atom *dest, int nAtoms, CARD32 present)
409505b261ecSmrg{
4096f7df2e56Smrg    register int i, bit;
409705b261ecSmrg
4098f7df2e56Smrg    for (i = 0, bit = 1; (i < nAtoms) && (present); i++, bit <<= 1) {
4099f7df2e56Smrg        if ((present & bit) == 0)
4100f7df2e56Smrg            continue;
4101f7df2e56Smrg        dest[i] = *wire++;
410205b261ecSmrg    }
410305b261ecSmrg    return wire;
410405b261ecSmrg}
410505b261ecSmrg
410605b261ecSmrgstatic Bool
4107f7df2e56Smrg_XkbCheckTypeName(Atom name, int typeNdx)
410805b261ecSmrg{
4109f7df2e56Smrg    const char *str;
411005b261ecSmrg
4111f7df2e56Smrg    str = NameForAtom(name);
4112f7df2e56Smrg    if ((strcmp(str, "ONE_LEVEL") == 0) || (strcmp(str, "TWO_LEVEL") == 0) ||
4113f7df2e56Smrg        (strcmp(str, "ALPHABETIC") == 0) || (strcmp(str, "KEYPAD") == 0))
4114f7df2e56Smrg        return FALSE;
41156747b715Smrg    return TRUE;
411605b261ecSmrg}
411705b261ecSmrg
41184642e01fSmrg/**
41194642e01fSmrg * Check the device-dependent data in the request against the device. Returns
41204642e01fSmrg * Success, or the appropriate error code.
41214642e01fSmrg */
41224642e01fSmrgstatic int
41234642e01fSmrg_XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
4124f7df2e56Smrg                  xkbSetNamesReq * stuff, CARD32 *data)
412505b261ecSmrg{
4126f7df2e56Smrg    XkbDescRec *xkb;
4127f7df2e56Smrg    CARD32 *tmp;
4128f7df2e56Smrg    Atom bad = None;
412905b261ecSmrg
41304642e01fSmrg    tmp = data;
41314642e01fSmrg    xkb = dev->key->xkbInfo->desc;
41324642e01fSmrg
41334642e01fSmrg    if (stuff->which & XkbKeyTypeNamesMask) {
41344642e01fSmrg        int i;
4135f7df2e56Smrg        CARD32 *old;
4136f7df2e56Smrg
4137f7df2e56Smrg        if (stuff->nTypes < 1) {
4138f7df2e56Smrg            client->errorValue = _XkbErrCode2(0x02, stuff->nTypes);
41394642e01fSmrg            return BadValue;
41404642e01fSmrg        }
4141f7df2e56Smrg        if ((unsigned) (stuff->firstType + stuff->nTypes - 1) >=
4142f7df2e56Smrg            xkb->map->num_types) {
4143f7df2e56Smrg            client->errorValue =
4144f7df2e56Smrg                _XkbErrCode4(0x03, stuff->firstType, stuff->nTypes,
4145f7df2e56Smrg                             xkb->map->num_types);
41464642e01fSmrg            return BadValue;
41474642e01fSmrg        }
4148f7df2e56Smrg        if (((unsigned) stuff->firstType) <= XkbLastRequiredType) {
4149f7df2e56Smrg            client->errorValue = _XkbErrCode2(0x04, stuff->firstType);
41504642e01fSmrg            return BadAccess;
41514642e01fSmrg        }
4152806e81e9Smrg        if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + stuff->nTypes))
4153806e81e9Smrg            return BadLength;
4154f7df2e56Smrg        old = tmp;
4155f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, stuff->nTypes, client->swapped, &bad);
41564642e01fSmrg        if (!tmp) {
4157f7df2e56Smrg            client->errorValue = bad;
41584642e01fSmrg            return BadAtom;
41594642e01fSmrg        }
4160f7df2e56Smrg        for (i = 0; i < stuff->nTypes; i++, old++) {
4161f7df2e56Smrg            if (!_XkbCheckTypeName((Atom) *old, stuff->firstType + i))
4162f7df2e56Smrg                client->errorValue = _XkbErrCode2(0x05, i);
41634642e01fSmrg        }
41644642e01fSmrg    }
4165f7df2e56Smrg    if (stuff->which & XkbKTLevelNamesMask) {
41664642e01fSmrg        unsigned i;
4167f7df2e56Smrg        XkbKeyTypePtr type;
4168f7df2e56Smrg        CARD8 *width;
4169f7df2e56Smrg
4170f7df2e56Smrg        if (stuff->nKTLevels < 1) {
4171f7df2e56Smrg            client->errorValue = _XkbErrCode2(0x05, stuff->nKTLevels);
41724642e01fSmrg            return BadValue;
41734642e01fSmrg        }
4174f7df2e56Smrg        if ((unsigned) (stuff->firstKTLevel + stuff->nKTLevels - 1) >=
4175f7df2e56Smrg            xkb->map->num_types) {
4176f7df2e56Smrg            client->errorValue = _XkbErrCode4(0x06, stuff->firstKTLevel,
4177f7df2e56Smrg                                              stuff->nKTLevels,
4178f7df2e56Smrg                                              xkb->map->num_types);
41794642e01fSmrg            return BadValue;
41804642e01fSmrg        }
4181f7df2e56Smrg        width = (CARD8 *) tmp;
4182f7df2e56Smrg        tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels));
4183806e81e9Smrg        if (!_XkbCheckRequestBounds(client, stuff, width, tmp))
4184806e81e9Smrg            return BadLength;
41854642e01fSmrg        type = &xkb->map->types[stuff->firstKTLevel];
4186f7df2e56Smrg        for (i = 0; i < stuff->nKTLevels; i++, type++) {
4187f7df2e56Smrg            if (width[i] == 0)
41884642e01fSmrg                continue;
4189f7df2e56Smrg            else if (width[i] != type->num_levels) {
4190f7df2e56Smrg                client->errorValue = _XkbErrCode4(0x07, i + stuff->firstKTLevel,
4191f7df2e56Smrg                                                  type->num_levels, width[i]);
41924642e01fSmrg                return BadMatch;
41934642e01fSmrg            }
4194806e81e9Smrg            if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + width[i]))
4195806e81e9Smrg                return BadLength;
4196f7df2e56Smrg            tmp = _XkbCheckAtoms(tmp, width[i], client->swapped, &bad);
41974642e01fSmrg            if (!tmp) {
4198f7df2e56Smrg                client->errorValue = bad;
41994642e01fSmrg                return BadAtom;
42004642e01fSmrg            }
42014642e01fSmrg        }
42024642e01fSmrg    }
4203f7df2e56Smrg    if (stuff->which & XkbIndicatorNamesMask) {
4204f7df2e56Smrg        if (stuff->indicators == 0) {
4205f7df2e56Smrg            client->errorValue = 0x08;
42064642e01fSmrg            return BadMatch;
42074642e01fSmrg        }
4208806e81e9Smrg        if (!_XkbCheckRequestBounds(client, stuff, tmp,
4209806e81e9Smrg                                    tmp + Ones(stuff->indicators)))
4210806e81e9Smrg            return BadLength;
4211f7df2e56Smrg        tmp = _XkbCheckMaskedAtoms(tmp, XkbNumIndicators, stuff->indicators,
4212f7df2e56Smrg                                   client->swapped, &bad);
42134642e01fSmrg        if (!tmp) {
4214f7df2e56Smrg            client->errorValue = bad;
42154642e01fSmrg            return BadAtom;
42164642e01fSmrg        }
42174642e01fSmrg    }
4218f7df2e56Smrg    if (stuff->which & XkbVirtualModNamesMask) {
4219f7df2e56Smrg        if (stuff->virtualMods == 0) {
4220f7df2e56Smrg            client->errorValue = 0x09;
42214642e01fSmrg            return BadMatch;
42224642e01fSmrg        }
4223806e81e9Smrg        if (!_XkbCheckRequestBounds(client, stuff, tmp,
4224806e81e9Smrg                                    tmp + Ones(stuff->virtualMods)))
4225806e81e9Smrg            return BadLength;
4226f7df2e56Smrg        tmp = _XkbCheckMaskedAtoms(tmp, XkbNumVirtualMods,
4227f7df2e56Smrg                                   (CARD32) stuff->virtualMods,
4228f7df2e56Smrg                                   client->swapped, &bad);
42294642e01fSmrg        if (!tmp) {
42304642e01fSmrg            client->errorValue = bad;
42314642e01fSmrg            return BadAtom;
42324642e01fSmrg        }
42334642e01fSmrg    }
4234f7df2e56Smrg    if (stuff->which & XkbGroupNamesMask) {
4235f7df2e56Smrg        if (stuff->groupNames == 0) {
4236f7df2e56Smrg            client->errorValue = 0x0a;
42374642e01fSmrg            return BadMatch;
42384642e01fSmrg        }
4239806e81e9Smrg        if (!_XkbCheckRequestBounds(client, stuff, tmp,
4240806e81e9Smrg                                    tmp + Ones(stuff->groupNames)))
4241806e81e9Smrg            return BadLength;
4242f7df2e56Smrg        tmp = _XkbCheckMaskedAtoms(tmp, XkbNumKbdGroups,
4243f7df2e56Smrg                                   (CARD32) stuff->groupNames,
4244f7df2e56Smrg                                   client->swapped, &bad);
42454642e01fSmrg        if (!tmp) {
42464642e01fSmrg            client->errorValue = bad;
42474642e01fSmrg            return BadAtom;
42484642e01fSmrg        }
42494642e01fSmrg    }
4250f7df2e56Smrg    if (stuff->which & XkbKeyNamesMask) {
4251f7df2e56Smrg        if (stuff->firstKey < (unsigned) xkb->min_key_code) {
4252f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x0b, xkb->min_key_code,
4253f7df2e56Smrg                                              stuff->firstKey);
42544642e01fSmrg            return BadValue;
42554642e01fSmrg        }
4256f7df2e56Smrg        if (((unsigned) (stuff->firstKey + stuff->nKeys - 1) >
4257f7df2e56Smrg             xkb->max_key_code) || (stuff->nKeys < 1)) {
4258f7df2e56Smrg            client->errorValue =
4259f7df2e56Smrg                _XkbErrCode4(0x0c, xkb->max_key_code, stuff->firstKey,
4260f7df2e56Smrg                             stuff->nKeys);
42614642e01fSmrg            return BadValue;
42624642e01fSmrg        }
4263806e81e9Smrg        if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + stuff->nKeys))
4264806e81e9Smrg            return BadLength;
4265f7df2e56Smrg        tmp += stuff->nKeys;
42664642e01fSmrg    }
4267f7df2e56Smrg    if ((stuff->which & XkbKeyAliasesMask) && (stuff->nKeyAliases > 0)) {
4268806e81e9Smrg        if (!_XkbCheckRequestBounds(client, stuff, tmp,
4269806e81e9Smrg                                    tmp + (stuff->nKeyAliases * 2)))
4270806e81e9Smrg            return BadLength;
4271f7df2e56Smrg        tmp += stuff->nKeyAliases * 2;
42724642e01fSmrg    }
4273f7df2e56Smrg    if (stuff->which & XkbRGNamesMask) {
4274f7df2e56Smrg        if (stuff->nRadioGroups < 1) {
4275f7df2e56Smrg            client->errorValue = _XkbErrCode2(0x0d, stuff->nRadioGroups);
42764642e01fSmrg            return BadValue;
42774642e01fSmrg        }
4278806e81e9Smrg        if (!_XkbCheckRequestBounds(client, stuff, tmp,
4279806e81e9Smrg                                    tmp + stuff->nRadioGroups))
4280806e81e9Smrg            return BadLength;
4281f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, stuff->nRadioGroups, client->swapped, &bad);
42824642e01fSmrg        if (!tmp) {
4283f7df2e56Smrg            client->errorValue = bad;
42844642e01fSmrg            return BadAtom;
42854642e01fSmrg        }
42864642e01fSmrg    }
4287f7df2e56Smrg    if ((tmp - ((CARD32 *) stuff)) != stuff->length) {
42884642e01fSmrg        client->errorValue = stuff->length;
42894642e01fSmrg        return BadLength;
42904642e01fSmrg    }
42914642e01fSmrg
42924642e01fSmrg    return Success;
42934642e01fSmrg}
42944642e01fSmrg
42954642e01fSmrgstatic int
4296f7df2e56Smrg_XkbSetNames(ClientPtr client, DeviceIntPtr dev, xkbSetNamesReq * stuff)
42974642e01fSmrg{
4298f7df2e56Smrg    XkbDescRec *xkb;
4299f7df2e56Smrg    XkbNamesRec *names;
4300f7df2e56Smrg    CARD32 *tmp;
4301f7df2e56Smrg    xkbNamesNotify nn;
43024642e01fSmrg
4303f7df2e56Smrg    tmp = (CARD32 *) &stuff[1];
43044642e01fSmrg    xkb = dev->key->xkbInfo->desc;
43054642e01fSmrg    names = xkb->names;
43064642e01fSmrg
4307f7df2e56Smrg    if (XkbAllocNames(xkb, stuff->which, stuff->nRadioGroups,
4308f7df2e56Smrg                      stuff->nKeyAliases) != Success) {
43094642e01fSmrg        return BadAlloc;
43104642e01fSmrg    }
43114642e01fSmrg
43126747b715Smrg    memset(&nn, 0, sizeof(xkbNamesNotify));
4313f7df2e56Smrg    nn.changed = stuff->which;
4314f7df2e56Smrg    tmp = (CARD32 *) &stuff[1];
4315f7df2e56Smrg    if (stuff->which & XkbKeycodesNameMask)
4316f7df2e56Smrg        names->keycodes = *tmp++;
4317f7df2e56Smrg    if (stuff->which & XkbGeometryNameMask)
4318f7df2e56Smrg        names->geometry = *tmp++;
4319f7df2e56Smrg    if (stuff->which & XkbSymbolsNameMask)
4320f7df2e56Smrg        names->symbols = *tmp++;
4321f7df2e56Smrg    if (stuff->which & XkbPhysSymbolsNameMask)
4322f7df2e56Smrg        names->phys_symbols = *tmp++;
4323f7df2e56Smrg    if (stuff->which & XkbTypesNameMask)
4324f7df2e56Smrg        names->types = *tmp++;
4325f7df2e56Smrg    if (stuff->which & XkbCompatNameMask)
4326f7df2e56Smrg        names->compat = *tmp++;
4327f7df2e56Smrg    if ((stuff->which & XkbKeyTypeNamesMask) && (stuff->nTypes > 0)) {
43284642e01fSmrg        register unsigned i;
43294642e01fSmrg        register XkbKeyTypePtr type;
43304642e01fSmrg
4331f7df2e56Smrg        type = &xkb->map->types[stuff->firstType];
4332f7df2e56Smrg        for (i = 0; i < stuff->nTypes; i++, type++) {
4333f7df2e56Smrg            type->name = *tmp++;
43344642e01fSmrg        }
4335f7df2e56Smrg        nn.firstType = stuff->firstType;
4336f7df2e56Smrg        nn.nTypes = stuff->nTypes;
43374642e01fSmrg    }
4338f7df2e56Smrg    if (stuff->which & XkbKTLevelNamesMask) {
4339f7df2e56Smrg        register XkbKeyTypePtr type;
43404642e01fSmrg        register unsigned i;
43414642e01fSmrg        CARD8 *width;
43424642e01fSmrg
4343f7df2e56Smrg        width = (CARD8 *) tmp;
4344f7df2e56Smrg        tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels));
4345f7df2e56Smrg        type = &xkb->map->types[stuff->firstKTLevel];
4346f7df2e56Smrg        for (i = 0; i < stuff->nKTLevels; i++, type++) {
4347f7df2e56Smrg            if (width[i] > 0) {
43484642e01fSmrg                if (type->level_names) {
43494642e01fSmrg                    register unsigned n;
4350f7df2e56Smrg
4351f7df2e56Smrg                    for (n = 0; n < width[i]; n++) {
4352f7df2e56Smrg                        type->level_names[n] = tmp[n];
43534642e01fSmrg                    }
43544642e01fSmrg                }
4355f7df2e56Smrg                tmp += width[i];
43564642e01fSmrg            }
43574642e01fSmrg        }
4358f7df2e56Smrg        nn.firstLevelName = 0;
4359f7df2e56Smrg        nn.nLevelNames = stuff->nTypes;
4360f7df2e56Smrg    }
4361f7df2e56Smrg    if (stuff->which & XkbIndicatorNamesMask) {
4362f7df2e56Smrg        tmp = _XkbCopyMaskedAtoms(tmp, names->indicators, XkbNumIndicators,
4363f7df2e56Smrg                                  stuff->indicators);
4364f7df2e56Smrg        nn.changedIndicators = stuff->indicators;
4365f7df2e56Smrg    }
4366f7df2e56Smrg    if (stuff->which & XkbVirtualModNamesMask) {
4367f7df2e56Smrg        tmp = _XkbCopyMaskedAtoms(tmp, names->vmods, XkbNumVirtualMods,
4368f7df2e56Smrg                                  stuff->virtualMods);
4369f7df2e56Smrg        nn.changedVirtualMods = stuff->virtualMods;
4370f7df2e56Smrg    }
4371f7df2e56Smrg    if (stuff->which & XkbGroupNamesMask) {
4372f7df2e56Smrg        tmp = _XkbCopyMaskedAtoms(tmp, names->groups, XkbNumKbdGroups,
4373f7df2e56Smrg                                  stuff->groupNames);
4374f7df2e56Smrg        nn.changedVirtualMods = stuff->groupNames;
4375f7df2e56Smrg    }
4376f7df2e56Smrg    if (stuff->which & XkbKeyNamesMask) {
4377f7df2e56Smrg        memcpy((char *) &names->keys[stuff->firstKey], (char *) tmp,
4378f7df2e56Smrg               stuff->nKeys * XkbKeyNameLength);
4379f7df2e56Smrg        tmp += stuff->nKeys;
4380f7df2e56Smrg        nn.firstKey = stuff->firstKey;
4381f7df2e56Smrg        nn.nKeys = stuff->nKeys;
4382f7df2e56Smrg    }
4383f7df2e56Smrg    if (stuff->which & XkbKeyAliasesMask) {
4384f7df2e56Smrg        if (stuff->nKeyAliases > 0) {
4385f7df2e56Smrg            register int na = stuff->nKeyAliases;
4386f7df2e56Smrg
4387f7df2e56Smrg            if (XkbAllocNames(xkb, XkbKeyAliasesMask, 0, na) != Success)
43884642e01fSmrg                return BadAlloc;
4389f7df2e56Smrg            memcpy((char *) names->key_aliases, (char *) tmp,
4390f7df2e56Smrg                   stuff->nKeyAliases * sizeof(XkbKeyAliasRec));
4391f7df2e56Smrg            tmp += stuff->nKeyAliases * 2;
43924642e01fSmrg        }
4393f7df2e56Smrg        else if (names->key_aliases != NULL) {
43946747b715Smrg            free(names->key_aliases);
4395f7df2e56Smrg            names->key_aliases = NULL;
4396f7df2e56Smrg            names->num_key_aliases = 0;
43974642e01fSmrg        }
4398f7df2e56Smrg        nn.nAliases = names->num_key_aliases;
43994642e01fSmrg    }
4400f7df2e56Smrg    if (stuff->which & XkbRGNamesMask) {
4401f7df2e56Smrg        if (stuff->nRadioGroups > 0) {
4402f7df2e56Smrg            register unsigned i, nrg;
4403f7df2e56Smrg
4404f7df2e56Smrg            nrg = stuff->nRadioGroups;
4405f7df2e56Smrg            if (XkbAllocNames(xkb, XkbRGNamesMask, nrg, 0) != Success)
44064642e01fSmrg                return BadAlloc;
44074642e01fSmrg
4408f7df2e56Smrg            for (i = 0; i < stuff->nRadioGroups; i++) {
4409f7df2e56Smrg                names->radio_groups[i] = tmp[i];
44104642e01fSmrg            }
4411f7df2e56Smrg            tmp += stuff->nRadioGroups;
44124642e01fSmrg        }
44134642e01fSmrg        else if (names->radio_groups) {
44146747b715Smrg            free(names->radio_groups);
4415f7df2e56Smrg            names->radio_groups = NULL;
4416f7df2e56Smrg            names->num_rg = 0;
44174642e01fSmrg        }
4418f7df2e56Smrg        nn.nRadioGroups = names->num_rg;
44194642e01fSmrg    }
44204642e01fSmrg    if (nn.changed) {
44214642e01fSmrg        Bool needExtEvent;
4422f7df2e56Smrg
4423f7df2e56Smrg        needExtEvent = (nn.changed & XkbIndicatorNamesMask) != 0;
4424f7df2e56Smrg        XkbSendNamesNotify(dev, &nn);
44254642e01fSmrg        if (needExtEvent) {
4426f7df2e56Smrg            XkbSrvLedInfoPtr sli;
4427f7df2e56Smrg            xkbExtensionDeviceNotify edev;
4428f7df2e56Smrg            register int i;
4429f7df2e56Smrg            register unsigned bit;
4430f7df2e56Smrg
4431f7df2e56Smrg            sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
4432f7df2e56Smrg                                    XkbXI_IndicatorsMask);
4433f7df2e56Smrg            sli->namesPresent = 0;
4434f7df2e56Smrg            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
4435f7df2e56Smrg                if (names->indicators[i] != None)
4436f7df2e56Smrg                    sli->namesPresent |= bit;
44374642e01fSmrg            }
44386747b715Smrg            memset(&edev, 0, sizeof(xkbExtensionDeviceNotify));
4439f7df2e56Smrg            edev.reason = XkbXI_IndicatorNamesMask;
4440f7df2e56Smrg            edev.ledClass = KbdFeedbackClass;
4441f7df2e56Smrg            edev.ledID = dev->kbdfeed->ctrl.id;
4442f7df2e56Smrg            edev.ledsDefined = sli->namesPresent | sli->mapsPresent;
4443f7df2e56Smrg            edev.ledState = sli->effectiveState;
4444f7df2e56Smrg            edev.firstBtn = 0;
4445f7df2e56Smrg            edev.nBtns = 0;
4446f7df2e56Smrg            edev.supported = XkbXI_AllFeaturesMask;
4447f7df2e56Smrg            edev.unsupported = 0;
4448f7df2e56Smrg            XkbSendExtensionDeviceNotify(dev, client, &edev);
44494642e01fSmrg        }
44504642e01fSmrg    }
44514642e01fSmrg    return Success;
44524642e01fSmrg}
44534642e01fSmrg
44544642e01fSmrgint
44554642e01fSmrgProcXkbSetNames(ClientPtr client)
44564642e01fSmrg{
4457f7df2e56Smrg    DeviceIntPtr dev;
4458f7df2e56Smrg    CARD32 *tmp;
4459f7df2e56Smrg    Atom bad;
4460f7df2e56Smrg    int rc;
44614642e01fSmrg
446205b261ecSmrg    REQUEST(xkbSetNamesReq);
446305b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetNamesReq);
446405b261ecSmrg
4465f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
4466f7df2e56Smrg        return BadAccess;
446705b261ecSmrg
44684642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
4469f7df2e56Smrg    CHK_MASK_LEGAL(0x01, stuff->which, XkbAllNamesMask);
447005b261ecSmrg
44714642e01fSmrg    /* check device-independent stuff */
4472f7df2e56Smrg    tmp = (CARD32 *) &stuff[1];
4473f7df2e56Smrg
4474806e81e9Smrg    if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
4475806e81e9Smrg        return BadLength;
4476f7df2e56Smrg    if (stuff->which & XkbKeycodesNameMask) {
4477f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4478f7df2e56Smrg        if (!tmp) {
4479f7df2e56Smrg            client->errorValue = bad;
4480f7df2e56Smrg            return BadAtom;
4481f7df2e56Smrg        }
4482f7df2e56Smrg    }
4483806e81e9Smrg    if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
4484806e81e9Smrg        return BadLength;
4485f7df2e56Smrg    if (stuff->which & XkbGeometryNameMask) {
4486f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4487f7df2e56Smrg        if (!tmp) {
4488f7df2e56Smrg            client->errorValue = bad;
4489f7df2e56Smrg            return BadAtom;
4490f7df2e56Smrg        }
4491f7df2e56Smrg    }
4492806e81e9Smrg    if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
4493806e81e9Smrg        return BadLength;
4494f7df2e56Smrg    if (stuff->which & XkbSymbolsNameMask) {
4495f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4496f7df2e56Smrg        if (!tmp) {
4497f7df2e56Smrg            client->errorValue = bad;
4498f7df2e56Smrg            return BadAtom;
4499f7df2e56Smrg        }
4500f7df2e56Smrg    }
4501806e81e9Smrg    if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
4502806e81e9Smrg        return BadLength;
4503f7df2e56Smrg    if (stuff->which & XkbPhysSymbolsNameMask) {
4504f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4505f7df2e56Smrg        if (!tmp) {
4506f7df2e56Smrg            client->errorValue = bad;
4507f7df2e56Smrg            return BadAtom;
4508f7df2e56Smrg        }
4509f7df2e56Smrg    }
4510806e81e9Smrg    if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
4511806e81e9Smrg        return BadLength;
4512f7df2e56Smrg    if (stuff->which & XkbTypesNameMask) {
4513f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4514f7df2e56Smrg        if (!tmp) {
4515f7df2e56Smrg            client->errorValue = bad;
4516f7df2e56Smrg            return BadAtom;
4517f7df2e56Smrg        }
4518f7df2e56Smrg    }
4519806e81e9Smrg    if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
4520806e81e9Smrg        return BadLength;
4521f7df2e56Smrg    if (stuff->which & XkbCompatNameMask) {
4522f7df2e56Smrg        tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4523f7df2e56Smrg        if (!tmp) {
4524f7df2e56Smrg            client->errorValue = bad;
4525f7df2e56Smrg            return BadAtom;
4526f7df2e56Smrg        }
452705b261ecSmrg    }
45284642e01fSmrg
45294642e01fSmrg    /* start of device-dependent tests */
45304642e01fSmrg    rc = _XkbSetNamesCheck(client, dev, stuff, tmp);
45314642e01fSmrg    if (rc != Success)
45324642e01fSmrg        return rc;
45334642e01fSmrg
4534f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
45354642e01fSmrg        DeviceIntPtr other;
45364642e01fSmrg
4537f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
4538f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
4539f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
4540f7df2e56Smrg
4541f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
4542f7df2e56Smrg                              DixManageAccess);
4543f7df2e56Smrg                if (rc == Success) {
45444642e01fSmrg                    rc = _XkbSetNamesCheck(client, other, stuff, tmp);
45454642e01fSmrg                    if (rc != Success)
45464642e01fSmrg                        return rc;
45474642e01fSmrg                }
45484642e01fSmrg            }
45494642e01fSmrg        }
455005b261ecSmrg    }
455105b261ecSmrg
455205b261ecSmrg    /* everything is okay -- update names */
455305b261ecSmrg
45544642e01fSmrg    rc = _XkbSetNames(client, dev, stuff);
45554642e01fSmrg    if (rc != Success)
45564642e01fSmrg        return rc;
455705b261ecSmrg
4558f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
45594642e01fSmrg        DeviceIntPtr other;
45604642e01fSmrg
4561f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
4562f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
4563f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
4564f7df2e56Smrg
4565f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
4566f7df2e56Smrg                              DixManageAccess);
45674642e01fSmrg                if (rc == Success)
45684642e01fSmrg                    _XkbSetNames(client, other, stuff);
45694642e01fSmrg            }
45704642e01fSmrg        }
457105b261ecSmrg    }
45724642e01fSmrg
45734642e01fSmrg    /* everything is okay -- update names */
45744642e01fSmrg
45756747b715Smrg    return Success;
457605b261ecSmrg}
457705b261ecSmrg
457805b261ecSmrg/***====================================================================***/
457905b261ecSmrg
45804642e01fSmrg#include "xkbgeom.h"
458105b261ecSmrg
458205b261ecSmrg#define	XkbSizeCountedString(s)  ((s)?((((2+strlen(s))+3)/4)*4):4)
458305b261ecSmrg
4584f7df2e56Smrg/**
4585f7df2e56Smrg * Write the zero-terminated string str into wire as a pascal string with a
4586f7df2e56Smrg * 16-bit length field prefixed before the actual string.
4587f7df2e56Smrg *
4588f7df2e56Smrg * @param wire The destination array, usually the wire struct
4589f7df2e56Smrg * @param str The source string as zero-terminated C string
4590f7df2e56Smrg * @param swap If TRUE, the length field is swapped.
4591f7df2e56Smrg *
4592f7df2e56Smrg * @return The input string in the format <string length><string> with a
4593f7df2e56Smrg * (swapped) 16 bit string length, non-zero terminated.
4594f7df2e56Smrg */
459505b261ecSmrgstatic char *
4596f7df2e56SmrgXkbWriteCountedString(char *wire, const char *str, Bool swap)
459705b261ecSmrg{
4598f7df2e56Smrg    CARD16 len, *pLen, paddedLen;
459905b261ecSmrg
46006747b715Smrg    if (!str)
46016747b715Smrg        return wire;
46026747b715Smrg
4603f7df2e56Smrg    len = strlen(str);
4604f7df2e56Smrg    pLen = (CARD16 *) wire;
4605f7df2e56Smrg    *pLen = len;
460605b261ecSmrg    if (swap) {
4607f7df2e56Smrg        swaps(pLen);
460805b261ecSmrg    }
4609f7df2e56Smrg    paddedLen = pad_to_int32(sizeof(len) + len) - sizeof(len);
4610f7df2e56Smrg    strncpy(&wire[sizeof(len)], str, paddedLen);
4611f7df2e56Smrg    wire += sizeof(len) + paddedLen;
461205b261ecSmrg    return wire;
461305b261ecSmrg}
461405b261ecSmrg
461505b261ecSmrgstatic int
461605b261ecSmrgXkbSizeGeomProperties(XkbGeometryPtr geom)
461705b261ecSmrg{
4618f7df2e56Smrg    register int i, size;
4619f7df2e56Smrg    XkbPropertyPtr prop;
4620f7df2e56Smrg
4621f7df2e56Smrg    for (size = i = 0, prop = geom->properties; i < geom->num_properties;
4622f7df2e56Smrg         i++, prop++) {
4623f7df2e56Smrg        size += XkbSizeCountedString(prop->name);
4624f7df2e56Smrg        size += XkbSizeCountedString(prop->value);
462505b261ecSmrg    }
462605b261ecSmrg    return size;
462705b261ecSmrg}
462805b261ecSmrg
462905b261ecSmrgstatic char *
4630f7df2e56SmrgXkbWriteGeomProperties(char *wire, XkbGeometryPtr geom, Bool swap)
463105b261ecSmrg{
4632f7df2e56Smrg    register int i;
4633f7df2e56Smrg    register XkbPropertyPtr prop;
4634f7df2e56Smrg
4635f7df2e56Smrg    for (i = 0, prop = geom->properties; i < geom->num_properties; i++, prop++) {
4636f7df2e56Smrg        wire = XkbWriteCountedString(wire, prop->name, swap);
4637f7df2e56Smrg        wire = XkbWriteCountedString(wire, prop->value, swap);
463805b261ecSmrg    }
463905b261ecSmrg    return wire;
464005b261ecSmrg}
464105b261ecSmrg
464205b261ecSmrgstatic int
464305b261ecSmrgXkbSizeGeomKeyAliases(XkbGeometryPtr geom)
464405b261ecSmrg{
4645f7df2e56Smrg    return geom->num_key_aliases * (2 * XkbKeyNameLength);
464605b261ecSmrg}
464705b261ecSmrg
464805b261ecSmrgstatic char *
4649f7df2e56SmrgXkbWriteGeomKeyAliases(char *wire, XkbGeometryPtr geom, Bool swap)
465005b261ecSmrg{
4651f7df2e56Smrg    register int sz;
4652f7df2e56Smrg
4653f7df2e56Smrg    sz = geom->num_key_aliases * (XkbKeyNameLength * 2);
4654f7df2e56Smrg    if (sz > 0) {
4655f7df2e56Smrg        memcpy(wire, (char *) geom->key_aliases, sz);
4656f7df2e56Smrg        wire += sz;
465705b261ecSmrg    }
465805b261ecSmrg    return wire;
465905b261ecSmrg}
466005b261ecSmrg
466105b261ecSmrgstatic int
466205b261ecSmrgXkbSizeGeomColors(XkbGeometryPtr geom)
466305b261ecSmrg{
4664f7df2e56Smrg    register int i, size;
4665f7df2e56Smrg    register XkbColorPtr color;
466605b261ecSmrg
4667f7df2e56Smrg    for (i = size = 0, color = geom->colors; i < geom->num_colors; i++, color++) {
4668f7df2e56Smrg        size += XkbSizeCountedString(color->spec);
466905b261ecSmrg    }
467005b261ecSmrg    return size;
467105b261ecSmrg}
467205b261ecSmrg
467305b261ecSmrgstatic char *
4674f7df2e56SmrgXkbWriteGeomColors(char *wire, XkbGeometryPtr geom, Bool swap)
467505b261ecSmrg{
4676f7df2e56Smrg    register int i;
4677f7df2e56Smrg    register XkbColorPtr color;
467805b261ecSmrg
4679f7df2e56Smrg    for (i = 0, color = geom->colors; i < geom->num_colors; i++, color++) {
4680f7df2e56Smrg        wire = XkbWriteCountedString(wire, color->spec, swap);
468105b261ecSmrg    }
468205b261ecSmrg    return wire;
468305b261ecSmrg}
468405b261ecSmrg
468505b261ecSmrgstatic int
468605b261ecSmrgXkbSizeGeomShapes(XkbGeometryPtr geom)
468705b261ecSmrg{
4688f7df2e56Smrg    register int i, size;
4689f7df2e56Smrg    register XkbShapePtr shape;
4690f7df2e56Smrg
4691f7df2e56Smrg    for (i = size = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) {
4692f7df2e56Smrg        register int n;
4693f7df2e56Smrg        register XkbOutlinePtr ol;
4694f7df2e56Smrg
4695f7df2e56Smrg        size += SIZEOF(xkbShapeWireDesc);
4696f7df2e56Smrg        for (n = 0, ol = shape->outlines; n < shape->num_outlines; n++, ol++) {
4697f7df2e56Smrg            size += SIZEOF(xkbOutlineWireDesc);
4698f7df2e56Smrg            size += ol->num_points * SIZEOF(xkbPointWireDesc);
4699f7df2e56Smrg        }
470005b261ecSmrg    }
470105b261ecSmrg    return size;
470205b261ecSmrg}
470305b261ecSmrg
470405b261ecSmrgstatic char *
4705f7df2e56SmrgXkbWriteGeomShapes(char *wire, XkbGeometryPtr geom, Bool swap)
470605b261ecSmrg{
4707f7df2e56Smrg    int i;
4708f7df2e56Smrg    XkbShapePtr shape;
4709f7df2e56Smrg    xkbShapeWireDesc *shapeWire;
4710f7df2e56Smrg
4711f7df2e56Smrg    for (i = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) {
4712f7df2e56Smrg        register int o;
4713f7df2e56Smrg        XkbOutlinePtr ol;
4714f7df2e56Smrg        xkbOutlineWireDesc *olWire;
4715f7df2e56Smrg
4716f7df2e56Smrg        shapeWire = (xkbShapeWireDesc *) wire;
4717f7df2e56Smrg        shapeWire->name = shape->name;
4718f7df2e56Smrg        shapeWire->nOutlines = shape->num_outlines;
4719f7df2e56Smrg        if (shape->primary != NULL)
4720f7df2e56Smrg            shapeWire->primaryNdx = XkbOutlineIndex(shape, shape->primary);
4721f7df2e56Smrg        else
4722f7df2e56Smrg            shapeWire->primaryNdx = XkbNoShape;
4723f7df2e56Smrg        if (shape->approx != NULL)
4724f7df2e56Smrg            shapeWire->approxNdx = XkbOutlineIndex(shape, shape->approx);
4725f7df2e56Smrg        else
4726f7df2e56Smrg            shapeWire->approxNdx = XkbNoShape;
4727f7df2e56Smrg        shapeWire->pad = 0;
4728f7df2e56Smrg        if (swap) {
4729f7df2e56Smrg            swapl(&shapeWire->name);
4730f7df2e56Smrg        }
4731f7df2e56Smrg        wire = (char *) &shapeWire[1];
4732f7df2e56Smrg        for (o = 0, ol = shape->outlines; o < shape->num_outlines; o++, ol++) {
4733f7df2e56Smrg            register int p;
4734f7df2e56Smrg            XkbPointPtr pt;
4735f7df2e56Smrg            xkbPointWireDesc *ptWire;
4736f7df2e56Smrg
4737f7df2e56Smrg            olWire = (xkbOutlineWireDesc *) wire;
4738f7df2e56Smrg            olWire->nPoints = ol->num_points;
4739f7df2e56Smrg            olWire->cornerRadius = ol->corner_radius;
4740f7df2e56Smrg            olWire->pad = 0;
4741f7df2e56Smrg            wire = (char *) &olWire[1];
4742f7df2e56Smrg            ptWire = (xkbPointWireDesc *) wire;
4743f7df2e56Smrg            for (p = 0, pt = ol->points; p < ol->num_points; p++, pt++) {
4744f7df2e56Smrg                ptWire[p].x = pt->x;
4745f7df2e56Smrg                ptWire[p].y = pt->y;
4746f7df2e56Smrg                if (swap) {
4747f7df2e56Smrg                    swaps(&ptWire[p].x);
4748f7df2e56Smrg                    swaps(&ptWire[p].y);
4749f7df2e56Smrg                }
4750f7df2e56Smrg            }
4751f7df2e56Smrg            wire = (char *) &ptWire[ol->num_points];
4752f7df2e56Smrg        }
475305b261ecSmrg    }
475405b261ecSmrg    return wire;
475505b261ecSmrg}
475605b261ecSmrg
475705b261ecSmrgstatic int
4758f7df2e56SmrgXkbSizeGeomDoodads(int num_doodads, XkbDoodadPtr doodad)
475905b261ecSmrg{
4760f7df2e56Smrg    register int i, size;
4761f7df2e56Smrg
4762f7df2e56Smrg    for (i = size = 0; i < num_doodads; i++, doodad++) {
4763f7df2e56Smrg        size += SIZEOF(xkbAnyDoodadWireDesc);
4764f7df2e56Smrg        if (doodad->any.type == XkbTextDoodad) {
4765f7df2e56Smrg            size += XkbSizeCountedString(doodad->text.text);
4766f7df2e56Smrg            size += XkbSizeCountedString(doodad->text.font);
4767f7df2e56Smrg        }
4768f7df2e56Smrg        else if (doodad->any.type == XkbLogoDoodad) {
4769f7df2e56Smrg            size += XkbSizeCountedString(doodad->logo.logo_name);
4770f7df2e56Smrg        }
477105b261ecSmrg    }
477205b261ecSmrg    return size;
477305b261ecSmrg}
477405b261ecSmrg
477505b261ecSmrgstatic char *
4776f7df2e56SmrgXkbWriteGeomDoodads(char *wire, int num_doodads, XkbDoodadPtr doodad, Bool swap)
477705b261ecSmrg{
4778f7df2e56Smrg    register int i;
4779f7df2e56Smrg    xkbDoodadWireDesc *doodadWire;
4780f7df2e56Smrg
4781f7df2e56Smrg    for (i = 0; i < num_doodads; i++, doodad++) {
4782f7df2e56Smrg        doodadWire = (xkbDoodadWireDesc *) wire;
4783f7df2e56Smrg        wire = (char *) &doodadWire[1];
4784f7df2e56Smrg        memset(doodadWire, 0, SIZEOF(xkbDoodadWireDesc));
4785f7df2e56Smrg        doodadWire->any.name = doodad->any.name;
4786f7df2e56Smrg        doodadWire->any.type = doodad->any.type;
4787f7df2e56Smrg        doodadWire->any.priority = doodad->any.priority;
4788f7df2e56Smrg        doodadWire->any.top = doodad->any.top;
4789f7df2e56Smrg        doodadWire->any.left = doodad->any.left;
4790f7df2e56Smrg        if (swap) {
4791f7df2e56Smrg            swapl(&doodadWire->any.name);
4792f7df2e56Smrg            swaps(&doodadWire->any.top);
4793f7df2e56Smrg            swaps(&doodadWire->any.left);
4794f7df2e56Smrg        }
4795f7df2e56Smrg        switch (doodad->any.type) {
4796f7df2e56Smrg        case XkbOutlineDoodad:
4797f7df2e56Smrg        case XkbSolidDoodad:
4798f7df2e56Smrg            doodadWire->shape.angle = doodad->shape.angle;
4799f7df2e56Smrg            doodadWire->shape.colorNdx = doodad->shape.color_ndx;
4800f7df2e56Smrg            doodadWire->shape.shapeNdx = doodad->shape.shape_ndx;
4801f7df2e56Smrg            if (swap) {
4802f7df2e56Smrg                swaps(&doodadWire->shape.angle);
4803f7df2e56Smrg            }
4804f7df2e56Smrg            break;
4805f7df2e56Smrg        case XkbTextDoodad:
4806f7df2e56Smrg            doodadWire->text.angle = doodad->text.angle;
4807f7df2e56Smrg            doodadWire->text.width = doodad->text.width;
4808f7df2e56Smrg            doodadWire->text.height = doodad->text.height;
4809f7df2e56Smrg            doodadWire->text.colorNdx = doodad->text.color_ndx;
4810f7df2e56Smrg            if (swap) {
4811f7df2e56Smrg                swaps(&doodadWire->text.angle);
4812f7df2e56Smrg                swaps(&doodadWire->text.width);
4813f7df2e56Smrg                swaps(&doodadWire->text.height);
4814f7df2e56Smrg            }
4815f7df2e56Smrg            wire = XkbWriteCountedString(wire, doodad->text.text, swap);
4816f7df2e56Smrg            wire = XkbWriteCountedString(wire, doodad->text.font, swap);
4817f7df2e56Smrg            break;
4818f7df2e56Smrg        case XkbIndicatorDoodad:
4819f7df2e56Smrg            doodadWire->indicator.shapeNdx = doodad->indicator.shape_ndx;
4820f7df2e56Smrg            doodadWire->indicator.onColorNdx = doodad->indicator.on_color_ndx;
4821f7df2e56Smrg            doodadWire->indicator.offColorNdx = doodad->indicator.off_color_ndx;
4822f7df2e56Smrg            break;
4823f7df2e56Smrg        case XkbLogoDoodad:
4824f7df2e56Smrg            doodadWire->logo.angle = doodad->logo.angle;
4825f7df2e56Smrg            doodadWire->logo.colorNdx = doodad->logo.color_ndx;
4826f7df2e56Smrg            doodadWire->logo.shapeNdx = doodad->logo.shape_ndx;
4827f7df2e56Smrg            wire = XkbWriteCountedString(wire, doodad->logo.logo_name, swap);
4828f7df2e56Smrg            break;
4829f7df2e56Smrg        default:
4830f7df2e56Smrg            ErrorF("[xkb] Unknown doodad type %d in XkbWriteGeomDoodads\n",
4831f7df2e56Smrg                   doodad->any.type);
4832f7df2e56Smrg            ErrorF("[xkb] Ignored\n");
4833f7df2e56Smrg            break;
4834f7df2e56Smrg        }
483505b261ecSmrg    }
483605b261ecSmrg    return wire;
483705b261ecSmrg}
483805b261ecSmrg
483905b261ecSmrgstatic char *
4840f7df2e56SmrgXkbWriteGeomOverlay(char *wire, XkbOverlayPtr ol, Bool swap)
484105b261ecSmrg{
4842f7df2e56Smrg    register int r;
4843f7df2e56Smrg    XkbOverlayRowPtr row;
4844f7df2e56Smrg    xkbOverlayWireDesc *olWire;
4845f7df2e56Smrg
4846f7df2e56Smrg    olWire = (xkbOverlayWireDesc *) wire;
4847f7df2e56Smrg    olWire->name = ol->name;
4848f7df2e56Smrg    olWire->nRows = ol->num_rows;
4849f7df2e56Smrg    olWire->pad1 = 0;
4850f7df2e56Smrg    olWire->pad2 = 0;
4851f7df2e56Smrg    if (swap) {
4852f7df2e56Smrg        swapl(&olWire->name);
4853f7df2e56Smrg    }
4854f7df2e56Smrg    wire = (char *) &olWire[1];
4855f7df2e56Smrg    for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) {
4856f7df2e56Smrg        unsigned int k;
4857f7df2e56Smrg        XkbOverlayKeyPtr key;
4858f7df2e56Smrg        xkbOverlayRowWireDesc *rowWire;
4859f7df2e56Smrg
4860f7df2e56Smrg        rowWire = (xkbOverlayRowWireDesc *) wire;
4861f7df2e56Smrg        rowWire->rowUnder = row->row_under;
4862f7df2e56Smrg        rowWire->nKeys = row->num_keys;
4863f7df2e56Smrg        rowWire->pad1 = 0;
4864f7df2e56Smrg        wire = (char *) &rowWire[1];
4865f7df2e56Smrg        for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
4866f7df2e56Smrg            xkbOverlayKeyWireDesc *keyWire;
4867f7df2e56Smrg
4868f7df2e56Smrg            keyWire = (xkbOverlayKeyWireDesc *) wire;
4869f7df2e56Smrg            memcpy(keyWire->over, key->over.name, XkbKeyNameLength);
4870f7df2e56Smrg            memcpy(keyWire->under, key->under.name, XkbKeyNameLength);
4871f7df2e56Smrg            wire = (char *) &keyWire[1];
4872f7df2e56Smrg        }
4873f7df2e56Smrg    }
4874f7df2e56Smrg    return wire;
487505b261ecSmrg}
487605b261ecSmrg
487705b261ecSmrgstatic int
487805b261ecSmrgXkbSizeGeomSections(XkbGeometryPtr geom)
487905b261ecSmrg{
4880f7df2e56Smrg    register int i, size;
4881f7df2e56Smrg    XkbSectionPtr section;
4882f7df2e56Smrg
4883f7df2e56Smrg    for (i = size = 0, section = geom->sections; i < geom->num_sections;
4884f7df2e56Smrg         i++, section++) {
4885f7df2e56Smrg        size += SIZEOF(xkbSectionWireDesc);
4886f7df2e56Smrg        if (section->rows) {
4887f7df2e56Smrg            int r;
4888f7df2e56Smrg            XkbRowPtr row;
4889f7df2e56Smrg
4890f7df2e56Smrg            for (r = 0, row = section->rows; r < section->num_rows; row++, r++) {
4891f7df2e56Smrg                size += SIZEOF(xkbRowWireDesc);
4892f7df2e56Smrg                size += row->num_keys * SIZEOF(xkbKeyWireDesc);
4893f7df2e56Smrg            }
4894f7df2e56Smrg        }
4895f7df2e56Smrg        if (section->doodads)
4896f7df2e56Smrg            size += XkbSizeGeomDoodads(section->num_doodads, section->doodads);
4897f7df2e56Smrg        if (section->overlays) {
4898f7df2e56Smrg            int o;
4899f7df2e56Smrg            XkbOverlayPtr ol;
4900f7df2e56Smrg
4901f7df2e56Smrg            for (o = 0, ol = section->overlays; o < section->num_overlays;
4902f7df2e56Smrg                 o++, ol++) {
4903f7df2e56Smrg                int r;
4904f7df2e56Smrg                XkbOverlayRowPtr row;
4905f7df2e56Smrg
4906f7df2e56Smrg                size += SIZEOF(xkbOverlayWireDesc);
4907f7df2e56Smrg                for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) {
4908f7df2e56Smrg                    size += SIZEOF(xkbOverlayRowWireDesc);
4909f7df2e56Smrg                    size += row->num_keys * SIZEOF(xkbOverlayKeyWireDesc);
4910f7df2e56Smrg                }
4911f7df2e56Smrg            }
4912f7df2e56Smrg        }
491305b261ecSmrg    }
491405b261ecSmrg    return size;
491505b261ecSmrg}
491605b261ecSmrg
491705b261ecSmrgstatic char *
4918f7df2e56SmrgXkbWriteGeomSections(char *wire, XkbGeometryPtr geom, Bool swap)
491905b261ecSmrg{
4920f7df2e56Smrg    register int i;
4921f7df2e56Smrg    XkbSectionPtr section;
4922f7df2e56Smrg    xkbSectionWireDesc *sectionWire;
4923f7df2e56Smrg
4924f7df2e56Smrg    for (i = 0, section = geom->sections; i < geom->num_sections;
4925f7df2e56Smrg         i++, section++) {
4926f7df2e56Smrg        sectionWire = (xkbSectionWireDesc *) wire;
4927f7df2e56Smrg        sectionWire->name = section->name;
4928f7df2e56Smrg        sectionWire->top = section->top;
4929f7df2e56Smrg        sectionWire->left = section->left;
4930f7df2e56Smrg        sectionWire->width = section->width;
4931f7df2e56Smrg        sectionWire->height = section->height;
4932f7df2e56Smrg        sectionWire->angle = section->angle;
4933f7df2e56Smrg        sectionWire->priority = section->priority;
4934f7df2e56Smrg        sectionWire->nRows = section->num_rows;
4935f7df2e56Smrg        sectionWire->nDoodads = section->num_doodads;
4936f7df2e56Smrg        sectionWire->nOverlays = section->num_overlays;
4937f7df2e56Smrg        sectionWire->pad = 0;
4938f7df2e56Smrg        if (swap) {
4939f7df2e56Smrg            swapl(&sectionWire->name);
4940f7df2e56Smrg            swaps(&sectionWire->top);
4941f7df2e56Smrg            swaps(&sectionWire->left);
4942f7df2e56Smrg            swaps(&sectionWire->width);
4943f7df2e56Smrg            swaps(&sectionWire->height);
4944f7df2e56Smrg            swaps(&sectionWire->angle);
4945f7df2e56Smrg        }
4946f7df2e56Smrg        wire = (char *) &sectionWire[1];
4947f7df2e56Smrg        if (section->rows) {
4948f7df2e56Smrg            int r;
4949f7df2e56Smrg            XkbRowPtr row;
4950f7df2e56Smrg            xkbRowWireDesc *rowWire;
4951f7df2e56Smrg
4952f7df2e56Smrg            for (r = 0, row = section->rows; r < section->num_rows; r++, row++) {
4953f7df2e56Smrg                rowWire = (xkbRowWireDesc *) wire;
4954f7df2e56Smrg                rowWire->top = row->top;
4955f7df2e56Smrg                rowWire->left = row->left;
4956f7df2e56Smrg                rowWire->nKeys = row->num_keys;
4957f7df2e56Smrg                rowWire->vertical = row->vertical;
4958f7df2e56Smrg                rowWire->pad = 0;
4959f7df2e56Smrg                if (swap) {
4960f7df2e56Smrg                    swaps(&rowWire->top);
4961f7df2e56Smrg                    swaps(&rowWire->left);
4962f7df2e56Smrg                }
4963f7df2e56Smrg                wire = (char *) &rowWire[1];
4964f7df2e56Smrg                if (row->keys) {
4965f7df2e56Smrg                    int k;
4966f7df2e56Smrg                    XkbKeyPtr key;
4967f7df2e56Smrg                    xkbKeyWireDesc *keyWire;
4968f7df2e56Smrg
4969f7df2e56Smrg                    keyWire = (xkbKeyWireDesc *) wire;
4970f7df2e56Smrg                    for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
4971f7df2e56Smrg                        memcpy(keyWire[k].name, key->name.name,
4972f7df2e56Smrg                               XkbKeyNameLength);
4973f7df2e56Smrg                        keyWire[k].gap = key->gap;
4974f7df2e56Smrg                        keyWire[k].shapeNdx = key->shape_ndx;
4975f7df2e56Smrg                        keyWire[k].colorNdx = key->color_ndx;
4976f7df2e56Smrg                        if (swap) {
4977f7df2e56Smrg                            swaps(&keyWire[k].gap);
4978f7df2e56Smrg                        }
4979f7df2e56Smrg                    }
4980f7df2e56Smrg                    wire = (char *) &keyWire[row->num_keys];
4981f7df2e56Smrg                }
4982f7df2e56Smrg            }
4983f7df2e56Smrg        }
4984f7df2e56Smrg        if (section->doodads) {
4985f7df2e56Smrg            wire = XkbWriteGeomDoodads(wire,
4986f7df2e56Smrg                                       section->num_doodads, section->doodads,
4987f7df2e56Smrg                                       swap);
4988f7df2e56Smrg        }
4989f7df2e56Smrg        if (section->overlays) {
4990f7df2e56Smrg            register int o;
4991f7df2e56Smrg
4992f7df2e56Smrg            for (o = 0; o < section->num_overlays; o++) {
4993f7df2e56Smrg                wire = XkbWriteGeomOverlay(wire, &section->overlays[o], swap);
4994f7df2e56Smrg            }
4995f7df2e56Smrg        }
499605b261ecSmrg    }
499705b261ecSmrg    return wire;
499805b261ecSmrg}
499905b261ecSmrg
500005b261ecSmrgstatic Status
5001f7df2e56SmrgXkbComputeGetGeometryReplySize(XkbGeometryPtr geom,
5002f7df2e56Smrg                               xkbGetGeometryReply * rep, Atom name)
500305b261ecSmrg{
5004f7df2e56Smrg    int len;
5005f7df2e56Smrg
5006f7df2e56Smrg    if (geom != NULL) {
5007f7df2e56Smrg        len = XkbSizeCountedString(geom->label_font);
5008f7df2e56Smrg        len += XkbSizeGeomProperties(geom);
5009f7df2e56Smrg        len += XkbSizeGeomColors(geom);
5010f7df2e56Smrg        len += XkbSizeGeomShapes(geom);
5011f7df2e56Smrg        len += XkbSizeGeomSections(geom);
5012f7df2e56Smrg        len += XkbSizeGeomDoodads(geom->num_doodads, geom->doodads);
5013f7df2e56Smrg        len += XkbSizeGeomKeyAliases(geom);
5014f7df2e56Smrg        rep->length = len / 4;
5015f7df2e56Smrg        rep->found = TRUE;
5016f7df2e56Smrg        rep->name = geom->name;
5017f7df2e56Smrg        rep->widthMM = geom->width_mm;
5018f7df2e56Smrg        rep->heightMM = geom->height_mm;
5019f7df2e56Smrg        rep->nProperties = geom->num_properties;
5020f7df2e56Smrg        rep->nColors = geom->num_colors;
5021f7df2e56Smrg        rep->nShapes = geom->num_shapes;
5022f7df2e56Smrg        rep->nSections = geom->num_sections;
5023f7df2e56Smrg        rep->nDoodads = geom->num_doodads;
5024f7df2e56Smrg        rep->nKeyAliases = geom->num_key_aliases;
5025f7df2e56Smrg        rep->baseColorNdx = XkbGeomColorIndex(geom, geom->base_color);
5026f7df2e56Smrg        rep->labelColorNdx = XkbGeomColorIndex(geom, geom->label_color);
502705b261ecSmrg    }
502805b261ecSmrg    else {
5029f7df2e56Smrg        rep->length = 0;
5030f7df2e56Smrg        rep->found = FALSE;
5031f7df2e56Smrg        rep->name = name;
5032f7df2e56Smrg        rep->widthMM = rep->heightMM = 0;
5033f7df2e56Smrg        rep->nProperties = rep->nColors = rep->nShapes = 0;
5034f7df2e56Smrg        rep->nSections = rep->nDoodads = 0;
5035f7df2e56Smrg        rep->nKeyAliases = 0;
5036f7df2e56Smrg        rep->labelColorNdx = rep->baseColorNdx = 0;
503705b261ecSmrg    }
503805b261ecSmrg    return Success;
503905b261ecSmrg}
504005b261ecSmrgstatic int
5041f7df2e56SmrgXkbSendGeometry(ClientPtr client,
5042f7df2e56Smrg                XkbGeometryPtr geom, xkbGetGeometryReply * rep, Bool freeGeom)
504305b261ecSmrg{
5044f7df2e56Smrg    char *desc, *start;
5045f7df2e56Smrg    int len;
5046f7df2e56Smrg
5047f7df2e56Smrg    if (geom != NULL) {
5048f7df2e56Smrg        start = desc = xallocarray(rep->length, 4);
5049f7df2e56Smrg        if (!start)
5050f7df2e56Smrg            return BadAlloc;
5051f7df2e56Smrg        len = rep->length * 4;
5052f7df2e56Smrg        desc = XkbWriteCountedString(desc, geom->label_font, client->swapped);
5053f7df2e56Smrg        if (rep->nProperties > 0)
5054f7df2e56Smrg            desc = XkbWriteGeomProperties(desc, geom, client->swapped);
5055f7df2e56Smrg        if (rep->nColors > 0)
5056f7df2e56Smrg            desc = XkbWriteGeomColors(desc, geom, client->swapped);
5057f7df2e56Smrg        if (rep->nShapes > 0)
5058f7df2e56Smrg            desc = XkbWriteGeomShapes(desc, geom, client->swapped);
5059f7df2e56Smrg        if (rep->nSections > 0)
5060f7df2e56Smrg            desc = XkbWriteGeomSections(desc, geom, client->swapped);
5061f7df2e56Smrg        if (rep->nDoodads > 0)
5062f7df2e56Smrg            desc = XkbWriteGeomDoodads(desc, geom->num_doodads, geom->doodads,
5063f7df2e56Smrg                                       client->swapped);
5064f7df2e56Smrg        if (rep->nKeyAliases > 0)
5065f7df2e56Smrg            desc = XkbWriteGeomKeyAliases(desc, geom, client->swapped);
5066f7df2e56Smrg        if ((desc - start) != (len)) {
5067f7df2e56Smrg            ErrorF
5068f7df2e56Smrg                ("[xkb] BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n",
5069f7df2e56Smrg                 len, (unsigned long) (desc - start));
5070f7df2e56Smrg        }
507105b261ecSmrg    }
507205b261ecSmrg    else {
5073f7df2e56Smrg        len = 0;
5074f7df2e56Smrg        start = NULL;
507505b261ecSmrg    }
507605b261ecSmrg    if (client->swapped) {
5077f7df2e56Smrg        swaps(&rep->sequenceNumber);
5078f7df2e56Smrg        swapl(&rep->length);
5079f7df2e56Smrg        swapl(&rep->name);
5080f7df2e56Smrg        swaps(&rep->widthMM);
5081f7df2e56Smrg        swaps(&rep->heightMM);
5082f7df2e56Smrg        swaps(&rep->nProperties);
5083f7df2e56Smrg        swaps(&rep->nColors);
5084f7df2e56Smrg        swaps(&rep->nShapes);
5085f7df2e56Smrg        swaps(&rep->nSections);
5086f7df2e56Smrg        swaps(&rep->nDoodads);
5087f7df2e56Smrg        swaps(&rep->nKeyAliases);
5088f7df2e56Smrg    }
5089f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetGeometryReply), rep);
5090f7df2e56Smrg    if (len > 0)
5091f7df2e56Smrg        WriteToClient(client, len, start);
5092f7df2e56Smrg    if (start != NULL)
5093f7df2e56Smrg        free((char *) start);
509405b261ecSmrg    if (freeGeom)
5095f7df2e56Smrg        XkbFreeGeometry(geom, XkbGeomAllMask, TRUE);
50966747b715Smrg    return Success;
509705b261ecSmrg}
509805b261ecSmrg
509905b261ecSmrgint
510005b261ecSmrgProcXkbGetGeometry(ClientPtr client)
510105b261ecSmrg{
5102f7df2e56Smrg    DeviceIntPtr dev;
510305b261ecSmrg    xkbGetGeometryReply rep;
5104f7df2e56Smrg    XkbGeometryPtr geom;
5105f7df2e56Smrg    Bool shouldFree;
5106f7df2e56Smrg    Status status;
510705b261ecSmrg
510805b261ecSmrg    REQUEST(xkbGetGeometryReq);
510905b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetGeometryReq);
511005b261ecSmrg
5111f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
5112f7df2e56Smrg        return BadAccess;
511305b261ecSmrg
51144642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
511505b261ecSmrg    CHK_ATOM_OR_NONE(stuff->name);
511605b261ecSmrg
5117f7df2e56Smrg    geom = XkbLookupNamedGeometry(dev, stuff->name, &shouldFree);
5118f7df2e56Smrg    rep = (xkbGetGeometryReply) {
5119f7df2e56Smrg        .type = X_Reply,
5120f7df2e56Smrg        .deviceID = dev->id,
5121f7df2e56Smrg        .sequenceNumber = client->sequence,
5122f7df2e56Smrg        .length = 0
5123f7df2e56Smrg    };
5124f7df2e56Smrg    status = XkbComputeGetGeometryReplySize(geom, &rep, stuff->name);
5125f7df2e56Smrg    if (status != Success)
5126f7df2e56Smrg        return status;
5127f7df2e56Smrg    else
5128f7df2e56Smrg        return XkbSendGeometry(client, geom, &rep, shouldFree);
512905b261ecSmrg}
513005b261ecSmrg
513105b261ecSmrg/***====================================================================***/
513205b261ecSmrg
51331e26616aSmrgstatic Status
51341e26616aSmrg_GetCountedString(char **wire_inout, ClientPtr client, char **str)
513505b261ecSmrg{
51361e26616aSmrg    char *wire, *next;
51371e26616aSmrg    CARD16 len;
513805b261ecSmrg
51391e26616aSmrg    wire = *wire_inout;
51402d19872aSmrg
51412d19872aSmrg    if (client->req_len <
51422d19872aSmrg        bytes_to_int32(wire + 2 - (char *) client->requestBuffer))
51432d19872aSmrg        return BadValue;
51442d19872aSmrg
51451e26616aSmrg    len = *(CARD16 *) wire;
51461e26616aSmrg    if (client->swapped) {
5147f7df2e56Smrg        swaps(&len);
514805b261ecSmrg    }
51491e26616aSmrg    next = wire + XkbPaddedSize(len + 2);
51501e26616aSmrg    /* Check we're still within the size of the request */
51511e26616aSmrg    if (client->req_len <
51521e26616aSmrg        bytes_to_int32(next - (char *) client->requestBuffer))
51531e26616aSmrg        return BadValue;
51541e26616aSmrg    *str = malloc(len + 1);
51551e26616aSmrg    if (!*str)
51561e26616aSmrg        return BadAlloc;
51571e26616aSmrg    memcpy(*str, &wire[2], len);
51581e26616aSmrg    *(*str + len) = '\0';
51591e26616aSmrg    *wire_inout = next;
51601e26616aSmrg    return Success;
516105b261ecSmrg}
516205b261ecSmrg
516305b261ecSmrgstatic Status
516490bea6a0Smrg_CheckSetDoodad(char **wire_inout, xkbSetGeometryReq *req,
5165f7df2e56Smrg                XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client)
516605b261ecSmrg{
5167f7df2e56Smrg    char *wire;
5168f7df2e56Smrg    xkbDoodadWireDesc *dWire;
5169f7df2e56Smrg    xkbAnyDoodadWireDesc any;
5170f7df2e56Smrg    xkbTextDoodadWireDesc text;
5171f7df2e56Smrg    XkbDoodadPtr doodad;
51721e26616aSmrg    Status status;
517305b261ecSmrg
5174f7df2e56Smrg    dWire = (xkbDoodadWireDesc *) (*wire_inout);
517590bea6a0Smrg    if (!_XkbCheckRequestBounds(client, req, dWire, dWire + 1))
517690bea6a0Smrg        return BadLength;
517790bea6a0Smrg
5178f7df2e56Smrg    any = dWire->any;
5179f7df2e56Smrg    wire = (char *) &dWire[1];
518005b261ecSmrg    if (client->swapped) {
5181f7df2e56Smrg        swapl(&any.name);
5182f7df2e56Smrg        swaps(&any.top);
5183f7df2e56Smrg        swaps(&any.left);
5184f7df2e56Smrg        swaps(&any.angle);
518505b261ecSmrg    }
518605b261ecSmrg    CHK_ATOM_ONLY(dWire->any.name);
5187f7df2e56Smrg    doodad = XkbAddGeomDoodad(geom, section, any.name);
518805b261ecSmrg    if (!doodad)
5189f7df2e56Smrg        return BadAlloc;
5190f7df2e56Smrg    doodad->any.type = dWire->any.type;
5191f7df2e56Smrg    doodad->any.priority = dWire->any.priority;
5192f7df2e56Smrg    doodad->any.top = any.top;
5193f7df2e56Smrg    doodad->any.left = any.left;
5194f7df2e56Smrg    doodad->any.angle = any.angle;
519505b261ecSmrg    switch (doodad->any.type) {
5196f7df2e56Smrg    case XkbOutlineDoodad:
5197f7df2e56Smrg    case XkbSolidDoodad:
5198f7df2e56Smrg        if (dWire->shape.colorNdx >= geom->num_colors) {
5199f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x40, geom->num_colors,
5200f7df2e56Smrg                                              dWire->shape.colorNdx);
5201f7df2e56Smrg            return BadMatch;
5202f7df2e56Smrg        }
5203f7df2e56Smrg        if (dWire->shape.shapeNdx >= geom->num_shapes) {
5204f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x41, geom->num_shapes,
5205f7df2e56Smrg                                              dWire->shape.shapeNdx);
5206f7df2e56Smrg            return BadMatch;
5207f7df2e56Smrg        }
5208f7df2e56Smrg        doodad->shape.color_ndx = dWire->shape.colorNdx;
5209f7df2e56Smrg        doodad->shape.shape_ndx = dWire->shape.shapeNdx;
5210f7df2e56Smrg        break;
5211f7df2e56Smrg    case XkbTextDoodad:
5212f7df2e56Smrg        if (dWire->text.colorNdx >= geom->num_colors) {
5213f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x42, geom->num_colors,
5214f7df2e56Smrg                                              dWire->text.colorNdx);
5215f7df2e56Smrg            return BadMatch;
5216f7df2e56Smrg        }
5217f7df2e56Smrg        text = dWire->text;
5218f7df2e56Smrg        if (client->swapped) {
5219f7df2e56Smrg            swaps(&text.width);
5220f7df2e56Smrg            swaps(&text.height);
5221f7df2e56Smrg        }
5222f7df2e56Smrg        doodad->text.width = text.width;
5223f7df2e56Smrg        doodad->text.height = text.height;
5224f7df2e56Smrg        doodad->text.color_ndx = dWire->text.colorNdx;
5225f7df2e56Smrg        status = _GetCountedString(&wire, client, &doodad->text.text);
5226f7df2e56Smrg        if (status != Success)
5227f7df2e56Smrg            return status;
5228f7df2e56Smrg        status = _GetCountedString(&wire, client, &doodad->text.font);
5229f7df2e56Smrg        if (status != Success) {
5230f7df2e56Smrg            free (doodad->text.text);
5231f7df2e56Smrg            return status;
5232f7df2e56Smrg        }
5233f7df2e56Smrg        break;
5234f7df2e56Smrg    case XkbIndicatorDoodad:
5235f7df2e56Smrg        if (dWire->indicator.onColorNdx >= geom->num_colors) {
5236f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x43, geom->num_colors,
5237f7df2e56Smrg                                              dWire->indicator.onColorNdx);
5238f7df2e56Smrg            return BadMatch;
5239f7df2e56Smrg        }
5240f7df2e56Smrg        if (dWire->indicator.offColorNdx >= geom->num_colors) {
5241f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x44, geom->num_colors,
5242f7df2e56Smrg                                              dWire->indicator.offColorNdx);
5243f7df2e56Smrg            return BadMatch;
5244f7df2e56Smrg        }
5245f7df2e56Smrg        if (dWire->indicator.shapeNdx >= geom->num_shapes) {
5246f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x45, geom->num_shapes,
5247f7df2e56Smrg                                              dWire->indicator.shapeNdx);
5248f7df2e56Smrg            return BadMatch;
5249f7df2e56Smrg        }
5250f7df2e56Smrg        doodad->indicator.shape_ndx = dWire->indicator.shapeNdx;
5251f7df2e56Smrg        doodad->indicator.on_color_ndx = dWire->indicator.onColorNdx;
5252f7df2e56Smrg        doodad->indicator.off_color_ndx = dWire->indicator.offColorNdx;
5253f7df2e56Smrg        break;
5254f7df2e56Smrg    case XkbLogoDoodad:
5255f7df2e56Smrg        if (dWire->logo.colorNdx >= geom->num_colors) {
5256f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x46, geom->num_colors,
5257f7df2e56Smrg                                              dWire->logo.colorNdx);
5258f7df2e56Smrg            return BadMatch;
5259f7df2e56Smrg        }
5260f7df2e56Smrg        if (dWire->logo.shapeNdx >= geom->num_shapes) {
5261f7df2e56Smrg            client->errorValue = _XkbErrCode3(0x47, geom->num_shapes,
5262f7df2e56Smrg                                              dWire->logo.shapeNdx);
5263f7df2e56Smrg            return BadMatch;
5264f7df2e56Smrg        }
5265f7df2e56Smrg        doodad->logo.color_ndx = dWire->logo.colorNdx;
5266f7df2e56Smrg        doodad->logo.shape_ndx = dWire->logo.shapeNdx;
5267f7df2e56Smrg        status = _GetCountedString(&wire, client, &doodad->logo.logo_name);
5268f7df2e56Smrg        if (status != Success)
5269f7df2e56Smrg            return status;
5270f7df2e56Smrg        break;
5271f7df2e56Smrg    default:
5272f7df2e56Smrg        client->errorValue = _XkbErrCode2(0x4F, dWire->any.type);
5273f7df2e56Smrg        return BadValue;
5274f7df2e56Smrg    }
5275f7df2e56Smrg    *wire_inout = wire;
5276f7df2e56Smrg    return Success;
5277f7df2e56Smrg}
5278f7df2e56Smrg
5279f7df2e56Smrgstatic Status
528090bea6a0Smrg_CheckSetOverlay(char **wire_inout, xkbSetGeometryReq *req,
5281f7df2e56Smrg                 XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client)
528205b261ecSmrg{
5283f7df2e56Smrg    register int r;
5284f7df2e56Smrg    char *wire;
5285f7df2e56Smrg    XkbOverlayPtr ol;
5286f7df2e56Smrg    xkbOverlayWireDesc *olWire;
5287f7df2e56Smrg    xkbOverlayRowWireDesc *rWire;
528805b261ecSmrg
5289f7df2e56Smrg    wire = *wire_inout;
5290f7df2e56Smrg    olWire = (xkbOverlayWireDesc *) wire;
529190bea6a0Smrg    if (!_XkbCheckRequestBounds(client, req, olWire, olWire + 1))
529290bea6a0Smrg        return BadLength;
529390bea6a0Smrg
5294f7df2e56Smrg    if (client->swapped) {
5295f7df2e56Smrg        swapl(&olWire->name);
5296f7df2e56Smrg    }
5297f7df2e56Smrg    CHK_ATOM_ONLY(olWire->name);
5298f7df2e56Smrg    ol = XkbAddGeomOverlay(section, olWire->name, olWire->nRows);
5299f7df2e56Smrg    rWire = (xkbOverlayRowWireDesc *) &olWire[1];
5300f7df2e56Smrg    for (r = 0; r < olWire->nRows; r++) {
5301f7df2e56Smrg        register int k;
5302f7df2e56Smrg        xkbOverlayKeyWireDesc *kWire;
5303f7df2e56Smrg        XkbOverlayRowPtr row;
5304f7df2e56Smrg
530590bea6a0Smrg        if (!_XkbCheckRequestBounds(client, req, rWire, rWire + 1))
530690bea6a0Smrg            return BadLength;
530790bea6a0Smrg
5308f7df2e56Smrg        if (rWire->rowUnder > section->num_rows) {
5309f7df2e56Smrg            client->errorValue = _XkbErrCode4(0x20, r, section->num_rows,
5310f7df2e56Smrg                                              rWire->rowUnder);
5311f7df2e56Smrg            return BadMatch;
5312f7df2e56Smrg        }
5313f7df2e56Smrg        row = XkbAddGeomOverlayRow(ol, rWire->rowUnder, rWire->nKeys);
5314f7df2e56Smrg        kWire = (xkbOverlayKeyWireDesc *) &rWire[1];
5315f7df2e56Smrg        for (k = 0; k < rWire->nKeys; k++, kWire++) {
531690bea6a0Smrg            if (!_XkbCheckRequestBounds(client, req, kWire, kWire + 1))
531790bea6a0Smrg                return BadLength;
531890bea6a0Smrg
5319f7df2e56Smrg            if (XkbAddGeomOverlayKey(ol, row,
5320f7df2e56Smrg                                     (char *) kWire->over,
5321f7df2e56Smrg                                     (char *) kWire->under) == NULL) {
5322f7df2e56Smrg                client->errorValue = _XkbErrCode3(0x21, r, k);
5323f7df2e56Smrg                return BadMatch;
5324f7df2e56Smrg            }
5325f7df2e56Smrg        }
5326f7df2e56Smrg        rWire = (xkbOverlayRowWireDesc *) kWire;
5327f7df2e56Smrg    }
5328f7df2e56Smrg    olWire = (xkbOverlayWireDesc *) rWire;
5329f7df2e56Smrg    wire = (char *) olWire;
5330f7df2e56Smrg    *wire_inout = wire;
5331f7df2e56Smrg    return Success;
5332f7df2e56Smrg}
5333f7df2e56Smrg
5334f7df2e56Smrgstatic Status
5335f7df2e56Smrg_CheckSetSections(XkbGeometryPtr geom,
5336f7df2e56Smrg                  xkbSetGeometryReq * req, char **wire_inout, ClientPtr client)
5337f7df2e56Smrg{
5338f7df2e56Smrg    Status status;
5339f7df2e56Smrg    register int s;
5340f7df2e56Smrg    char *wire;
5341f7df2e56Smrg    xkbSectionWireDesc *sWire;
5342f7df2e56Smrg    XkbSectionPtr section;
5343f7df2e56Smrg
5344f7df2e56Smrg    wire = *wire_inout;
5345f7df2e56Smrg    if (req->nSections < 1)
5346f7df2e56Smrg        return Success;
5347f7df2e56Smrg    sWire = (xkbSectionWireDesc *) wire;
5348f7df2e56Smrg    for (s = 0; s < req->nSections; s++) {
5349f7df2e56Smrg        register int r;
5350f7df2e56Smrg        xkbRowWireDesc *rWire;
5351f7df2e56Smrg
535290bea6a0Smrg        if (!_XkbCheckRequestBounds(client, req, sWire, sWire + 1))
535390bea6a0Smrg            return BadLength;
535490bea6a0Smrg
5355f7df2e56Smrg        if (client->swapped) {
5356f7df2e56Smrg            swapl(&sWire->name);
5357f7df2e56Smrg            swaps(&sWire->top);
5358f7df2e56Smrg            swaps(&sWire->left);
5359f7df2e56Smrg            swaps(&sWire->width);
5360f7df2e56Smrg            swaps(&sWire->height);
5361f7df2e56Smrg            swaps(&sWire->angle);
5362f7df2e56Smrg        }
5363f7df2e56Smrg        CHK_ATOM_ONLY(sWire->name);
5364f7df2e56Smrg        section = XkbAddGeomSection(geom, sWire->name, sWire->nRows,
5365f7df2e56Smrg                                    sWire->nDoodads, sWire->nOverlays);
5366f7df2e56Smrg        if (!section)
5367f7df2e56Smrg            return BadAlloc;
5368f7df2e56Smrg        section->priority = sWire->priority;
5369f7df2e56Smrg        section->top = sWire->top;
5370f7df2e56Smrg        section->left = sWire->left;
5371f7df2e56Smrg        section->width = sWire->width;
5372f7df2e56Smrg        section->height = sWire->height;
5373f7df2e56Smrg        section->angle = sWire->angle;
5374f7df2e56Smrg        rWire = (xkbRowWireDesc *) &sWire[1];
5375f7df2e56Smrg        for (r = 0; r < sWire->nRows; r++) {
5376f7df2e56Smrg            register int k;
5377f7df2e56Smrg            XkbRowPtr row;
5378f7df2e56Smrg            xkbKeyWireDesc *kWire;
5379f7df2e56Smrg
538090bea6a0Smrg            if (!_XkbCheckRequestBounds(client, req, rWire, rWire + 1))
538190bea6a0Smrg                return BadLength;
538290bea6a0Smrg
5383f7df2e56Smrg            if (client->swapped) {
5384f7df2e56Smrg                swaps(&rWire->top);
5385f7df2e56Smrg                swaps(&rWire->left);
5386f7df2e56Smrg            }
5387f7df2e56Smrg            row = XkbAddGeomRow(section, rWire->nKeys);
5388f7df2e56Smrg            if (!row)
5389f7df2e56Smrg                return BadAlloc;
5390f7df2e56Smrg            row->top = rWire->top;
5391f7df2e56Smrg            row->left = rWire->left;
5392f7df2e56Smrg            row->vertical = rWire->vertical;
5393f7df2e56Smrg            kWire = (xkbKeyWireDesc *) &rWire[1];
539490bea6a0Smrg            for (k = 0; k < rWire->nKeys; k++, kWire++) {
5395f7df2e56Smrg                XkbKeyPtr key;
5396f7df2e56Smrg
539790bea6a0Smrg                if (!_XkbCheckRequestBounds(client, req, kWire, kWire + 1))
539890bea6a0Smrg                    return BadLength;
539990bea6a0Smrg
5400f7df2e56Smrg                key = XkbAddGeomKey(row);
5401f7df2e56Smrg                if (!key)
5402f7df2e56Smrg                    return BadAlloc;
540390bea6a0Smrg                memcpy(key->name.name, kWire->name, XkbKeyNameLength);
540490bea6a0Smrg                key->gap = kWire->gap;
540590bea6a0Smrg                key->shape_ndx = kWire->shapeNdx;
540690bea6a0Smrg                key->color_ndx = kWire->colorNdx;
5407f7df2e56Smrg                if (key->shape_ndx >= geom->num_shapes) {
5408f7df2e56Smrg                    client->errorValue = _XkbErrCode3(0x10, key->shape_ndx,
5409f7df2e56Smrg                                                      geom->num_shapes);
5410f7df2e56Smrg                    return BadMatch;
5411f7df2e56Smrg                }
5412f7df2e56Smrg                if (key->color_ndx >= geom->num_colors) {
5413f7df2e56Smrg                    client->errorValue = _XkbErrCode3(0x11, key->color_ndx,
5414f7df2e56Smrg                                                      geom->num_colors);
5415f7df2e56Smrg                    return BadMatch;
5416f7df2e56Smrg                }
5417f7df2e56Smrg            }
541890bea6a0Smrg            rWire = (xkbRowWireDesc *)kWire;
5419f7df2e56Smrg        }
5420f7df2e56Smrg        wire = (char *) rWire;
5421f7df2e56Smrg        if (sWire->nDoodads > 0) {
5422f7df2e56Smrg            register int d;
5423f7df2e56Smrg
5424f7df2e56Smrg            for (d = 0; d < sWire->nDoodads; d++) {
542590bea6a0Smrg                status = _CheckSetDoodad(&wire, req, geom, section, client);
5426f7df2e56Smrg                if (status != Success)
5427f7df2e56Smrg                    return status;
5428f7df2e56Smrg            }
5429f7df2e56Smrg        }
5430f7df2e56Smrg        if (sWire->nOverlays > 0) {
5431f7df2e56Smrg            register int o;
5432f7df2e56Smrg
5433f7df2e56Smrg            for (o = 0; o < sWire->nOverlays; o++) {
543490bea6a0Smrg                status = _CheckSetOverlay(&wire, req, geom, section, client);
5435f7df2e56Smrg                if (status != Success)
5436f7df2e56Smrg                    return status;
5437f7df2e56Smrg            }
5438f7df2e56Smrg        }
5439f7df2e56Smrg        sWire = (xkbSectionWireDesc *) wire;
5440f7df2e56Smrg    }
5441f7df2e56Smrg    wire = (char *) sWire;
5442f7df2e56Smrg    *wire_inout = wire;
5443f7df2e56Smrg    return Success;
5444f7df2e56Smrg}
5445f7df2e56Smrg
5446f7df2e56Smrgstatic Status
5447f7df2e56Smrg_CheckSetShapes(XkbGeometryPtr geom,
5448f7df2e56Smrg                xkbSetGeometryReq * req, char **wire_inout, ClientPtr client)
5449f7df2e56Smrg{
5450f7df2e56Smrg    register int i;
5451f7df2e56Smrg    char *wire;
5452f7df2e56Smrg
5453f7df2e56Smrg    wire = *wire_inout;
5454f7df2e56Smrg    if (req->nShapes < 1) {
5455f7df2e56Smrg        client->errorValue = _XkbErrCode2(0x06, req->nShapes);
5456f7df2e56Smrg        return BadValue;
545705b261ecSmrg    }
545805b261ecSmrg    else {
5459f7df2e56Smrg        xkbShapeWireDesc *shapeWire;
5460f7df2e56Smrg        XkbShapePtr shape;
5461f7df2e56Smrg        register int o;
5462f7df2e56Smrg
5463f7df2e56Smrg        shapeWire = (xkbShapeWireDesc *) wire;
5464f7df2e56Smrg        for (i = 0; i < req->nShapes; i++) {
5465f7df2e56Smrg            xkbOutlineWireDesc *olWire;
5466f7df2e56Smrg            XkbOutlinePtr ol;
5467f7df2e56Smrg
546890bea6a0Smrg            if (!_XkbCheckRequestBounds(client, req, shapeWire, shapeWire + 1))
546990bea6a0Smrg                return BadLength;
547090bea6a0Smrg
5471f7df2e56Smrg            shape =
5472f7df2e56Smrg                XkbAddGeomShape(geom, shapeWire->name, shapeWire->nOutlines);
5473f7df2e56Smrg            if (!shape)
5474f7df2e56Smrg                return BadAlloc;
5475f7df2e56Smrg            olWire = (xkbOutlineWireDesc *) (&shapeWire[1]);
5476f7df2e56Smrg            for (o = 0; o < shapeWire->nOutlines; o++) {
5477f7df2e56Smrg                register int p;
5478f7df2e56Smrg                XkbPointPtr pt;
5479f7df2e56Smrg                xkbPointWireDesc *ptWire;
5480f7df2e56Smrg
548190bea6a0Smrg                if (!_XkbCheckRequestBounds(client, req, olWire, olWire + 1))
548290bea6a0Smrg                    return BadLength;
548390bea6a0Smrg
5484f7df2e56Smrg                ol = XkbAddGeomOutline(shape, olWire->nPoints);
5485f7df2e56Smrg                if (!ol)
5486f7df2e56Smrg                    return BadAlloc;
5487f7df2e56Smrg                ol->corner_radius = olWire->cornerRadius;
5488f7df2e56Smrg                ptWire = (xkbPointWireDesc *) &olWire[1];
548990bea6a0Smrg                for (p = 0, pt = ol->points; p < olWire->nPoints; p++, pt++, ptWire++) {
549090bea6a0Smrg                    if (!_XkbCheckRequestBounds(client, req, ptWire, ptWire + 1))
549190bea6a0Smrg                        return BadLength;
549290bea6a0Smrg
549390bea6a0Smrg                    pt->x = ptWire->x;
549490bea6a0Smrg                    pt->y = ptWire->y;
5495f7df2e56Smrg                    if (client->swapped) {
5496f7df2e56Smrg                        swaps(&pt->x);
5497f7df2e56Smrg                        swaps(&pt->y);
5498f7df2e56Smrg                    }
5499f7df2e56Smrg                }
5500f7df2e56Smrg                ol->num_points = olWire->nPoints;
550190bea6a0Smrg                olWire = (xkbOutlineWireDesc *)ptWire;
5502f7df2e56Smrg            }
5503f7df2e56Smrg            if (shapeWire->primaryNdx != XkbNoShape)
5504f7df2e56Smrg                shape->primary = &shape->outlines[shapeWire->primaryNdx];
5505f7df2e56Smrg            if (shapeWire->approxNdx != XkbNoShape)
5506f7df2e56Smrg                shape->approx = &shape->outlines[shapeWire->approxNdx];
5507f7df2e56Smrg            shapeWire = (xkbShapeWireDesc *) olWire;
5508f7df2e56Smrg        }
5509f7df2e56Smrg        wire = (char *) shapeWire;
5510f7df2e56Smrg    }
5511f7df2e56Smrg    if (geom->num_shapes != req->nShapes) {
5512f7df2e56Smrg        client->errorValue = _XkbErrCode3(0x07, geom->num_shapes, req->nShapes);
5513f7df2e56Smrg        return BadMatch;
5514f7df2e56Smrg    }
5515f7df2e56Smrg
5516f7df2e56Smrg    *wire_inout = wire;
551705b261ecSmrg    return Success;
551805b261ecSmrg}
551905b261ecSmrg
552005b261ecSmrgstatic Status
5521f7df2e56Smrg_CheckSetGeom(XkbGeometryPtr geom, xkbSetGeometryReq * req, ClientPtr client)
552205b261ecSmrg{
5523f7df2e56Smrg    register int i;
5524f7df2e56Smrg    Status status;
5525f7df2e56Smrg    char *wire;
552605b261ecSmrg
5527f7df2e56Smrg    wire = (char *) &req[1];
55281e26616aSmrg    status = _GetCountedString(&wire, client, &geom->label_font);
55291e26616aSmrg    if (status != Success)
55301e26616aSmrg        return status;
55311e26616aSmrg
55321e26616aSmrg    for (i = 0; i < req->nProperties; i++) {
5533f7df2e56Smrg        char *name, *val;
55341e26616aSmrg
55351e26616aSmrg        status = _GetCountedString(&wire, client, &name);
55361e26616aSmrg        if (status != Success)
55371e26616aSmrg            return status;
55381e26616aSmrg        status = _GetCountedString(&wire, client, &val);
55391e26616aSmrg        if (status != Success) {
55406747b715Smrg            free(name);
55411e26616aSmrg            return status;
554205b261ecSmrg        }
5543f7df2e56Smrg        if (XkbAddGeomProperty(geom, name, val) == NULL) {
55446747b715Smrg            free(name);
55456747b715Smrg            free(val);
5546f7df2e56Smrg            return BadAlloc;
554705b261ecSmrg        }
55486747b715Smrg        free(name);
55496747b715Smrg        free(val);
555005b261ecSmrg    }
555105b261ecSmrg
5552f7df2e56Smrg    if (req->nColors < 2) {
5553f7df2e56Smrg        client->errorValue = _XkbErrCode3(0x01, 2, req->nColors);
5554f7df2e56Smrg        return BadValue;
555505b261ecSmrg    }
5556f7df2e56Smrg    if (req->baseColorNdx > req->nColors) {
5557f7df2e56Smrg        client->errorValue =
5558f7df2e56Smrg            _XkbErrCode3(0x03, req->nColors, req->baseColorNdx);
5559f7df2e56Smrg        return BadMatch;
556005b261ecSmrg    }
5561f7df2e56Smrg    if (req->labelColorNdx > req->nColors) {
5562f7df2e56Smrg        client->errorValue =
5563f7df2e56Smrg            _XkbErrCode3(0x03, req->nColors, req->labelColorNdx);
5564f7df2e56Smrg        return BadMatch;
556505b261ecSmrg    }
5566f7df2e56Smrg    if (req->labelColorNdx == req->baseColorNdx) {
5567f7df2e56Smrg        client->errorValue = _XkbErrCode3(0x04, req->baseColorNdx,
5568f7df2e56Smrg                                          req->labelColorNdx);
5569f7df2e56Smrg        return BadMatch;
557005b261ecSmrg    }
557105b261ecSmrg
55721e26616aSmrg    for (i = 0; i < req->nColors; i++) {
5573f7df2e56Smrg        char *name;
5574f7df2e56Smrg
55751e26616aSmrg        status = _GetCountedString(&wire, client, &name);
55761e26616aSmrg        if (status != Success)
55771e26616aSmrg            return status;
5578f7df2e56Smrg        if (!XkbAddGeomColor(geom, name, geom->num_colors)) {
55796747b715Smrg            free(name);
5580f7df2e56Smrg            return BadAlloc;
558105b261ecSmrg        }
55826747b715Smrg        free(name);
558305b261ecSmrg    }
5584f7df2e56Smrg    if (req->nColors != geom->num_colors) {
5585f7df2e56Smrg        client->errorValue = _XkbErrCode3(0x05, req->nColors, geom->num_colors);
5586f7df2e56Smrg        return BadMatch;
558705b261ecSmrg    }
5588f7df2e56Smrg    geom->label_color = &geom->colors[req->labelColorNdx];
5589f7df2e56Smrg    geom->base_color = &geom->colors[req->baseColorNdx];
559005b261ecSmrg
5591f7df2e56Smrg    if ((status = _CheckSetShapes(geom, req, &wire, client)) != Success)
5592f7df2e56Smrg        return status;
559305b261ecSmrg
5594f7df2e56Smrg    if ((status = _CheckSetSections(geom, req, &wire, client)) != Success)
5595f7df2e56Smrg        return status;
559605b261ecSmrg
5597f7df2e56Smrg    for (i = 0; i < req->nDoodads; i++) {
559890bea6a0Smrg        status = _CheckSetDoodad(&wire, req, geom, NULL, client);
5599f7df2e56Smrg        if (status != Success)
5600f7df2e56Smrg            return status;
560105b261ecSmrg    }
560205b261ecSmrg
5603f7df2e56Smrg    for (i = 0; i < req->nKeyAliases; i++) {
560490bea6a0Smrg        if (!_XkbCheckRequestBounds(client, req, wire, wire + XkbKeyNameLength))
560590bea6a0Smrg                return BadLength;
560690bea6a0Smrg
5607f7df2e56Smrg        if (XkbAddGeomKeyAlias(geom, &wire[XkbKeyNameLength], wire) == NULL)
5608f7df2e56Smrg            return BadAlloc;
5609f7df2e56Smrg        wire += 2 * XkbKeyNameLength;
561005b261ecSmrg    }
561105b261ecSmrg    return Success;
561205b261ecSmrg}
561305b261ecSmrg
56144642e01fSmrgstatic int
5615f7df2e56Smrg_XkbSetGeometry(ClientPtr client, DeviceIntPtr dev, xkbSetGeometryReq * stuff)
561605b261ecSmrg{
5617f7df2e56Smrg    XkbDescPtr xkb;
5618f7df2e56Smrg    Bool new_name;
5619f7df2e56Smrg    xkbNewKeyboardNotify nkn;
5620f7df2e56Smrg    XkbGeometryPtr geom, old;
5621f7df2e56Smrg    XkbGeometrySizesRec sizes;
5622f7df2e56Smrg    Status status;
5623f7df2e56Smrg
5624f7df2e56Smrg    xkb = dev->key->xkbInfo->desc;
5625f7df2e56Smrg    old = xkb->geom;
5626f7df2e56Smrg    xkb->geom = NULL;
5627f7df2e56Smrg
5628f7df2e56Smrg    sizes.which = XkbGeomAllMask;
5629f7df2e56Smrg    sizes.num_properties = stuff->nProperties;
5630f7df2e56Smrg    sizes.num_colors = stuff->nColors;
5631f7df2e56Smrg    sizes.num_shapes = stuff->nShapes;
5632f7df2e56Smrg    sizes.num_sections = stuff->nSections;
5633f7df2e56Smrg    sizes.num_doodads = stuff->nDoodads;
5634f7df2e56Smrg    sizes.num_key_aliases = stuff->nKeyAliases;
5635f7df2e56Smrg    if ((status = XkbAllocGeometry(xkb, &sizes)) != Success) {
5636f7df2e56Smrg        xkb->geom = old;
56374642e01fSmrg        return status;
563805b261ecSmrg    }
5639f7df2e56Smrg    geom = xkb->geom;
5640f7df2e56Smrg    geom->name = stuff->name;
5641f7df2e56Smrg    geom->width_mm = stuff->widthMM;
5642f7df2e56Smrg    geom->height_mm = stuff->heightMM;
5643f7df2e56Smrg    if ((status = _CheckSetGeom(geom, stuff, client)) != Success) {
5644f7df2e56Smrg        XkbFreeGeometry(geom, XkbGeomAllMask, TRUE);
5645f7df2e56Smrg        xkb->geom = old;
56464642e01fSmrg        return status;
564705b261ecSmrg    }
5648f7df2e56Smrg    new_name = (xkb->names->geometry != geom->name);
5649f7df2e56Smrg    xkb->names->geometry = geom->name;
565005b261ecSmrg    if (old)
5651f7df2e56Smrg        XkbFreeGeometry(old, XkbGeomAllMask, TRUE);
565205b261ecSmrg    if (new_name) {
5653f7df2e56Smrg        xkbNamesNotify nn;
5654f7df2e56Smrg
56556747b715Smrg        memset(&nn, 0, sizeof(xkbNamesNotify));
5656f7df2e56Smrg        nn.changed = XkbGeometryNameMask;
5657f7df2e56Smrg        XkbSendNamesNotify(dev, &nn);
5658f7df2e56Smrg    }
5659f7df2e56Smrg    nkn.deviceID = nkn.oldDeviceID = dev->id;
5660f7df2e56Smrg    nkn.minKeyCode = nkn.oldMinKeyCode = xkb->min_key_code;
5661f7df2e56Smrg    nkn.maxKeyCode = nkn.oldMaxKeyCode = xkb->max_key_code;
5662f7df2e56Smrg    nkn.requestMajor = XkbReqCode;
5663f7df2e56Smrg    nkn.requestMinor = X_kbSetGeometry;
5664f7df2e56Smrg    nkn.changed = XkbNKN_GeometryMask;
5665f7df2e56Smrg    XkbSendNewKeyboardNotify(dev, &nkn);
566605b261ecSmrg    return Success;
566705b261ecSmrg}
566805b261ecSmrg
56694642e01fSmrgint
56704642e01fSmrgProcXkbSetGeometry(ClientPtr client)
56714642e01fSmrg{
5672f7df2e56Smrg    DeviceIntPtr dev;
5673f7df2e56Smrg    int rc;
56744642e01fSmrg
56754642e01fSmrg    REQUEST(xkbSetGeometryReq);
56764642e01fSmrg    REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq);
56774642e01fSmrg
5678f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
5679f7df2e56Smrg        return BadAccess;
56804642e01fSmrg
56814642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
56824642e01fSmrg    CHK_ATOM_OR_NONE(stuff->name);
56834642e01fSmrg
56844642e01fSmrg    rc = _XkbSetGeometry(client, dev, stuff);
56854642e01fSmrg    if (rc != Success)
56864642e01fSmrg        return rc;
56874642e01fSmrg
5688f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd) {
56894642e01fSmrg        DeviceIntPtr other;
5690f7df2e56Smrg
5691f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
5692f7df2e56Smrg            if ((other != dev) && other->key && !IsMaster(other) &&
5693f7df2e56Smrg                GetMaster(other, MASTER_KEYBOARD) == dev) {
5694f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
5695f7df2e56Smrg                              DixManageAccess);
56964642e01fSmrg                if (rc == Success)
56974642e01fSmrg                    _XkbSetGeometry(client, other, stuff);
56984642e01fSmrg            }
56994642e01fSmrg        }
57004642e01fSmrg    }
57014642e01fSmrg
57024642e01fSmrg    return Success;
57034642e01fSmrg}
57044642e01fSmrg
570505b261ecSmrg/***====================================================================***/
570605b261ecSmrg
570705b261ecSmrgint
570805b261ecSmrgProcXkbPerClientFlags(ClientPtr client)
570905b261ecSmrg{
5710f7df2e56Smrg    DeviceIntPtr dev;
5711f7df2e56Smrg    xkbPerClientFlagsReply rep;
5712f7df2e56Smrg    XkbInterestPtr interest;
57134642e01fSmrg    Mask access_mode = DixGetAttrAccess | DixSetAttrAccess;
571405b261ecSmrg
571505b261ecSmrg    REQUEST(xkbPerClientFlagsReq);
571605b261ecSmrg    REQUEST_SIZE_MATCH(xkbPerClientFlagsReq);
571705b261ecSmrg
5718f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
5719f7df2e56Smrg        return BadAccess;
572005b261ecSmrg
57214642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
5722f7df2e56Smrg    CHK_MASK_LEGAL(0x01, stuff->change, XkbPCF_AllFlagsMask);
5723f7df2e56Smrg    CHK_MASK_MATCH(0x02, stuff->change, stuff->value);
572405b261ecSmrg
5725f7df2e56Smrg    interest = XkbFindClientResource((DevicePtr) dev, client);
572605b261ecSmrg    if (stuff->change) {
5727f7df2e56Smrg        client->xkbClientFlags &= ~stuff->change;
5728f7df2e56Smrg        client->xkbClientFlags |= stuff->value;
572905b261ecSmrg    }
5730f7df2e56Smrg    if (stuff->change & XkbPCF_AutoResetControlsMask) {
5731f7df2e56Smrg        Bool want;
5732f7df2e56Smrg
5733f7df2e56Smrg        want = stuff->value & XkbPCF_AutoResetControlsMask;
5734f7df2e56Smrg        if (interest && !want) {
5735f7df2e56Smrg            interest->autoCtrls = interest->autoCtrlValues = 0;
5736f7df2e56Smrg        }
5737f7df2e56Smrg        else if (want && (!interest)) {
5738f7df2e56Smrg            XID id = FakeClientID(client->index);
5739f7df2e56Smrg
5740f7df2e56Smrg            if (!AddResource(id, RT_XKBCLIENT, dev))
5741f7df2e56Smrg                return BadAlloc;
5742f7df2e56Smrg            interest = XkbAddClientResource((DevicePtr) dev, client, id);
5743f7df2e56Smrg            if (!interest)
5744f7df2e56Smrg                return BadAlloc;
5745f7df2e56Smrg        }
5746f7df2e56Smrg        if (interest && want) {
5747f7df2e56Smrg            register unsigned affect;
5748f7df2e56Smrg
5749f7df2e56Smrg            affect = stuff->ctrlsToChange;
5750f7df2e56Smrg
5751f7df2e56Smrg            CHK_MASK_LEGAL(0x03, affect, XkbAllBooleanCtrlsMask);
5752f7df2e56Smrg            CHK_MASK_MATCH(0x04, affect, stuff->autoCtrls);
5753f7df2e56Smrg            CHK_MASK_MATCH(0x05, stuff->autoCtrls, stuff->autoCtrlValues);
5754f7df2e56Smrg
5755f7df2e56Smrg            interest->autoCtrls &= ~affect;
5756f7df2e56Smrg            interest->autoCtrlValues &= ~affect;
5757f7df2e56Smrg            interest->autoCtrls |= stuff->autoCtrls & affect;
5758f7df2e56Smrg            interest->autoCtrlValues |= stuff->autoCtrlValues & affect;
5759f7df2e56Smrg        }
576005b261ecSmrg    }
5761f7df2e56Smrg
5762f7df2e56Smrg    rep = (xkbPerClientFlagsReply) {
5763f7df2e56Smrg        .type = X_Reply,
5764f7df2e56Smrg        .sequenceNumber = client->sequence,
5765f7df2e56Smrg        .length = 0,
5766f7df2e56Smrg        .supported = XkbPCF_AllFlagsMask,
5767f7df2e56Smrg        .value = client->xkbClientFlags & XkbPCF_AllFlagsMask,
5768f7df2e56Smrg        .autoCtrls = interest ? interest->autoCtrls : 0,
5769f7df2e56Smrg        .autoCtrlValues =  interest ? interest->autoCtrlValues : 0,
5770f7df2e56Smrg    };
5771f7df2e56Smrg    if (client->swapped) {
5772f7df2e56Smrg        swaps(&rep.sequenceNumber);
5773f7df2e56Smrg        swapl(&rep.supported);
5774f7df2e56Smrg        swapl(&rep.value);
5775f7df2e56Smrg        swapl(&rep.autoCtrls);
5776f7df2e56Smrg        swapl(&rep.autoCtrlValues);
577705b261ecSmrg    }
5778f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbPerClientFlagsReply), &rep);
57796747b715Smrg    return Success;
578005b261ecSmrg}
578105b261ecSmrg
578205b261ecSmrg/***====================================================================***/
578305b261ecSmrg
578405b261ecSmrg/* all latin-1 alphanumerics, plus parens, minus, underscore, slash */
578505b261ecSmrg/* and wildcards */
578605b261ecSmrgstatic unsigned char componentSpecLegal[] = {
5787f7df2e56Smrg    0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x87,
5788f7df2e56Smrg    0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07,
5789f7df2e56Smrg    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5790f7df2e56Smrg    0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
579105b261ecSmrg};
579205b261ecSmrg
579305b261ecSmrg/* same as above but accepts percent, plus and bar too */
579405b261ecSmrgstatic unsigned char componentExprLegal[] = {
5795f7df2e56Smrg    0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0xff, 0x87,
5796f7df2e56Smrg    0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x17,
5797f7df2e56Smrg    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5798f7df2e56Smrg    0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
579905b261ecSmrg};
580005b261ecSmrg
580105b261ecSmrgstatic char *
5802f7df2e56SmrgGetComponentSpec(unsigned char **pWire, Bool allowExpr, int *errRtrn)
580305b261ecSmrg{
5804f7df2e56Smrg    int len;
5805f7df2e56Smrg    register int i;
5806f7df2e56Smrg    unsigned char *wire, *str, *tmp, *legal;
5807f7df2e56Smrg
5808f7df2e56Smrg    if (allowExpr)
5809f7df2e56Smrg        legal = &componentExprLegal[0];
5810f7df2e56Smrg    else
5811f7df2e56Smrg        legal = &componentSpecLegal[0];
5812f7df2e56Smrg
5813f7df2e56Smrg    wire = *pWire;
5814f7df2e56Smrg    len = (*(unsigned char *) wire++);
5815f7df2e56Smrg    if (len > 0) {
5816f7df2e56Smrg        str = calloc(1, len + 1);
5817f7df2e56Smrg        if (str) {
5818f7df2e56Smrg            tmp = str;
5819f7df2e56Smrg            for (i = 0; i < len; i++) {
5820f7df2e56Smrg                if (legal[(*wire) / 8] & (1 << ((*wire) % 8)))
5821f7df2e56Smrg                    *tmp++ = *wire++;
5822f7df2e56Smrg                else
5823f7df2e56Smrg                    wire++;
5824f7df2e56Smrg            }
5825f7df2e56Smrg            if (tmp != str)
5826f7df2e56Smrg                *tmp++ = '\0';
5827f7df2e56Smrg            else {
5828f7df2e56Smrg                free(str);
5829f7df2e56Smrg                str = NULL;
5830f7df2e56Smrg            }
5831f7df2e56Smrg        }
5832f7df2e56Smrg        else {
5833f7df2e56Smrg            *errRtrn = BadAlloc;
5834f7df2e56Smrg        }
583505b261ecSmrg    }
583605b261ecSmrg    else {
5837f7df2e56Smrg        str = NULL;
583805b261ecSmrg    }
5839f7df2e56Smrg    *pWire = wire;
5840f7df2e56Smrg    return (char *) str;
584105b261ecSmrg}
584205b261ecSmrg
584305b261ecSmrg/***====================================================================***/
584405b261ecSmrg
584505b261ecSmrgint
584605b261ecSmrgProcXkbListComponents(ClientPtr client)
584705b261ecSmrg{
5848f7df2e56Smrg    DeviceIntPtr dev;
5849f7df2e56Smrg    xkbListComponentsReply rep;
5850f7df2e56Smrg    unsigned len;
5851f7df2e56Smrg    unsigned char *str;
5852f7df2e56Smrg    uint8_t size;
5853f7df2e56Smrg    int i;
585405b261ecSmrg
585505b261ecSmrg    REQUEST(xkbListComponentsReq);
585605b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbListComponentsReq);
585705b261ecSmrg
5858f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
5859f7df2e56Smrg        return BadAccess;
586005b261ecSmrg
58614642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
586205b261ecSmrg
5863f7df2e56Smrg    /* The request is followed by six Pascal strings (i.e. size in characters
5864f7df2e56Smrg     * followed by a string pattern) describing what the client wants us to
5865f7df2e56Smrg     * list.  We don't care, but might as well check they haven't got the
5866f7df2e56Smrg     * length wrong. */
5867f7df2e56Smrg    str = (unsigned char *) &stuff[1];
5868f7df2e56Smrg    for (i = 0; i < 6; i++) {
5869f7df2e56Smrg        size = *((uint8_t *)str);
5870f7df2e56Smrg        len = (str + size + 1) - ((unsigned char *) stuff);
5871f7df2e56Smrg        if ((XkbPaddedSize(len) / 4) > stuff->length)
5872f7df2e56Smrg            return BadLength;
5873f7df2e56Smrg        str += (size + 1);
5874f7df2e56Smrg    }
5875f7df2e56Smrg    if ((XkbPaddedSize(len) / 4) != stuff->length)
5876f7df2e56Smrg        return BadLength;
5877f7df2e56Smrg    rep = (xkbListComponentsReply) {
5878f7df2e56Smrg        .type = X_Reply,
5879f7df2e56Smrg        .deviceID = dev->id,
5880f7df2e56Smrg        .sequenceNumber = client->sequence,
5881f7df2e56Smrg        .length = 0,
5882f7df2e56Smrg        .nKeymaps = 0,
5883f7df2e56Smrg        .nKeycodes = 0,
5884f7df2e56Smrg        .nTypes = 0,
5885f7df2e56Smrg        .nCompatMaps = 0,
5886f7df2e56Smrg        .nSymbols = 0,
5887f7df2e56Smrg        .nGeometries = 0,
5888f7df2e56Smrg        .extra = 0
5889f7df2e56Smrg    };
589005b261ecSmrg    if (client->swapped) {
5891f7df2e56Smrg        swaps(&rep.sequenceNumber);
5892f7df2e56Smrg        swapl(&rep.length);
5893f7df2e56Smrg        swaps(&rep.nKeymaps);
5894f7df2e56Smrg        swaps(&rep.nKeycodes);
5895f7df2e56Smrg        swaps(&rep.nTypes);
5896f7df2e56Smrg        swaps(&rep.nCompatMaps);
5897f7df2e56Smrg        swaps(&rep.nSymbols);
5898f7df2e56Smrg        swaps(&rep.nGeometries);
5899f7df2e56Smrg        swaps(&rep.extra);
5900f7df2e56Smrg    }
5901f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbListComponentsReply), &rep);
59026747b715Smrg    return Success;
590305b261ecSmrg}
590405b261ecSmrg
590505b261ecSmrg/***====================================================================***/
590605b261ecSmrgint
590705b261ecSmrgProcXkbGetKbdByName(ClientPtr client)
590805b261ecSmrg{
5909f7df2e56Smrg    DeviceIntPtr dev;
5910f7df2e56Smrg    DeviceIntPtr tmpd;
5911f7df2e56Smrg    DeviceIntPtr master;
5912f7df2e56Smrg    xkbGetKbdByNameReply rep = { 0 };
5913f7df2e56Smrg    xkbGetMapReply mrep = { 0 };
5914f7df2e56Smrg    xkbGetCompatMapReply crep = { 0 };
5915f7df2e56Smrg    xkbGetIndicatorMapReply irep = { 0 };
5916f7df2e56Smrg    xkbGetNamesReply nrep = { 0 };
5917f7df2e56Smrg    xkbGetGeometryReply grep = { 0 };
5918f7df2e56Smrg    XkbComponentNamesRec names = { 0 };
5919f7df2e56Smrg    XkbDescPtr xkb, new;
5920f7df2e56Smrg    XkbEventCauseRec cause;
5921f7df2e56Smrg    unsigned char *str;
5922f7df2e56Smrg    char mapFile[PATH_MAX];
5923f7df2e56Smrg    unsigned len;
5924f7df2e56Smrg    unsigned fwant, fneed, reported;
5925f7df2e56Smrg    int status;
5926f7df2e56Smrg    Bool geom_changed;
5927f7df2e56Smrg    XkbSrvLedInfoPtr old_sli;
5928f7df2e56Smrg    XkbSrvLedInfoPtr sli;
59294642e01fSmrg    Mask access_mode = DixGetAttrAccess | DixManageAccess;
593005b261ecSmrg
593105b261ecSmrg    REQUEST(xkbGetKbdByNameReq);
593205b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq);
593305b261ecSmrg
5934f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
5935f7df2e56Smrg        return BadAccess;
593605b261ecSmrg
59374642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
5938f7df2e56Smrg    master = GetMaster(dev, MASTER_KEYBOARD);
593905b261ecSmrg
594005b261ecSmrg    xkb = dev->key->xkbInfo->desc;
5941f7df2e56Smrg    status = Success;
5942f7df2e56Smrg    str = (unsigned char *) &stuff[1];
59432d19872aSmrg    {
59442d19872aSmrg        char *keymap = GetComponentSpec(&str, TRUE, &status);  /* keymap, unsupported */
59452d19872aSmrg        if (keymap) {
59462d19872aSmrg            free(keymap);
59472d19872aSmrg            return BadMatch;
59482d19872aSmrg        }
59492d19872aSmrg    }
5950f7df2e56Smrg    names.keycodes = GetComponentSpec(&str, TRUE, &status);
5951f7df2e56Smrg    names.types = GetComponentSpec(&str, TRUE, &status);
5952f7df2e56Smrg    names.compat = GetComponentSpec(&str, TRUE, &status);
5953f7df2e56Smrg    names.symbols = GetComponentSpec(&str, TRUE, &status);
5954f7df2e56Smrg    names.geometry = GetComponentSpec(&str, TRUE, &status);
59552d19872aSmrg    if (status == Success) {
59562d19872aSmrg        len = str - ((unsigned char *) stuff);
59572d19872aSmrg        if ((XkbPaddedSize(len) / 4) != stuff->length)
59582d19872aSmrg            status = BadLength;
59592d19872aSmrg    }
59602d19872aSmrg
59612d19872aSmrg    if (status != Success) {
59622d19872aSmrg        free(names.keycodes);
59632d19872aSmrg        free(names.types);
59642d19872aSmrg        free(names.compat);
59652d19872aSmrg        free(names.symbols);
59662d19872aSmrg        free(names.geometry);
5967f7df2e56Smrg        return status;
59682d19872aSmrg    }
5969f7df2e56Smrg
5970f7df2e56Smrg    CHK_MASK_LEGAL(0x01, stuff->want, XkbGBN_AllComponentsMask);
5971f7df2e56Smrg    CHK_MASK_LEGAL(0x02, stuff->need, XkbGBN_AllComponentsMask);
5972f7df2e56Smrg
597305b261ecSmrg    if (stuff->load)
5974f7df2e56Smrg        fwant = XkbGBN_AllComponentsMask;
5975f7df2e56Smrg    else
5976f7df2e56Smrg        fwant = stuff->want | stuff->need;
5977f7df2e56Smrg    if ((!names.compat) &&
5978f7df2e56Smrg        (fwant & (XkbGBN_CompatMapMask | XkbGBN_IndicatorMapMask))) {
5979f7df2e56Smrg        names.compat = Xstrdup("%");
598005b261ecSmrg    }
5981f7df2e56Smrg    if ((!names.types) && (fwant & (XkbGBN_TypesMask))) {
5982f7df2e56Smrg        names.types = Xstrdup("%");
59834642e01fSmrg    }
5984f7df2e56Smrg    if ((!names.symbols) && (fwant & XkbGBN_SymbolsMask)) {
5985f7df2e56Smrg        names.symbols = Xstrdup("%");
59864642e01fSmrg    }
5987f7df2e56Smrg    geom_changed = ((names.geometry != NULL) &&
5988f7df2e56Smrg                    (strcmp(names.geometry, "%") != 0));
5989f7df2e56Smrg    if ((!names.geometry) && (fwant & XkbGBN_GeometryMask)) {
5990f7df2e56Smrg        names.geometry = Xstrdup("%");
5991f7df2e56Smrg        geom_changed = FALSE;
599205b261ecSmrg    }
599305b261ecSmrg
59946747b715Smrg    memset(mapFile, 0, PATH_MAX);
5995f7df2e56Smrg    rep.type = X_Reply;
599605b261ecSmrg    rep.deviceID = dev->id;
599705b261ecSmrg    rep.sequenceNumber = client->sequence;
599805b261ecSmrg    rep.length = 0;
599905b261ecSmrg    rep.minKeyCode = xkb->min_key_code;
600005b261ecSmrg    rep.maxKeyCode = xkb->max_key_code;
6001f7df2e56Smrg    rep.loaded = FALSE;
6002f7df2e56Smrg    fwant =
6003f7df2e56Smrg        XkbConvertGetByNameComponents(TRUE, stuff->want) | XkmVirtualModsMask;
6004f7df2e56Smrg    fneed = XkbConvertGetByNameComponents(TRUE, stuff->need);
6005f7df2e56Smrg    rep.reported = XkbConvertGetByNameComponents(FALSE, fwant | fneed);
600605b261ecSmrg    if (stuff->load) {
6007f7df2e56Smrg        fneed |= XkmKeymapRequired;
6008f7df2e56Smrg        fwant |= XkmKeymapLegal;
600905b261ecSmrg    }
6010f7df2e56Smrg    if ((fwant | fneed) & XkmSymbolsMask) {
6011f7df2e56Smrg        fneed |= XkmKeyNamesIndex | XkmTypesIndex;
6012f7df2e56Smrg        fwant |= XkmIndicatorsIndex;
601305b261ecSmrg    }
601405b261ecSmrg
601505b261ecSmrg    /* We pass dev in here so we can get the old names out if needed. */
6016f7df2e56Smrg    rep.found = XkbDDXLoadKeymapByNames(dev, &names, fwant, fneed, &new,
6017f7df2e56Smrg                                        mapFile, PATH_MAX);
6018f7df2e56Smrg    rep.newKeyboard = FALSE;
6019f7df2e56Smrg    rep.pad1 = rep.pad2 = rep.pad3 = rep.pad4 = 0;
6020f7df2e56Smrg
6021f7df2e56Smrg    stuff->want |= stuff->need;
6022f7df2e56Smrg    if (new == NULL)
6023f7df2e56Smrg        rep.reported = 0;
602405b261ecSmrg    else {
6025f7df2e56Smrg        if (stuff->load)
6026f7df2e56Smrg            rep.loaded = TRUE;
6027f7df2e56Smrg        if (stuff->load ||
6028f7df2e56Smrg            ((rep.reported & XkbGBN_SymbolsMask) && (new->compat))) {
6029f7df2e56Smrg            XkbChangesRec changes;
6030f7df2e56Smrg
6031f7df2e56Smrg            memset(&changes, 0, sizeof(changes));
6032f7df2e56Smrg            XkbUpdateDescActions(new,
6033f7df2e56Smrg                                 new->min_key_code, XkbNumKeys(new), &changes);
6034f7df2e56Smrg        }
603505b261ecSmrg
6036f7df2e56Smrg        if (new->map == NULL)
6037f7df2e56Smrg            rep.reported &= ~(XkbGBN_SymbolsMask | XkbGBN_TypesMask);
6038f7df2e56Smrg        else if (rep.reported & (XkbGBN_SymbolsMask | XkbGBN_TypesMask)) {
6039f7df2e56Smrg            mrep.type = X_Reply;
6040f7df2e56Smrg            mrep.deviceID = dev->id;
6041f7df2e56Smrg            mrep.sequenceNumber = client->sequence;
6042f7df2e56Smrg            mrep.length =
6043f7df2e56Smrg                ((SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply)) >> 2);
6044f7df2e56Smrg            mrep.minKeyCode = new->min_key_code;
6045f7df2e56Smrg            mrep.maxKeyCode = new->max_key_code;
6046f7df2e56Smrg            mrep.present = 0;
6047f7df2e56Smrg            mrep.totalSyms = mrep.totalActs =
6048f7df2e56Smrg                mrep.totalKeyBehaviors = mrep.totalKeyExplicit =
6049f7df2e56Smrg                mrep.totalModMapKeys = mrep.totalVModMapKeys = 0;
6050f7df2e56Smrg            if (rep.reported & (XkbGBN_TypesMask | XkbGBN_ClientSymbolsMask)) {
6051f7df2e56Smrg                mrep.present |= XkbKeyTypesMask;
6052f7df2e56Smrg                mrep.firstType = 0;
6053f7df2e56Smrg                mrep.nTypes = mrep.totalTypes = new->map->num_types;
6054f7df2e56Smrg            }
6055f7df2e56Smrg            else {
6056f7df2e56Smrg                mrep.firstType = mrep.nTypes = 0;
6057f7df2e56Smrg                mrep.totalTypes = 0;
6058f7df2e56Smrg            }
6059f7df2e56Smrg            if (rep.reported & XkbGBN_ClientSymbolsMask) {
6060f7df2e56Smrg                mrep.present |= (XkbKeySymsMask | XkbModifierMapMask);
6061f7df2e56Smrg                mrep.firstKeySym = mrep.firstModMapKey = new->min_key_code;
6062f7df2e56Smrg                mrep.nKeySyms = mrep.nModMapKeys = XkbNumKeys(new);
6063f7df2e56Smrg            }
6064f7df2e56Smrg            else {
6065f7df2e56Smrg                mrep.firstKeySym = mrep.firstModMapKey = 0;
6066f7df2e56Smrg                mrep.nKeySyms = mrep.nModMapKeys = 0;
6067f7df2e56Smrg            }
6068f7df2e56Smrg            if (rep.reported & XkbGBN_ServerSymbolsMask) {
6069f7df2e56Smrg                mrep.present |= XkbAllServerInfoMask;
6070f7df2e56Smrg                mrep.virtualMods = ~0;
6071f7df2e56Smrg                mrep.firstKeyAct = mrep.firstKeyBehavior =
6072f7df2e56Smrg                    mrep.firstKeyExplicit = new->min_key_code;
6073f7df2e56Smrg                mrep.nKeyActs = mrep.nKeyBehaviors =
6074f7df2e56Smrg                    mrep.nKeyExplicit = XkbNumKeys(new);
6075f7df2e56Smrg                mrep.firstVModMapKey = new->min_key_code;
6076f7df2e56Smrg                mrep.nVModMapKeys = XkbNumKeys(new);
6077f7df2e56Smrg            }
6078f7df2e56Smrg            else {
6079f7df2e56Smrg                mrep.virtualMods = 0;
6080f7df2e56Smrg                mrep.firstKeyAct = mrep.firstKeyBehavior =
6081f7df2e56Smrg                    mrep.firstKeyExplicit = 0;
6082f7df2e56Smrg                mrep.nKeyActs = mrep.nKeyBehaviors = mrep.nKeyExplicit = 0;
6083f7df2e56Smrg            }
6084f7df2e56Smrg            XkbComputeGetMapReplySize(new, &mrep);
6085f7df2e56Smrg            rep.length += SIZEOF(xGenericReply) / 4 + mrep.length;
6086f7df2e56Smrg        }
6087f7df2e56Smrg        if (new->compat == NULL)
6088f7df2e56Smrg            rep.reported &= ~XkbGBN_CompatMapMask;
6089f7df2e56Smrg        else if (rep.reported & XkbGBN_CompatMapMask) {
6090f7df2e56Smrg            crep.type = X_Reply;
6091f7df2e56Smrg            crep.deviceID = dev->id;
6092f7df2e56Smrg            crep.sequenceNumber = client->sequence;
6093f7df2e56Smrg            crep.length = 0;
6094f7df2e56Smrg            crep.groups = XkbAllGroupsMask;
6095f7df2e56Smrg            crep.firstSI = 0;
6096f7df2e56Smrg            crep.nSI = crep.nTotalSI = new->compat->num_si;
6097f7df2e56Smrg            XkbComputeGetCompatMapReplySize(new->compat, &crep);
6098f7df2e56Smrg            rep.length += SIZEOF(xGenericReply) / 4 + crep.length;
6099f7df2e56Smrg        }
6100f7df2e56Smrg        if (new->indicators == NULL)
6101f7df2e56Smrg            rep.reported &= ~XkbGBN_IndicatorMapMask;
6102f7df2e56Smrg        else if (rep.reported & XkbGBN_IndicatorMapMask) {
6103f7df2e56Smrg            irep.type = X_Reply;
6104f7df2e56Smrg            irep.deviceID = dev->id;
6105f7df2e56Smrg            irep.sequenceNumber = client->sequence;
6106f7df2e56Smrg            irep.length = 0;
6107f7df2e56Smrg            irep.which = XkbAllIndicatorsMask;
6108f7df2e56Smrg            XkbComputeGetIndicatorMapReplySize(new->indicators, &irep);
6109f7df2e56Smrg            rep.length += SIZEOF(xGenericReply) / 4 + irep.length;
6110f7df2e56Smrg        }
6111f7df2e56Smrg        if (new->names == NULL)
6112f7df2e56Smrg            rep.reported &= ~(XkbGBN_OtherNamesMask | XkbGBN_KeyNamesMask);
6113f7df2e56Smrg        else if (rep.reported & (XkbGBN_OtherNamesMask | XkbGBN_KeyNamesMask)) {
6114f7df2e56Smrg            nrep.type = X_Reply;
6115f7df2e56Smrg            nrep.deviceID = dev->id;
6116f7df2e56Smrg            nrep.sequenceNumber = client->sequence;
6117f7df2e56Smrg            nrep.length = 0;
6118f7df2e56Smrg            nrep.minKeyCode = new->min_key_code;
6119f7df2e56Smrg            nrep.maxKeyCode = new->max_key_code;
6120f7df2e56Smrg            if (rep.reported & XkbGBN_OtherNamesMask) {
6121f7df2e56Smrg                nrep.which = XkbAllNamesMask;
6122f7df2e56Smrg                if (new->map != NULL)
6123f7df2e56Smrg                    nrep.nTypes = new->map->num_types;
6124f7df2e56Smrg                else
6125f7df2e56Smrg                    nrep.nTypes = 0;
6126f7df2e56Smrg                nrep.nKTLevels = 0;
6127f7df2e56Smrg                nrep.groupNames = XkbAllGroupsMask;
6128f7df2e56Smrg                nrep.virtualMods = XkbAllVirtualModsMask;
6129f7df2e56Smrg                nrep.indicators = XkbAllIndicatorsMask;
6130f7df2e56Smrg                nrep.nRadioGroups = new->names->num_rg;
6131f7df2e56Smrg            }
6132f7df2e56Smrg            else {
6133f7df2e56Smrg                nrep.which = 0;
6134f7df2e56Smrg                nrep.nTypes = 0;
6135f7df2e56Smrg                nrep.nKTLevels = 0;
6136f7df2e56Smrg                nrep.groupNames = 0;
6137f7df2e56Smrg                nrep.virtualMods = 0;
6138f7df2e56Smrg                nrep.indicators = 0;
6139f7df2e56Smrg                nrep.nRadioGroups = 0;
6140f7df2e56Smrg            }
6141f7df2e56Smrg            if (rep.reported & XkbGBN_KeyNamesMask) {
6142f7df2e56Smrg                nrep.which |= XkbKeyNamesMask;
6143f7df2e56Smrg                nrep.firstKey = new->min_key_code;
6144f7df2e56Smrg                nrep.nKeys = XkbNumKeys(new);
6145f7df2e56Smrg                nrep.nKeyAliases = new->names->num_key_aliases;
6146f7df2e56Smrg                if (nrep.nKeyAliases)
6147f7df2e56Smrg                    nrep.which |= XkbKeyAliasesMask;
6148f7df2e56Smrg            }
6149f7df2e56Smrg            else {
6150f7df2e56Smrg                nrep.which &= ~(XkbKeyNamesMask | XkbKeyAliasesMask);
6151f7df2e56Smrg                nrep.firstKey = nrep.nKeys = 0;
6152f7df2e56Smrg                nrep.nKeyAliases = 0;
6153f7df2e56Smrg            }
6154f7df2e56Smrg            XkbComputeGetNamesReplySize(new, &nrep);
6155f7df2e56Smrg            rep.length += SIZEOF(xGenericReply) / 4 + nrep.length;
6156f7df2e56Smrg        }
6157f7df2e56Smrg        if (new->geom == NULL)
6158f7df2e56Smrg            rep.reported &= ~XkbGBN_GeometryMask;
6159f7df2e56Smrg        else if (rep.reported & XkbGBN_GeometryMask) {
6160f7df2e56Smrg            grep.type = X_Reply;
6161f7df2e56Smrg            grep.deviceID = dev->id;
6162f7df2e56Smrg            grep.sequenceNumber = client->sequence;
6163f7df2e56Smrg            grep.length = 0;
6164f7df2e56Smrg            grep.found = TRUE;
6165f7df2e56Smrg            grep.pad = 0;
6166f7df2e56Smrg            grep.widthMM = grep.heightMM = 0;
6167f7df2e56Smrg            grep.nProperties = grep.nColors = grep.nShapes = 0;
6168f7df2e56Smrg            grep.nSections = grep.nDoodads = 0;
6169f7df2e56Smrg            grep.baseColorNdx = grep.labelColorNdx = 0;
6170f7df2e56Smrg            XkbComputeGetGeometryReplySize(new->geom, &grep, None);
6171f7df2e56Smrg            rep.length += SIZEOF(xGenericReply) / 4 + grep.length;
6172f7df2e56Smrg        }
6173f7df2e56Smrg    }
6174f7df2e56Smrg
6175f7df2e56Smrg    reported = rep.reported;
6176f7df2e56Smrg    if (client->swapped) {
6177f7df2e56Smrg        swaps(&rep.sequenceNumber);
6178f7df2e56Smrg        swapl(&rep.length);
6179f7df2e56Smrg        swaps(&rep.found);
6180f7df2e56Smrg        swaps(&rep.reported);
6181f7df2e56Smrg    }
6182f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetKbdByNameReply), &rep);
6183f7df2e56Smrg    if (reported & (XkbGBN_SymbolsMask | XkbGBN_TypesMask))
6184f7df2e56Smrg        XkbSendMap(client, new, &mrep);
6185f7df2e56Smrg    if (reported & XkbGBN_CompatMapMask)
6186f7df2e56Smrg        XkbSendCompatMap(client, new->compat, &crep);
6187f7df2e56Smrg    if (reported & XkbGBN_IndicatorMapMask)
6188f7df2e56Smrg        XkbSendIndicatorMap(client, new->indicators, &irep);
6189f7df2e56Smrg    if (reported & (XkbGBN_KeyNamesMask | XkbGBN_OtherNamesMask))
6190f7df2e56Smrg        XkbSendNames(client, new, &nrep);
6191f7df2e56Smrg    if (reported & XkbGBN_GeometryMask)
6192f7df2e56Smrg        XkbSendGeometry(client, new->geom, &grep, FALSE);
6193f7df2e56Smrg    if (rep.loaded) {
6194f7df2e56Smrg        XkbDescPtr old_xkb;
6195f7df2e56Smrg        xkbNewKeyboardNotify nkn;
6196f7df2e56Smrg
6197f7df2e56Smrg        old_xkb = xkb;
6198f7df2e56Smrg        xkb = new;
6199f7df2e56Smrg        dev->key->xkbInfo->desc = xkb;
6200f7df2e56Smrg        new = old_xkb;          /* so it'll get freed automatically */
6201f7df2e56Smrg
6202f7df2e56Smrg        XkbCopyControls(xkb, old_xkb);
6203f7df2e56Smrg
6204f7df2e56Smrg        nkn.deviceID = nkn.oldDeviceID = dev->id;
6205f7df2e56Smrg        nkn.minKeyCode = new->min_key_code;
6206f7df2e56Smrg        nkn.maxKeyCode = new->max_key_code;
6207f7df2e56Smrg        nkn.oldMinKeyCode = xkb->min_key_code;
6208f7df2e56Smrg        nkn.oldMaxKeyCode = xkb->max_key_code;
6209f7df2e56Smrg        nkn.requestMajor = XkbReqCode;
6210f7df2e56Smrg        nkn.requestMinor = X_kbGetKbdByName;
6211f7df2e56Smrg        nkn.changed = XkbNKN_KeycodesMask;
6212f7df2e56Smrg        if (geom_changed)
6213f7df2e56Smrg            nkn.changed |= XkbNKN_GeometryMask;
6214f7df2e56Smrg        XkbSendNewKeyboardNotify(dev, &nkn);
6215f7df2e56Smrg
6216f7df2e56Smrg        /* Update the map and LED info on the device itself, as well as
6217f7df2e56Smrg         * any slaves if it's an MD, or its MD if it's an SD and was the
6218f7df2e56Smrg         * last device used on that MD. */
621905b261ecSmrg        for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
6220f7df2e56Smrg            if (tmpd != dev && GetMaster(tmpd, MASTER_KEYBOARD) != dev &&
6221f7df2e56Smrg                (tmpd != master || dev != master->lastSlave))
6222f7df2e56Smrg                continue;
6223f7df2e56Smrg
6224f7df2e56Smrg            if (tmpd != dev)
6225f7df2e56Smrg                XkbDeviceApplyKeymap(tmpd, xkb);
6226f7df2e56Smrg
6227f7df2e56Smrg            if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) {
6228f7df2e56Smrg                old_sli = tmpd->kbdfeed->xkb_sli;
6229f7df2e56Smrg                tmpd->kbdfeed->xkb_sli = NULL;
6230f7df2e56Smrg                sli = XkbAllocSrvLedInfo(tmpd, tmpd->kbdfeed, NULL, 0);
6231f7df2e56Smrg                if (sli) {
6232f7df2e56Smrg                    sli->explicitState = old_sli->explicitState;
6233f7df2e56Smrg                    sli->effectiveState = old_sli->effectiveState;
623405b261ecSmrg                }
6235f7df2e56Smrg                tmpd->kbdfeed->xkb_sli = sli;
6236f7df2e56Smrg                XkbFreeSrvLedInfo(old_sli);
623705b261ecSmrg            }
623805b261ecSmrg        }
6239f7df2e56Smrg    }
6240f7df2e56Smrg    if ((new != NULL) && (new != xkb)) {
6241f7df2e56Smrg        XkbFreeKeyboard(new, XkbAllComponentsMask, TRUE);
6242f7df2e56Smrg        new = NULL;
624305b261ecSmrg    }
62449ace9065Smrg    XkbFreeComponentNames(&names, FALSE);
6245f7df2e56Smrg    XkbSetCauseXkbReq(&cause, X_kbGetKbdByName, client);
6246f7df2e56Smrg    XkbUpdateAllDeviceIndicators(NULL, &cause);
6247f7df2e56Smrg
62486747b715Smrg    return Success;
624905b261ecSmrg}
625005b261ecSmrg
625105b261ecSmrg/***====================================================================***/
625205b261ecSmrg
625305b261ecSmrgstatic int
6254f7df2e56SmrgComputeDeviceLedInfoSize(DeviceIntPtr dev,
6255f7df2e56Smrg                         unsigned int what, XkbSrvLedInfoPtr sli)
625605b261ecSmrg{
6257f7df2e56Smrg    int nNames, nMaps;
6258f7df2e56Smrg    register unsigned n, bit;
6259f7df2e56Smrg
6260f7df2e56Smrg    if (sli == NULL)
6261f7df2e56Smrg        return 0;
6262f7df2e56Smrg    nNames = nMaps = 0;
6263f7df2e56Smrg    if ((what & XkbXI_IndicatorNamesMask) == 0)
6264f7df2e56Smrg        sli->namesPresent = 0;
6265f7df2e56Smrg    if ((what & XkbXI_IndicatorMapsMask) == 0)
6266f7df2e56Smrg        sli->mapsPresent = 0;
6267f7df2e56Smrg
6268f7df2e56Smrg    for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6269f7df2e56Smrg        if (sli->names && sli->names[n] != None) {
6270f7df2e56Smrg            sli->namesPresent |= bit;
6271f7df2e56Smrg            nNames++;
6272f7df2e56Smrg        }
6273f7df2e56Smrg        if (sli->maps && XkbIM_InUse(&sli->maps[n])) {
6274f7df2e56Smrg            sli->mapsPresent |= bit;
6275f7df2e56Smrg            nMaps++;
6276f7df2e56Smrg        }
6277f7df2e56Smrg    }
6278f7df2e56Smrg    return (nNames * 4) + (nMaps * SIZEOF(xkbIndicatorMapWireDesc));
627905b261ecSmrg}
628005b261ecSmrg
6281f7df2e56Smrgstatic int
6282f7df2e56SmrgCheckDeviceLedFBs(DeviceIntPtr dev,
6283f7df2e56Smrg                  int class,
6284f7df2e56Smrg                  int id, xkbGetDeviceInfoReply * rep, ClientPtr client)
628505b261ecSmrg{
6286f7df2e56Smrg    int nFBs = 0;
6287f7df2e56Smrg    int length = 0;
6288f7df2e56Smrg    Bool classOk;
6289f7df2e56Smrg
6290f7df2e56Smrg    if (class == XkbDfltXIClass) {
6291f7df2e56Smrg        if (dev->kbdfeed)
6292f7df2e56Smrg            class = KbdFeedbackClass;
6293f7df2e56Smrg        else if (dev->leds)
6294f7df2e56Smrg            class = LedFeedbackClass;
6295f7df2e56Smrg        else {
6296f7df2e56Smrg            client->errorValue = _XkbErrCode2(XkbErr_BadClass, class);
6297f7df2e56Smrg            return XkbKeyboardErrorCode;
6298f7df2e56Smrg        }
6299f7df2e56Smrg    }
6300f7df2e56Smrg    classOk = FALSE;
6301f7df2e56Smrg    if ((dev->kbdfeed) &&
6302f7df2e56Smrg        ((class == KbdFeedbackClass) || (class == XkbAllXIClasses))) {
6303f7df2e56Smrg        KbdFeedbackPtr kf;
6304f7df2e56Smrg
6305f7df2e56Smrg        classOk = TRUE;
6306f7df2e56Smrg        for (kf = dev->kbdfeed; (kf); kf = kf->next) {
6307f7df2e56Smrg            if ((id != XkbAllXIIds) && (id != XkbDfltXIId) &&
6308f7df2e56Smrg                (id != kf->ctrl.id))
6309f7df2e56Smrg                continue;
6310f7df2e56Smrg            nFBs++;
6311f7df2e56Smrg            length += SIZEOF(xkbDeviceLedsWireDesc);
6312f7df2e56Smrg            if (!kf->xkb_sli)
6313f7df2e56Smrg                kf->xkb_sli = XkbAllocSrvLedInfo(dev, kf, NULL, 0);
6314f7df2e56Smrg            length += ComputeDeviceLedInfoSize(dev, rep->present, kf->xkb_sli);
6315f7df2e56Smrg            if (id != XkbAllXIIds)
6316f7df2e56Smrg                break;
6317f7df2e56Smrg        }
6318f7df2e56Smrg    }
6319f7df2e56Smrg    if ((dev->leds) &&
6320f7df2e56Smrg        ((class == LedFeedbackClass) || (class == XkbAllXIClasses))) {
6321f7df2e56Smrg        LedFeedbackPtr lf;
6322f7df2e56Smrg
6323f7df2e56Smrg        classOk = TRUE;
6324f7df2e56Smrg        for (lf = dev->leds; (lf); lf = lf->next) {
6325f7df2e56Smrg            if ((id != XkbAllXIIds) && (id != XkbDfltXIId) &&
6326f7df2e56Smrg                (id != lf->ctrl.id))
6327f7df2e56Smrg                continue;
6328f7df2e56Smrg            nFBs++;
6329f7df2e56Smrg            length += SIZEOF(xkbDeviceLedsWireDesc);
6330f7df2e56Smrg            if (!lf->xkb_sli)
6331f7df2e56Smrg                lf->xkb_sli = XkbAllocSrvLedInfo(dev, NULL, lf, 0);
6332f7df2e56Smrg            length += ComputeDeviceLedInfoSize(dev, rep->present, lf->xkb_sli);
6333f7df2e56Smrg            if (id != XkbAllXIIds)
6334f7df2e56Smrg                break;
6335f7df2e56Smrg        }
6336f7df2e56Smrg    }
6337f7df2e56Smrg    if (nFBs > 0) {
6338f7df2e56Smrg        rep->nDeviceLedFBs = nFBs;
6339f7df2e56Smrg        rep->length += (length / 4);
6340f7df2e56Smrg        return Success;
6341f7df2e56Smrg    }
6342f7df2e56Smrg    if (classOk)
6343f7df2e56Smrg        client->errorValue = _XkbErrCode2(XkbErr_BadId, id);
6344f7df2e56Smrg    else
6345f7df2e56Smrg        client->errorValue = _XkbErrCode2(XkbErr_BadClass, class);
634605b261ecSmrg    return XkbKeyboardErrorCode;
634705b261ecSmrg}
634805b261ecSmrg
634905b261ecSmrgstatic int
6350f7df2e56SmrgSendDeviceLedInfo(XkbSrvLedInfoPtr sli, ClientPtr client)
635105b261ecSmrg{
6352f7df2e56Smrg    xkbDeviceLedsWireDesc wire;
6353f7df2e56Smrg    int length;
6354f7df2e56Smrg
6355f7df2e56Smrg    length = 0;
6356f7df2e56Smrg    wire.ledClass = sli->class;
6357f7df2e56Smrg    wire.ledID = sli->id;
6358f7df2e56Smrg    wire.namesPresent = sli->namesPresent;
6359f7df2e56Smrg    wire.mapsPresent = sli->mapsPresent;
6360f7df2e56Smrg    wire.physIndicators = sli->physIndicators;
6361f7df2e56Smrg    wire.state = sli->effectiveState;
636205b261ecSmrg    if (client->swapped) {
6363f7df2e56Smrg        swaps(&wire.ledClass);
6364f7df2e56Smrg        swaps(&wire.ledID);
6365f7df2e56Smrg        swapl(&wire.namesPresent);
6366f7df2e56Smrg        swapl(&wire.mapsPresent);
6367f7df2e56Smrg        swapl(&wire.physIndicators);
6368f7df2e56Smrg        swapl(&wire.state);
6369f7df2e56Smrg    }
6370f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbDeviceLedsWireDesc), &wire);
6371f7df2e56Smrg    length += SIZEOF(xkbDeviceLedsWireDesc);
6372f7df2e56Smrg    if (sli->namesPresent | sli->mapsPresent) {
6373f7df2e56Smrg        register unsigned i, bit;
6374f7df2e56Smrg
6375f7df2e56Smrg        if (sli->namesPresent) {
6376f7df2e56Smrg            CARD32 awire;
6377f7df2e56Smrg
6378f7df2e56Smrg            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
6379f7df2e56Smrg                if (sli->namesPresent & bit) {
6380f7df2e56Smrg                    awire = (CARD32) sli->names[i];
6381f7df2e56Smrg                    if (client->swapped) {
6382f7df2e56Smrg                        swapl(&awire);
6383f7df2e56Smrg                    }
6384f7df2e56Smrg                    WriteToClient(client, 4, &awire);
6385f7df2e56Smrg                    length += 4;
6386f7df2e56Smrg                }
6387f7df2e56Smrg            }
6388f7df2e56Smrg        }
6389f7df2e56Smrg        if (sli->mapsPresent) {
6390f7df2e56Smrg            for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
6391f7df2e56Smrg                xkbIndicatorMapWireDesc iwire;
6392f7df2e56Smrg
6393f7df2e56Smrg                if (sli->mapsPresent & bit) {
6394f7df2e56Smrg                    iwire.flags = sli->maps[i].flags;
6395f7df2e56Smrg                    iwire.whichGroups = sli->maps[i].which_groups;
6396f7df2e56Smrg                    iwire.groups = sli->maps[i].groups;
6397f7df2e56Smrg                    iwire.whichMods = sli->maps[i].which_mods;
6398f7df2e56Smrg                    iwire.mods = sli->maps[i].mods.mask;
6399f7df2e56Smrg                    iwire.realMods = sli->maps[i].mods.real_mods;
6400f7df2e56Smrg                    iwire.virtualMods = sli->maps[i].mods.vmods;
6401f7df2e56Smrg                    iwire.ctrls = sli->maps[i].ctrls;
6402f7df2e56Smrg                    if (client->swapped) {
6403f7df2e56Smrg                        swaps(&iwire.virtualMods);
6404f7df2e56Smrg                        swapl(&iwire.ctrls);
6405f7df2e56Smrg                    }
6406f7df2e56Smrg                    WriteToClient(client, SIZEOF(xkbIndicatorMapWireDesc),
6407f7df2e56Smrg                                  &iwire);
6408f7df2e56Smrg                    length += SIZEOF(xkbIndicatorMapWireDesc);
6409f7df2e56Smrg                }
6410f7df2e56Smrg            }
6411f7df2e56Smrg        }
641205b261ecSmrg    }
641305b261ecSmrg    return length;
641405b261ecSmrg}
641505b261ecSmrg
641605b261ecSmrgstatic int
6417f7df2e56SmrgSendDeviceLedFBs(DeviceIntPtr dev,
6418f7df2e56Smrg                 int class, int id, unsigned wantLength, ClientPtr client)
641905b261ecSmrg{
6420f7df2e56Smrg    int length = 0;
6421f7df2e56Smrg
6422f7df2e56Smrg    if (class == XkbDfltXIClass) {
6423f7df2e56Smrg        if (dev->kbdfeed)
6424f7df2e56Smrg            class = KbdFeedbackClass;
6425f7df2e56Smrg        else if (dev->leds)
6426f7df2e56Smrg            class = LedFeedbackClass;
6427f7df2e56Smrg    }
6428f7df2e56Smrg    if ((dev->kbdfeed) &&
6429f7df2e56Smrg        ((class == KbdFeedbackClass) || (class == XkbAllXIClasses))) {
6430f7df2e56Smrg        KbdFeedbackPtr kf;
6431f7df2e56Smrg
6432f7df2e56Smrg        for (kf = dev->kbdfeed; (kf); kf = kf->next) {
6433f7df2e56Smrg            if ((id == XkbAllXIIds) || (id == XkbDfltXIId) ||
6434f7df2e56Smrg                (id == kf->ctrl.id)) {
6435f7df2e56Smrg                length += SendDeviceLedInfo(kf->xkb_sli, client);
6436f7df2e56Smrg                if (id != XkbAllXIIds)
6437f7df2e56Smrg                    break;
6438f7df2e56Smrg            }
6439f7df2e56Smrg        }
6440f7df2e56Smrg    }
6441f7df2e56Smrg    if ((dev->leds) &&
6442f7df2e56Smrg        ((class == LedFeedbackClass) || (class == XkbAllXIClasses))) {
6443f7df2e56Smrg        LedFeedbackPtr lf;
6444f7df2e56Smrg
6445f7df2e56Smrg        for (lf = dev->leds; (lf); lf = lf->next) {
6446f7df2e56Smrg            if ((id == XkbAllXIIds) || (id == XkbDfltXIId) ||
6447f7df2e56Smrg                (id == lf->ctrl.id)) {
6448f7df2e56Smrg                length += SendDeviceLedInfo(lf->xkb_sli, client);
6449f7df2e56Smrg                if (id != XkbAllXIIds)
6450f7df2e56Smrg                    break;
6451f7df2e56Smrg            }
6452f7df2e56Smrg        }
6453f7df2e56Smrg    }
6454f7df2e56Smrg    if (length == wantLength)
6455f7df2e56Smrg        return Success;
6456f7df2e56Smrg    else
6457f7df2e56Smrg        return BadLength;
645805b261ecSmrg}
645905b261ecSmrg
646005b261ecSmrgint
646105b261ecSmrgProcXkbGetDeviceInfo(ClientPtr client)
646205b261ecSmrg{
6463f7df2e56Smrg    DeviceIntPtr dev;
6464f7df2e56Smrg    xkbGetDeviceInfoReply rep;
6465f7df2e56Smrg    int status, nDeviceLedFBs;
6466f7df2e56Smrg    unsigned length, nameLen;
6467f7df2e56Smrg    CARD16 ledClass, ledID;
6468f7df2e56Smrg    unsigned wanted;
6469f7df2e56Smrg    char *str;
647005b261ecSmrg
647105b261ecSmrg    REQUEST(xkbGetDeviceInfoReq);
647205b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq);
647305b261ecSmrg
6474f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
6475f7df2e56Smrg        return BadAccess;
647605b261ecSmrg
6477f7df2e56Smrg    wanted = stuff->wanted;
647805b261ecSmrg
64794642e01fSmrg    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
6480f7df2e56Smrg    CHK_MASK_LEGAL(0x01, wanted, XkbXI_AllDeviceFeaturesMask);
6481f7df2e56Smrg
6482f7df2e56Smrg    if ((!dev->button) || ((stuff->nBtns < 1) && (!stuff->allBtns)))
6483f7df2e56Smrg        wanted &= ~XkbXI_ButtonActionsMask;
6484f7df2e56Smrg    if ((!dev->kbdfeed) && (!dev->leds))
6485f7df2e56Smrg        wanted &= ~XkbXI_IndicatorsMask;
6486f7df2e56Smrg
6487f7df2e56Smrg    nameLen = XkbSizeCountedString(dev->name);
6488f7df2e56Smrg    rep = (xkbGetDeviceInfoReply) {
6489f7df2e56Smrg        .type = X_Reply,
6490f7df2e56Smrg        .deviceID = dev->id,
6491f7df2e56Smrg        .sequenceNumber = client->sequence,
6492f7df2e56Smrg        .length = nameLen / 4,
6493f7df2e56Smrg        .present = wanted,
6494f7df2e56Smrg        .supported = XkbXI_AllDeviceFeaturesMask,
6495f7df2e56Smrg        .unsupported = 0,
6496f7df2e56Smrg        .nDeviceLedFBs = 0,
6497f7df2e56Smrg        .firstBtnWanted = 0,
6498f7df2e56Smrg        .nBtnsWanted = 0,
6499f7df2e56Smrg        .firstBtnRtrn = 0,
6500f7df2e56Smrg        .nBtnsRtrn = 0,
6501f7df2e56Smrg        .totalBtns = dev->button ? dev->button->numButtons : 0,
6502f7df2e56Smrg        .hasOwnState = (dev->key && dev->key->xkbInfo),
6503f7df2e56Smrg        .dfltKbdFB = dev->kbdfeed ? dev->kbdfeed->ctrl.id : XkbXINone,
6504f7df2e56Smrg        .dfltLedFB = dev->leds ? dev->leds->ctrl.id : XkbXINone,
6505f7df2e56Smrg        .devType = dev->xinput_type
6506f7df2e56Smrg    };
6507f7df2e56Smrg
6508f7df2e56Smrg    ledClass = stuff->ledClass;
6509f7df2e56Smrg    ledID = stuff->ledID;
6510f7df2e56Smrg
6511f7df2e56Smrg    if (wanted & XkbXI_ButtonActionsMask) {
6512f7df2e56Smrg        if (stuff->allBtns) {
6513f7df2e56Smrg            stuff->firstBtn = 0;
6514f7df2e56Smrg            stuff->nBtns = dev->button->numButtons;
6515f7df2e56Smrg        }
651605b261ecSmrg
6517f7df2e56Smrg        if ((stuff->firstBtn + stuff->nBtns) > dev->button->numButtons) {
6518f7df2e56Smrg            client->errorValue = _XkbErrCode4(0x02, dev->button->numButtons,
6519f7df2e56Smrg                                              stuff->firstBtn, stuff->nBtns);
6520f7df2e56Smrg            return BadValue;
6521f7df2e56Smrg        }
6522f7df2e56Smrg        else {
6523f7df2e56Smrg            rep.firstBtnWanted = stuff->firstBtn;
6524f7df2e56Smrg            rep.nBtnsWanted = stuff->nBtns;
6525f7df2e56Smrg            if (dev->button->xkb_acts != NULL) {
6526f7df2e56Smrg                XkbAction *act;
6527f7df2e56Smrg                register int i;
6528f7df2e56Smrg
6529f7df2e56Smrg                rep.firstBtnRtrn = stuff->firstBtn;
6530f7df2e56Smrg                rep.nBtnsRtrn = stuff->nBtns;
6531f7df2e56Smrg                act = &dev->button->xkb_acts[rep.firstBtnWanted];
6532f7df2e56Smrg                for (i = 0; i < rep.nBtnsRtrn; i++, act++) {
6533f7df2e56Smrg                    if (act->type != XkbSA_NoAction)
6534f7df2e56Smrg                        break;
6535f7df2e56Smrg                }
6536f7df2e56Smrg                rep.firstBtnRtrn += i;
6537f7df2e56Smrg                rep.nBtnsRtrn -= i;
6538f7df2e56Smrg                act =
6539f7df2e56Smrg                    &dev->button->xkb_acts[rep.firstBtnRtrn + rep.nBtnsRtrn -
6540f7df2e56Smrg                                           1];
6541f7df2e56Smrg                for (i = 0; i < rep.nBtnsRtrn; i++, act--) {
6542f7df2e56Smrg                    if (act->type != XkbSA_NoAction)
6543f7df2e56Smrg                        break;
6544f7df2e56Smrg                }
6545f7df2e56Smrg                rep.nBtnsRtrn -= i;
6546f7df2e56Smrg            }
6547f7df2e56Smrg            rep.length += (rep.nBtnsRtrn * SIZEOF(xkbActionWireDesc)) / 4;
6548f7df2e56Smrg        }
6549f7df2e56Smrg    }
655005b261ecSmrg
6551f7df2e56Smrg    if (wanted & XkbXI_IndicatorsMask) {
6552f7df2e56Smrg        status = CheckDeviceLedFBs(dev, ledClass, ledID, &rep, client);
6553f7df2e56Smrg        if (status != Success)
6554f7df2e56Smrg            return status;
6555f7df2e56Smrg    }
6556f7df2e56Smrg    length = rep.length * 4;
655705b261ecSmrg    nDeviceLedFBs = rep.nDeviceLedFBs;
655805b261ecSmrg    if (client->swapped) {
6559f7df2e56Smrg        swaps(&rep.sequenceNumber);
6560f7df2e56Smrg        swapl(&rep.length);
6561f7df2e56Smrg        swaps(&rep.present);
6562f7df2e56Smrg        swaps(&rep.supported);
6563f7df2e56Smrg        swaps(&rep.unsupported);
6564f7df2e56Smrg        swaps(&rep.nDeviceLedFBs);
6565f7df2e56Smrg        swaps(&rep.dfltKbdFB);
6566f7df2e56Smrg        swaps(&rep.dfltLedFB);
6567f7df2e56Smrg        swapl(&rep.devType);
6568f7df2e56Smrg    }
6569f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbGetDeviceInfoReply), &rep);
6570f7df2e56Smrg
6571f7df2e56Smrg    str = malloc(nameLen);
6572f7df2e56Smrg    if (!str)
6573f7df2e56Smrg        return BadAlloc;
6574f7df2e56Smrg    XkbWriteCountedString(str, dev->name, client->swapped);
6575f7df2e56Smrg    WriteToClient(client, nameLen, str);
65766747b715Smrg    free(str);
6577f7df2e56Smrg    length -= nameLen;
6578f7df2e56Smrg
6579f7df2e56Smrg    if (rep.nBtnsRtrn > 0) {
6580f7df2e56Smrg        int sz;
6581f7df2e56Smrg        xkbActionWireDesc *awire;
6582f7df2e56Smrg
6583f7df2e56Smrg        sz = rep.nBtnsRtrn * SIZEOF(xkbActionWireDesc);
6584f7df2e56Smrg        awire = (xkbActionWireDesc *) &dev->button->xkb_acts[rep.firstBtnRtrn];
6585f7df2e56Smrg        WriteToClient(client, sz, awire);
6586f7df2e56Smrg        length -= sz;
6587f7df2e56Smrg    }
6588f7df2e56Smrg    if (nDeviceLedFBs > 0) {
6589f7df2e56Smrg        status = SendDeviceLedFBs(dev, ledClass, ledID, length, client);
6590f7df2e56Smrg        if (status != Success)
6591f7df2e56Smrg            return status;
6592f7df2e56Smrg    }
6593f7df2e56Smrg    else if (length != 0) {
6594f7df2e56Smrg        ErrorF("[xkb] Internal Error!  BadLength in ProcXkbGetDeviceInfo\n");
6595f7df2e56Smrg        ErrorF("[xkb]                  Wrote %d fewer bytes than expected\n",
6596f7df2e56Smrg               length);
6597f7df2e56Smrg        return BadLength;
659805b261ecSmrg    }
65996747b715Smrg    return Success;
660005b261ecSmrg}
660105b261ecSmrg
660205b261ecSmrgstatic char *
6603f7df2e56SmrgCheckSetDeviceIndicators(char *wire,
6604f7df2e56Smrg                         DeviceIntPtr dev,
660590bea6a0Smrg                         int num, int *status_rtrn, ClientPtr client,
660690bea6a0Smrg                         xkbSetDeviceInfoReq * stuff)
660705b261ecSmrg{
6608f7df2e56Smrg    xkbDeviceLedsWireDesc *ledWire;
6609f7df2e56Smrg    int i;
6610f7df2e56Smrg    XkbSrvLedInfoPtr sli;
6611f7df2e56Smrg
6612f7df2e56Smrg    ledWire = (xkbDeviceLedsWireDesc *) wire;
6613f7df2e56Smrg    for (i = 0; i < num; i++) {
661490bea6a0Smrg        if (!_XkbCheckRequestBounds(client, stuff, ledWire, ledWire + 1)) {
661590bea6a0Smrg            *status_rtrn = BadLength;
661690bea6a0Smrg            return (char *) ledWire;
661790bea6a0Smrg        }
661890bea6a0Smrg
6619f7df2e56Smrg        if (client->swapped) {
6620f7df2e56Smrg            swaps(&ledWire->ledClass);
6621f7df2e56Smrg            swaps(&ledWire->ledID);
6622f7df2e56Smrg            swapl(&ledWire->namesPresent);
6623f7df2e56Smrg            swapl(&ledWire->mapsPresent);
6624f7df2e56Smrg            swapl(&ledWire->physIndicators);
6625f7df2e56Smrg        }
6626f7df2e56Smrg
6627f7df2e56Smrg        sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID,
6628f7df2e56Smrg                                XkbXI_IndicatorsMask);
6629f7df2e56Smrg        if (sli != NULL) {
6630f7df2e56Smrg            register int n;
6631f7df2e56Smrg            register unsigned bit;
6632f7df2e56Smrg            int nMaps, nNames;
6633f7df2e56Smrg            CARD32 *atomWire;
6634f7df2e56Smrg            xkbIndicatorMapWireDesc *mapWire;
6635f7df2e56Smrg
6636f7df2e56Smrg            nMaps = nNames = 0;
6637f7df2e56Smrg            for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6638f7df2e56Smrg                if (ledWire->namesPresent & bit)
6639f7df2e56Smrg                    nNames++;
6640f7df2e56Smrg                if (ledWire->mapsPresent & bit)
6641f7df2e56Smrg                    nMaps++;
6642f7df2e56Smrg            }
6643f7df2e56Smrg            atomWire = (CARD32 *) &ledWire[1];
6644f7df2e56Smrg            if (nNames > 0) {
6645f7df2e56Smrg                for (n = 0; n < nNames; n++) {
664690bea6a0Smrg                    if (!_XkbCheckRequestBounds(client, stuff, atomWire, atomWire + 1)) {
664790bea6a0Smrg                        *status_rtrn = BadLength;
664890bea6a0Smrg                        return (char *) atomWire;
664990bea6a0Smrg                    }
665090bea6a0Smrg
6651f7df2e56Smrg                    if (client->swapped) {
6652f7df2e56Smrg                        swapl(atomWire);
6653f7df2e56Smrg                    }
6654f7df2e56Smrg                    CHK_ATOM_OR_NONE3(((Atom) (*atomWire)), client->errorValue,
6655f7df2e56Smrg                                      *status_rtrn, NULL);
6656f7df2e56Smrg                    atomWire++;
6657f7df2e56Smrg                }
6658f7df2e56Smrg            }
6659f7df2e56Smrg            mapWire = (xkbIndicatorMapWireDesc *) atomWire;
6660f7df2e56Smrg            if (nMaps > 0) {
6661f7df2e56Smrg                for (n = 0; n < nMaps; n++) {
666290bea6a0Smrg                    if (!_XkbCheckRequestBounds(client, stuff, mapWire, mapWire + 1)) {
666390bea6a0Smrg                        *status_rtrn = BadLength;
666490bea6a0Smrg                        return (char *) mapWire;
666590bea6a0Smrg                    }
6666f7df2e56Smrg                    if (client->swapped) {
6667f7df2e56Smrg                        swaps(&mapWire->virtualMods);
6668f7df2e56Smrg                        swapl(&mapWire->ctrls);
6669f7df2e56Smrg                    }
6670f7df2e56Smrg                    CHK_MASK_LEGAL3(0x21, mapWire->whichGroups,
6671f7df2e56Smrg                                    XkbIM_UseAnyGroup,
6672f7df2e56Smrg                                    client->errorValue, *status_rtrn, NULL);
6673f7df2e56Smrg                    CHK_MASK_LEGAL3(0x22, mapWire->whichMods, XkbIM_UseAnyMods,
6674f7df2e56Smrg                                    client->errorValue, *status_rtrn, NULL);
6675f7df2e56Smrg                    mapWire++;
6676f7df2e56Smrg                }
6677f7df2e56Smrg            }
6678f7df2e56Smrg            ledWire = (xkbDeviceLedsWireDesc *) mapWire;
6679f7df2e56Smrg        }
6680f7df2e56Smrg        else {
6681f7df2e56Smrg            /* SHOULD NEVER HAPPEN */
6682f7df2e56Smrg            return (char *) ledWire;
6683f7df2e56Smrg        }
6684f7df2e56Smrg    }
6685f7df2e56Smrg    return (char *) ledWire;
668605b261ecSmrg}
668705b261ecSmrg
668805b261ecSmrgstatic char *
6689f7df2e56SmrgSetDeviceIndicators(char *wire,
6690f7df2e56Smrg                    DeviceIntPtr dev,
6691f7df2e56Smrg                    unsigned changed,
6692f7df2e56Smrg                    int num,
6693f7df2e56Smrg                    int *status_rtrn,
6694806e81e9Smrg                    ClientPtr client,
6695806e81e9Smrg                    xkbExtensionDeviceNotify * ev,
6696806e81e9Smrg                    xkbSetDeviceInfoReq * stuff)
669705b261ecSmrg{
6698f7df2e56Smrg    xkbDeviceLedsWireDesc *ledWire;
6699f7df2e56Smrg    int i;
6700f7df2e56Smrg    XkbEventCauseRec cause;
6701f7df2e56Smrg    unsigned namec, mapc, statec;
6702f7df2e56Smrg    xkbExtensionDeviceNotify ed;
6703f7df2e56Smrg    XkbChangesRec changes;
6704f7df2e56Smrg    DeviceIntPtr kbd;
6705f7df2e56Smrg
6706f7df2e56Smrg    memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify));
6707f7df2e56Smrg    memset((char *) &changes, 0, sizeof(XkbChangesRec));
6708f7df2e56Smrg    XkbSetCauseXkbReq(&cause, X_kbSetDeviceInfo, client);
6709f7df2e56Smrg    ledWire = (xkbDeviceLedsWireDesc *) wire;
6710f7df2e56Smrg    for (i = 0; i < num; i++) {
6711f7df2e56Smrg        register int n;
6712f7df2e56Smrg        register unsigned bit;
6713f7df2e56Smrg        CARD32 *atomWire;
6714f7df2e56Smrg        xkbIndicatorMapWireDesc *mapWire;
6715f7df2e56Smrg        XkbSrvLedInfoPtr sli;
6716f7df2e56Smrg
6717f7df2e56Smrg        namec = mapc = statec = 0;
6718f7df2e56Smrg        sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID,
6719f7df2e56Smrg                                XkbXI_IndicatorMapsMask);
6720f7df2e56Smrg        if (!sli) {
6721f7df2e56Smrg            /* SHOULD NEVER HAPPEN!! */
6722f7df2e56Smrg            return (char *) ledWire;
6723f7df2e56Smrg        }
672405b261ecSmrg
6725f7df2e56Smrg        atomWire = (CARD32 *) &ledWire[1];
6726f7df2e56Smrg        if (changed & XkbXI_IndicatorNamesMask) {
6727f7df2e56Smrg            namec = sli->namesPresent | ledWire->namesPresent;
6728f7df2e56Smrg            memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom));
6729f7df2e56Smrg        }
6730f7df2e56Smrg        if (ledWire->namesPresent) {
6731f7df2e56Smrg            sli->namesPresent = ledWire->namesPresent;
6732f7df2e56Smrg            memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom));
6733f7df2e56Smrg            for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6734f7df2e56Smrg                if (ledWire->namesPresent & bit) {
6735f7df2e56Smrg                    sli->names[n] = (Atom) *atomWire;
6736f7df2e56Smrg                    if (sli->names[n] == None)
6737f7df2e56Smrg                        ledWire->namesPresent &= ~bit;
6738f7df2e56Smrg                    atomWire++;
6739f7df2e56Smrg                }
6740f7df2e56Smrg            }
6741f7df2e56Smrg        }
6742f7df2e56Smrg        mapWire = (xkbIndicatorMapWireDesc *) atomWire;
6743f7df2e56Smrg        if (changed & XkbXI_IndicatorMapsMask) {
6744f7df2e56Smrg            mapc = sli->mapsPresent | ledWire->mapsPresent;
6745f7df2e56Smrg            sli->mapsPresent = ledWire->mapsPresent;
6746f7df2e56Smrg            memset((char *) sli->maps, 0,
6747f7df2e56Smrg                   XkbNumIndicators * sizeof(XkbIndicatorMapRec));
6748f7df2e56Smrg        }
6749f7df2e56Smrg        if (ledWire->mapsPresent) {
6750f7df2e56Smrg            for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6751f7df2e56Smrg                if (ledWire->mapsPresent & bit) {
6752f7df2e56Smrg                    sli->maps[n].flags = mapWire->flags;
6753f7df2e56Smrg                    sli->maps[n].which_groups = mapWire->whichGroups;
6754f7df2e56Smrg                    sli->maps[n].groups = mapWire->groups;
6755f7df2e56Smrg                    sli->maps[n].which_mods = mapWire->whichMods;
6756f7df2e56Smrg                    sli->maps[n].mods.mask = mapWire->mods;
6757f7df2e56Smrg                    sli->maps[n].mods.real_mods = mapWire->realMods;
6758f7df2e56Smrg                    sli->maps[n].mods.vmods = mapWire->virtualMods;
6759f7df2e56Smrg                    sli->maps[n].ctrls = mapWire->ctrls;
6760f7df2e56Smrg                    mapWire++;
6761f7df2e56Smrg                }
6762f7df2e56Smrg            }
6763f7df2e56Smrg        }
6764f7df2e56Smrg        if (changed & XkbXI_IndicatorStateMask) {
6765f7df2e56Smrg            statec = sli->effectiveState ^ ledWire->state;
6766f7df2e56Smrg            sli->explicitState &= ~statec;
6767f7df2e56Smrg            sli->explicitState |= (ledWire->state & statec);
6768f7df2e56Smrg        }
6769f7df2e56Smrg        if (namec)
6770f7df2e56Smrg            XkbApplyLedNameChanges(dev, sli, namec, &ed, &changes, &cause);
6771f7df2e56Smrg        if (mapc)
6772f7df2e56Smrg            XkbApplyLedMapChanges(dev, sli, mapc, &ed, &changes, &cause);
6773f7df2e56Smrg        if (statec)
6774f7df2e56Smrg            XkbApplyLedStateChanges(dev, sli, statec, &ed, &changes, &cause);
6775f7df2e56Smrg
6776f7df2e56Smrg        kbd = dev;
6777f7df2e56Smrg        if ((sli->flags & XkbSLI_HasOwnState) == 0)
6778f7df2e56Smrg            kbd = inputInfo.keyboard;
6779f7df2e56Smrg
6780f7df2e56Smrg        XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause);
6781f7df2e56Smrg        ledWire = (xkbDeviceLedsWireDesc *) mapWire;
6782f7df2e56Smrg    }
6783f7df2e56Smrg    return (char *) ledWire;
6784f7df2e56Smrg}
678505b261ecSmrg
67864642e01fSmrgstatic int
678790bea6a0Smrg_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev,
6788f7df2e56Smrg                  xkbSetDeviceInfoReq * stuff)
67894642e01fSmrg{
6790f7df2e56Smrg    char *wire;
6791f7df2e56Smrg
6792f7df2e56Smrg    wire = (char *) &stuff[1];
6793f7df2e56Smrg    if (stuff->change & XkbXI_ButtonActionsMask) {
679490bea6a0Smrg        int sz = stuff->nBtns * SIZEOF(xkbActionWireDesc);
679590bea6a0Smrg        if (!_XkbCheckRequestBounds(client, stuff, wire, (char *) wire + sz))
679690bea6a0Smrg            return BadLength;
679790bea6a0Smrg
6798f7df2e56Smrg        if (!dev->button) {
6799f7df2e56Smrg            client->errorValue = _XkbErrCode2(XkbErr_BadClass, ButtonClass);
6800f7df2e56Smrg            return XkbKeyboardErrorCode;
6801f7df2e56Smrg        }
6802f7df2e56Smrg        if ((stuff->firstBtn + stuff->nBtns) > dev->button->numButtons) {
6803f7df2e56Smrg            client->errorValue =
6804f7df2e56Smrg                _XkbErrCode4(0x02, stuff->firstBtn, stuff->nBtns,
6805f7df2e56Smrg                             dev->button->numButtons);
6806f7df2e56Smrg            return BadMatch;
6807f7df2e56Smrg        }
680890bea6a0Smrg        wire += sz;
6809f7df2e56Smrg    }
6810f7df2e56Smrg    if (stuff->change & XkbXI_IndicatorsMask) {
6811f7df2e56Smrg        int status = Success;
6812f7df2e56Smrg
6813f7df2e56Smrg        wire = CheckSetDeviceIndicators(wire, dev, stuff->nDeviceLedFBs,
681490bea6a0Smrg                                        &status, client, stuff);
6815f7df2e56Smrg        if (status != Success)
6816f7df2e56Smrg            return status;
6817f7df2e56Smrg    }
6818f7df2e56Smrg    if (((wire - ((char *) stuff)) / 4) != stuff->length)
6819f7df2e56Smrg        return BadLength;
682005b261ecSmrg
68214642e01fSmrg    return Success;
68224642e01fSmrg}
68234642e01fSmrg
68244642e01fSmrgstatic int
682590bea6a0Smrg_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev,
682690bea6a0Smrg                  xkbSetDeviceInfoReq * stuff)
68274642e01fSmrg{
6828f7df2e56Smrg    char *wire;
6829f7df2e56Smrg    xkbExtensionDeviceNotify ed;
6830f7df2e56Smrg
6831f7df2e56Smrg    memset((char *) &ed, 0, SIZEOF(xkbExtensionDeviceNotify));
6832f7df2e56Smrg    ed.deviceID = dev->id;
6833f7df2e56Smrg    wire = (char *) &stuff[1];
6834f7df2e56Smrg    if (stuff->change & XkbXI_ButtonActionsMask) {
6835806e81e9Smrg	int nBtns, sz, i;
6836f7df2e56Smrg        XkbAction *acts;
6837f7df2e56Smrg        DeviceIntPtr kbd;
6838f7df2e56Smrg
6839f7df2e56Smrg        nBtns = dev->button->numButtons;
6840f7df2e56Smrg        acts = dev->button->xkb_acts;
6841f7df2e56Smrg        if (acts == NULL) {
6842f7df2e56Smrg            acts = calloc(nBtns, sizeof(XkbAction));
6843f7df2e56Smrg            if (!acts)
6844f7df2e56Smrg                return BadAlloc;
6845f7df2e56Smrg            dev->button->xkb_acts = acts;
6846f7df2e56Smrg        }
6847806e81e9Smrg        if (stuff->firstBtn + stuff->nBtns > nBtns)
6848806e81e9Smrg            return BadValue;
6849f7df2e56Smrg        sz = stuff->nBtns * SIZEOF(xkbActionWireDesc);
6850f7df2e56Smrg        memcpy((char *) &acts[stuff->firstBtn], (char *) wire, sz);
6851f7df2e56Smrg        wire += sz;
6852f7df2e56Smrg        ed.reason |= XkbXI_ButtonActionsMask;
6853f7df2e56Smrg        ed.firstBtn = stuff->firstBtn;
6854f7df2e56Smrg        ed.nBtns = stuff->nBtns;
6855f7df2e56Smrg
6856f7df2e56Smrg        if (dev->key)
6857f7df2e56Smrg            kbd = dev;
6858f7df2e56Smrg        else
6859f7df2e56Smrg            kbd = inputInfo.keyboard;
6860f7df2e56Smrg        acts = &dev->button->xkb_acts[stuff->firstBtn];
6861f7df2e56Smrg        for (i = 0; i < stuff->nBtns; i++, acts++) {
6862f7df2e56Smrg            if (acts->type != XkbSA_NoAction)
6863f7df2e56Smrg                XkbSetActionKeyMods(kbd->key->xkbInfo->desc, acts, 0);
6864f7df2e56Smrg        }
6865f7df2e56Smrg    }
6866f7df2e56Smrg    if (stuff->change & XkbXI_IndicatorsMask) {
6867f7df2e56Smrg        int status = Success;
6868f7df2e56Smrg
6869f7df2e56Smrg        wire = SetDeviceIndicators(wire, dev, stuff->change,
6870806e81e9Smrg                                   stuff->nDeviceLedFBs, &status, client, &ed,
6871806e81e9Smrg                                   stuff);
6872f7df2e56Smrg        if (status != Success)
6873f7df2e56Smrg            return status;
6874f7df2e56Smrg    }
6875f7df2e56Smrg    if ((stuff->change) && (ed.reason))
6876f7df2e56Smrg        XkbSendExtensionDeviceNotify(dev, client, &ed);
68774642e01fSmrg    return Success;
68784642e01fSmrg}
68794642e01fSmrg
68804642e01fSmrgint
68814642e01fSmrgProcXkbSetDeviceInfo(ClientPtr client)
68824642e01fSmrg{
6883f7df2e56Smrg    DeviceIntPtr dev;
6884f7df2e56Smrg    int rc;
68854642e01fSmrg
68864642e01fSmrg    REQUEST(xkbSetDeviceInfoReq);
68874642e01fSmrg    REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq);
68884642e01fSmrg
6889f7df2e56Smrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
6890f7df2e56Smrg        return BadAccess;
68914642e01fSmrg
68924642e01fSmrg    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
6893f7df2e56Smrg    CHK_MASK_LEGAL(0x01, stuff->change, XkbXI_AllFeaturesMask);
68944642e01fSmrg
68954642e01fSmrg    rc = _XkbSetDeviceInfoCheck(client, dev, stuff);
68964642e01fSmrg
68974642e01fSmrg    if (rc != Success)
68984642e01fSmrg        return rc;
68994642e01fSmrg
6900f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd ||
6901f7df2e56Smrg        stuff->deviceSpec == XkbUseCorePtr) {
69024642e01fSmrg        DeviceIntPtr other;
6903f7df2e56Smrg
6904f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
6905f7df2e56Smrg            if (((other != dev) && !IsMaster(other) &&
6906f7df2e56Smrg                 GetMaster(other, MASTER_KEYBOARD) == dev) &&
69074642e01fSmrg                ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
6908f7df2e56Smrg                 (stuff->deviceSpec == XkbUseCorePtr && other->button))) {
6909f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
6910f7df2e56Smrg                              DixManageAccess);
6911f7df2e56Smrg                if (rc == Success) {
69124642e01fSmrg                    rc = _XkbSetDeviceInfoCheck(client, other, stuff);
69134642e01fSmrg                    if (rc != Success)
69144642e01fSmrg                        return rc;
69154642e01fSmrg                }
69164642e01fSmrg            }
69174642e01fSmrg        }
69184642e01fSmrg    }
69194642e01fSmrg
69204642e01fSmrg    /* checks done, apply */
69214642e01fSmrg    rc = _XkbSetDeviceInfo(client, dev, stuff);
69224642e01fSmrg    if (rc != Success)
69234642e01fSmrg        return rc;
69244642e01fSmrg
6925f7df2e56Smrg    if (stuff->deviceSpec == XkbUseCoreKbd ||
6926f7df2e56Smrg        stuff->deviceSpec == XkbUseCorePtr) {
69274642e01fSmrg        DeviceIntPtr other;
6928f7df2e56Smrg
6929f7df2e56Smrg        for (other = inputInfo.devices; other; other = other->next) {
6930f7df2e56Smrg            if (((other != dev) && !IsMaster(other) &&
6931f7df2e56Smrg                 GetMaster(other, MASTER_KEYBOARD) == dev) &&
69324642e01fSmrg                ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
6933f7df2e56Smrg                 (stuff->deviceSpec == XkbUseCorePtr && other->button))) {
6934f7df2e56Smrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
6935f7df2e56Smrg                              DixManageAccess);
6936f7df2e56Smrg                if (rc == Success) {
69374642e01fSmrg                    rc = _XkbSetDeviceInfo(client, other, stuff);
69384642e01fSmrg                    if (rc != Success)
69394642e01fSmrg                        return rc;
69404642e01fSmrg                }
69414642e01fSmrg            }
69424642e01fSmrg        }
69434642e01fSmrg    }
69444642e01fSmrg
69456747b715Smrg    return Success;
694605b261ecSmrg}
694705b261ecSmrg
694805b261ecSmrg/***====================================================================***/
694905b261ecSmrg
695005b261ecSmrgint
695105b261ecSmrgProcXkbSetDebuggingFlags(ClientPtr client)
695205b261ecSmrg{
6953f7df2e56Smrg    CARD32 newFlags, newCtrls, extraLength;
6954f7df2e56Smrg    xkbSetDebuggingFlagsReply rep;
6955f7df2e56Smrg    int rc;
695605b261ecSmrg
695705b261ecSmrg    REQUEST(xkbSetDebuggingFlagsReq);
695805b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq);
695905b261ecSmrg
69604642e01fSmrg    rc = XaceHook(XACE_SERVER_ACCESS, client, DixDebugAccess);
69614642e01fSmrg    if (rc != Success)
6962f7df2e56Smrg        return rc;
69634642e01fSmrg
6964f7df2e56Smrg    newFlags = xkbDebugFlags & (~stuff->affectFlags);
6965f7df2e56Smrg    newFlags |= (stuff->flags & stuff->affectFlags);
6966f7df2e56Smrg    newCtrls = xkbDebugCtrls & (~stuff->affectCtrls);
6967f7df2e56Smrg    newCtrls |= (stuff->ctrls & stuff->affectCtrls);
696805b261ecSmrg    if (xkbDebugFlags || newFlags || stuff->msgLength) {
6969f7df2e56Smrg        ErrorF("[xkb] XkbDebug: Setting debug flags to 0x%lx\n",
6970f7df2e56Smrg               (long) newFlags);
6971f7df2e56Smrg        if (newCtrls != xkbDebugCtrls)
6972f7df2e56Smrg            ErrorF("[xkb] XkbDebug: Setting debug controls to 0x%lx\n",
6973f7df2e56Smrg                   (long) newCtrls);
6974f7df2e56Smrg    }
6975f7df2e56Smrg    extraLength = (stuff->length << 2) - sz_xkbSetDebuggingFlagsReq;
6976f7df2e56Smrg    if (stuff->msgLength > 0) {
6977f7df2e56Smrg        char *msg;
6978f7df2e56Smrg
6979f7df2e56Smrg        if (extraLength < XkbPaddedSize(stuff->msgLength)) {
6980f7df2e56Smrg            ErrorF
6981f7df2e56Smrg                ("[xkb] XkbDebug: msgLength= %d, length= %ld (should be %d)\n",
6982f7df2e56Smrg                 stuff->msgLength, (long) extraLength,
6983f7df2e56Smrg                 XkbPaddedSize(stuff->msgLength));
6984f7df2e56Smrg            return BadLength;
6985f7df2e56Smrg        }
6986f7df2e56Smrg        msg = (char *) &stuff[1];
6987f7df2e56Smrg        if (msg[stuff->msgLength - 1] != '\0') {
6988f7df2e56Smrg            ErrorF("[xkb] XkbDebug: message not null-terminated\n");
6989f7df2e56Smrg            return BadValue;
6990f7df2e56Smrg        }
6991f7df2e56Smrg        ErrorF("[xkb] XkbDebug: %s\n", msg);
699205b261ecSmrg    }
699305b261ecSmrg    xkbDebugFlags = newFlags;
699405b261ecSmrg    xkbDebugCtrls = newCtrls;
699505b261ecSmrg
6996f7df2e56Smrg    rep = (xkbSetDebuggingFlagsReply) {
6997f7df2e56Smrg        .type = X_Reply,
6998f7df2e56Smrg        .sequenceNumber = client->sequence,
6999f7df2e56Smrg        .length = 0,
7000f7df2e56Smrg        .currentFlags = newFlags,
7001f7df2e56Smrg        .currentCtrls = newCtrls,
7002f7df2e56Smrg        .supportedFlags = ~0,
7003f7df2e56Smrg        .supportedCtrls = ~0
7004f7df2e56Smrg    };
7005f7df2e56Smrg    if (client->swapped) {
7006f7df2e56Smrg        swaps(&rep.sequenceNumber);
7007f7df2e56Smrg        swapl(&rep.currentFlags);
7008f7df2e56Smrg        swapl(&rep.currentCtrls);
7009f7df2e56Smrg        swapl(&rep.supportedFlags);
7010f7df2e56Smrg        swapl(&rep.supportedCtrls);
7011f7df2e56Smrg    }
7012f7df2e56Smrg    WriteToClient(client, SIZEOF(xkbSetDebuggingFlagsReply), &rep);
70136747b715Smrg    return Success;
701405b261ecSmrg}
701505b261ecSmrg
701605b261ecSmrg/***====================================================================***/
701705b261ecSmrg
701805b261ecSmrgstatic int
7019f7df2e56SmrgProcXkbDispatch(ClientPtr client)
702005b261ecSmrg{
702105b261ecSmrg    REQUEST(xReq);
7022f7df2e56Smrg    switch (stuff->data) {
702305b261ecSmrg    case X_kbUseExtension:
7024f7df2e56Smrg        return ProcXkbUseExtension(client);
702505b261ecSmrg    case X_kbSelectEvents:
7026f7df2e56Smrg        return ProcXkbSelectEvents(client);
702705b261ecSmrg    case X_kbBell:
7028f7df2e56Smrg        return ProcXkbBell(client);
702905b261ecSmrg    case X_kbGetState:
7030f7df2e56Smrg        return ProcXkbGetState(client);
703105b261ecSmrg    case X_kbLatchLockState:
7032f7df2e56Smrg        return ProcXkbLatchLockState(client);
703305b261ecSmrg    case X_kbGetControls:
7034f7df2e56Smrg        return ProcXkbGetControls(client);
703505b261ecSmrg    case X_kbSetControls:
7036f7df2e56Smrg        return ProcXkbSetControls(client);
703705b261ecSmrg    case X_kbGetMap:
7038f7df2e56Smrg        return ProcXkbGetMap(client);
703905b261ecSmrg    case X_kbSetMap:
7040f7df2e56Smrg        return ProcXkbSetMap(client);
704105b261ecSmrg    case X_kbGetCompatMap:
7042f7df2e56Smrg        return ProcXkbGetCompatMap(client);
704305b261ecSmrg    case X_kbSetCompatMap:
7044f7df2e56Smrg        return ProcXkbSetCompatMap(client);
704505b261ecSmrg    case X_kbGetIndicatorState:
7046f7df2e56Smrg        return ProcXkbGetIndicatorState(client);
704705b261ecSmrg    case X_kbGetIndicatorMap:
7048f7df2e56Smrg        return ProcXkbGetIndicatorMap(client);
704905b261ecSmrg    case X_kbSetIndicatorMap:
7050f7df2e56Smrg        return ProcXkbSetIndicatorMap(client);
705105b261ecSmrg    case X_kbGetNamedIndicator:
7052f7df2e56Smrg        return ProcXkbGetNamedIndicator(client);
705305b261ecSmrg    case X_kbSetNamedIndicator:
7054f7df2e56Smrg        return ProcXkbSetNamedIndicator(client);
705505b261ecSmrg    case X_kbGetNames:
7056f7df2e56Smrg        return ProcXkbGetNames(client);
705705b261ecSmrg    case X_kbSetNames:
7058f7df2e56Smrg        return ProcXkbSetNames(client);
705905b261ecSmrg    case X_kbGetGeometry:
7060f7df2e56Smrg        return ProcXkbGetGeometry(client);
706105b261ecSmrg    case X_kbSetGeometry:
7062f7df2e56Smrg        return ProcXkbSetGeometry(client);
706305b261ecSmrg    case X_kbPerClientFlags:
7064f7df2e56Smrg        return ProcXkbPerClientFlags(client);
706505b261ecSmrg    case X_kbListComponents:
7066f7df2e56Smrg        return ProcXkbListComponents(client);
706705b261ecSmrg    case X_kbGetKbdByName:
7068f7df2e56Smrg        return ProcXkbGetKbdByName(client);
706905b261ecSmrg    case X_kbGetDeviceInfo:
7070f7df2e56Smrg        return ProcXkbGetDeviceInfo(client);
707105b261ecSmrg    case X_kbSetDeviceInfo:
7072f7df2e56Smrg        return ProcXkbSetDeviceInfo(client);
707305b261ecSmrg    case X_kbSetDebuggingFlags:
7074f7df2e56Smrg        return ProcXkbSetDebuggingFlags(client);
707505b261ecSmrg    default:
7076f7df2e56Smrg        return BadRequest;
707705b261ecSmrg    }
707805b261ecSmrg}
707905b261ecSmrg
708005b261ecSmrgstatic int
7081f7df2e56SmrgXkbClientGone(void *data, XID id)
708205b261ecSmrg{
7083f7df2e56Smrg    DevicePtr pXDev = (DevicePtr) data;
708405b261ecSmrg
7085f7df2e56Smrg    if (!XkbRemoveResourceClient(pXDev, id)) {
7086f7df2e56Smrg        ErrorF
7087f7df2e56Smrg            ("[xkb] Internal Error! bad RemoveResourceClient in XkbClientGone\n");
708805b261ecSmrg    }
708905b261ecSmrg    return 1;
709005b261ecSmrg}
709105b261ecSmrg
709205b261ecSmrgvoid
709305b261ecSmrgXkbExtensionInit(void)
709405b261ecSmrg{
709505b261ecSmrg    ExtensionEntry *extEntry;
709605b261ecSmrg
70976747b715Smrg    RT_XKBCLIENT = CreateNewResourceType(XkbClientGone, "XkbClient");
70986747b715Smrg    if (!RT_XKBCLIENT)
7099f7df2e56Smrg        return;
71006747b715Smrg
71016747b715Smrg    if (!XkbInitPrivates())
7102f7df2e56Smrg        return;
71036747b715Smrg
710405b261ecSmrg    if ((extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors,
7105f7df2e56Smrg                                 ProcXkbDispatch, SProcXkbDispatch,
7106f7df2e56Smrg                                 NULL, StandardMinorOpcode))) {
7107f7df2e56Smrg        XkbReqCode = (unsigned char) extEntry->base;
7108f7df2e56Smrg        XkbEventBase = (unsigned char) extEntry->eventBase;
7109f7df2e56Smrg        XkbErrorBase = (unsigned char) extEntry->errorBase;
7110f7df2e56Smrg        XkbKeyboardErrorCode = XkbErrorBase + XkbKeyboard;
711105b261ecSmrg    }
711205b261ecSmrg    return;
711305b261ecSmrg}
7114