xkb.c revision 1e26616a
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
905b261ecSmrgdocumentation, and that the name of Silicon Graphics not be
1005b261ecSmrgused in advertising or publicity pertaining to distribution
1105b261ecSmrgof the software without specific prior written permission.
1205b261ecSmrgSilicon 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
1605b261ecSmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
1705b261ecSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1805b261ecSmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
1905b261ecSmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
2005b261ecSmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
2105b261ecSmrgDATA 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"
394642e01fSmrg#include "xace.h"
4005b261ecSmrg#include "xkb.h"
416747b715Smrg#include "protocol-versions.h"
4205b261ecSmrg
4305b261ecSmrg#include <X11/extensions/XI.h>
446747b715Smrg#include <X11/extensions/XKMformat.h>
4505b261ecSmrg
466747b715Smrgint		XkbEventBase;
4705b261ecSmrgstatic	int	XkbErrorBase;
486747b715Smrgint		XkbReqCode;
496747b715Smrgint		XkbKeyboardErrorCode;
506747b715SmrgCARD32		xkbDebugFlags = 0;
5105b261ecSmrgstatic CARD32	xkbDebugCtrls = 0;
5205b261ecSmrg
5305b261ecSmrgstatic RESTYPE	RT_XKBCLIENT;
5405b261ecSmrg
5505b261ecSmrg/***====================================================================***/
5605b261ecSmrg
574642e01fSmrg#define	CHK_DEVICE(dev, id, client, access_mode, lf) {\
5805b261ecSmrg    int why;\
594642e01fSmrg    int rc = lf(&(dev), id, client, access_mode, &why);\
604642e01fSmrg    if (rc != Success) {\
614642e01fSmrg	client->errorValue = _XkbErrCode2(why, id);\
624642e01fSmrg	return rc;\
6305b261ecSmrg    }\
6405b261ecSmrg}
6505b261ecSmrg
664642e01fSmrg#define	CHK_KBD_DEVICE(dev, id, client, mode) \
674642e01fSmrg    CHK_DEVICE(dev, id, client, mode, _XkbLookupKeyboard)
684642e01fSmrg#define	CHK_LED_DEVICE(dev, id, client, mode) \
694642e01fSmrg    CHK_DEVICE(dev, id, client, mode, _XkbLookupLedDevice)
704642e01fSmrg#define	CHK_BELL_DEVICE(dev, id, client, mode) \
714642e01fSmrg    CHK_DEVICE(dev, id, client, mode, _XkbLookupBellDevice)
724642e01fSmrg#define	CHK_ANY_DEVICE(dev, id, client, mode) \
734642e01fSmrg    CHK_DEVICE(dev, id, client, mode, _XkbLookupAnyDevice)
7405b261ecSmrg
7505b261ecSmrg#define	CHK_ATOM_ONLY2(a,ev,er) {\
7605b261ecSmrg	if (((a)==None)||(!ValidAtom((a)))) {\
7705b261ecSmrg	    (ev)= (XID)(a);\
7805b261ecSmrg	    return er;\
7905b261ecSmrg	}\
8005b261ecSmrg}
8105b261ecSmrg#define	CHK_ATOM_ONLY(a) \
8205b261ecSmrg	CHK_ATOM_ONLY2(a,client->errorValue,BadAtom)
8305b261ecSmrg
8405b261ecSmrg#define	CHK_ATOM_OR_NONE3(a,ev,er,ret) {\
8505b261ecSmrg	if (((a)!=None)&&(!ValidAtom((a)))) {\
8605b261ecSmrg	    (ev)= (XID)(a);\
8705b261ecSmrg	    (er)= BadAtom;\
8805b261ecSmrg	    return ret;\
8905b261ecSmrg	}\
9005b261ecSmrg}
9105b261ecSmrg#define	CHK_ATOM_OR_NONE2(a,ev,er) {\
9205b261ecSmrg	if (((a)!=None)&&(!ValidAtom((a)))) {\
9305b261ecSmrg	    (ev)= (XID)(a);\
9405b261ecSmrg	    return er;\
9505b261ecSmrg	}\
9605b261ecSmrg}
9705b261ecSmrg#define	CHK_ATOM_OR_NONE(a) \
9805b261ecSmrg	CHK_ATOM_OR_NONE2(a,client->errorValue,BadAtom)
9905b261ecSmrg
10005b261ecSmrg#define	CHK_MASK_LEGAL3(err,mask,legal,ev,er,ret)	{\
10105b261ecSmrg	if ((mask)&(~(legal))) { \
10205b261ecSmrg	    (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\
10305b261ecSmrg	    (er)= BadValue;\
10405b261ecSmrg	    return ret;\
10505b261ecSmrg	}\
10605b261ecSmrg}
10705b261ecSmrg#define	CHK_MASK_LEGAL2(err,mask,legal,ev,er)	{\
10805b261ecSmrg	if ((mask)&(~(legal))) { \
10905b261ecSmrg	    (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\
11005b261ecSmrg	    return er;\
11105b261ecSmrg	}\
11205b261ecSmrg}
11305b261ecSmrg#define	CHK_MASK_LEGAL(err,mask,legal) \
11405b261ecSmrg	CHK_MASK_LEGAL2(err,mask,legal,client->errorValue,BadValue)
11505b261ecSmrg
11605b261ecSmrg#define	CHK_MASK_MATCH(err,affect,value) {\
11705b261ecSmrg	if ((value)&(~(affect))) { \
11805b261ecSmrg	    client->errorValue= _XkbErrCode2((err),((value)&(~(affect))));\
11905b261ecSmrg	    return BadMatch;\
12005b261ecSmrg	}\
12105b261ecSmrg}
12205b261ecSmrg#define	CHK_MASK_OVERLAP(err,m1,m2) {\
12305b261ecSmrg	if ((m1)&(m2)) { \
12405b261ecSmrg	    client->errorValue= _XkbErrCode2((err),((m1)&(m2)));\
12505b261ecSmrg	    return BadMatch;\
12605b261ecSmrg	}\
12705b261ecSmrg}
12805b261ecSmrg#define	CHK_KEY_RANGE2(err,first,num,x,ev,er) {\
12905b261ecSmrg	if (((unsigned)(first)+(num)-1)>(x)->max_key_code) {\
13005b261ecSmrg	    (ev)=_XkbErrCode4(err,(first),(num),(x)->max_key_code);\
13105b261ecSmrg	    return er;\
13205b261ecSmrg	}\
13305b261ecSmrg	else if ( (first)<(x)->min_key_code ) {\
13405b261ecSmrg	    (ev)=_XkbErrCode3(err+1,(first),xkb->min_key_code);\
13505b261ecSmrg	    return er;\
13605b261ecSmrg	}\
13705b261ecSmrg}
13805b261ecSmrg#define	CHK_KEY_RANGE(err,first,num,x)  \
13905b261ecSmrg	CHK_KEY_RANGE2(err,first,num,x,client->errorValue,BadValue)
14005b261ecSmrg
14105b261ecSmrg#define	CHK_REQ_KEY_RANGE2(err,first,num,r,ev,er) {\
14205b261ecSmrg	if (((unsigned)(first)+(num)-1)>(r)->maxKeyCode) {\
14305b261ecSmrg	    (ev)=_XkbErrCode4(err,(first),(num),(r)->maxKeyCode);\
14405b261ecSmrg	    return er;\
14505b261ecSmrg	}\
14605b261ecSmrg	else if ( (first)<(r)->minKeyCode ) {\
14705b261ecSmrg	    (ev)=_XkbErrCode3(err+1,(first),(r)->minKeyCode);\
14805b261ecSmrg	    return er;\
14905b261ecSmrg	}\
15005b261ecSmrg}
15105b261ecSmrg#define	CHK_REQ_KEY_RANGE(err,first,num,r)  \
15205b261ecSmrg	CHK_REQ_KEY_RANGE2(err,first,num,r,client->errorValue,BadValue)
15305b261ecSmrg
15405b261ecSmrg/***====================================================================***/
15505b261ecSmrg
15605b261ecSmrgint
15705b261ecSmrgProcXkbUseExtension(ClientPtr client)
15805b261ecSmrg{
15905b261ecSmrg    REQUEST(xkbUseExtensionReq);
16005b261ecSmrg    xkbUseExtensionReply	rep;
16105b261ecSmrg    register int n;
16205b261ecSmrg    int	supported;
16305b261ecSmrg
16405b261ecSmrg    REQUEST_SIZE_MATCH(xkbUseExtensionReq);
1656747b715Smrg    if (stuff->wantedMajor != SERVER_XKB_MAJOR_VERSION) {
16605b261ecSmrg	/* pre-release version 0.65 is compatible with 1.00 */
1676747b715Smrg	supported= ((SERVER_XKB_MAJOR_VERSION==1)&&
16805b261ecSmrg		    (stuff->wantedMajor==0)&&(stuff->wantedMinor==65));
16905b261ecSmrg    }
17005b261ecSmrg    else supported = 1;
17105b261ecSmrg
17205b261ecSmrg    if ((supported) && (!(client->xkbClientFlags&_XkbClientInitialized))) {
17305b261ecSmrg	client->xkbClientFlags= _XkbClientInitialized;
17405b261ecSmrg	client->vMajor= stuff->wantedMajor;
17505b261ecSmrg	client->vMinor= stuff->wantedMinor;
17605b261ecSmrg    }
17705b261ecSmrg    else if (xkbDebugFlags&0x1) {
1784642e01fSmrg	ErrorF("[xkb] Rejecting client %d (0x%lx) (wants %d.%02d, have %d.%02d)\n",
17905b261ecSmrg					client->index,
18005b261ecSmrg					(long)client->clientAsMask,
18105b261ecSmrg					stuff->wantedMajor,stuff->wantedMinor,
1826747b715Smrg					SERVER_XKB_MAJOR_VERSION,SERVER_XKB_MINOR_VERSION);
18305b261ecSmrg    }
1846747b715Smrg    memset(&rep, 0, sizeof(xkbUseExtensionReply));
18505b261ecSmrg    rep.type = X_Reply;
18605b261ecSmrg    rep.supported = supported;
18705b261ecSmrg    rep.length = 0;
18805b261ecSmrg    rep.sequenceNumber = client->sequence;
1896747b715Smrg    rep.serverMajor = SERVER_XKB_MAJOR_VERSION;
1906747b715Smrg    rep.serverMinor = SERVER_XKB_MINOR_VERSION;
19105b261ecSmrg    if ( client->swapped ) {
19205b261ecSmrg	swaps(&rep.sequenceNumber, n);
19305b261ecSmrg	swaps(&rep.serverMajor, n);
19405b261ecSmrg	swaps(&rep.serverMinor, n);
19505b261ecSmrg    }
19605b261ecSmrg    WriteToClient(client,SIZEOF(xkbUseExtensionReply), (char *)&rep);
1976747b715Smrg    return Success;
19805b261ecSmrg}
19905b261ecSmrg
20005b261ecSmrg/***====================================================================***/
20105b261ecSmrg
20205b261ecSmrgint
20305b261ecSmrgProcXkbSelectEvents(ClientPtr client)
20405b261ecSmrg{
20505b261ecSmrg    unsigned		legal;
20605b261ecSmrg    DeviceIntPtr 	dev;
20705b261ecSmrg    XkbInterestPtr	masks;
20805b261ecSmrg    REQUEST(xkbSelectEventsReq);
20905b261ecSmrg
21005b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSelectEventsReq);
21105b261ecSmrg
21205b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
21305b261ecSmrg	return BadAccess;
21405b261ecSmrg
2154642e01fSmrg    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixUseAccess);
21605b261ecSmrg
21705b261ecSmrg    if (((stuff->affectWhich&XkbMapNotifyMask)!=0)&&(stuff->affectMap)) {
21805b261ecSmrg	client->mapNotifyMask&= ~stuff->affectMap;
21905b261ecSmrg	client->mapNotifyMask|= (stuff->affectMap&stuff->map);
22005b261ecSmrg    }
22105b261ecSmrg    if ((stuff->affectWhich&(~XkbMapNotifyMask))==0)
2226747b715Smrg	return Success;
22305b261ecSmrg
22405b261ecSmrg    masks = XkbFindClientResource((DevicePtr)dev,client);
22505b261ecSmrg    if (!masks){
22605b261ecSmrg	XID id = FakeClientID(client->index);
2276747b715Smrg	if (!AddResource(id,RT_XKBCLIENT,dev))
2286747b715Smrg	    return BadAlloc;
22905b261ecSmrg	masks= XkbAddClientResource((DevicePtr)dev,client,id);
23005b261ecSmrg    }
23105b261ecSmrg    if (masks) {
23205b261ecSmrg	union {
23305b261ecSmrg	    CARD8	*c8;
23405b261ecSmrg	    CARD16	*c16;
23505b261ecSmrg	    CARD32	*c32;
23605b261ecSmrg	} from,to;
23705b261ecSmrg	register unsigned bit,ndx,maskLeft,dataLeft,size;
23805b261ecSmrg
23905b261ecSmrg	from.c8= (CARD8 *)&stuff[1];
24005b261ecSmrg	dataLeft= (stuff->length*4)-SIZEOF(xkbSelectEventsReq);
24105b261ecSmrg	maskLeft= (stuff->affectWhich&(~XkbMapNotifyMask));
24205b261ecSmrg	for (ndx=0,bit=1; (maskLeft!=0); ndx++, bit<<=1) {
24305b261ecSmrg	    if ((bit&maskLeft)==0)
24405b261ecSmrg		continue;
24505b261ecSmrg	    maskLeft&= ~bit;
24605b261ecSmrg	    switch (ndx) {
24705b261ecSmrg		case XkbNewKeyboardNotify:
24805b261ecSmrg		    to.c16= &client->newKeyboardNotifyMask;
24905b261ecSmrg		    legal= XkbAllNewKeyboardEventsMask;
25005b261ecSmrg		    size= 2;
25105b261ecSmrg		    break;
25205b261ecSmrg		case XkbStateNotify:
25305b261ecSmrg		    to.c16= &masks->stateNotifyMask;
25405b261ecSmrg		    legal= XkbAllStateEventsMask;
25505b261ecSmrg		    size= 2;
25605b261ecSmrg		    break;
25705b261ecSmrg		case XkbControlsNotify:
25805b261ecSmrg		    to.c32= &masks->ctrlsNotifyMask;
25905b261ecSmrg		    legal= XkbAllControlEventsMask;
26005b261ecSmrg		    size= 4;
26105b261ecSmrg		    break;
26205b261ecSmrg		case XkbIndicatorStateNotify:
26305b261ecSmrg		    to.c32= &masks->iStateNotifyMask;
26405b261ecSmrg		    legal= XkbAllIndicatorEventsMask;
26505b261ecSmrg		    size= 4;
26605b261ecSmrg		    break;
26705b261ecSmrg		case XkbIndicatorMapNotify:
26805b261ecSmrg		    to.c32= &masks->iMapNotifyMask;
26905b261ecSmrg		    legal= XkbAllIndicatorEventsMask;
27005b261ecSmrg		    size= 4;
27105b261ecSmrg		    break;
27205b261ecSmrg		case XkbNamesNotify:
27305b261ecSmrg		    to.c16= &masks->namesNotifyMask;
27405b261ecSmrg		    legal= XkbAllNameEventsMask;
27505b261ecSmrg		    size= 2;
27605b261ecSmrg		    break;
27705b261ecSmrg		case XkbCompatMapNotify:
27805b261ecSmrg		    to.c8= &masks->compatNotifyMask;
27905b261ecSmrg		    legal= XkbAllCompatMapEventsMask;
28005b261ecSmrg		    size= 1;
28105b261ecSmrg		    break;
28205b261ecSmrg		case XkbBellNotify:
28305b261ecSmrg		    to.c8= &masks->bellNotifyMask;
28405b261ecSmrg		    legal= XkbAllBellEventsMask;
28505b261ecSmrg		    size= 1;
28605b261ecSmrg		    break;
28705b261ecSmrg		case XkbActionMessage:
28805b261ecSmrg		    to.c8= &masks->actionMessageMask;
28905b261ecSmrg		    legal= XkbAllActionMessagesMask;
29005b261ecSmrg		    size= 1;
29105b261ecSmrg		    break;
29205b261ecSmrg		case XkbAccessXNotify:
29305b261ecSmrg		    to.c16= &masks->accessXNotifyMask;
29405b261ecSmrg		    legal= XkbAllAccessXEventsMask;
29505b261ecSmrg		    size= 2;
29605b261ecSmrg		    break;
29705b261ecSmrg		case XkbExtensionDeviceNotify:
29805b261ecSmrg		    to.c16= &masks->extDevNotifyMask;
29905b261ecSmrg		    legal= XkbAllExtensionDeviceEventsMask;
30005b261ecSmrg		    size= 2;
30105b261ecSmrg		    break;
30205b261ecSmrg		default:
30305b261ecSmrg		    client->errorValue = _XkbErrCode2(33,bit);
30405b261ecSmrg		    return BadValue;
30505b261ecSmrg	    }
30605b261ecSmrg
30705b261ecSmrg	    if (stuff->clear&bit) {
30805b261ecSmrg		if (size==2)		to.c16[0]= 0;
30905b261ecSmrg		else if (size==4)	to.c32[0]= 0;
31005b261ecSmrg		else			to.c8[0]=  0;
31105b261ecSmrg	    }
31205b261ecSmrg	    else if (stuff->selectAll&bit) {
31305b261ecSmrg		if (size==2)		to.c16[0]= ~0;
31405b261ecSmrg		else if (size==4)	to.c32[0]= ~0;
31505b261ecSmrg		else			to.c8[0]=  ~0;
31605b261ecSmrg	    }
31705b261ecSmrg	    else {
31805b261ecSmrg		if (dataLeft<(size*2))
31905b261ecSmrg		    return BadLength;
32005b261ecSmrg		if (size==2) {
32105b261ecSmrg		    CHK_MASK_MATCH(ndx,from.c16[0],from.c16[1]);
32205b261ecSmrg		    CHK_MASK_LEGAL(ndx,from.c16[0],legal);
32305b261ecSmrg		    to.c16[0]&= ~from.c16[0];
32405b261ecSmrg		    to.c16[0]|= (from.c16[0]&from.c16[1]);
32505b261ecSmrg		}
32605b261ecSmrg		else if (size==4) {
32705b261ecSmrg		    CHK_MASK_MATCH(ndx,from.c32[0],from.c32[1]);
32805b261ecSmrg		    CHK_MASK_LEGAL(ndx,from.c32[0],legal);
32905b261ecSmrg		    to.c32[0]&= ~from.c32[0];
33005b261ecSmrg		    to.c32[0]|= (from.c32[0]&from.c32[1]);
33105b261ecSmrg		}
33205b261ecSmrg		else  {
33305b261ecSmrg		    CHK_MASK_MATCH(ndx,from.c8[0],from.c8[1]);
33405b261ecSmrg		    CHK_MASK_LEGAL(ndx,from.c8[0],legal);
33505b261ecSmrg		    to.c8[0]&= ~from.c8[0];
33605b261ecSmrg		    to.c8[0]|= (from.c8[0]&from.c8[1]);
33705b261ecSmrg		    size= 2;
33805b261ecSmrg		}
33905b261ecSmrg		from.c8+= (size*2);
34005b261ecSmrg		dataLeft-= (size*2);
34105b261ecSmrg	    }
34205b261ecSmrg	}
34305b261ecSmrg	if (dataLeft>2) {
3444642e01fSmrg	    ErrorF("[xkb] Extra data (%d bytes) after SelectEvents\n",dataLeft);
34505b261ecSmrg	    return BadLength;
34605b261ecSmrg	}
3476747b715Smrg	return Success;
34805b261ecSmrg    }
34905b261ecSmrg    return BadAlloc;
35005b261ecSmrg}
35105b261ecSmrg
35205b261ecSmrg/***====================================================================***/
3534642e01fSmrg/**
3544642e01fSmrg * Ring a bell on the given device for the given client.
3554642e01fSmrg */
3564642e01fSmrgstatic int
3574642e01fSmrg_XkbBell(ClientPtr client, DeviceIntPtr dev, WindowPtr pWin,
3584642e01fSmrg         int bellClass, int bellID, int pitch, int duration,
3594642e01fSmrg         int percent, int forceSound, int eventOnly, Atom name)
3604642e01fSmrg{
3614642e01fSmrg    int         base;
3624642e01fSmrg    pointer     ctrl;
3634642e01fSmrg    int         oldPitch, oldDuration;
3644642e01fSmrg    int         newPercent;
3654642e01fSmrg
3664642e01fSmrg    if (bellClass == KbdFeedbackClass) {
3674642e01fSmrg        KbdFeedbackPtr	k;
3684642e01fSmrg        if (bellID==XkbDfltXIId)
3694642e01fSmrg            k= dev->kbdfeed;
3704642e01fSmrg        else {
3714642e01fSmrg            for (k=dev->kbdfeed; k; k=k->next) {
3724642e01fSmrg                if (k->ctrl.id == bellID)
3734642e01fSmrg                    break;
3744642e01fSmrg            }
3754642e01fSmrg        }
3764642e01fSmrg        if (!k) {
3774642e01fSmrg            client->errorValue = _XkbErrCode2(0x5,bellID);
3784642e01fSmrg            return BadValue;
3794642e01fSmrg        }
3804642e01fSmrg        base = k->ctrl.bell;
3814642e01fSmrg        ctrl = (pointer) &(k->ctrl);
3824642e01fSmrg        oldPitch= k->ctrl.bell_pitch;
3834642e01fSmrg        oldDuration= k->ctrl.bell_duration;
3844642e01fSmrg        if (pitch!=0) {
3854642e01fSmrg            if (pitch==-1)
3864642e01fSmrg                k->ctrl.bell_pitch= defaultKeyboardControl.bell_pitch;
3874642e01fSmrg            else k->ctrl.bell_pitch= pitch;
3884642e01fSmrg        }
3894642e01fSmrg        if (duration!=0) {
3904642e01fSmrg            if (duration==-1)
3914642e01fSmrg                k->ctrl.bell_duration= defaultKeyboardControl.bell_duration;
3924642e01fSmrg            else k->ctrl.bell_duration= duration;
3934642e01fSmrg        }
3944642e01fSmrg    }
3954642e01fSmrg    else if (bellClass == BellFeedbackClass) {
3964642e01fSmrg        BellFeedbackPtr	b;
3974642e01fSmrg        if (bellID==XkbDfltXIId)
3984642e01fSmrg            b= dev->bell;
3994642e01fSmrg        else {
4004642e01fSmrg            for (b=dev->bell; b; b=b->next) {
4014642e01fSmrg                if (b->ctrl.id == bellID)
4024642e01fSmrg                    break;
4034642e01fSmrg            }
4044642e01fSmrg        }
4054642e01fSmrg        if (!b) {
4064642e01fSmrg            client->errorValue = _XkbErrCode2(0x6,bellID);
4074642e01fSmrg            return BadValue;
4084642e01fSmrg        }
4094642e01fSmrg        base = b->ctrl.percent;
4104642e01fSmrg        ctrl = (pointer) &(b->ctrl);
4114642e01fSmrg        oldPitch= b->ctrl.pitch;
4124642e01fSmrg        oldDuration= b->ctrl.duration;
4134642e01fSmrg        if (pitch!=0) {
4144642e01fSmrg            if (pitch==-1)
4154642e01fSmrg                b->ctrl.pitch= defaultKeyboardControl.bell_pitch;
4164642e01fSmrg            else b->ctrl.pitch= pitch;
4174642e01fSmrg        }
4184642e01fSmrg        if (duration!=0) {
4194642e01fSmrg            if (duration==-1)
4204642e01fSmrg                b->ctrl.duration= defaultKeyboardControl.bell_duration;
4214642e01fSmrg            else b->ctrl.duration= duration;
4224642e01fSmrg        }
4234642e01fSmrg    }
4244642e01fSmrg    else {
4254642e01fSmrg        client->errorValue = _XkbErrCode2(0x7, bellClass);
4264642e01fSmrg        return BadValue;
4274642e01fSmrg    }
4284642e01fSmrg
4294642e01fSmrg    newPercent = (base * percent)/100;
4304642e01fSmrg    if (percent < 0)
4314642e01fSmrg         newPercent = base + newPercent;
4324642e01fSmrg    else newPercent = base - newPercent + percent;
4334642e01fSmrg
4344642e01fSmrg    XkbHandleBell(forceSound, eventOnly,
4354642e01fSmrg                  dev, newPercent, ctrl, bellClass,
4364642e01fSmrg                  name, pWin, client);
4374642e01fSmrg    if ((pitch!=0)||(duration!=0)) {
4384642e01fSmrg        if (bellClass == KbdFeedbackClass) {
4394642e01fSmrg            KbdFeedbackPtr      k;
4404642e01fSmrg            k= (KbdFeedbackPtr)ctrl;
4414642e01fSmrg            if (pitch!=0)
4424642e01fSmrg                k->ctrl.bell_pitch= oldPitch;
4434642e01fSmrg            if (duration!=0)
4444642e01fSmrg                k->ctrl.bell_duration= oldDuration;
4454642e01fSmrg        }
4464642e01fSmrg        else {
4474642e01fSmrg            BellFeedbackPtr     b;
4484642e01fSmrg            b= (BellFeedbackPtr)ctrl;
4494642e01fSmrg            if (pitch!=0)
4504642e01fSmrg                b->ctrl.pitch= oldPitch;
4514642e01fSmrg            if (duration!=0)
4524642e01fSmrg                b->ctrl.duration= oldDuration;
4534642e01fSmrg        }
4544642e01fSmrg    }
4554642e01fSmrg
4564642e01fSmrg    return Success;
4574642e01fSmrg}
45805b261ecSmrg
45905b261ecSmrgint
46005b261ecSmrgProcXkbBell(ClientPtr client)
46105b261ecSmrg{
46205b261ecSmrg    REQUEST(xkbBellReq);
46305b261ecSmrg    DeviceIntPtr dev;
46405b261ecSmrg    WindowPtr	 pWin;
4654642e01fSmrg    int rc;
46605b261ecSmrg
46705b261ecSmrg    REQUEST_SIZE_MATCH(xkbBellReq);
46805b261ecSmrg
46905b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
47005b261ecSmrg	return BadAccess;
47105b261ecSmrg
4724642e01fSmrg    CHK_BELL_DEVICE(dev, stuff->deviceSpec, client, DixBellAccess);
47305b261ecSmrg    CHK_ATOM_OR_NONE(stuff->name);
47405b261ecSmrg
4754642e01fSmrg    /* device-independent checks request for sane values */
47605b261ecSmrg    if ((stuff->forceSound)&&(stuff->eventOnly)) {
47705b261ecSmrg	client->errorValue=_XkbErrCode3(0x1,stuff->forceSound,stuff->eventOnly);
47805b261ecSmrg	return BadMatch;
47905b261ecSmrg    }
48005b261ecSmrg    if (stuff->percent < -100 || stuff->percent > 100) {
48105b261ecSmrg	client->errorValue = _XkbErrCode2(0x2,stuff->percent);
48205b261ecSmrg	return BadValue;
48305b261ecSmrg    }
48405b261ecSmrg    if (stuff->duration<-1) {
48505b261ecSmrg	client->errorValue = _XkbErrCode2(0x3,stuff->duration);
48605b261ecSmrg	return BadValue;
48705b261ecSmrg    }
48805b261ecSmrg    if (stuff->pitch<-1) {
48905b261ecSmrg	client->errorValue = _XkbErrCode2(0x4,stuff->pitch);
49005b261ecSmrg	return BadValue;
49105b261ecSmrg    }
49205b261ecSmrg
49305b261ecSmrg    if (stuff->bellClass == XkbDfltXIClass) {
49405b261ecSmrg	if (dev->kbdfeed!=NULL)
49505b261ecSmrg	     stuff->bellClass= KbdFeedbackClass;
49605b261ecSmrg	else stuff->bellClass= BellFeedbackClass;
49705b261ecSmrg    }
4984642e01fSmrg
49905b261ecSmrg    if (stuff->window!=None) {
5004642e01fSmrg	rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
5014642e01fSmrg	if (rc != Success) {
50205b261ecSmrg	    client->errorValue= stuff->window;
5034642e01fSmrg	    return rc;
50405b261ecSmrg	}
50505b261ecSmrg    }
50605b261ecSmrg    else pWin= NULL;
50705b261ecSmrg
5084642e01fSmrg    /* Client wants to ring a bell on the core keyboard?
5094642e01fSmrg       Ring the bell on the core keyboard (which does nothing, but if that
5104642e01fSmrg       fails the client is screwed anyway), and then on all extension devices.
5114642e01fSmrg       Fail if the core keyboard fails but not the extension devices.  this
5124642e01fSmrg       may cause some keyboards to ding and others to stay silent. Fix
5134642e01fSmrg       your client to use explicit keyboards to avoid this.
5144642e01fSmrg
5154642e01fSmrg       dev is the device the client requested.
5164642e01fSmrg     */
5174642e01fSmrg    rc = _XkbBell(client, dev, pWin, stuff->bellClass, stuff->bellID,
5184642e01fSmrg                  stuff->pitch, stuff->duration, stuff->percent,
5194642e01fSmrg                  stuff->forceSound, stuff->eventOnly, stuff->name);
5204642e01fSmrg
5214642e01fSmrg    if ((rc == Success) && ((stuff->deviceSpec == XkbUseCoreKbd) ||
5224642e01fSmrg                            (stuff->deviceSpec == XkbUseCorePtr)))
5234642e01fSmrg    {
5244642e01fSmrg        DeviceIntPtr other;
5254642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
5264642e01fSmrg        {
5276747b715Smrg            if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev)
5284642e01fSmrg            {
5294642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixBellAccess);
5304642e01fSmrg                if (rc == Success)
5314642e01fSmrg                    _XkbBell(client, other, pWin, stuff->bellClass,
5324642e01fSmrg                             stuff->bellID, stuff->pitch, stuff->duration,
5334642e01fSmrg                             stuff->percent, stuff->forceSound,
5344642e01fSmrg                             stuff->eventOnly, stuff->name);
5354642e01fSmrg            }
5364642e01fSmrg        }
5374642e01fSmrg        rc = Success; /* reset to success, that's what we got for the VCK */
53805b261ecSmrg    }
5394642e01fSmrg
5404642e01fSmrg    return rc;
54105b261ecSmrg}
54205b261ecSmrg
54305b261ecSmrg/***====================================================================***/
54405b261ecSmrg
54505b261ecSmrgint
54605b261ecSmrgProcXkbGetState(ClientPtr client)
54705b261ecSmrg{
54805b261ecSmrg    REQUEST(xkbGetStateReq);
54905b261ecSmrg    DeviceIntPtr	dev;
55005b261ecSmrg    xkbGetStateReply	 rep;
55105b261ecSmrg    XkbStateRec		*xkb;
55205b261ecSmrg
55305b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetStateReq);
55405b261ecSmrg
55505b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
55605b261ecSmrg	return BadAccess;
55705b261ecSmrg
5586747b715Smrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
55905b261ecSmrg
56005b261ecSmrg    xkb= &dev->key->xkbInfo->state;
5616747b715Smrg    memset(&rep, 0, sizeof(xkbGetStateReply));
56205b261ecSmrg    rep.type= X_Reply;
56305b261ecSmrg    rep.sequenceNumber= client->sequence;
56405b261ecSmrg    rep.length = 0;
56505b261ecSmrg    rep.deviceID = dev->id;
5666747b715Smrg    rep.mods = XkbStateFieldFromRec(xkb) & 0xff;
56705b261ecSmrg    rep.baseMods = xkb->base_mods;
56805b261ecSmrg    rep.lockedMods = xkb->locked_mods;
56905b261ecSmrg    rep.latchedMods = xkb->latched_mods;
57005b261ecSmrg    rep.group = xkb->group;
57105b261ecSmrg    rep.baseGroup = xkb->base_group;
57205b261ecSmrg    rep.latchedGroup = xkb->latched_group;
57305b261ecSmrg    rep.lockedGroup = xkb->locked_group;
57405b261ecSmrg    rep.compatState = xkb->compat_state;
57505b261ecSmrg    rep.ptrBtnState = xkb->ptr_buttons;
57605b261ecSmrg    if (client->swapped) {
57705b261ecSmrg	register int n;
57805b261ecSmrg	swaps(&rep.sequenceNumber,n);
57905b261ecSmrg	swaps(&rep.ptrBtnState,n);
58005b261ecSmrg    }
58105b261ecSmrg    WriteToClient(client, SIZEOF(xkbGetStateReply), (char *)&rep);
5826747b715Smrg    return Success;
58305b261ecSmrg}
58405b261ecSmrg
58505b261ecSmrg/***====================================================================***/
58605b261ecSmrg
58705b261ecSmrgint
58805b261ecSmrgProcXkbLatchLockState(ClientPtr client)
58905b261ecSmrg{
59005b261ecSmrg    int status;
59105b261ecSmrg    DeviceIntPtr dev, tmpd;
59205b261ecSmrg    XkbStateRec	oldState,*newState;
59305b261ecSmrg    CARD16 changed;
59405b261ecSmrg    xkbStateNotify sn;
59505b261ecSmrg    XkbEventCauseRec cause;
59605b261ecSmrg
59705b261ecSmrg    REQUEST(xkbLatchLockStateReq);
59805b261ecSmrg    REQUEST_SIZE_MATCH(xkbLatchLockStateReq);
59905b261ecSmrg
60005b261ecSmrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
60105b261ecSmrg	return BadAccess;
60205b261ecSmrg
6034642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
60405b261ecSmrg    CHK_MASK_MATCH(0x01, stuff->affectModLocks, stuff->modLocks);
60505b261ecSmrg    CHK_MASK_MATCH(0x01, stuff->affectModLatches, stuff->modLatches);
60605b261ecSmrg
60705b261ecSmrg    status = Success;
60805b261ecSmrg
60905b261ecSmrg    for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
6106747b715Smrg        if ((tmpd == dev) || (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) {
6116747b715Smrg            if (!tmpd->key || !tmpd->key->xkbInfo)
61205b261ecSmrg                continue;
61305b261ecSmrg
61405b261ecSmrg            oldState = tmpd->key->xkbInfo->state;
61505b261ecSmrg            newState = &tmpd->key->xkbInfo->state;
61605b261ecSmrg            if (stuff->affectModLocks) {
61705b261ecSmrg                newState->locked_mods &= ~stuff->affectModLocks;
61805b261ecSmrg                newState->locked_mods |= (stuff->affectModLocks & stuff->modLocks);
61905b261ecSmrg            }
62005b261ecSmrg            if (status == Success && stuff->lockGroup)
62105b261ecSmrg                newState->locked_group = stuff->groupLock;
62205b261ecSmrg            if (status == Success && stuff->affectModLatches)
62305b261ecSmrg                status = XkbLatchModifiers(tmpd, stuff->affectModLatches,
62405b261ecSmrg                                           stuff->modLatches);
62505b261ecSmrg            if (status == Success && stuff->latchGroup)
62605b261ecSmrg                status = XkbLatchGroup(tmpd, stuff->groupLatch);
62705b261ecSmrg
62805b261ecSmrg            if (status != Success)
62905b261ecSmrg                return status;
63005b261ecSmrg
63105b261ecSmrg            XkbComputeDerivedState(tmpd->key->xkbInfo);
63205b261ecSmrg
63305b261ecSmrg            changed = XkbStateChangedFlags(&oldState, newState);
63405b261ecSmrg            if (changed) {
63505b261ecSmrg                sn.keycode = 0;
63605b261ecSmrg                sn.eventType = 0;
63705b261ecSmrg                sn.requestMajor = XkbReqCode;
63805b261ecSmrg                sn.requestMinor = X_kbLatchLockState;
63905b261ecSmrg                sn.changed = changed;
64005b261ecSmrg                XkbSendStateNotify(tmpd, &sn);
6416747b715Smrg                changed = XkbIndicatorsToUpdate(tmpd, changed, FALSE);
64205b261ecSmrg                if (changed) {
64305b261ecSmrg                    XkbSetCauseXkbReq(&cause, X_kbLatchLockState, client);
6446747b715Smrg                    XkbUpdateIndicators(tmpd, changed, TRUE, NULL, &cause);
64505b261ecSmrg	        }
64605b261ecSmrg            }
64705b261ecSmrg        }
64805b261ecSmrg    }
64905b261ecSmrg
6506747b715Smrg    return Success;
65105b261ecSmrg}
65205b261ecSmrg
65305b261ecSmrg/***====================================================================***/
65405b261ecSmrg
65505b261ecSmrgint
65605b261ecSmrgProcXkbGetControls(ClientPtr client)
65705b261ecSmrg{
65805b261ecSmrg    xkbGetControlsReply rep;
65905b261ecSmrg    XkbControlsPtr	xkb;
66005b261ecSmrg    DeviceIntPtr 	dev;
66105b261ecSmrg    register int 	n;
66205b261ecSmrg
66305b261ecSmrg    REQUEST(xkbGetControlsReq);
66405b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetControlsReq);
66505b261ecSmrg
66605b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
66705b261ecSmrg	return BadAccess;
66805b261ecSmrg
6694642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
67005b261ecSmrg
67105b261ecSmrg    xkb = dev->key->xkbInfo->desc->ctrls;
67205b261ecSmrg    rep.type = X_Reply;
6736747b715Smrg    rep.length = bytes_to_int32(SIZEOF(xkbGetControlsReply)-
6746747b715Smrg		  SIZEOF(xGenericReply));
67505b261ecSmrg    rep.sequenceNumber = client->sequence;
67605b261ecSmrg    rep.deviceID = ((DeviceIntPtr)dev)->id;
67705b261ecSmrg    rep.numGroups = xkb->num_groups;
67805b261ecSmrg    rep.groupsWrap = xkb->groups_wrap;
67905b261ecSmrg    rep.internalMods = xkb->internal.mask;
68005b261ecSmrg    rep.ignoreLockMods = xkb->ignore_lock.mask;
68105b261ecSmrg    rep.internalRealMods = xkb->internal.real_mods;
68205b261ecSmrg    rep.ignoreLockRealMods = xkb->ignore_lock.real_mods;
68305b261ecSmrg    rep.internalVMods = xkb->internal.vmods;
68405b261ecSmrg    rep.ignoreLockVMods = xkb->ignore_lock.vmods;
68505b261ecSmrg    rep.enabledCtrls = xkb->enabled_ctrls;
68605b261ecSmrg    rep.repeatDelay = xkb->repeat_delay;
68705b261ecSmrg    rep.repeatInterval = xkb->repeat_interval;
68805b261ecSmrg    rep.slowKeysDelay = xkb->slow_keys_delay;
68905b261ecSmrg    rep.debounceDelay = xkb->debounce_delay;
69005b261ecSmrg    rep.mkDelay = xkb->mk_delay;
69105b261ecSmrg    rep.mkInterval = xkb->mk_interval;
69205b261ecSmrg    rep.mkTimeToMax = xkb->mk_time_to_max;
69305b261ecSmrg    rep.mkMaxSpeed = xkb->mk_max_speed;
69405b261ecSmrg    rep.mkCurve = xkb->mk_curve;
69505b261ecSmrg    rep.mkDfltBtn = xkb->mk_dflt_btn;
69605b261ecSmrg    rep.axTimeout = xkb->ax_timeout;
69705b261ecSmrg    rep.axtCtrlsMask = xkb->axt_ctrls_mask;
69805b261ecSmrg    rep.axtCtrlsValues = xkb->axt_ctrls_values;
69905b261ecSmrg    rep.axtOptsMask = xkb->axt_opts_mask;
70005b261ecSmrg    rep.axtOptsValues = xkb->axt_opts_values;
70105b261ecSmrg    rep.axOptions = xkb->ax_options;
70205b261ecSmrg    memcpy(rep.perKeyRepeat,xkb->per_key_repeat,XkbPerKeyBitArraySize);
70305b261ecSmrg    if (client->swapped) {
70405b261ecSmrg    	swaps(&rep.sequenceNumber, n);
70505b261ecSmrg	swapl(&rep.length,n);
70605b261ecSmrg	swaps(&rep.internalVMods, n);
70705b261ecSmrg	swaps(&rep.ignoreLockVMods, n);
70805b261ecSmrg	swapl(&rep.enabledCtrls, n);
70905b261ecSmrg	swaps(&rep.repeatDelay, n);
71005b261ecSmrg	swaps(&rep.repeatInterval, n);
71105b261ecSmrg	swaps(&rep.slowKeysDelay, n);
71205b261ecSmrg	swaps(&rep.debounceDelay, n);
71305b261ecSmrg	swaps(&rep.mkDelay, n);
71405b261ecSmrg	swaps(&rep.mkInterval, n);
71505b261ecSmrg	swaps(&rep.mkTimeToMax, n);
71605b261ecSmrg	swaps(&rep.mkMaxSpeed, n);
71705b261ecSmrg	swaps(&rep.mkCurve, n);
71805b261ecSmrg	swaps(&rep.axTimeout, n);
71905b261ecSmrg	swapl(&rep.axtCtrlsMask, n);
72005b261ecSmrg	swapl(&rep.axtCtrlsValues, n);
72105b261ecSmrg	swaps(&rep.axtOptsMask, n);
72205b261ecSmrg	swaps(&rep.axtOptsValues, n);
72305b261ecSmrg	swaps(&rep.axOptions, n);
72405b261ecSmrg    }
72505b261ecSmrg    WriteToClient(client, SIZEOF(xkbGetControlsReply), (char *)&rep);
7266747b715Smrg    return Success;
72705b261ecSmrg}
72805b261ecSmrg
72905b261ecSmrgint
73005b261ecSmrgProcXkbSetControls(ClientPtr client)
73105b261ecSmrg{
73205b261ecSmrg    DeviceIntPtr 	dev, tmpd;
73305b261ecSmrg    XkbSrvInfoPtr	xkbi;
73405b261ecSmrg    XkbControlsPtr	ctrl;
73505b261ecSmrg    XkbControlsRec	new,old;
73605b261ecSmrg    xkbControlsNotify	cn;
73705b261ecSmrg    XkbEventCauseRec	cause;
73805b261ecSmrg    XkbSrvLedInfoPtr	sli;
73905b261ecSmrg
74005b261ecSmrg    REQUEST(xkbSetControlsReq);
74105b261ecSmrg    REQUEST_SIZE_MATCH(xkbSetControlsReq);
74205b261ecSmrg
74305b261ecSmrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
74405b261ecSmrg	return BadAccess;
74505b261ecSmrg
7464642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
74705b261ecSmrg    CHK_MASK_LEGAL(0x01, stuff->changeCtrls, XkbAllControlsMask);
74805b261ecSmrg
7496747b715Smrg    for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
7506747b715Smrg        if (!tmpd->key || !tmpd->key->xkbInfo)
7516747b715Smrg            continue;
7526747b715Smrg        if ((tmpd == dev) || (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) {
75305b261ecSmrg            xkbi = tmpd->key->xkbInfo;
75405b261ecSmrg            ctrl = xkbi->desc->ctrls;
75505b261ecSmrg            new = *ctrl;
75605b261ecSmrg            XkbSetCauseXkbReq(&cause, X_kbSetControls, client);
75705b261ecSmrg
75805b261ecSmrg            if (stuff->changeCtrls & XkbInternalModsMask) {
75905b261ecSmrg                CHK_MASK_MATCH(0x02, stuff->affectInternalMods,
76005b261ecSmrg                               stuff->internalMods);
76105b261ecSmrg                CHK_MASK_MATCH(0x03, stuff->affectInternalVMods,
76205b261ecSmrg                               stuff->internalVMods);
76305b261ecSmrg
76405b261ecSmrg                new.internal.real_mods &= ~(stuff->affectInternalMods);
76505b261ecSmrg                new.internal.real_mods |= (stuff->affectInternalMods &
76605b261ecSmrg                                           stuff->internalMods);
76705b261ecSmrg                new.internal.vmods &= ~(stuff->affectInternalVMods);
76805b261ecSmrg                new.internal.vmods |= (stuff->affectInternalVMods &
76905b261ecSmrg                                       stuff->internalVMods);
77005b261ecSmrg                new.internal.mask = new.internal.real_mods |
77105b261ecSmrg                                    XkbMaskForVMask(xkbi->desc,
77205b261ecSmrg                                                    new.internal.vmods);
77305b261ecSmrg            }
77405b261ecSmrg
77505b261ecSmrg            if (stuff->changeCtrls & XkbIgnoreLockModsMask) {
77605b261ecSmrg                CHK_MASK_MATCH(0x4, stuff->affectIgnoreLockMods,
77705b261ecSmrg                               stuff->ignoreLockMods);
77805b261ecSmrg                CHK_MASK_MATCH(0x5, stuff->affectIgnoreLockVMods,
77905b261ecSmrg                               stuff->ignoreLockVMods);
78005b261ecSmrg
78105b261ecSmrg                new.ignore_lock.real_mods &= ~(stuff->affectIgnoreLockMods);
78205b261ecSmrg                new.ignore_lock.real_mods |= (stuff->affectIgnoreLockMods &
78305b261ecSmrg                                              stuff->ignoreLockMods);
78405b261ecSmrg                new.ignore_lock.vmods &= ~(stuff->affectIgnoreLockVMods);
78505b261ecSmrg                new.ignore_lock.vmods |= (stuff->affectIgnoreLockVMods &
78605b261ecSmrg                                          stuff->ignoreLockVMods);
78705b261ecSmrg                new.ignore_lock.mask = new.ignore_lock.real_mods |
78805b261ecSmrg                                       XkbMaskForVMask(xkbi->desc,
78905b261ecSmrg                                                       new.ignore_lock.vmods);
79005b261ecSmrg            }
79105b261ecSmrg
79205b261ecSmrg            CHK_MASK_MATCH(0x06, stuff->affectEnabledCtrls,
79305b261ecSmrg                           stuff->enabledCtrls);
79405b261ecSmrg            if (stuff->affectEnabledCtrls) {
79505b261ecSmrg                CHK_MASK_LEGAL(0x07, stuff->affectEnabledCtrls,
79605b261ecSmrg                               XkbAllBooleanCtrlsMask);
79705b261ecSmrg
79805b261ecSmrg                new.enabled_ctrls &= ~(stuff->affectEnabledCtrls);
79905b261ecSmrg                new.enabled_ctrls |= (stuff->affectEnabledCtrls &
80005b261ecSmrg                                      stuff->enabledCtrls);
80105b261ecSmrg            }
80205b261ecSmrg
80305b261ecSmrg            if (stuff->changeCtrls & XkbRepeatKeysMask) {
80405b261ecSmrg                if (stuff->repeatDelay < 1 || stuff->repeatInterval < 1) {
80505b261ecSmrg                    client->errorValue = _XkbErrCode3(0x08, stuff->repeatDelay,
80605b261ecSmrg                                                      stuff->repeatInterval);
80705b261ecSmrg                    return BadValue;
80805b261ecSmrg                }
80905b261ecSmrg
81005b261ecSmrg                new.repeat_delay = stuff->repeatDelay;
81105b261ecSmrg                new.repeat_interval = stuff->repeatInterval;
81205b261ecSmrg            }
81305b261ecSmrg
81405b261ecSmrg            if (stuff->changeCtrls & XkbSlowKeysMask) {
81505b261ecSmrg                if (stuff->slowKeysDelay < 1) {
81605b261ecSmrg                    client->errorValue = _XkbErrCode2(0x09,
81705b261ecSmrg                                                      stuff->slowKeysDelay);
81805b261ecSmrg                    return BadValue;
81905b261ecSmrg                }
82005b261ecSmrg
82105b261ecSmrg                new.slow_keys_delay = stuff->slowKeysDelay;
82205b261ecSmrg            }
82305b261ecSmrg
82405b261ecSmrg            if (stuff->changeCtrls & XkbBounceKeysMask) {
82505b261ecSmrg                if (stuff->debounceDelay < 1) {
82605b261ecSmrg                    client->errorValue = _XkbErrCode2(0x0A,
82705b261ecSmrg                                                      stuff->debounceDelay);
82805b261ecSmrg                    return BadValue;
82905b261ecSmrg                }
83005b261ecSmrg
83105b261ecSmrg                new.debounce_delay = stuff->debounceDelay;
83205b261ecSmrg            }
83305b261ecSmrg
83405b261ecSmrg            if (stuff->changeCtrls & XkbMouseKeysMask) {
83505b261ecSmrg                if (stuff->mkDfltBtn > XkbMaxMouseKeysBtn) {
83605b261ecSmrg                    client->errorValue = _XkbErrCode2(0x0B, stuff->mkDfltBtn);
83705b261ecSmrg                    return BadValue;
83805b261ecSmrg                }
83905b261ecSmrg
84005b261ecSmrg                new.mk_dflt_btn = stuff->mkDfltBtn;
84105b261ecSmrg            }
84205b261ecSmrg
84305b261ecSmrg            if (stuff->changeCtrls & XkbMouseKeysAccelMask) {
84405b261ecSmrg                if (stuff->mkDelay < 1 || stuff->mkInterval < 1 ||
84505b261ecSmrg                    stuff->mkTimeToMax < 1 || stuff->mkMaxSpeed < 1 ||
84605b261ecSmrg                    stuff->mkCurve < -1000) {
84705b261ecSmrg                    client->errorValue = _XkbErrCode2(0x0C,0);
84805b261ecSmrg                    return BadValue;
84905b261ecSmrg                }
85005b261ecSmrg
85105b261ecSmrg                new.mk_delay = stuff->mkDelay;
85205b261ecSmrg                new.mk_interval = stuff->mkInterval;
85305b261ecSmrg                new.mk_time_to_max = stuff->mkTimeToMax;
85405b261ecSmrg                new.mk_max_speed = stuff->mkMaxSpeed;
85505b261ecSmrg                new.mk_curve = stuff->mkCurve;
85605b261ecSmrg                AccessXComputeCurveFactor(xkbi, &new);
85705b261ecSmrg            }
85805b261ecSmrg
85905b261ecSmrg            if (stuff->changeCtrls & XkbGroupsWrapMask) {
86005b261ecSmrg                unsigned act, num;
86105b261ecSmrg
86205b261ecSmrg                act = XkbOutOfRangeGroupAction(stuff->groupsWrap);
86305b261ecSmrg                switch (act) {
86405b261ecSmrg                case XkbRedirectIntoRange:
86505b261ecSmrg                    num = XkbOutOfRangeGroupNumber(stuff->groupsWrap);
86605b261ecSmrg                    if (num >= new.num_groups) {
86705b261ecSmrg                        client->errorValue = _XkbErrCode3(0x0D, new.num_groups,
86805b261ecSmrg                                                          num);
86905b261ecSmrg                        return BadValue;
87005b261ecSmrg                    }
87105b261ecSmrg                case XkbWrapIntoRange:
87205b261ecSmrg                case XkbClampIntoRange:
87305b261ecSmrg                    break;
87405b261ecSmrg                default:
87505b261ecSmrg                    client->errorValue = _XkbErrCode2(0x0E, act);
87605b261ecSmrg                    return BadValue;
87705b261ecSmrg                }
87805b261ecSmrg
87905b261ecSmrg                new.groups_wrap= stuff->groupsWrap;
88005b261ecSmrg            }
88105b261ecSmrg
88205b261ecSmrg            CHK_MASK_LEGAL(0x0F, stuff->axOptions, XkbAX_AllOptionsMask);
88305b261ecSmrg            if (stuff->changeCtrls & XkbAccessXKeysMask) {
88405b261ecSmrg                new.ax_options = stuff->axOptions & XkbAX_AllOptionsMask;
88505b261ecSmrg            }
88605b261ecSmrg            else {
88705b261ecSmrg                if (stuff->changeCtrls & XkbStickyKeysMask) {
88805b261ecSmrg                    new.ax_options &= ~(XkbAX_SKOptionsMask);
88905b261ecSmrg                    new.ax_options |= (stuff->axOptions & XkbAX_SKOptionsMask);
89005b261ecSmrg                }
89105b261ecSmrg
89205b261ecSmrg                if (stuff->changeCtrls & XkbAccessXFeedbackMask) {
89305b261ecSmrg                    new.ax_options &= ~(XkbAX_FBOptionsMask);
89405b261ecSmrg                    new.ax_options |= (stuff->axOptions & XkbAX_FBOptionsMask);
89505b261ecSmrg                }
89605b261ecSmrg            }
89705b261ecSmrg
89805b261ecSmrg            if (stuff->changeCtrls & XkbAccessXTimeoutMask) {
89905b261ecSmrg                if (stuff->axTimeout < 1) {
90005b261ecSmrg                    client->errorValue = _XkbErrCode2(0x10, stuff->axTimeout);
90105b261ecSmrg                    return BadValue;
90205b261ecSmrg                }
90305b261ecSmrg                CHK_MASK_MATCH(0x11, stuff->axtCtrlsMask,
90405b261ecSmrg                               stuff->axtCtrlsValues);
90505b261ecSmrg                CHK_MASK_LEGAL(0x12, stuff->axtCtrlsMask,
90605b261ecSmrg                               XkbAllBooleanCtrlsMask);
90705b261ecSmrg                CHK_MASK_MATCH(0x13, stuff->axtOptsMask, stuff->axtOptsValues);
90805b261ecSmrg                CHK_MASK_LEGAL(0x14, stuff->axtOptsMask, XkbAX_AllOptionsMask);
90905b261ecSmrg                new.ax_timeout = stuff->axTimeout;
91005b261ecSmrg                new.axt_ctrls_mask = stuff->axtCtrlsMask;
91105b261ecSmrg                new.axt_ctrls_values = (stuff->axtCtrlsValues &
91205b261ecSmrg                                        stuff->axtCtrlsMask);
91305b261ecSmrg                new.axt_opts_mask = stuff->axtOptsMask;
91405b261ecSmrg                new.axt_opts_values = (stuff->axtOptsValues &
91505b261ecSmrg                                       stuff->axtOptsMask);
91605b261ecSmrg            }
91705b261ecSmrg
9189ace9065Smrg            if (stuff->changeCtrls & XkbPerKeyRepeatMask) {
91905b261ecSmrg                memcpy(new.per_key_repeat, stuff->perKeyRepeat,
92005b261ecSmrg                       XkbPerKeyBitArraySize);
9219ace9065Smrg                if (xkbi->repeatKey &&
9229ace9065Smrg                    !BitIsOn(new.per_key_repeat, xkbi->repeatKey)) {
9239ace9065Smrg                    AccessXCancelRepeatKey(xkbi, xkbi->repeatKey);
9249ace9065Smrg                }
9259ace9065Smrg            }
92605b261ecSmrg
92705b261ecSmrg            old= *ctrl;
92805b261ecSmrg            *ctrl= new;
92905b261ecSmrg            XkbDDXChangeControls(tmpd, &old, ctrl);
93005b261ecSmrg
9316747b715Smrg            if (XkbComputeControlsNotify(tmpd, &old, ctrl, &cn, FALSE)) {
93205b261ecSmrg                cn.keycode = 0;
93305b261ecSmrg                cn.eventType = 0;
93405b261ecSmrg                cn.requestMajor = XkbReqCode;
93505b261ecSmrg                cn.requestMinor = X_kbSetControls;
93605b261ecSmrg                XkbSendControlsNotify(tmpd, &cn);
93705b261ecSmrg            }
93805b261ecSmrg
93905b261ecSmrg            sli = XkbFindSrvLedInfo(tmpd, XkbDfltXIClass, XkbDfltXIId, 0);
94005b261ecSmrg            if (sli)
9416747b715Smrg                XkbUpdateIndicators(tmpd, sli->usesControls, TRUE, NULL,
94205b261ecSmrg                                    &cause);
94305b261ecSmrg
94405b261ecSmrg            /* If sticky keys were disabled, clear all locks and latches */
94505b261ecSmrg            if ((old.enabled_ctrls & XkbStickyKeysMask) &&
94605b261ecSmrg                !(ctrl->enabled_ctrls & XkbStickyKeysMask))
9476747b715Smrg                XkbClearAllLatchesAndLocks(tmpd, xkbi, TRUE, &cause);
94805b261ecSmrg        }
94905b261ecSmrg    }
95005b261ecSmrg
9516747b715Smrg    return Success;
95205b261ecSmrg}
95305b261ecSmrg
95405b261ecSmrg/***====================================================================***/
95505b261ecSmrg
95605b261ecSmrgstatic int
95705b261ecSmrgXkbSizeKeyTypes(XkbDescPtr xkb,xkbGetMapReply *rep)
95805b261ecSmrg{
95905b261ecSmrg    XkbKeyTypeRec 	*type;
96005b261ecSmrg    unsigned		i,len;
96105b261ecSmrg
96205b261ecSmrg    len= 0;
96305b261ecSmrg    if (((rep->present&XkbKeyTypesMask)==0)||(rep->nTypes<1)||
96405b261ecSmrg	(!xkb)||(!xkb->map)||(!xkb->map->types)) {
96505b261ecSmrg	rep->present&= ~XkbKeyTypesMask;
96605b261ecSmrg	rep->firstType= rep->nTypes= 0;
96705b261ecSmrg	return 0;
96805b261ecSmrg    }
96905b261ecSmrg    type= &xkb->map->types[rep->firstType];
97005b261ecSmrg    for (i=0;i<rep->nTypes;i++,type++){
97105b261ecSmrg	len+= SIZEOF(xkbKeyTypeWireDesc);
97205b261ecSmrg	if (type->map_count>0) {
97305b261ecSmrg	    len+= (type->map_count*SIZEOF(xkbKTMapEntryWireDesc));
97405b261ecSmrg	    if (type->preserve)
97505b261ecSmrg		len+= (type->map_count*SIZEOF(xkbModsWireDesc));
97605b261ecSmrg	}
97705b261ecSmrg    }
97805b261ecSmrg    return len;
97905b261ecSmrg}
98005b261ecSmrg
98105b261ecSmrgstatic char *
98205b261ecSmrgXkbWriteKeyTypes(	XkbDescPtr		xkb,
98305b261ecSmrg			xkbGetMapReply *	rep,
98405b261ecSmrg			char *			buf,
98505b261ecSmrg			ClientPtr 		client)
98605b261ecSmrg{
98705b261ecSmrg    XkbKeyTypePtr	type;
98805b261ecSmrg    unsigned		i;
98905b261ecSmrg    xkbKeyTypeWireDesc *wire;
99005b261ecSmrg
99105b261ecSmrg    type= &xkb->map->types[rep->firstType];
99205b261ecSmrg    for (i=0;i<rep->nTypes;i++,type++) {
99305b261ecSmrg	register unsigned n;
99405b261ecSmrg	wire= (xkbKeyTypeWireDesc *)buf;
99505b261ecSmrg	wire->mask = type->mods.mask;
99605b261ecSmrg	wire->realMods = type->mods.real_mods;
99705b261ecSmrg	wire->virtualMods = type->mods.vmods;
99805b261ecSmrg	wire->numLevels = type->num_levels;
99905b261ecSmrg	wire->nMapEntries = type->map_count;
100005b261ecSmrg	wire->preserve = (type->preserve!=NULL);
100105b261ecSmrg	if (client->swapped) {
100205b261ecSmrg	    register int n;
100305b261ecSmrg	    swaps(&wire->virtualMods,n);
100405b261ecSmrg	}
100505b261ecSmrg
100605b261ecSmrg	buf= (char *)&wire[1];
100705b261ecSmrg	if (wire->nMapEntries>0) {
100805b261ecSmrg	    xkbKTMapEntryWireDesc *	wire;
100905b261ecSmrg	    XkbKTMapEntryPtr		entry;
101005b261ecSmrg	    wire= (xkbKTMapEntryWireDesc *)buf;
101105b261ecSmrg	    entry= type->map;
101205b261ecSmrg	    for (n=0;n<type->map_count;n++,wire++,entry++) {
101305b261ecSmrg		wire->active= entry->active;
101405b261ecSmrg		wire->mask= entry->mods.mask;
101505b261ecSmrg		wire->level= entry->level;
101605b261ecSmrg		wire->realMods= entry->mods.real_mods;
101705b261ecSmrg		wire->virtualMods= entry->mods.vmods;
101805b261ecSmrg		if (client->swapped) {
101905b261ecSmrg		    register int n;
102005b261ecSmrg		    swaps(&wire->virtualMods,n);
102105b261ecSmrg		}
102205b261ecSmrg	    }
102305b261ecSmrg	    buf= (char *)wire;
102405b261ecSmrg	    if (type->preserve!=NULL) {
102505b261ecSmrg		xkbModsWireDesc *	pwire;
102605b261ecSmrg		XkbModsPtr		preserve;
102705b261ecSmrg		pwire= (xkbModsWireDesc *)buf;
102805b261ecSmrg		preserve= type->preserve;
102905b261ecSmrg		for (n=0;n<type->map_count;n++,pwire++,preserve++) {
103005b261ecSmrg		    pwire->mask= preserve->mask;
103105b261ecSmrg		    pwire->realMods= preserve->real_mods;
103205b261ecSmrg		    pwire->virtualMods= preserve->vmods;
103305b261ecSmrg		    if (client->swapped) {
103405b261ecSmrg			register int n;
103505b261ecSmrg			swaps(&pwire->virtualMods,n);
103605b261ecSmrg		    }
103705b261ecSmrg		}
103805b261ecSmrg		buf= (char *)pwire;
103905b261ecSmrg	    }
104005b261ecSmrg	}
104105b261ecSmrg    }
104205b261ecSmrg    return buf;
104305b261ecSmrg}
104405b261ecSmrg
104505b261ecSmrgstatic int
104605b261ecSmrgXkbSizeKeySyms(XkbDescPtr xkb,xkbGetMapReply *rep)
104705b261ecSmrg{
104805b261ecSmrg    XkbSymMapPtr	symMap;
104905b261ecSmrg    unsigned		i,len;
105005b261ecSmrg    unsigned		nSyms,nSymsThisKey;
105105b261ecSmrg
105205b261ecSmrg    if (((rep->present&XkbKeySymsMask)==0)||(rep->nKeySyms<1)||
105305b261ecSmrg	(!xkb)||(!xkb->map)||(!xkb->map->key_sym_map)) {
105405b261ecSmrg	rep->present&= ~XkbKeySymsMask;
105505b261ecSmrg	rep->firstKeySym= rep->nKeySyms= 0;
105605b261ecSmrg	rep->totalSyms= 0;
105705b261ecSmrg	return 0;
105805b261ecSmrg    }
105905b261ecSmrg    len= rep->nKeySyms*SIZEOF(xkbSymMapWireDesc);
106005b261ecSmrg    symMap = &xkb->map->key_sym_map[rep->firstKeySym];
106105b261ecSmrg    for (i=nSyms=0;i<rep->nKeySyms;i++,symMap++) {
106205b261ecSmrg	if (symMap->offset!=0) {
106305b261ecSmrg	    nSymsThisKey= XkbNumGroups(symMap->group_info)*symMap->width;
106405b261ecSmrg	    nSyms+= nSymsThisKey;
106505b261ecSmrg	}
106605b261ecSmrg    }
106705b261ecSmrg    len+= nSyms*4;
106805b261ecSmrg    rep->totalSyms= nSyms;
106905b261ecSmrg    return len;
107005b261ecSmrg}
107105b261ecSmrg
107205b261ecSmrgstatic int
107305b261ecSmrgXkbSizeVirtualMods(XkbDescPtr xkb,xkbGetMapReply *rep)
107405b261ecSmrg{
107505b261ecSmrgregister unsigned i,nMods,bit;
107605b261ecSmrg
107705b261ecSmrg    if (((rep->present&XkbVirtualModsMask)==0)||(rep->virtualMods==0)||
107805b261ecSmrg	(!xkb)||(!xkb->server)) {
107905b261ecSmrg	rep->present&= ~XkbVirtualModsMask;
108005b261ecSmrg	rep->virtualMods= 0;
108105b261ecSmrg	return 0;
108205b261ecSmrg    }
108305b261ecSmrg    for (i=nMods=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
108405b261ecSmrg        if (rep->virtualMods&bit)
108505b261ecSmrg	    nMods++;
108605b261ecSmrg    }
108705b261ecSmrg    return XkbPaddedSize(nMods);
108805b261ecSmrg}
108905b261ecSmrg
109005b261ecSmrgstatic char *
109105b261ecSmrgXkbWriteKeySyms(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,ClientPtr client)
109205b261ecSmrg{
109305b261ecSmrgregister KeySym *	pSym;
109405b261ecSmrgXkbSymMapPtr		symMap;
109505b261ecSmrgxkbSymMapWireDesc *	outMap;
109605b261ecSmrgregister unsigned	i;
109705b261ecSmrg
109805b261ecSmrg    symMap = &xkb->map->key_sym_map[rep->firstKeySym];
109905b261ecSmrg    for (i=0;i<rep->nKeySyms;i++,symMap++) {
110005b261ecSmrg	outMap = (xkbSymMapWireDesc *)buf;
110105b261ecSmrg	outMap->ktIndex[0] = symMap->kt_index[0];
110205b261ecSmrg	outMap->ktIndex[1] = symMap->kt_index[1];
110305b261ecSmrg	outMap->ktIndex[2] = symMap->kt_index[2];
110405b261ecSmrg	outMap->ktIndex[3] = symMap->kt_index[3];
110505b261ecSmrg	outMap->groupInfo = symMap->group_info;
110605b261ecSmrg	outMap->width= symMap->width;
110705b261ecSmrg	outMap->nSyms = symMap->width*XkbNumGroups(symMap->group_info);
110805b261ecSmrg	buf= (char *)&outMap[1];
110905b261ecSmrg	if (outMap->nSyms==0)
111005b261ecSmrg	    continue;
111105b261ecSmrg
111205b261ecSmrg	pSym = &xkb->map->syms[symMap->offset];
111305b261ecSmrg	memcpy((char *)buf,(char *)pSym,outMap->nSyms*4);
111405b261ecSmrg	if (client->swapped) {
111505b261ecSmrg	    register int n,nSyms= outMap->nSyms;
111605b261ecSmrg	    swaps(&outMap->nSyms,n);
111705b261ecSmrg	    while (nSyms-->0) {
111805b261ecSmrg		swapl(buf,n);
111905b261ecSmrg		buf+= 4;
112005b261ecSmrg	    }
112105b261ecSmrg	}
112205b261ecSmrg	else buf+= outMap->nSyms*4;
112305b261ecSmrg    }
112405b261ecSmrg    return buf;
112505b261ecSmrg}
112605b261ecSmrg
112705b261ecSmrgstatic int
112805b261ecSmrgXkbSizeKeyActions(XkbDescPtr xkb,xkbGetMapReply *rep)
112905b261ecSmrg{
113005b261ecSmrg    unsigned		i,len,nActs;
113105b261ecSmrg    register KeyCode	firstKey;
113205b261ecSmrg
113305b261ecSmrg    if (((rep->present&XkbKeyActionsMask)==0)||(rep->nKeyActs<1)||
113405b261ecSmrg	(!xkb)||(!xkb->server)||(!xkb->server->key_acts)) {
113505b261ecSmrg	rep->present&= ~XkbKeyActionsMask;
113605b261ecSmrg	rep->firstKeyAct= rep->nKeyActs= 0;
113705b261ecSmrg	rep->totalActs= 0;
113805b261ecSmrg	return 0;
113905b261ecSmrg    }
114005b261ecSmrg    firstKey= rep->firstKeyAct;
114105b261ecSmrg    for (nActs=i=0;i<rep->nKeyActs;i++) {
114205b261ecSmrg	if (xkb->server->key_acts[i+firstKey]!=0)
114305b261ecSmrg	    nActs+= XkbKeyNumActions(xkb,i+firstKey);
114405b261ecSmrg    }
114505b261ecSmrg    len= XkbPaddedSize(rep->nKeyActs)+(nActs*SIZEOF(xkbActionWireDesc));
114605b261ecSmrg    rep->totalActs= nActs;
114705b261ecSmrg    return len;
114805b261ecSmrg}
114905b261ecSmrg
115005b261ecSmrgstatic char *
115105b261ecSmrgXkbWriteKeyActions(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
115205b261ecSmrg							ClientPtr client)
115305b261ecSmrg{
115405b261ecSmrg    unsigned		i;
115505b261ecSmrg    CARD8 *		numDesc;
115605b261ecSmrg    XkbAnyAction *	actDesc;
115705b261ecSmrg
115805b261ecSmrg    numDesc = (CARD8 *)buf;
115905b261ecSmrg    for (i=0;i<rep->nKeyActs;i++) {
116005b261ecSmrg	if (xkb->server->key_acts[i+rep->firstKeyAct]==0)
116105b261ecSmrg	     numDesc[i] = 0;
116205b261ecSmrg	else numDesc[i] = XkbKeyNumActions(xkb,(i+rep->firstKeyAct));
116305b261ecSmrg    }
116405b261ecSmrg    buf+= XkbPaddedSize(rep->nKeyActs);
116505b261ecSmrg
116605b261ecSmrg    actDesc = (XkbAnyAction *)buf;
116705b261ecSmrg    for (i=0;i<rep->nKeyActs;i++) {
116805b261ecSmrg	if (xkb->server->key_acts[i+rep->firstKeyAct]!=0) {
116905b261ecSmrg	    unsigned int num;
117005b261ecSmrg	    num = XkbKeyNumActions(xkb,(i+rep->firstKeyAct));
117105b261ecSmrg	    memcpy((char *)actDesc,
117205b261ecSmrg		   (char*)XkbKeyActionsPtr(xkb,(i+rep->firstKeyAct)),
117305b261ecSmrg		   num*SIZEOF(xkbActionWireDesc));
117405b261ecSmrg	    actDesc+= num;
117505b261ecSmrg	}
117605b261ecSmrg    }
117705b261ecSmrg    buf = (char *)actDesc;
117805b261ecSmrg    return buf;
117905b261ecSmrg}
118005b261ecSmrg
118105b261ecSmrgstatic int
118205b261ecSmrgXkbSizeKeyBehaviors(XkbDescPtr xkb,xkbGetMapReply *rep)
118305b261ecSmrg{
118405b261ecSmrg    unsigned		i,len,nBhvr;
118505b261ecSmrg    XkbBehavior *	bhv;
118605b261ecSmrg
118705b261ecSmrg    if (((rep->present&XkbKeyBehaviorsMask)==0)||(rep->nKeyBehaviors<1)||
118805b261ecSmrg	(!xkb)||(!xkb->server)||(!xkb->server->behaviors)) {
118905b261ecSmrg	rep->present&= ~XkbKeyBehaviorsMask;
119005b261ecSmrg	rep->firstKeyBehavior= rep->nKeyBehaviors= 0;
119105b261ecSmrg	rep->totalKeyBehaviors= 0;
119205b261ecSmrg	return 0;
119305b261ecSmrg    }
119405b261ecSmrg    bhv= &xkb->server->behaviors[rep->firstKeyBehavior];
119505b261ecSmrg    for (nBhvr=i=0;i<rep->nKeyBehaviors;i++,bhv++) {
119605b261ecSmrg	if (bhv->type!=XkbKB_Default)
119705b261ecSmrg	    nBhvr++;
119805b261ecSmrg    }
119905b261ecSmrg    len= nBhvr*SIZEOF(xkbBehaviorWireDesc);
120005b261ecSmrg    rep->totalKeyBehaviors= nBhvr;
120105b261ecSmrg    return len;
120205b261ecSmrg}
120305b261ecSmrg
120405b261ecSmrgstatic char *
120505b261ecSmrgXkbWriteKeyBehaviors(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
120605b261ecSmrg							ClientPtr client)
120705b261ecSmrg{
120805b261ecSmrg    unsigned		i;
120905b261ecSmrg    xkbBehaviorWireDesc	*wire;
121005b261ecSmrg    XkbBehavior		*pBhvr;
121105b261ecSmrg
121205b261ecSmrg    wire = (xkbBehaviorWireDesc *)buf;
121305b261ecSmrg    pBhvr= &xkb->server->behaviors[rep->firstKeyBehavior];
121405b261ecSmrg    for (i=0;i<rep->nKeyBehaviors;i++,pBhvr++) {
121505b261ecSmrg	if (pBhvr->type!=XkbKB_Default) {
121605b261ecSmrg	    wire->key=  i+rep->firstKeyBehavior;
121705b261ecSmrg	    wire->type= pBhvr->type;
121805b261ecSmrg	    wire->data= pBhvr->data;
121905b261ecSmrg	    wire++;
122005b261ecSmrg	}
122105b261ecSmrg    }
122205b261ecSmrg    buf = (char *)wire;
122305b261ecSmrg    return buf;
122405b261ecSmrg}
122505b261ecSmrg
122605b261ecSmrgstatic int
122705b261ecSmrgXkbSizeExplicit(XkbDescPtr xkb,xkbGetMapReply *rep)
122805b261ecSmrg{
122905b261ecSmrg    unsigned	i,len,nRtrn;
123005b261ecSmrg
123105b261ecSmrg    if (((rep->present&XkbExplicitComponentsMask)==0)||(rep->nKeyExplicit<1)||
123205b261ecSmrg	(!xkb)||(!xkb->server)||(!xkb->server->explicit)) {
123305b261ecSmrg	rep->present&= ~XkbExplicitComponentsMask;
123405b261ecSmrg	rep->firstKeyExplicit= rep->nKeyExplicit= 0;
123505b261ecSmrg	rep->totalKeyExplicit= 0;
123605b261ecSmrg	return 0;
123705b261ecSmrg    }
123805b261ecSmrg    for (nRtrn=i=0;i<rep->nKeyExplicit;i++) {
123905b261ecSmrg	if (xkb->server->explicit[i+rep->firstKeyExplicit]!=0)
124005b261ecSmrg	    nRtrn++;
124105b261ecSmrg    }
124205b261ecSmrg    rep->totalKeyExplicit= nRtrn;
124305b261ecSmrg    len= XkbPaddedSize(nRtrn*2); /* two bytes per non-zero explicit component */
124405b261ecSmrg    return len;
124505b261ecSmrg}
124605b261ecSmrg
124705b261ecSmrgstatic char *
124805b261ecSmrgXkbWriteExplicit(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,ClientPtr client)
124905b261ecSmrg{
125005b261ecSmrgunsigned	i;
125105b261ecSmrgchar *		start;
125205b261ecSmrgunsigned char *	pExp;
125305b261ecSmrg
125405b261ecSmrg    start= buf;
125505b261ecSmrg    pExp= &xkb->server->explicit[rep->firstKeyExplicit];
125605b261ecSmrg    for (i=0;i<rep->nKeyExplicit;i++,pExp++) {
125705b261ecSmrg	if (*pExp!=0) {
125805b261ecSmrg	    *buf++= i+rep->firstKeyExplicit;
125905b261ecSmrg	    *buf++= *pExp;
126005b261ecSmrg	}
126105b261ecSmrg    }
126205b261ecSmrg    i= XkbPaddedSize(buf-start)-(buf-start); /* pad to word boundary */
126305b261ecSmrg    return buf+i;
126405b261ecSmrg}
126505b261ecSmrg
126605b261ecSmrgstatic int
126705b261ecSmrgXkbSizeModifierMap(XkbDescPtr xkb,xkbGetMapReply *rep)
126805b261ecSmrg{
126905b261ecSmrg    unsigned	i,len,nRtrn;
127005b261ecSmrg
127105b261ecSmrg    if (((rep->present&XkbModifierMapMask)==0)||(rep->nModMapKeys<1)||
127205b261ecSmrg	(!xkb)||(!xkb->map)||(!xkb->map->modmap)) {
127305b261ecSmrg	rep->present&= ~XkbModifierMapMask;
127405b261ecSmrg	rep->firstModMapKey= rep->nModMapKeys= 0;
127505b261ecSmrg	rep->totalModMapKeys= 0;
127605b261ecSmrg	return 0;
127705b261ecSmrg    }
127805b261ecSmrg    for (nRtrn=i=0;i<rep->nModMapKeys;i++) {
127905b261ecSmrg	if (xkb->map->modmap[i+rep->firstModMapKey]!=0)
128005b261ecSmrg	    nRtrn++;
128105b261ecSmrg    }
128205b261ecSmrg    rep->totalModMapKeys= nRtrn;
128305b261ecSmrg    len= XkbPaddedSize(nRtrn*2); /* two bytes per non-zero modmap component */
128405b261ecSmrg    return len;
128505b261ecSmrg}
128605b261ecSmrg
128705b261ecSmrgstatic char *
128805b261ecSmrgXkbWriteModifierMap(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
128905b261ecSmrg							ClientPtr client)
129005b261ecSmrg{
129105b261ecSmrgunsigned	i;
129205b261ecSmrgchar *		start;
129305b261ecSmrgunsigned char *	pMap;
129405b261ecSmrg
129505b261ecSmrg    start= buf;
129605b261ecSmrg    pMap= &xkb->map->modmap[rep->firstModMapKey];
129705b261ecSmrg    for (i=0;i<rep->nModMapKeys;i++,pMap++) {
129805b261ecSmrg	if (*pMap!=0) {
129905b261ecSmrg	    *buf++= i+rep->firstModMapKey;
130005b261ecSmrg	    *buf++= *pMap;
130105b261ecSmrg	}
130205b261ecSmrg    }
130305b261ecSmrg    i= XkbPaddedSize(buf-start)-(buf-start); /* pad to word boundary */
130405b261ecSmrg    return buf+i;
130505b261ecSmrg}
130605b261ecSmrg
130705b261ecSmrgstatic int
130805b261ecSmrgXkbSizeVirtualModMap(XkbDescPtr xkb,xkbGetMapReply *rep)
130905b261ecSmrg{
131005b261ecSmrg    unsigned	i,len,nRtrn;
131105b261ecSmrg
131205b261ecSmrg    if (((rep->present&XkbVirtualModMapMask)==0)||(rep->nVModMapKeys<1)||
131305b261ecSmrg	(!xkb)||(!xkb->server)||(!xkb->server->vmodmap)) {
131405b261ecSmrg	rep->present&= ~XkbVirtualModMapMask;
131505b261ecSmrg	rep->firstVModMapKey= rep->nVModMapKeys= 0;
131605b261ecSmrg	rep->totalVModMapKeys= 0;
131705b261ecSmrg	return 0;
131805b261ecSmrg    }
131952397711Smrg    for (nRtrn=i=0;i<rep->nVModMapKeys;i++) {
132005b261ecSmrg	if (xkb->server->vmodmap[i+rep->firstVModMapKey]!=0)
132105b261ecSmrg	    nRtrn++;
132205b261ecSmrg    }
132305b261ecSmrg    rep->totalVModMapKeys= nRtrn;
132405b261ecSmrg    len= nRtrn*SIZEOF(xkbVModMapWireDesc);
132505b261ecSmrg    return len;
132605b261ecSmrg}
132705b261ecSmrg
132805b261ecSmrgstatic char *
132905b261ecSmrgXkbWriteVirtualModMap(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
133005b261ecSmrg							ClientPtr client)
133105b261ecSmrg{
133205b261ecSmrgunsigned		i;
133305b261ecSmrgxkbVModMapWireDesc *	wire;
133405b261ecSmrgunsigned short *	pMap;
133505b261ecSmrg
133605b261ecSmrg    wire= (xkbVModMapWireDesc *)buf;
133705b261ecSmrg    pMap= &xkb->server->vmodmap[rep->firstVModMapKey];
133852397711Smrg    for (i=0;i<rep->nVModMapKeys;i++,pMap++) {
133905b261ecSmrg	if (*pMap!=0) {
134005b261ecSmrg	    wire->key= i+rep->firstVModMapKey;
134105b261ecSmrg	    wire->vmods= *pMap;
134205b261ecSmrg	    wire++;
134305b261ecSmrg	}
134405b261ecSmrg    }
134505b261ecSmrg    return (char *)wire;
134605b261ecSmrg}
134705b261ecSmrg
134805b261ecSmrgstatic Status
134905b261ecSmrgXkbComputeGetMapReplySize(XkbDescPtr xkb,xkbGetMapReply *rep)
135005b261ecSmrg{
135105b261ecSmrgint	len;
135205b261ecSmrg
135305b261ecSmrg    rep->minKeyCode= xkb->min_key_code;
135405b261ecSmrg    rep->maxKeyCode= xkb->max_key_code;
135505b261ecSmrg    len= XkbSizeKeyTypes(xkb,rep);
135605b261ecSmrg    len+= XkbSizeKeySyms(xkb,rep);
135705b261ecSmrg    len+= XkbSizeKeyActions(xkb,rep);
135805b261ecSmrg    len+= XkbSizeKeyBehaviors(xkb,rep);
135905b261ecSmrg    len+= XkbSizeVirtualMods(xkb,rep);
136005b261ecSmrg    len+= XkbSizeExplicit(xkb,rep);
136105b261ecSmrg    len+= XkbSizeModifierMap(xkb,rep);
136205b261ecSmrg    len+= XkbSizeVirtualModMap(xkb,rep);
136305b261ecSmrg    rep->length+= (len/4);
136405b261ecSmrg    return Success;
136505b261ecSmrg}
136605b261ecSmrg
136705b261ecSmrgstatic int
136805b261ecSmrgXkbSendMap(ClientPtr client,XkbDescPtr xkb,xkbGetMapReply *rep)
136905b261ecSmrg{
137005b261ecSmrgunsigned	i,len;
137105b261ecSmrgchar		*desc,*start;
137205b261ecSmrg
137305b261ecSmrg    len= (rep->length*4)-(SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply));
13746747b715Smrg    start= desc= calloc(1, len);
137505b261ecSmrg    if (!start)
137605b261ecSmrg	return BadAlloc;
137705b261ecSmrg    if ( rep->nTypes>0 )
137805b261ecSmrg	desc = XkbWriteKeyTypes(xkb,rep,desc,client);
137905b261ecSmrg    if ( rep->nKeySyms>0 )
138005b261ecSmrg	desc = XkbWriteKeySyms(xkb,rep,desc,client);
138105b261ecSmrg    if ( rep->nKeyActs>0 )
138205b261ecSmrg	desc = XkbWriteKeyActions(xkb,rep,desc,client);
138305b261ecSmrg    if ( rep->totalKeyBehaviors>0 )
138405b261ecSmrg	desc = XkbWriteKeyBehaviors(xkb,rep,desc,client);
138505b261ecSmrg    if ( rep->virtualMods ) {
138605b261ecSmrg	register int sz,bit;
138705b261ecSmrg	for (i=sz=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
138805b261ecSmrg	    if (rep->virtualMods&bit) {
138905b261ecSmrg		desc[sz++]= xkb->server->vmods[i];
139005b261ecSmrg	    }
139105b261ecSmrg	}
139205b261ecSmrg	desc+= XkbPaddedSize(sz);
139305b261ecSmrg    }
139405b261ecSmrg    if ( rep->totalKeyExplicit>0 )
139505b261ecSmrg	desc= XkbWriteExplicit(xkb,rep,desc,client);
139605b261ecSmrg    if ( rep->totalModMapKeys>0 )
139705b261ecSmrg	desc= XkbWriteModifierMap(xkb,rep,desc,client);
139805b261ecSmrg    if ( rep->totalVModMapKeys>0 )
139905b261ecSmrg	desc= XkbWriteVirtualModMap(xkb,rep,desc,client);
140005b261ecSmrg    if ((desc-start)!=(len)) {
14014642e01fSmrg	ErrorF("[xkb] BOGUS LENGTH in write keyboard desc, expected %d, got %ld\n",
140205b261ecSmrg					len, (unsigned long)(desc-start));
140305b261ecSmrg    }
140405b261ecSmrg    if (client->swapped) {
140505b261ecSmrg	register int n;
140605b261ecSmrg	swaps(&rep->sequenceNumber,n);
140705b261ecSmrg	swapl(&rep->length,n);
140805b261ecSmrg	swaps(&rep->present,n);
140905b261ecSmrg	swaps(&rep->totalSyms,n);
141005b261ecSmrg	swaps(&rep->totalActs,n);
141105b261ecSmrg    }
141205b261ecSmrg    WriteToClient(client, (i=SIZEOF(xkbGetMapReply)), (char *)rep);
141305b261ecSmrg    WriteToClient(client, len, start);
14146747b715Smrg    free((char *)start);
14156747b715Smrg    return Success;
141605b261ecSmrg}
141705b261ecSmrg
141805b261ecSmrgint
141905b261ecSmrgProcXkbGetMap(ClientPtr client)
142005b261ecSmrg{
142105b261ecSmrg    DeviceIntPtr	 dev;
142205b261ecSmrg    xkbGetMapReply	 rep;
142305b261ecSmrg    XkbDescRec		*xkb;
142405b261ecSmrg    int			 n,status;
142505b261ecSmrg
142605b261ecSmrg    REQUEST(xkbGetMapReq);
142705b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetMapReq);
142805b261ecSmrg
142905b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
143005b261ecSmrg	return BadAccess;
143105b261ecSmrg
14324642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
143305b261ecSmrg    CHK_MASK_OVERLAP(0x01,stuff->full,stuff->partial);
143405b261ecSmrg    CHK_MASK_LEGAL(0x02,stuff->full,XkbAllMapComponentsMask);
143505b261ecSmrg    CHK_MASK_LEGAL(0x03,stuff->partial,XkbAllMapComponentsMask);
143605b261ecSmrg
143705b261ecSmrg    xkb= dev->key->xkbInfo->desc;
14386747b715Smrg    memset(&rep, 0, sizeof(xkbGetMapReply));
143905b261ecSmrg    rep.type= X_Reply;
144005b261ecSmrg    rep.sequenceNumber= client->sequence;
144105b261ecSmrg    rep.length = (SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2;
144205b261ecSmrg    rep.deviceID = dev->id;
144305b261ecSmrg    rep.present = stuff->partial|stuff->full;
144405b261ecSmrg    rep.minKeyCode = xkb->min_key_code;
144505b261ecSmrg    rep.maxKeyCode = xkb->max_key_code;
144605b261ecSmrg    if ( stuff->full&XkbKeyTypesMask ) {
144705b261ecSmrg	rep.firstType = 0;
144805b261ecSmrg	rep.nTypes = xkb->map->num_types;
144905b261ecSmrg    }
145005b261ecSmrg    else if (stuff->partial&XkbKeyTypesMask) {
145105b261ecSmrg	if (((unsigned)stuff->firstType+stuff->nTypes)>xkb->map->num_types) {
145205b261ecSmrg	    client->errorValue = _XkbErrCode4(0x04,xkb->map->num_types,
145305b261ecSmrg					stuff->firstType,stuff->nTypes);
145405b261ecSmrg	    return BadValue;
145505b261ecSmrg	}
145605b261ecSmrg	rep.firstType = stuff->firstType;
145705b261ecSmrg	rep.nTypes = stuff->nTypes;
145805b261ecSmrg    }
145905b261ecSmrg    else rep.nTypes = 0;
146005b261ecSmrg    rep.totalTypes = xkb->map->num_types;
146105b261ecSmrg
146205b261ecSmrg    n= XkbNumKeys(xkb);
146305b261ecSmrg    if ( stuff->full&XkbKeySymsMask ) {
146405b261ecSmrg	rep.firstKeySym = xkb->min_key_code;
146505b261ecSmrg	rep.nKeySyms = n;
146605b261ecSmrg    }
146705b261ecSmrg    else if (stuff->partial&XkbKeySymsMask) {
146805b261ecSmrg	CHK_KEY_RANGE(0x05,stuff->firstKeySym,stuff->nKeySyms,xkb);
146905b261ecSmrg	rep.firstKeySym = stuff->firstKeySym;
147005b261ecSmrg	rep.nKeySyms = stuff->nKeySyms;
147105b261ecSmrg    }
147205b261ecSmrg    else rep.nKeySyms = 0;
147305b261ecSmrg    rep.totalSyms= 0;
147405b261ecSmrg
147505b261ecSmrg    if ( stuff->full&XkbKeyActionsMask ) {
147605b261ecSmrg	rep.firstKeyAct= xkb->min_key_code;
147705b261ecSmrg	rep.nKeyActs= n;
147805b261ecSmrg    }
147905b261ecSmrg    else if (stuff->partial&XkbKeyActionsMask) {
148005b261ecSmrg	CHK_KEY_RANGE(0x07,stuff->firstKeyAct,stuff->nKeyActs,xkb);
148105b261ecSmrg	rep.firstKeyAct= stuff->firstKeyAct;
148205b261ecSmrg	rep.nKeyActs= stuff->nKeyActs;
148305b261ecSmrg    }
148405b261ecSmrg    else rep.nKeyActs= 0;
148505b261ecSmrg    rep.totalActs= 0;
148605b261ecSmrg
148705b261ecSmrg    if ( stuff->full&XkbKeyBehaviorsMask ) {
148805b261ecSmrg	rep.firstKeyBehavior = xkb->min_key_code;
148905b261ecSmrg	rep.nKeyBehaviors = n;
149005b261ecSmrg    }
149105b261ecSmrg    else if (stuff->partial&XkbKeyBehaviorsMask) {
149205b261ecSmrg	CHK_KEY_RANGE(0x09,stuff->firstKeyBehavior,stuff->nKeyBehaviors,xkb);
149305b261ecSmrg	rep.firstKeyBehavior= stuff->firstKeyBehavior;
149405b261ecSmrg	rep.nKeyBehaviors= stuff->nKeyBehaviors;
149505b261ecSmrg    }
149605b261ecSmrg    else rep.nKeyBehaviors = 0;
149705b261ecSmrg    rep.totalKeyBehaviors= 0;
149805b261ecSmrg
149905b261ecSmrg    if (stuff->full&XkbVirtualModsMask)
150005b261ecSmrg	rep.virtualMods= ~0;
150105b261ecSmrg    else if (stuff->partial&XkbVirtualModsMask)
150205b261ecSmrg	rep.virtualMods= stuff->virtualMods;
150305b261ecSmrg
150405b261ecSmrg    if (stuff->full&XkbExplicitComponentsMask) {
150505b261ecSmrg	rep.firstKeyExplicit= xkb->min_key_code;
150605b261ecSmrg	rep.nKeyExplicit= n;
150705b261ecSmrg    }
150805b261ecSmrg    else if (stuff->partial&XkbExplicitComponentsMask) {
150905b261ecSmrg	CHK_KEY_RANGE(0x0B,stuff->firstKeyExplicit,stuff->nKeyExplicit,xkb);
151005b261ecSmrg	rep.firstKeyExplicit= stuff->firstKeyExplicit;
151105b261ecSmrg	rep.nKeyExplicit= stuff->nKeyExplicit;
151205b261ecSmrg    }
151305b261ecSmrg    else rep.nKeyExplicit = 0;
151405b261ecSmrg    rep.totalKeyExplicit=  0;
151505b261ecSmrg
151605b261ecSmrg    if (stuff->full&XkbModifierMapMask) {
151705b261ecSmrg	rep.firstModMapKey= xkb->min_key_code;
151805b261ecSmrg	rep.nModMapKeys= n;
151905b261ecSmrg    }
152005b261ecSmrg    else if (stuff->partial&XkbModifierMapMask) {
152105b261ecSmrg	CHK_KEY_RANGE(0x0D,stuff->firstModMapKey,stuff->nModMapKeys,xkb);
152205b261ecSmrg	rep.firstModMapKey= stuff->firstModMapKey;
152305b261ecSmrg	rep.nModMapKeys= stuff->nModMapKeys;
152405b261ecSmrg    }
152505b261ecSmrg    else rep.nModMapKeys = 0;
152605b261ecSmrg    rep.totalModMapKeys= 0;
152705b261ecSmrg
152805b261ecSmrg    if (stuff->full&XkbVirtualModMapMask) {
152905b261ecSmrg	rep.firstVModMapKey= xkb->min_key_code;
153005b261ecSmrg	rep.nVModMapKeys= n;
153105b261ecSmrg    }
153205b261ecSmrg    else if (stuff->partial&XkbVirtualModMapMask) {
153305b261ecSmrg	CHK_KEY_RANGE(0x0F,stuff->firstVModMapKey,stuff->nVModMapKeys,xkb);
153405b261ecSmrg	rep.firstVModMapKey= stuff->firstVModMapKey;
153505b261ecSmrg	rep.nVModMapKeys= stuff->nVModMapKeys;
153605b261ecSmrg    }
153705b261ecSmrg    else rep.nVModMapKeys = 0;
153805b261ecSmrg    rep.totalVModMapKeys= 0;
153905b261ecSmrg
154005b261ecSmrg    if ((status=XkbComputeGetMapReplySize(xkb,&rep))!=Success)
154105b261ecSmrg	return status;
154205b261ecSmrg    return XkbSendMap(client,xkb,&rep);
154305b261ecSmrg}
154405b261ecSmrg
154505b261ecSmrg/***====================================================================***/
154605b261ecSmrg
154705b261ecSmrgstatic int
154805b261ecSmrgCheckKeyTypes(	ClientPtr	client,
154905b261ecSmrg		XkbDescPtr	xkb,
155005b261ecSmrg		xkbSetMapReq *	req,
155105b261ecSmrg		xkbKeyTypeWireDesc **wireRtrn,
155205b261ecSmrg		int	 *	nMapsRtrn,
155305b261ecSmrg		CARD8 *		mapWidthRtrn)
155405b261ecSmrg{
155505b261ecSmrgunsigned		nMaps;
155605b261ecSmrgregister unsigned	i,n;
155705b261ecSmrgregister CARD8 *	map;
155805b261ecSmrgregister xkbKeyTypeWireDesc	*wire = *wireRtrn;
155905b261ecSmrg
156005b261ecSmrg    if (req->firstType>((unsigned)xkb->map->num_types)) {
156105b261ecSmrg	*nMapsRtrn = _XkbErrCode3(0x01,req->firstType,xkb->map->num_types);
156205b261ecSmrg	return 0;
156305b261ecSmrg    }
156405b261ecSmrg    if (req->flags&XkbSetMapResizeTypes) {
156505b261ecSmrg	nMaps = req->firstType+req->nTypes;
156605b261ecSmrg	if (nMaps<XkbNumRequiredTypes) {  /* canonical types must be there */
156705b261ecSmrg	    *nMapsRtrn= _XkbErrCode4(0x02,req->firstType,req->nTypes,4);
156805b261ecSmrg	    return 0;
156905b261ecSmrg	}
157005b261ecSmrg    }
157105b261ecSmrg    else if (req->present&XkbKeyTypesMask) {
157205b261ecSmrg	nMaps = xkb->map->num_types;
157305b261ecSmrg	if ((req->firstType+req->nTypes)>nMaps) {
157405b261ecSmrg	    *nMapsRtrn = req->firstType+req->nTypes;
157505b261ecSmrg	    return 0;
157605b261ecSmrg	}
157705b261ecSmrg    }
157805b261ecSmrg    else {
157905b261ecSmrg	*nMapsRtrn = xkb->map->num_types;
158005b261ecSmrg	for (i=0;i<xkb->map->num_types;i++) {
158105b261ecSmrg	    mapWidthRtrn[i] = xkb->map->types[i].num_levels;
158205b261ecSmrg	}
158305b261ecSmrg	return 1;
158405b261ecSmrg    }
158505b261ecSmrg
158605b261ecSmrg    for (i=0;i<req->firstType;i++) {
158705b261ecSmrg	mapWidthRtrn[i] = xkb->map->types[i].num_levels;
158805b261ecSmrg    }
158905b261ecSmrg    for (i=0;i<req->nTypes;i++) {
159005b261ecSmrg	unsigned	width;
159105b261ecSmrg	if (client->swapped) {
159205b261ecSmrg	    register int s;
159305b261ecSmrg	    swaps(&wire->virtualMods,s);
159405b261ecSmrg	}
159505b261ecSmrg	n= i+req->firstType;
159605b261ecSmrg	width= wire->numLevels;
159705b261ecSmrg	if (width<1) {
159805b261ecSmrg	    *nMapsRtrn= _XkbErrCode3(0x04,n,width);
159905b261ecSmrg	    return 0;
160005b261ecSmrg	}
160105b261ecSmrg	else if ((n==XkbOneLevelIndex)&&(width!=1)) { /* must be width 1 */
160205b261ecSmrg	    *nMapsRtrn= _XkbErrCode3(0x05,n,width);
160305b261ecSmrg	    return 0;
160405b261ecSmrg	}
160505b261ecSmrg	else if ((width!=2)&&
160605b261ecSmrg		 ((n==XkbTwoLevelIndex)||(n==XkbKeypadIndex)||
160705b261ecSmrg		  (n==XkbAlphabeticIndex))) {
160805b261ecSmrg	    /* TWO_LEVEL, ALPHABETIC and KEYPAD must be width 2 */
160905b261ecSmrg	    *nMapsRtrn= _XkbErrCode3(0x05,n,width);
161005b261ecSmrg	    return 0;
161105b261ecSmrg	}
161205b261ecSmrg	if (wire->nMapEntries>0) {
161305b261ecSmrg	    xkbKTSetMapEntryWireDesc *	mapWire;
161405b261ecSmrg	    xkbModsWireDesc *		preWire;
161505b261ecSmrg	    mapWire= (xkbKTSetMapEntryWireDesc *)&wire[1];
161605b261ecSmrg	    preWire= (xkbModsWireDesc *)&mapWire[wire->nMapEntries];
161705b261ecSmrg	    for (n=0;n<wire->nMapEntries;n++) {
161805b261ecSmrg		if (client->swapped) {
161905b261ecSmrg		    register int s;
162005b261ecSmrg		    swaps(&mapWire[n].virtualMods,s);
162105b261ecSmrg		}
162205b261ecSmrg		if (mapWire[n].realMods&(~wire->realMods)) {
162305b261ecSmrg		    *nMapsRtrn= _XkbErrCode4(0x06,n,mapWire[n].realMods,
162405b261ecSmrg						 wire->realMods);
162505b261ecSmrg		    return 0;
162605b261ecSmrg		}
162705b261ecSmrg		if (mapWire[n].virtualMods&(~wire->virtualMods)) {
162805b261ecSmrg		    *nMapsRtrn= _XkbErrCode3(0x07,n,mapWire[n].virtualMods);
162905b261ecSmrg		    return 0;
163005b261ecSmrg		}
163105b261ecSmrg		if (mapWire[n].level>=wire->numLevels) {
163205b261ecSmrg		    *nMapsRtrn= _XkbErrCode4(0x08,n,wire->numLevels,
163305b261ecSmrg						 mapWire[n].level);
163405b261ecSmrg		    return 0;
163505b261ecSmrg		}
163605b261ecSmrg		if (wire->preserve) {
163705b261ecSmrg		    if (client->swapped) {
163805b261ecSmrg			register int s;
163905b261ecSmrg			swaps(&preWire[n].virtualMods,s);
164005b261ecSmrg		    }
164105b261ecSmrg		    if (preWire[n].realMods&(~mapWire[n].realMods)) {
164205b261ecSmrg			*nMapsRtrn= _XkbErrCode4(0x09,n,preWire[n].realMods,
164305b261ecSmrg							mapWire[n].realMods);
164405b261ecSmrg			return 0;
164505b261ecSmrg		    }
164605b261ecSmrg		    if (preWire[n].virtualMods&(~mapWire[n].virtualMods)) {
164705b261ecSmrg			*nMapsRtrn=_XkbErrCode3(0x0a,n,preWire[n].virtualMods);
164805b261ecSmrg			return 0;
164905b261ecSmrg		    }
165005b261ecSmrg		}
165105b261ecSmrg	    }
165205b261ecSmrg	    if (wire->preserve)
165305b261ecSmrg		 map= (CARD8 *)&preWire[wire->nMapEntries];
165405b261ecSmrg	    else map= (CARD8 *)&mapWire[wire->nMapEntries];
165505b261ecSmrg	}
165605b261ecSmrg	else map= (CARD8 *)&wire[1];
165705b261ecSmrg	mapWidthRtrn[i+req->firstType] = wire->numLevels;
165805b261ecSmrg	wire= (xkbKeyTypeWireDesc *)map;
165905b261ecSmrg    }
166005b261ecSmrg    for (i=req->firstType+req->nTypes;i<nMaps;i++) {
166105b261ecSmrg	mapWidthRtrn[i] = xkb->map->types[i].num_levels;
166205b261ecSmrg    }
166305b261ecSmrg    *nMapsRtrn = nMaps;
166405b261ecSmrg    *wireRtrn = wire;
166505b261ecSmrg    return 1;
166605b261ecSmrg}
166705b261ecSmrg
166805b261ecSmrgstatic int
166905b261ecSmrgCheckKeySyms(	ClientPtr		client,
167005b261ecSmrg		XkbDescPtr		xkb,
167105b261ecSmrg		xkbSetMapReq *		req,
167205b261ecSmrg		int			nTypes,
167305b261ecSmrg		CARD8 *	 		mapWidths,
167405b261ecSmrg		CARD16 *	 	symsPerKey,
167505b261ecSmrg		xkbSymMapWireDesc **	wireRtrn,
167605b261ecSmrg		int *			errorRtrn)
167705b261ecSmrg{
167805b261ecSmrgregister unsigned	i;
167905b261ecSmrgXkbSymMapPtr		map;
168005b261ecSmrgxkbSymMapWireDesc*	wire = *wireRtrn;
168105b261ecSmrg
168205b261ecSmrg    if (!(XkbKeySymsMask&req->present))
168305b261ecSmrg	return 1;
168405b261ecSmrg    CHK_REQ_KEY_RANGE2(0x11,req->firstKeySym,req->nKeySyms,req,(*errorRtrn),0);
168505b261ecSmrg    for (i=0;i<req->nKeySyms;i++) {
168605b261ecSmrg	KeySym *pSyms;
168705b261ecSmrg	register unsigned nG;
168805b261ecSmrg	if (client->swapped) {
168905b261ecSmrg	    swaps(&wire->nSyms,nG);
169005b261ecSmrg	}
169105b261ecSmrg	nG = XkbNumGroups(wire->groupInfo);
169205b261ecSmrg	if (nG>XkbNumKbdGroups) {
169305b261ecSmrg	    *errorRtrn = _XkbErrCode3(0x14,i+req->firstKeySym,nG);
169405b261ecSmrg	    return 0;
169505b261ecSmrg	}
169605b261ecSmrg	if (nG>0) {
169705b261ecSmrg	    register int g,w;
169805b261ecSmrg	    for (g=w=0;g<nG;g++) {
169905b261ecSmrg		if (wire->ktIndex[g]>=(unsigned)nTypes) {
170005b261ecSmrg		    *errorRtrn= _XkbErrCode4(0x15,i+req->firstKeySym,g,
170105b261ecSmrg		    					   wire->ktIndex[g]);
170205b261ecSmrg		    return 0;
170305b261ecSmrg		}
170405b261ecSmrg		if (mapWidths[wire->ktIndex[g]]>w)
170505b261ecSmrg		    w= mapWidths[wire->ktIndex[g]];
170605b261ecSmrg	    }
170705b261ecSmrg	    if (wire->width!=w) {
170805b261ecSmrg		*errorRtrn= _XkbErrCode3(0x16,i+req->firstKeySym,wire->width);
170905b261ecSmrg		return 0;
171005b261ecSmrg	    }
171105b261ecSmrg	    w*= nG;
171205b261ecSmrg	    symsPerKey[i+req->firstKeySym] = w;
171305b261ecSmrg	    if (w!=wire->nSyms) {
171405b261ecSmrg		*errorRtrn=_XkbErrCode4(0x16,i+req->firstKeySym,wire->nSyms,w);
171505b261ecSmrg		return 0;
171605b261ecSmrg	    }
171705b261ecSmrg	}
171805b261ecSmrg	else if (wire->nSyms!=0) {
171905b261ecSmrg	    *errorRtrn = _XkbErrCode3(0x17,i+req->firstKeySym,wire->nSyms);
172005b261ecSmrg	    return 0;
172105b261ecSmrg	}
172205b261ecSmrg	pSyms = (KeySym *)&wire[1];
172305b261ecSmrg	wire = (xkbSymMapWireDesc *)&pSyms[wire->nSyms];
172405b261ecSmrg    }
172505b261ecSmrg
172605b261ecSmrg    map = &xkb->map->key_sym_map[i];
172705b261ecSmrg    for (;i<=(unsigned)xkb->max_key_code;i++,map++) {
172805b261ecSmrg	register int g,nG,w;
172905b261ecSmrg	nG= XkbKeyNumGroups(xkb,i);
173005b261ecSmrg	for (w=g=0;g<nG;g++)  {
173105b261ecSmrg	    if (map->kt_index[g]>=(unsigned)nTypes) {
173205b261ecSmrg		*errorRtrn = _XkbErrCode4(0x18,i,g,map->kt_index[g]);
173305b261ecSmrg		return 0;
173405b261ecSmrg	    }
173505b261ecSmrg	    if (mapWidths[map->kt_index[g]]>w)
173605b261ecSmrg		    w= mapWidths[map->kt_index[g]];
173705b261ecSmrg	}
173805b261ecSmrg	symsPerKey[i] = w*nG;
173905b261ecSmrg    }
174005b261ecSmrg    *wireRtrn = wire;
174105b261ecSmrg    return 1;
174205b261ecSmrg}
174305b261ecSmrg
174405b261ecSmrgstatic int
174505b261ecSmrgCheckKeyActions(	XkbDescPtr	xkb,
174605b261ecSmrg			xkbSetMapReq *	req,
174705b261ecSmrg			int		nTypes,
174805b261ecSmrg			CARD8 *		mapWidths,
174905b261ecSmrg			CARD16 *	symsPerKey,
175005b261ecSmrg			CARD8 **	wireRtrn,
175105b261ecSmrg			int *		nActsRtrn)
175205b261ecSmrg{
175305b261ecSmrgint			 nActs;
175405b261ecSmrgCARD8 *			 wire = *wireRtrn;
175505b261ecSmrgregister unsigned	 i;
175605b261ecSmrg
175705b261ecSmrg    if (!(XkbKeyActionsMask&req->present))
175805b261ecSmrg	return 1;
175905b261ecSmrg    CHK_REQ_KEY_RANGE2(0x21,req->firstKeyAct,req->nKeyActs,req,(*nActsRtrn),0);
176005b261ecSmrg    for (nActs=i=0;i<req->nKeyActs;i++) {
176105b261ecSmrg	if (wire[0]!=0) {
176205b261ecSmrg	    if (wire[0]==symsPerKey[i+req->firstKeyAct])
176305b261ecSmrg		nActs+= wire[0];
176405b261ecSmrg	    else {
176505b261ecSmrg		*nActsRtrn= _XkbErrCode3(0x23,i+req->firstKeyAct,wire[0]);
176605b261ecSmrg		return 0;
176705b261ecSmrg	    }
176805b261ecSmrg	}
176905b261ecSmrg	wire++;
177005b261ecSmrg    }
177105b261ecSmrg    if (req->nKeyActs%4)
177205b261ecSmrg	wire+= 4-(req->nKeyActs%4);
177305b261ecSmrg    *wireRtrn = (CARD8 *)(((XkbAnyAction *)wire)+nActs);
177405b261ecSmrg    *nActsRtrn = nActs;
177505b261ecSmrg    return 1;
177605b261ecSmrg}
177705b261ecSmrg
177805b261ecSmrgstatic int
177905b261ecSmrgCheckKeyBehaviors(	XkbDescPtr 		xkb,
178005b261ecSmrg			xkbSetMapReq *		req,
178105b261ecSmrg			xkbBehaviorWireDesc **	wireRtrn,
178205b261ecSmrg			int *			errorRtrn)
178305b261ecSmrg{
178405b261ecSmrgregister xkbBehaviorWireDesc *	wire = *wireRtrn;
178505b261ecSmrgregister XkbServerMapPtr	server = xkb->server;
178605b261ecSmrgregister unsigned	 	i;
178705b261ecSmrgunsigned			first,last;
178805b261ecSmrg
178905b261ecSmrg    if (((req->present&XkbKeyBehaviorsMask)==0)||(req->nKeyBehaviors<1)) {
179005b261ecSmrg	req->present&= ~XkbKeyBehaviorsMask;
179105b261ecSmrg	req->nKeyBehaviors= 0;
179205b261ecSmrg	return 1;
179305b261ecSmrg    }
179405b261ecSmrg    first= req->firstKeyBehavior;
179505b261ecSmrg    last=  req->firstKeyBehavior+req->nKeyBehaviors-1;
179605b261ecSmrg    if (first<req->minKeyCode) {
179705b261ecSmrg	*errorRtrn = _XkbErrCode3(0x31,first,req->minKeyCode);
179805b261ecSmrg	return 0;
179905b261ecSmrg    }
180005b261ecSmrg    if (last>req->maxKeyCode) {
180105b261ecSmrg	*errorRtrn = _XkbErrCode3(0x32,last,req->maxKeyCode);
180205b261ecSmrg	return 0;
180305b261ecSmrg    }
180405b261ecSmrg
180505b261ecSmrg    for (i=0;i<req->totalKeyBehaviors;i++,wire++) {
180605b261ecSmrg	if ((wire->key<first)||(wire->key>last)) {
180705b261ecSmrg	    *errorRtrn = _XkbErrCode4(0x33,first,last,wire->key);
180805b261ecSmrg	    return 0;
180905b261ecSmrg	}
181005b261ecSmrg	if ((wire->type&XkbKB_Permanent)&&
181105b261ecSmrg	    ((server->behaviors[wire->key].type!=wire->type)||
181205b261ecSmrg	     (server->behaviors[wire->key].data!=wire->data))) {
181305b261ecSmrg	    *errorRtrn = _XkbErrCode3(0x33,wire->key,wire->type);
181405b261ecSmrg	    return 0;
181505b261ecSmrg	}
181605b261ecSmrg	if ((wire->type==XkbKB_RadioGroup)&&
181705b261ecSmrg		((wire->data&(~XkbKB_RGAllowNone))>XkbMaxRadioGroups)) {
181805b261ecSmrg	    *errorRtrn= _XkbErrCode4(0x34,wire->key,wire->data,
181905b261ecSmrg							XkbMaxRadioGroups);
182005b261ecSmrg	    return 0;
182105b261ecSmrg	}
182205b261ecSmrg	if ((wire->type==XkbKB_Overlay1)||(wire->type==XkbKB_Overlay2)) {
182305b261ecSmrg	    CHK_KEY_RANGE2(0x35,wire->key,1,xkb,*errorRtrn,0);
182405b261ecSmrg	}
182505b261ecSmrg    }
182605b261ecSmrg    *wireRtrn = wire;
182705b261ecSmrg    return 1;
182805b261ecSmrg}
182905b261ecSmrg
183005b261ecSmrgstatic int
183105b261ecSmrgCheckVirtualMods(	XkbDescRec *	xkb,
183205b261ecSmrg			xkbSetMapReq *	req,
183305b261ecSmrg			CARD8 **	wireRtrn,
183405b261ecSmrg			int *		errorRtrn)
183505b261ecSmrg{
183605b261ecSmrgregister CARD8		*wire = *wireRtrn;
183705b261ecSmrgregister unsigned 	 i,nMods,bit;
183805b261ecSmrg
183905b261ecSmrg    if (((req->present&XkbVirtualModsMask)==0)||(req->virtualMods==0))
184005b261ecSmrg	return 1;
184105b261ecSmrg    for (i=nMods=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
184205b261ecSmrg	if (req->virtualMods&bit)
184305b261ecSmrg	    nMods++;
184405b261ecSmrg    }
184505b261ecSmrg    *wireRtrn= (wire+XkbPaddedSize(nMods));
184605b261ecSmrg    return 1;
184705b261ecSmrg}
184805b261ecSmrg
184905b261ecSmrgstatic int
185005b261ecSmrgCheckKeyExplicit(	XkbDescPtr	xkb,
185105b261ecSmrg			xkbSetMapReq *	req,
185205b261ecSmrg			CARD8 **	wireRtrn,
185305b261ecSmrg			int	*	errorRtrn)
185405b261ecSmrg{
185505b261ecSmrgregister CARD8 *	wire = *wireRtrn;
185605b261ecSmrgCARD8	*		start;
185705b261ecSmrgregister unsigned 	i;
185805b261ecSmrgint			first,last;
185905b261ecSmrg
186005b261ecSmrg    if (((req->present&XkbExplicitComponentsMask)==0)||(req->nKeyExplicit<1)) {
186105b261ecSmrg	req->present&= ~XkbExplicitComponentsMask;
186205b261ecSmrg	req->nKeyExplicit= 0;
186305b261ecSmrg	return 1;
186405b261ecSmrg    }
186505b261ecSmrg    first= req->firstKeyExplicit;
186605b261ecSmrg    last=  first+req->nKeyExplicit-1;
186705b261ecSmrg    if (first<req->minKeyCode) {
186805b261ecSmrg	*errorRtrn = _XkbErrCode3(0x51,first,req->minKeyCode);
186905b261ecSmrg	return 0;
187005b261ecSmrg    }
187105b261ecSmrg    if (last>req->maxKeyCode) {
187205b261ecSmrg	*errorRtrn = _XkbErrCode3(0x52,last,req->maxKeyCode);
187305b261ecSmrg	return 0;
187405b261ecSmrg    }
187505b261ecSmrg    start= wire;
187605b261ecSmrg    for (i=0;i<req->totalKeyExplicit;i++,wire+=2) {
187705b261ecSmrg	if ((wire[0]<first)||(wire[0]>last)) {
187805b261ecSmrg	    *errorRtrn = _XkbErrCode4(0x53,first,last,wire[0]);
187905b261ecSmrg	    return 0;
188005b261ecSmrg	}
188105b261ecSmrg	if (wire[1]&(~XkbAllExplicitMask)) {
188205b261ecSmrg	     *errorRtrn= _XkbErrCode3(0x52,~XkbAllExplicitMask,wire[1]);
188305b261ecSmrg	     return 0;
188405b261ecSmrg	}
188505b261ecSmrg    }
188605b261ecSmrg    wire+= XkbPaddedSize(wire-start)-(wire-start);
188705b261ecSmrg    *wireRtrn= wire;
188805b261ecSmrg    return 1;
188905b261ecSmrg}
189005b261ecSmrg
189105b261ecSmrgstatic int
189205b261ecSmrgCheckModifierMap(XkbDescPtr xkb,xkbSetMapReq *req,CARD8 **wireRtrn,int *errRtrn)
189305b261ecSmrg{
189405b261ecSmrgregister CARD8 *	wire = *wireRtrn;
189505b261ecSmrgCARD8	*		start;
189605b261ecSmrgregister unsigned 	i;
189705b261ecSmrgint			first,last;
189805b261ecSmrg
189905b261ecSmrg    if (((req->present&XkbModifierMapMask)==0)||(req->nModMapKeys<1)) {
190005b261ecSmrg	req->present&= ~XkbModifierMapMask;
190105b261ecSmrg	req->nModMapKeys= 0;
190205b261ecSmrg	return 1;
190305b261ecSmrg    }
190405b261ecSmrg    first= req->firstModMapKey;
190505b261ecSmrg    last=  first+req->nModMapKeys-1;
190605b261ecSmrg    if (first<req->minKeyCode) {
190705b261ecSmrg	*errRtrn = _XkbErrCode3(0x61,first,req->minKeyCode);
190805b261ecSmrg	return 0;
190905b261ecSmrg    }
191005b261ecSmrg    if (last>req->maxKeyCode) {
191105b261ecSmrg	*errRtrn = _XkbErrCode3(0x62,last,req->maxKeyCode);
191205b261ecSmrg	return 0;
191305b261ecSmrg    }
191405b261ecSmrg    start= wire;
191505b261ecSmrg    for (i=0;i<req->totalModMapKeys;i++,wire+=2) {
191605b261ecSmrg	if ((wire[0]<first)||(wire[0]>last)) {
191705b261ecSmrg	    *errRtrn = _XkbErrCode4(0x63,first,last,wire[0]);
191805b261ecSmrg	    return 0;
191905b261ecSmrg	}
192005b261ecSmrg    }
192105b261ecSmrg    wire+= XkbPaddedSize(wire-start)-(wire-start);
192205b261ecSmrg    *wireRtrn= wire;
192305b261ecSmrg    return 1;
192405b261ecSmrg}
192505b261ecSmrg
192605b261ecSmrgstatic int
192705b261ecSmrgCheckVirtualModMap(	XkbDescPtr xkb,
192805b261ecSmrg			xkbSetMapReq *req,
192905b261ecSmrg			xkbVModMapWireDesc **wireRtrn,
193005b261ecSmrg			int *errRtrn)
193105b261ecSmrg{
193205b261ecSmrgregister xkbVModMapWireDesc *	wire = *wireRtrn;
193305b261ecSmrgregister unsigned 		i;
193405b261ecSmrgint				first,last;
193505b261ecSmrg
193605b261ecSmrg    if (((req->present&XkbVirtualModMapMask)==0)||(req->nVModMapKeys<1)) {
193705b261ecSmrg	req->present&= ~XkbVirtualModMapMask;
193805b261ecSmrg	req->nVModMapKeys= 0;
193905b261ecSmrg	return 1;
194005b261ecSmrg    }
194105b261ecSmrg    first= req->firstVModMapKey;
194205b261ecSmrg    last=  first+req->nVModMapKeys-1;
194305b261ecSmrg    if (first<req->minKeyCode) {
194405b261ecSmrg	*errRtrn = _XkbErrCode3(0x71,first,req->minKeyCode);
194505b261ecSmrg	return 0;
194605b261ecSmrg    }
194705b261ecSmrg    if (last>req->maxKeyCode) {
194805b261ecSmrg	*errRtrn = _XkbErrCode3(0x72,last,req->maxKeyCode);
194905b261ecSmrg	return 0;
195005b261ecSmrg    }
195105b261ecSmrg    for (i=0;i<req->totalVModMapKeys;i++,wire++) {
195205b261ecSmrg	if ((wire->key<first)||(wire->key>last)) {
195305b261ecSmrg	    *errRtrn = _XkbErrCode4(0x73,first,last,wire->key);
195405b261ecSmrg	    return 0;
195505b261ecSmrg	}
195605b261ecSmrg    }
195705b261ecSmrg    *wireRtrn= wire;
195805b261ecSmrg    return 1;
195905b261ecSmrg}
196005b261ecSmrg
196105b261ecSmrgstatic char *
196205b261ecSmrgSetKeyTypes(	XkbDescPtr		xkb,
196305b261ecSmrg		xkbSetMapReq *		req,
196405b261ecSmrg		xkbKeyTypeWireDesc *	wire,
196505b261ecSmrg		XkbChangesPtr		changes)
196605b261ecSmrg{
196705b261ecSmrgregister unsigned	i;
196805b261ecSmrgunsigned		first,last;
196905b261ecSmrgCARD8			*map;
197005b261ecSmrg
197105b261ecSmrg    if ((unsigned)(req->firstType+req->nTypes)>xkb->map->size_types) {
197205b261ecSmrg	i= req->firstType+req->nTypes;
197305b261ecSmrg	if (XkbAllocClientMap(xkb,XkbKeyTypesMask,i)!=Success) {
197405b261ecSmrg	    return NULL;
197505b261ecSmrg	}
197605b261ecSmrg    }
197705b261ecSmrg    if ((unsigned)(req->firstType+req->nTypes)>xkb->map->num_types)
197805b261ecSmrg	xkb->map->num_types= req->firstType+req->nTypes;
197905b261ecSmrg
198005b261ecSmrg    for (i=0;i<req->nTypes;i++) {
198105b261ecSmrg	XkbKeyTypePtr		pOld;
198205b261ecSmrg	register unsigned 	n;
198305b261ecSmrg
198405b261ecSmrg	if (XkbResizeKeyType(xkb,i+req->firstType,wire->nMapEntries,
198505b261ecSmrg				wire->preserve,wire->numLevels)!=Success) {
198605b261ecSmrg	    return NULL;
198705b261ecSmrg	}
198805b261ecSmrg	pOld = &xkb->map->types[i+req->firstType];
198905b261ecSmrg	map = (CARD8 *)&wire[1];
199005b261ecSmrg
199105b261ecSmrg	pOld->mods.real_mods = wire->realMods;
199205b261ecSmrg	pOld->mods.vmods= wire->virtualMods;
199305b261ecSmrg	pOld->num_levels = wire->numLevels;
199405b261ecSmrg	pOld->map_count= wire->nMapEntries;
199505b261ecSmrg
199605b261ecSmrg	pOld->mods.mask= pOld->mods.real_mods|
199705b261ecSmrg					XkbMaskForVMask(xkb,pOld->mods.vmods);
199805b261ecSmrg
199905b261ecSmrg	if (wire->nMapEntries) {
200005b261ecSmrg	    xkbKTSetMapEntryWireDesc *mapWire;
200105b261ecSmrg	    xkbModsWireDesc *preWire;
200205b261ecSmrg	    unsigned tmp;
200305b261ecSmrg	    mapWire= (xkbKTSetMapEntryWireDesc *)map;
200405b261ecSmrg	    preWire= (xkbModsWireDesc *)&mapWire[wire->nMapEntries];
200505b261ecSmrg	    for (n=0;n<wire->nMapEntries;n++) {
200605b261ecSmrg		pOld->map[n].active= 1;
200705b261ecSmrg		pOld->map[n].mods.mask= mapWire[n].realMods;
200805b261ecSmrg		pOld->map[n].mods.real_mods= mapWire[n].realMods;
200905b261ecSmrg		pOld->map[n].mods.vmods= mapWire[n].virtualMods;
201005b261ecSmrg		pOld->map[n].level= mapWire[n].level;
201105b261ecSmrg		if (mapWire[n].virtualMods!=0) {
201205b261ecSmrg		    tmp= XkbMaskForVMask(xkb,mapWire[n].virtualMods);
201305b261ecSmrg		    pOld->map[n].active= (tmp!=0);
201405b261ecSmrg		    pOld->map[n].mods.mask|= tmp;
201505b261ecSmrg		}
201605b261ecSmrg		if (wire->preserve) {
201705b261ecSmrg		    pOld->preserve[n].real_mods= preWire[n].realMods;
201805b261ecSmrg		    pOld->preserve[n].vmods= preWire[n].virtualMods;
201905b261ecSmrg		    tmp= XkbMaskForVMask(xkb,preWire[n].virtualMods);
202005b261ecSmrg		    pOld->preserve[n].mask= preWire[n].realMods|tmp;
202105b261ecSmrg		}
202205b261ecSmrg	    }
202305b261ecSmrg	    if (wire->preserve)
202405b261ecSmrg		 map= (CARD8 *)&preWire[wire->nMapEntries];
202505b261ecSmrg	    else map= (CARD8 *)&mapWire[wire->nMapEntries];
202605b261ecSmrg	}
202705b261ecSmrg	else map= (CARD8 *)&wire[1];
202805b261ecSmrg	wire = (xkbKeyTypeWireDesc *)map;
202905b261ecSmrg    }
203005b261ecSmrg    first= req->firstType;
203105b261ecSmrg    last= first+req->nTypes-1; /* last changed type */
203205b261ecSmrg    if (changes->map.changed&XkbKeyTypesMask) {
203305b261ecSmrg	int oldLast;
203405b261ecSmrg	oldLast= changes->map.first_type+changes->map.num_types-1;
203505b261ecSmrg	if (changes->map.first_type<first)
203605b261ecSmrg	    first= changes->map.first_type;
203705b261ecSmrg	if (oldLast>last)
203805b261ecSmrg	    last= oldLast;
203905b261ecSmrg    }
204005b261ecSmrg    changes->map.changed|= XkbKeyTypesMask;
204105b261ecSmrg    changes->map.first_type = first;
204205b261ecSmrg    changes->map.num_types = (last-first)+1;
204305b261ecSmrg    return (char *)wire;
204405b261ecSmrg}
204505b261ecSmrg
204605b261ecSmrgstatic char *
204705b261ecSmrgSetKeySyms(	ClientPtr		client,
204805b261ecSmrg		XkbDescPtr		xkb,
204905b261ecSmrg		xkbSetMapReq *		req,
205005b261ecSmrg		xkbSymMapWireDesc *	wire,
205105b261ecSmrg		XkbChangesPtr 		changes,
205205b261ecSmrg		DeviceIntPtr		dev)
205305b261ecSmrg{
205405b261ecSmrgregister unsigned 	i,s;
205505b261ecSmrgXkbSymMapPtr		oldMap;
205605b261ecSmrgKeySym *		newSyms;
205705b261ecSmrgKeySym *		pSyms;
205805b261ecSmrgunsigned		first,last;
205905b261ecSmrg
206005b261ecSmrg    oldMap = &xkb->map->key_sym_map[req->firstKeySym];
206105b261ecSmrg    for (i=0;i<req->nKeySyms;i++,oldMap++) {
206205b261ecSmrg	pSyms = (KeySym *)&wire[1];
206305b261ecSmrg	if (wire->nSyms>0) {
206405b261ecSmrg	    newSyms = XkbResizeKeySyms(xkb,i+req->firstKeySym,wire->nSyms);
206505b261ecSmrg	    for (s=0;s<wire->nSyms;s++) {
206605b261ecSmrg		newSyms[s]= pSyms[s];
206705b261ecSmrg	    }
206805b261ecSmrg	    if (client->swapped) {
206905b261ecSmrg		int n;
207005b261ecSmrg		for (s=0;s<wire->nSyms;s++) {
207105b261ecSmrg		    swapl(&newSyms[s],n);
207205b261ecSmrg		}
207305b261ecSmrg	    }
207405b261ecSmrg	}
207505b261ecSmrg	oldMap->kt_index[0] = wire->ktIndex[0];
207605b261ecSmrg	oldMap->kt_index[1] = wire->ktIndex[1];
207705b261ecSmrg	oldMap->kt_index[2] = wire->ktIndex[2];
207805b261ecSmrg	oldMap->kt_index[3] = wire->ktIndex[3];
207905b261ecSmrg	oldMap->group_info = wire->groupInfo;
208005b261ecSmrg	oldMap->width = wire->width;
208105b261ecSmrg	wire= (xkbSymMapWireDesc *)&pSyms[wire->nSyms];
208205b261ecSmrg    }
208305b261ecSmrg    first= req->firstKeySym;
208405b261ecSmrg    last= first+req->nKeySyms-1;
208505b261ecSmrg    if (changes->map.changed&XkbKeySymsMask) {
208605b261ecSmrg	int oldLast= (changes->map.first_key_sym+changes->map.num_key_syms-1);
208705b261ecSmrg	if (changes->map.first_key_sym<first)
208805b261ecSmrg	    first= changes->map.first_key_sym;
208905b261ecSmrg	if (oldLast>last)
209005b261ecSmrg	    last= oldLast;
209105b261ecSmrg    }
209205b261ecSmrg    changes->map.changed|= XkbKeySymsMask;
209305b261ecSmrg    changes->map.first_key_sym = first;
209405b261ecSmrg    changes->map.num_key_syms = (last-first+1);
209505b261ecSmrg
209605b261ecSmrg    s= 0;
209705b261ecSmrg    for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
209805b261ecSmrg	if (XkbKeyNumGroups(xkb,i)>s)
209905b261ecSmrg	    s= XkbKeyNumGroups(xkb,i);
210005b261ecSmrg    }
210105b261ecSmrg    if (s!=xkb->ctrls->num_groups) {
210205b261ecSmrg	xkbControlsNotify	cn;
210305b261ecSmrg	XkbControlsRec		old;
210405b261ecSmrg	cn.keycode= 0;
210505b261ecSmrg	cn.eventType= 0;
210605b261ecSmrg	cn.requestMajor= XkbReqCode;
210705b261ecSmrg	cn.requestMinor= X_kbSetMap;
210805b261ecSmrg	old= *xkb->ctrls;
210905b261ecSmrg	xkb->ctrls->num_groups= s;
21106747b715Smrg	if (XkbComputeControlsNotify(dev,&old,xkb->ctrls,&cn,FALSE))
211105b261ecSmrg	    XkbSendControlsNotify(dev,&cn);
211205b261ecSmrg    }
211305b261ecSmrg    return (char *)wire;
211405b261ecSmrg}
211505b261ecSmrg
211605b261ecSmrgstatic char *
211705b261ecSmrgSetKeyActions(	XkbDescPtr	xkb,
211805b261ecSmrg		xkbSetMapReq *	req,
211905b261ecSmrg		CARD8 *		wire,
212005b261ecSmrg		XkbChangesPtr	changes)
212105b261ecSmrg{
212205b261ecSmrgregister unsigned	i,first,last;
212305b261ecSmrgCARD8 *			nActs = wire;
212405b261ecSmrgXkbAction *		newActs;
212505b261ecSmrg
212605b261ecSmrg    wire+= XkbPaddedSize(req->nKeyActs);
212705b261ecSmrg    for (i=0;i<req->nKeyActs;i++) {
212805b261ecSmrg	if (nActs[i]==0)
212905b261ecSmrg	    xkb->server->key_acts[i+req->firstKeyAct]= 0;
213005b261ecSmrg	else {
213105b261ecSmrg	    newActs= XkbResizeKeyActions(xkb,i+req->firstKeyAct,nActs[i]);
213205b261ecSmrg	    memcpy((char *)newActs,(char *)wire,
213305b261ecSmrg					nActs[i]*SIZEOF(xkbActionWireDesc));
213405b261ecSmrg	    wire+= nActs[i]*SIZEOF(xkbActionWireDesc);
213505b261ecSmrg	}
213605b261ecSmrg    }
213705b261ecSmrg    first= req->firstKeyAct;
213805b261ecSmrg    last= (first+req->nKeyActs-1);
213905b261ecSmrg    if (changes->map.changed&XkbKeyActionsMask) {
214005b261ecSmrg	int oldLast;
214105b261ecSmrg	oldLast= changes->map.first_key_act+changes->map.num_key_acts-1;
214205b261ecSmrg	if (changes->map.first_key_act<first)
214305b261ecSmrg	    first= changes->map.first_key_act;
214405b261ecSmrg	if (oldLast>last)
214505b261ecSmrg	    last= oldLast;
214605b261ecSmrg    }
214705b261ecSmrg    changes->map.changed|= XkbKeyActionsMask;
214805b261ecSmrg    changes->map.first_key_act= first;
214905b261ecSmrg    changes->map.num_key_acts= (last-first+1);
215005b261ecSmrg    return (char *)wire;
215105b261ecSmrg}
215205b261ecSmrg
215305b261ecSmrgstatic char *
215405b261ecSmrgSetKeyBehaviors(	XkbSrvInfoPtr	 xkbi,
215505b261ecSmrg    			xkbSetMapReq	*req,
215605b261ecSmrg    			xkbBehaviorWireDesc	*wire,
215705b261ecSmrg    			XkbChangesPtr	 changes)
215805b261ecSmrg{
215905b261ecSmrgregister unsigned i;
216005b261ecSmrgint maxRG = -1;
216105b261ecSmrgXkbDescPtr       xkb = xkbi->desc;
216205b261ecSmrgXkbServerMapPtr	 server = xkb->server;
216305b261ecSmrgunsigned	 first,last;
216405b261ecSmrg
216505b261ecSmrg    first= req->firstKeyBehavior;
216605b261ecSmrg    last= req->firstKeyBehavior+req->nKeyBehaviors-1;
21676747b715Smrg    memset(&server->behaviors[first], 0, req->nKeyBehaviors*sizeof(XkbBehavior));
216805b261ecSmrg    for (i=0;i<req->totalKeyBehaviors;i++) {
216905b261ecSmrg	if ((server->behaviors[wire->key].type&XkbKB_Permanent)==0) {
217005b261ecSmrg	    server->behaviors[wire->key].type= wire->type;
217105b261ecSmrg	    server->behaviors[wire->key].data= wire->data;
217205b261ecSmrg	    if ((wire->type==XkbKB_RadioGroup)&&(((int)wire->data)>maxRG))
217305b261ecSmrg		maxRG= wire->data + 1;
217405b261ecSmrg	}
217505b261ecSmrg	wire++;
217605b261ecSmrg    }
217705b261ecSmrg
217805b261ecSmrg    if (maxRG>(int)xkbi->nRadioGroups) {
217905b261ecSmrg        int sz = maxRG*sizeof(XkbRadioGroupRec);
218005b261ecSmrg        if (xkbi->radioGroups)
21816747b715Smrg             xkbi->radioGroups= realloc(xkbi->radioGroups,sz);
21826747b715Smrg        else xkbi->radioGroups= calloc(1, sz);
218305b261ecSmrg        if (xkbi->radioGroups) {
218405b261ecSmrg             if (xkbi->nRadioGroups)
21856747b715Smrg                 memset(&xkbi->radioGroups[xkbi->nRadioGroups], 0,
218605b261ecSmrg                        (maxRG-xkbi->nRadioGroups)*sizeof(XkbRadioGroupRec));
218705b261ecSmrg             xkbi->nRadioGroups= maxRG;
218805b261ecSmrg        }
218905b261ecSmrg        else xkbi->nRadioGroups= 0;
219005b261ecSmrg        /* should compute members here */
219105b261ecSmrg    }
219205b261ecSmrg    if (changes->map.changed&XkbKeyBehaviorsMask) {
219305b261ecSmrg	unsigned oldLast;
219405b261ecSmrg	oldLast= changes->map.first_key_behavior+
219505b261ecSmrg					changes->map.num_key_behaviors-1;
219605b261ecSmrg        if (changes->map.first_key_behavior<req->firstKeyBehavior)
219705b261ecSmrg             first= changes->map.first_key_behavior;
219805b261ecSmrg        if (oldLast>last)
219905b261ecSmrg            last= oldLast;
220005b261ecSmrg    }
220105b261ecSmrg    changes->map.changed|= XkbKeyBehaviorsMask;
220205b261ecSmrg    changes->map.first_key_behavior = first;
220305b261ecSmrg    changes->map.num_key_behaviors = (last-first+1);
220405b261ecSmrg    return (char *)wire;
220505b261ecSmrg}
220605b261ecSmrg
220705b261ecSmrgstatic char *
220805b261ecSmrgSetVirtualMods(XkbSrvInfoPtr xkbi,xkbSetMapReq *req,CARD8 *wire,
220905b261ecSmrg						XkbChangesPtr changes)
221005b261ecSmrg{
221105b261ecSmrgregister int 		i,bit,nMods;
221205b261ecSmrgXkbServerMapPtr		srv = xkbi->desc->server;
221305b261ecSmrg
221405b261ecSmrg    if (((req->present&XkbVirtualModsMask)==0)||(req->virtualMods==0))
221505b261ecSmrg	return (char *)wire;
221605b261ecSmrg    for (i=nMods=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
221705b261ecSmrg	if (req->virtualMods&bit) {
221805b261ecSmrg	    if (srv->vmods[i]!=wire[nMods]) {
221905b261ecSmrg		changes->map.changed|= XkbVirtualModsMask;
222005b261ecSmrg		changes->map.vmods|= bit;
222105b261ecSmrg		srv->vmods[i]= wire[nMods];
222205b261ecSmrg	    }
222305b261ecSmrg	    nMods++;
222405b261ecSmrg	}
222505b261ecSmrg    }
222605b261ecSmrg    return (char *)(wire+XkbPaddedSize(nMods));
222705b261ecSmrg}
222805b261ecSmrg
222905b261ecSmrgstatic char *
223005b261ecSmrgSetKeyExplicit(XkbSrvInfoPtr xkbi,xkbSetMapReq *req,CARD8 *wire,
223105b261ecSmrg							XkbChangesPtr changes)
223205b261ecSmrg{
223305b261ecSmrgregister unsigned	i,first,last;
223405b261ecSmrgXkbServerMapPtr		xkb = xkbi->desc->server;
223505b261ecSmrgCARD8 *			start;
223605b261ecSmrg
223705b261ecSmrg    start= wire;
223805b261ecSmrg    first= req->firstKeyExplicit;
223905b261ecSmrg    last=  req->firstKeyExplicit+req->nKeyExplicit-1;
22406747b715Smrg    memset(&xkb->explicit[first], 0, req->nKeyExplicit);
224105b261ecSmrg    for (i=0;i<req->totalKeyExplicit;i++,wire+= 2) {
224205b261ecSmrg	xkb->explicit[wire[0]]= wire[1];
224305b261ecSmrg    }
224405b261ecSmrg    if (first>0) {
224505b261ecSmrg	if (changes->map.changed&XkbExplicitComponentsMask) {
224605b261ecSmrg	    int oldLast;
224705b261ecSmrg	    oldLast= changes->map.first_key_explicit+
224805b261ecSmrg					changes->map.num_key_explicit-1;
224905b261ecSmrg	    if (changes->map.first_key_explicit<first)
225005b261ecSmrg		first= changes->map.first_key_explicit;
225105b261ecSmrg	    if (oldLast>last)
225205b261ecSmrg		last= oldLast;
225305b261ecSmrg	}
225405b261ecSmrg	changes->map.first_key_explicit= first;
225505b261ecSmrg	changes->map.num_key_explicit= (last-first)+1;
225605b261ecSmrg    }
225705b261ecSmrg    wire+= XkbPaddedSize(wire-start)-(wire-start);
225805b261ecSmrg    return (char *)wire;
225905b261ecSmrg}
226005b261ecSmrg
226105b261ecSmrgstatic char *
226205b261ecSmrgSetModifierMap(	XkbSrvInfoPtr	xkbi,
226305b261ecSmrg		xkbSetMapReq *	req,
226405b261ecSmrg		CARD8 *		wire,
226505b261ecSmrg		XkbChangesPtr	changes)
226605b261ecSmrg{
226705b261ecSmrgregister unsigned	i,first,last;
226805b261ecSmrgXkbClientMapPtr		xkb = xkbi->desc->map;
226905b261ecSmrgCARD8 *			start;
227005b261ecSmrg
227105b261ecSmrg    start= wire;
227205b261ecSmrg    first= req->firstModMapKey;
227305b261ecSmrg    last=  req->firstModMapKey+req->nModMapKeys-1;
22746747b715Smrg    memset(&xkb->modmap[first], 0, req->nModMapKeys);
227505b261ecSmrg    for (i=0;i<req->totalModMapKeys;i++,wire+= 2) {
227605b261ecSmrg	xkb->modmap[wire[0]]= wire[1];
227705b261ecSmrg    }
227805b261ecSmrg    if (first>0) {
227905b261ecSmrg	if (changes->map.changed&XkbModifierMapMask) {
228005b261ecSmrg	    int oldLast;
228105b261ecSmrg	    oldLast= changes->map.first_modmap_key+
228205b261ecSmrg						changes->map.num_modmap_keys-1;
228305b261ecSmrg	    if (changes->map.first_modmap_key<first)
228405b261ecSmrg		first= changes->map.first_modmap_key;
228505b261ecSmrg	    if (oldLast>last)
228605b261ecSmrg		last= oldLast;
228705b261ecSmrg	}
228805b261ecSmrg	changes->map.first_modmap_key= first;
228905b261ecSmrg	changes->map.num_modmap_keys= (last-first)+1;
229005b261ecSmrg    }
229105b261ecSmrg    wire+= XkbPaddedSize(wire-start)-(wire-start);
229205b261ecSmrg    return (char *)wire;
229305b261ecSmrg}
229405b261ecSmrg
229505b261ecSmrgstatic char *
229605b261ecSmrgSetVirtualModMap(	XkbSrvInfoPtr		xkbi,
229705b261ecSmrg			xkbSetMapReq *		req,
229805b261ecSmrg			xkbVModMapWireDesc *	wire,
229905b261ecSmrg			XkbChangesPtr 		changes)
230005b261ecSmrg{
230105b261ecSmrgregister unsigned	i,first,last;
230205b261ecSmrgXkbServerMapPtr		srv = xkbi->desc->server;
230305b261ecSmrg
230405b261ecSmrg    first= req->firstVModMapKey;
230505b261ecSmrg    last=  req->firstVModMapKey+req->nVModMapKeys-1;
23066747b715Smrg    memset(&srv->vmodmap[first], 0, req->nVModMapKeys*sizeof(unsigned short));
230705b261ecSmrg    for (i=0;i<req->totalVModMapKeys;i++,wire++) {
230805b261ecSmrg	srv->vmodmap[wire->key]= wire->vmods;
230905b261ecSmrg    }
231005b261ecSmrg    if (first>0) {
231105b261ecSmrg	if (changes->map.changed&XkbVirtualModMapMask) {
231205b261ecSmrg	    int oldLast;
231305b261ecSmrg	    oldLast= changes->map.first_vmodmap_key+
231405b261ecSmrg					changes->map.num_vmodmap_keys-1;
231505b261ecSmrg	    if (changes->map.first_vmodmap_key<first)
231605b261ecSmrg		first= changes->map.first_vmodmap_key;
231705b261ecSmrg	    if (oldLast>last)
231805b261ecSmrg		last= oldLast;
231905b261ecSmrg	}
232005b261ecSmrg	changes->map.first_vmodmap_key= first;
232105b261ecSmrg	changes->map.num_vmodmap_keys= (last-first)+1;
232205b261ecSmrg    }
232305b261ecSmrg    return (char *)wire;
232405b261ecSmrg}
232505b261ecSmrg
23264642e01fSmrg/**
23274642e01fSmrg * Check if the given request can be applied to the given device but don't
23284642e01fSmrg * actually do anything..
23294642e01fSmrg */
23304642e01fSmrgstatic int
23314642e01fSmrg_XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq *req, char* values)
233205b261ecSmrg{
23334642e01fSmrg    XkbSrvInfoPtr       xkbi;
23344642e01fSmrg    XkbDescPtr          xkb;
23354642e01fSmrg    int                 error;
23364642e01fSmrg    int                 nTypes = 0, nActions;
23378223e2f2Smrg    CARD8               mapWidths[XkbMaxLegalKeyCode + 1] = {0};
23388223e2f2Smrg    CARD16              symsPerKey[XkbMaxLegalKeyCode + 1] = {0};
23399ace9065Smrg    XkbSymMapPtr        map;
23409ace9065Smrg    int                 i;
234105b261ecSmrg
234205b261ecSmrg    xkbi= dev->key->xkbInfo;
234305b261ecSmrg    xkb = xkbi->desc;
234405b261ecSmrg
23454642e01fSmrg    if ((xkb->min_key_code != req->minKeyCode)||
23464642e01fSmrg        (xkb->max_key_code != req->maxKeyCode)) {
234705b261ecSmrg	if (client->vMajor!=1) { /* pre 1.0 versions of Xlib have a bug */
23484642e01fSmrg	    req->minKeyCode= xkb->min_key_code;
23494642e01fSmrg	    req->maxKeyCode= xkb->max_key_code;
235005b261ecSmrg	}
235105b261ecSmrg	else {
23524642e01fSmrg	    if (!XkbIsLegalKeycode(req->minKeyCode)) {
23534642e01fSmrg		client->errorValue = _XkbErrCode3(2, req->minKeyCode, req->maxKeyCode);
235405b261ecSmrg		return BadValue;
235505b261ecSmrg	    }
23564642e01fSmrg	    if (req->minKeyCode > req->maxKeyCode) {
23574642e01fSmrg		client->errorValue = _XkbErrCode3(3, req->minKeyCode, req->maxKeyCode);
235805b261ecSmrg		return BadMatch;
235905b261ecSmrg	    }
236005b261ecSmrg	}
236105b261ecSmrg    }
236205b261ecSmrg
23634642e01fSmrg    if ((req->present & XkbKeyTypesMask) &&
23644642e01fSmrg	(!CheckKeyTypes(client,xkb,req,(xkbKeyTypeWireDesc **)&values,
236505b261ecSmrg						&nTypes,mapWidths))) {
236605b261ecSmrg	client->errorValue = nTypes;
236705b261ecSmrg	return BadValue;
236805b261ecSmrg    }
23699ace9065Smrg
23709ace9065Smrg    /* symsPerKey/mapWidths must be filled regardless of client-side flags */
23719ace9065Smrg    map = &xkb->map->key_sym_map[xkb->min_key_code];
23729ace9065Smrg    for (i=xkb->min_key_code;i<xkb->max_key_code;i++,map++) {
23739ace9065Smrg	register int g,ng,w;
23749ace9065Smrg	ng= XkbNumGroups(map->group_info);
23759ace9065Smrg	for (w=g=0;g<ng;g++) {
23769ace9065Smrg	    if (map->kt_index[g]>=(unsigned)nTypes) {
23779ace9065Smrg		client->errorValue = _XkbErrCode4(0x13,i,g,map->kt_index[g]);
23789ace9065Smrg		return 0;
23799ace9065Smrg	    }
23809ace9065Smrg	    if (mapWidths[map->kt_index[g]]>w)
23819ace9065Smrg		w= mapWidths[map->kt_index[g]];
23829ace9065Smrg	}
23839ace9065Smrg	symsPerKey[i] = w*ng;
23849ace9065Smrg    }
23859ace9065Smrg
23864642e01fSmrg    if ((req->present & XkbKeySymsMask) &&
23874642e01fSmrg	(!CheckKeySyms(client,xkb,req,nTypes,mapWidths,symsPerKey,
23884642e01fSmrg					(xkbSymMapWireDesc **)&values,&error))) {
238905b261ecSmrg	client->errorValue = error;
239005b261ecSmrg	return BadValue;
239105b261ecSmrg    }
239205b261ecSmrg
23934642e01fSmrg    if ((req->present & XkbKeyActionsMask) &&
23944642e01fSmrg	(!CheckKeyActions(xkb,req,nTypes,mapWidths,symsPerKey,
23954642e01fSmrg						(CARD8 **)&values,&nActions))) {
239605b261ecSmrg	client->errorValue = nActions;
239705b261ecSmrg	return BadValue;
239805b261ecSmrg    }
239905b261ecSmrg
24004642e01fSmrg    if ((req->present & XkbKeyBehaviorsMask) &&
24014642e01fSmrg	(!CheckKeyBehaviors(xkb,req,(xkbBehaviorWireDesc**)&values,&error))) {
240205b261ecSmrg	client->errorValue = error;
240305b261ecSmrg	return BadValue;
240405b261ecSmrg    }
240505b261ecSmrg
24064642e01fSmrg    if ((req->present & XkbVirtualModsMask) &&
24074642e01fSmrg	(!CheckVirtualMods(xkb,req,(CARD8 **)&values,&error))) {
240805b261ecSmrg	client->errorValue= error;
240905b261ecSmrg	return BadValue;
241005b261ecSmrg    }
24114642e01fSmrg    if ((req->present&XkbExplicitComponentsMask) &&
24124642e01fSmrg	(!CheckKeyExplicit(xkb,req,(CARD8 **)&values,&error))) {
241305b261ecSmrg	client->errorValue= error;
241405b261ecSmrg	return BadValue;
241505b261ecSmrg    }
24164642e01fSmrg    if ((req->present&XkbModifierMapMask) &&
24174642e01fSmrg	(!CheckModifierMap(xkb,req,(CARD8 **)&values,&error))) {
241805b261ecSmrg	client->errorValue= error;
241905b261ecSmrg	return BadValue;
242005b261ecSmrg    }
24214642e01fSmrg    if ((req->present&XkbVirtualModMapMask) &&
24224642e01fSmrg	(!CheckVirtualModMap(xkb,req,(xkbVModMapWireDesc **)&values,&error))) {
242305b261ecSmrg	client->errorValue= error;
242405b261ecSmrg	return BadValue;
242505b261ecSmrg    }
24264642e01fSmrg
24274642e01fSmrg    if (((values-((char *)req))/4)!= req->length) {
24284642e01fSmrg	ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after check)\n");
24294642e01fSmrg	client->errorValue = values-((char *)&req[1]);
243005b261ecSmrg	return BadLength;
243105b261ecSmrg    }
24324642e01fSmrg
24334642e01fSmrg    return Success;
24344642e01fSmrg}
24354642e01fSmrg
24364642e01fSmrg/**
24374642e01fSmrg * Apply the given request on the given device.
24384642e01fSmrg */
24394642e01fSmrgstatic int
24404642e01fSmrg_XkbSetMap(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq *req, char *values)
24414642e01fSmrg{
24424642e01fSmrg    XkbEventCauseRec	cause;
24434642e01fSmrg    XkbChangesRec	change;
24444642e01fSmrg    Bool		sentNKN;
24454642e01fSmrg    XkbSrvInfoPtr       xkbi;
24464642e01fSmrg    XkbDescPtr          xkb;
24474642e01fSmrg
24484642e01fSmrg    xkbi= dev->key->xkbInfo;
24494642e01fSmrg    xkb = xkbi->desc;
24504642e01fSmrg
24514642e01fSmrg    XkbSetCauseXkbReq(&cause,X_kbSetMap,client);
24526747b715Smrg    memset(&change, 0, sizeof(change));
24536747b715Smrg    sentNKN = FALSE;
24544642e01fSmrg    if ((xkb->min_key_code!=req->minKeyCode)||
24554642e01fSmrg        (xkb->max_key_code!=req->maxKeyCode)) {
245605b261ecSmrg	Status			status;
245705b261ecSmrg	xkbNewKeyboardNotify	nkn;
24584642e01fSmrg	nkn.deviceID = nkn.oldDeviceID = dev->id;
24594642e01fSmrg	nkn.oldMinKeyCode = xkb->min_key_code;
24604642e01fSmrg	nkn.oldMaxKeyCode = xkb->max_key_code;
24614642e01fSmrg	status= XkbChangeKeycodeRange(xkb, req->minKeyCode,
24624642e01fSmrg                                      req->maxKeyCode, &change);
24634642e01fSmrg	if (status != Success)
24644642e01fSmrg	    return status; /* oh-oh. what about the other keyboards? */
24654642e01fSmrg	nkn.minKeyCode = xkb->min_key_code;
24664642e01fSmrg	nkn.maxKeyCode = xkb->max_key_code;
24674642e01fSmrg	nkn.requestMajor = XkbReqCode;
24684642e01fSmrg	nkn.requestMinor = X_kbSetMap;
24694642e01fSmrg	nkn.changed = XkbNKN_KeycodesMask;
247005b261ecSmrg	XkbSendNewKeyboardNotify(dev,&nkn);
24716747b715Smrg	sentNKN = TRUE;
24724642e01fSmrg    }
24734642e01fSmrg
24744642e01fSmrg    if (req->present&XkbKeyTypesMask) {
24754642e01fSmrg	values = SetKeyTypes(xkb,req,(xkbKeyTypeWireDesc *)values,&change);
24764642e01fSmrg	if (!values)	goto allocFailure;
24774642e01fSmrg    }
24784642e01fSmrg    if (req->present&XkbKeySymsMask) {
24794642e01fSmrg	values = SetKeySyms(client,xkb,req,(xkbSymMapWireDesc *)values,&change,dev);
24804642e01fSmrg	if (!values)	goto allocFailure;
24814642e01fSmrg    }
24824642e01fSmrg    if (req->present&XkbKeyActionsMask) {
24834642e01fSmrg	values = SetKeyActions(xkb,req,(CARD8 *)values,&change);
24844642e01fSmrg	if (!values)	goto allocFailure;
24854642e01fSmrg    }
24864642e01fSmrg    if (req->present&XkbKeyBehaviorsMask) {
24874642e01fSmrg	values= SetKeyBehaviors(xkbi,req,(xkbBehaviorWireDesc *)values,&change);
24884642e01fSmrg	if (!values)	goto allocFailure;
24894642e01fSmrg    }
24904642e01fSmrg    if (req->present&XkbVirtualModsMask)
24914642e01fSmrg	values= SetVirtualMods(xkbi,req,(CARD8 *)values,&change);
24924642e01fSmrg    if (req->present&XkbExplicitComponentsMask)
24934642e01fSmrg	values= SetKeyExplicit(xkbi,req,(CARD8 *)values,&change);
24944642e01fSmrg    if (req->present&XkbModifierMapMask)
24954642e01fSmrg	values= SetModifierMap(xkbi,req,(CARD8 *)values,&change);
24964642e01fSmrg    if (req->present&XkbVirtualModMapMask)
24974642e01fSmrg	values= SetVirtualModMap(xkbi,req,(xkbVModMapWireDesc *)values,&change);
24984642e01fSmrg    if (((values-((char *)req))/4)!=req->length) {
24994642e01fSmrg	ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after set)\n");
25004642e01fSmrg	client->errorValue = values-((char *)&req[1]);
250105b261ecSmrg	return BadLength;
250205b261ecSmrg    }
25034642e01fSmrg    if (req->flags&XkbSetMapRecomputeActions) {
250405b261ecSmrg	KeyCode		first,last,firstMM,lastMM;
250505b261ecSmrg	if (change.map.num_key_syms>0) {
250605b261ecSmrg	    first= change.map.first_key_sym;
250705b261ecSmrg	    last= first+change.map.num_key_syms-1;
250805b261ecSmrg	}
250905b261ecSmrg	else first= last= 0;
251005b261ecSmrg	if (change.map.num_modmap_keys>0) {
251105b261ecSmrg	    firstMM= change.map.first_modmap_key;
251205b261ecSmrg	    lastMM= first+change.map.num_modmap_keys-1;
251305b261ecSmrg	}
251405b261ecSmrg	else firstMM= lastMM= 0;
251505b261ecSmrg	if ((last>0) && (lastMM>0)) {
251605b261ecSmrg	    if (firstMM<first)
251705b261ecSmrg		first= firstMM;
251805b261ecSmrg	    if (lastMM>last)
251905b261ecSmrg		last= lastMM;
252005b261ecSmrg	}
252105b261ecSmrg	else if (lastMM>0) {
252205b261ecSmrg	    first= firstMM;
252305b261ecSmrg	    last= lastMM;
252405b261ecSmrg	}
252505b261ecSmrg	if (last>0) {
252605b261ecSmrg	    unsigned check= 0;
252705b261ecSmrg	    XkbUpdateActions(dev,first,(last-first+1),&change,&check,&cause);
252805b261ecSmrg	    if (check)
252905b261ecSmrg		XkbCheckSecondaryEffects(xkbi,check,&change,&cause);
253005b261ecSmrg	}
253105b261ecSmrg    }
253205b261ecSmrg    if (!sentNKN)
253305b261ecSmrg	XkbSendNotification(dev,&change,&cause);
253405b261ecSmrg
25354642e01fSmrg    return Success;
253605b261ecSmrgallocFailure:
253705b261ecSmrg    return BadAlloc;
253805b261ecSmrg}
253905b261ecSmrg
25404642e01fSmrg
25414642e01fSmrgint
25424642e01fSmrgProcXkbSetMap(ClientPtr client)
25434642e01fSmrg{
25444642e01fSmrg    DeviceIntPtr	dev;
25454642e01fSmrg    char *		tmp;
25464642e01fSmrg    int                 rc;
25474642e01fSmrg
25484642e01fSmrg    REQUEST(xkbSetMapReq);
25494642e01fSmrg    REQUEST_AT_LEAST_SIZE(xkbSetMapReq);
25504642e01fSmrg
25514642e01fSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
25524642e01fSmrg	return BadAccess;
25534642e01fSmrg
25544642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
25554642e01fSmrg    CHK_MASK_LEGAL(0x01,stuff->present,XkbAllMapComponentsMask);
25564642e01fSmrg
25574642e01fSmrg    tmp = (char *)&stuff[1];
25584642e01fSmrg
25594642e01fSmrg    /* Check if we can to the SetMap on the requested device. If this
25604642e01fSmrg       succeeds, do the same thing for all extension devices (if needed).
25614642e01fSmrg       If any of them fails, fail.  */
25624642e01fSmrg    rc = _XkbSetMapChecks(client, dev, stuff, tmp);
25634642e01fSmrg
25644642e01fSmrg    if (rc != Success)
25654642e01fSmrg        return rc;
25664642e01fSmrg
25674642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd)
25684642e01fSmrg    {
25694642e01fSmrg        DeviceIntPtr other;
25704642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
25714642e01fSmrg        {
25726747b715Smrg            if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev)
25734642e01fSmrg            {
25744642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
25754642e01fSmrg                if (rc == Success)
25764642e01fSmrg                {
25774642e01fSmrg                    rc = _XkbSetMapChecks(client, other, stuff, tmp);
25784642e01fSmrg                    if (rc != Success)
25794642e01fSmrg                        return rc;
25804642e01fSmrg                }
25814642e01fSmrg            }
25824642e01fSmrg        }
25834642e01fSmrg    }
25844642e01fSmrg
25854642e01fSmrg    /* We know now that we will succed with the SetMap. In theory anyway. */
25864642e01fSmrg    rc = _XkbSetMap(client, dev, stuff, tmp);
25874642e01fSmrg    if (rc != Success)
25884642e01fSmrg        return rc;
25894642e01fSmrg
25904642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd)
25914642e01fSmrg    {
25924642e01fSmrg        DeviceIntPtr other;
25934642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
25944642e01fSmrg        {
25956747b715Smrg            if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev)
25964642e01fSmrg            {
25974642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
25984642e01fSmrg                if (rc == Success)
25994642e01fSmrg                    _XkbSetMap(client, other, stuff, tmp);
26004642e01fSmrg                /* ignore rc. if the SetMap failed although the check above
26014642e01fSmrg                   reported true there isn't much we can do. we still need to
26024642e01fSmrg                   set all other devices, hoping that at least they stay in
26034642e01fSmrg                   sync. */
26044642e01fSmrg            }
26054642e01fSmrg        }
26064642e01fSmrg    }
26074642e01fSmrg
26086747b715Smrg    return Success;
26094642e01fSmrg}
26104642e01fSmrg
261105b261ecSmrg/***====================================================================***/
261205b261ecSmrg
261305b261ecSmrgstatic Status
261405b261ecSmrgXkbComputeGetCompatMapReplySize(	XkbCompatMapPtr 	compat,
261505b261ecSmrg					xkbGetCompatMapReply *	rep)
261605b261ecSmrg{
261705b261ecSmrgunsigned	 size,nGroups;
261805b261ecSmrg
261905b261ecSmrg    nGroups= 0;
262005b261ecSmrg    if (rep->groups!=0) {
262105b261ecSmrg	register int i,bit;
262205b261ecSmrg	for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
262305b261ecSmrg	    if (rep->groups&bit)
262405b261ecSmrg		nGroups++;
262505b261ecSmrg	}
262605b261ecSmrg    }
262705b261ecSmrg    size= nGroups*SIZEOF(xkbModsWireDesc);
262805b261ecSmrg    size+= (rep->nSI*SIZEOF(xkbSymInterpretWireDesc));
262905b261ecSmrg    rep->length= size/4;
263005b261ecSmrg    return Success;
263105b261ecSmrg}
263205b261ecSmrg
263305b261ecSmrgstatic int
263405b261ecSmrgXkbSendCompatMap(	ClientPtr 		client,
263505b261ecSmrg			XkbCompatMapPtr 	compat,
263605b261ecSmrg			xkbGetCompatMapReply *	rep)
263705b261ecSmrg{
263805b261ecSmrgchar	*	data;
263905b261ecSmrgint		size;
264005b261ecSmrg
264105b261ecSmrg    size= rep->length*4;
264205b261ecSmrg    if (size>0) {
26436747b715Smrg	data = malloc(size);
264405b261ecSmrg	if (data) {
264505b261ecSmrg	    register unsigned i,bit;
264605b261ecSmrg	    xkbModsWireDesc *	grp;
264705b261ecSmrg	    XkbSymInterpretPtr	sym= &compat->sym_interpret[rep->firstSI];
264805b261ecSmrg	    xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data;
264905b261ecSmrg	    for (i=0;i<rep->nSI;i++,sym++,wire++) {
265005b261ecSmrg		wire->sym= sym->sym;
265105b261ecSmrg		wire->mods= sym->mods;
265205b261ecSmrg		wire->match= sym->match;
265305b261ecSmrg		wire->virtualMod= sym->virtual_mod;
265405b261ecSmrg		wire->flags= sym->flags;
265505b261ecSmrg		memcpy((char*)&wire->act,(char*)&sym->act,sz_xkbActionWireDesc);
265605b261ecSmrg		if (client->swapped) {
265705b261ecSmrg		    register int n;
265805b261ecSmrg		    swapl(&wire->sym,n);
265905b261ecSmrg		}
266005b261ecSmrg	    }
266105b261ecSmrg	    if (rep->groups) {
266205b261ecSmrg		grp = (xkbModsWireDesc *)wire;
266305b261ecSmrg		for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
266405b261ecSmrg		    if (rep->groups&bit) {
266505b261ecSmrg			grp->mask= compat->groups[i].mask;
266605b261ecSmrg			grp->realMods= compat->groups[i].real_mods;
266705b261ecSmrg			grp->virtualMods= compat->groups[i].vmods;
266805b261ecSmrg			if (client->swapped) {
266905b261ecSmrg			    register int n;
267005b261ecSmrg			    swaps(&grp->virtualMods,n);
267105b261ecSmrg			}
267205b261ecSmrg			grp++;
267305b261ecSmrg		    }
267405b261ecSmrg		}
267505b261ecSmrg		wire= (xkbSymInterpretWireDesc*)grp;
267605b261ecSmrg	    }
267705b261ecSmrg	}
267805b261ecSmrg	else return BadAlloc;
267905b261ecSmrg    }
268005b261ecSmrg    else data= NULL;
268105b261ecSmrg
268205b261ecSmrg    if (client->swapped) {
268305b261ecSmrg	register int n;
268405b261ecSmrg	swaps(&rep->sequenceNumber,n);
268505b261ecSmrg	swapl(&rep->length,n);
268605b261ecSmrg	swaps(&rep->firstSI,n);
268705b261ecSmrg	swaps(&rep->nSI,n);
268805b261ecSmrg	swaps(&rep->nTotalSI,n);
268905b261ecSmrg    }
269005b261ecSmrg
269105b261ecSmrg    WriteToClient(client, SIZEOF(xkbGetCompatMapReply), (char *)rep);
269205b261ecSmrg    if (data) {
269305b261ecSmrg	WriteToClient(client, size, data);
26946747b715Smrg	free((char *)data);
269505b261ecSmrg    }
26966747b715Smrg    return Success;
269705b261ecSmrg}
269805b261ecSmrg
269905b261ecSmrgint
270005b261ecSmrgProcXkbGetCompatMap(ClientPtr client)
270105b261ecSmrg{
270205b261ecSmrg    xkbGetCompatMapReply 	rep;
270305b261ecSmrg    DeviceIntPtr 		dev;
270405b261ecSmrg    XkbDescPtr			xkb;
270505b261ecSmrg    XkbCompatMapPtr		compat;
270605b261ecSmrg
270705b261ecSmrg    REQUEST(xkbGetCompatMapReq);
270805b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetCompatMapReq);
270905b261ecSmrg
271005b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
271105b261ecSmrg	return BadAccess;
271205b261ecSmrg
27134642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
271405b261ecSmrg
271505b261ecSmrg    xkb = dev->key->xkbInfo->desc;
271605b261ecSmrg    compat= xkb->compat;
271705b261ecSmrg
271805b261ecSmrg    rep.type = X_Reply;
271905b261ecSmrg    rep.deviceID = dev->id;
272005b261ecSmrg    rep.sequenceNumber = client->sequence;
272105b261ecSmrg    rep.length = 0;
272205b261ecSmrg    rep.firstSI = stuff->firstSI;
272305b261ecSmrg    rep.nSI = stuff->nSI;
272405b261ecSmrg    if (stuff->getAllSI) {
272505b261ecSmrg	rep.firstSI = 0;
272605b261ecSmrg	rep.nSI = compat->num_si;
272705b261ecSmrg    }
272805b261ecSmrg    else if ((((unsigned)stuff->nSI)>0)&&
272905b261ecSmrg		((unsigned)(stuff->firstSI+stuff->nSI-1)>=compat->num_si)) {
273005b261ecSmrg	client->errorValue = _XkbErrCode2(0x05,compat->num_si);
273105b261ecSmrg	return BadValue;
273205b261ecSmrg    }
273305b261ecSmrg    rep.nTotalSI = compat->num_si;
273405b261ecSmrg    rep.groups= stuff->groups;
273505b261ecSmrg    XkbComputeGetCompatMapReplySize(compat,&rep);
273605b261ecSmrg    return XkbSendCompatMap(client,compat,&rep);
273705b261ecSmrg}
273805b261ecSmrg
27394642e01fSmrg/**
27404642e01fSmrg * Apply the given request on the given device.
27416747b715Smrg * If dryRun is TRUE, then value checks are performed, but the device isn't
27424642e01fSmrg * modified.
27434642e01fSmrg */
27444642e01fSmrgstatic int
27454642e01fSmrg_XkbSetCompatMap(ClientPtr client, DeviceIntPtr dev,
27464642e01fSmrg                 xkbSetCompatMapReq *req, char* data, BOOL dryRun)
274705b261ecSmrg{
27484642e01fSmrg    XkbSrvInfoPtr       xkbi;
27494642e01fSmrg    XkbDescPtr          xkb;
27504642e01fSmrg    XkbCompatMapPtr     compat;
27514642e01fSmrg    int                 nGroups;
27524642e01fSmrg    unsigned            i,bit;
275305b261ecSmrg
275405b261ecSmrg    xkbi = dev->key->xkbInfo;
27554642e01fSmrg    xkb = xkbi->desc;
27564642e01fSmrg    compat = xkb->compat;
27574642e01fSmrg
27584642e01fSmrg    if ((req->nSI>0)||(req->truncateSI)) {
275905b261ecSmrg	xkbSymInterpretWireDesc *wire;
27604642e01fSmrg	if (req->firstSI>compat->num_si) {
276105b261ecSmrg	    client->errorValue = _XkbErrCode2(0x02,compat->num_si);
276205b261ecSmrg	    return BadValue;
276305b261ecSmrg	}
276405b261ecSmrg	wire= (xkbSymInterpretWireDesc *)data;
27654642e01fSmrg	wire+= req->nSI;
276605b261ecSmrg	data = (char *)wire;
276705b261ecSmrg    }
27684642e01fSmrg
276905b261ecSmrg    nGroups= 0;
27704642e01fSmrg    if (req->groups!=0) {
277105b261ecSmrg	for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
27724642e01fSmrg	    if ( req->groups&bit )
277305b261ecSmrg		nGroups++;
277405b261ecSmrg	}
277505b261ecSmrg    }
277605b261ecSmrg    data+= nGroups*SIZEOF(xkbModsWireDesc);
27774642e01fSmrg    if (((data-((char *)req))/4)!=req->length) {
277805b261ecSmrg	return BadLength;
277905b261ecSmrg    }
27804642e01fSmrg
27814642e01fSmrg    /* Done all the checks we can do */
27824642e01fSmrg    if (dryRun)
27834642e01fSmrg        return Success;
27844642e01fSmrg
27854642e01fSmrg    data = (char *)&req[1];
27864642e01fSmrg    if (req->nSI>0) {
278705b261ecSmrg	xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data;
278805b261ecSmrg	XkbSymInterpretPtr	sym;
27894642e01fSmrg	if ((unsigned)(req->firstSI+req->nSI)>compat->num_si) {
27904642e01fSmrg	    compat->num_si= req->firstSI+req->nSI;
27916747b715Smrg	    compat->sym_interpret= realloc(compat->sym_interpret,
27926747b715Smrg					    compat->num_si * sizeof(XkbSymInterpretRec));
279305b261ecSmrg	    if (!compat->sym_interpret) {
279405b261ecSmrg		compat->num_si= 0;
279505b261ecSmrg		return BadAlloc;
279605b261ecSmrg	    }
279705b261ecSmrg	}
27984642e01fSmrg	else if (req->truncateSI) {
27994642e01fSmrg	    compat->num_si = req->firstSI+req->nSI;
280005b261ecSmrg	}
28014642e01fSmrg	sym = &compat->sym_interpret[req->firstSI];
28024642e01fSmrg	for (i=0;i<req->nSI;i++,wire++,sym++) {
280305b261ecSmrg	    if (client->swapped) {
28044642e01fSmrg		int n;
280505b261ecSmrg		swapl(&wire->sym,n);
280605b261ecSmrg	    }
280705b261ecSmrg	    sym->sym= wire->sym;
280805b261ecSmrg	    sym->mods= wire->mods;
280905b261ecSmrg	    sym->match= wire->match;
281005b261ecSmrg	    sym->flags= wire->flags;
281105b261ecSmrg	    sym->virtual_mod= wire->virtualMod;
281205b261ecSmrg	    memcpy((char *)&sym->act,(char *)&wire->act,
28134642e01fSmrg                   SIZEOF(xkbActionWireDesc));
281405b261ecSmrg	}
281505b261ecSmrg	data = (char *)wire;
281605b261ecSmrg    }
28174642e01fSmrg    else if (req->truncateSI) {
28184642e01fSmrg	compat->num_si = req->firstSI;
281905b261ecSmrg    }
282005b261ecSmrg
28214642e01fSmrg    if (req->groups!=0) {
28224642e01fSmrg	unsigned i, bit;
282305b261ecSmrg	xkbModsWireDesc *wire = (xkbModsWireDesc *)data;
28244642e01fSmrg	for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
28254642e01fSmrg	    if (req->groups & bit) {
282605b261ecSmrg		if (client->swapped) {
28274642e01fSmrg		    int n;
282805b261ecSmrg		    swaps(&wire->virtualMods,n);
282905b261ecSmrg		}
283005b261ecSmrg		compat->groups[i].mask= wire->realMods;
283105b261ecSmrg		compat->groups[i].real_mods= wire->realMods;
283205b261ecSmrg		compat->groups[i].vmods= wire->virtualMods;
283305b261ecSmrg		if (wire->virtualMods!=0) {
283405b261ecSmrg		    unsigned tmp;
283505b261ecSmrg		    tmp= XkbMaskForVMask(xkb,wire->virtualMods);
283605b261ecSmrg		    compat->groups[i].mask|= tmp;
283705b261ecSmrg		}
283805b261ecSmrg		data+= SIZEOF(xkbModsWireDesc);
283905b261ecSmrg		wire= (xkbModsWireDesc *)data;
284005b261ecSmrg	    }
284105b261ecSmrg	}
284205b261ecSmrg    }
28434642e01fSmrg    i= XkbPaddedSize((data-((char *)req)));
28444642e01fSmrg    if ((i/4)!=req->length) {
28454642e01fSmrg	ErrorF("[xkb] Internal length error on read in _XkbSetCompatMap\n");
284605b261ecSmrg	return BadLength;
284705b261ecSmrg    }
28484642e01fSmrg
284905b261ecSmrg    if (dev->xkb_interest) {
285005b261ecSmrg	xkbCompatMapNotify ev;
285105b261ecSmrg	ev.deviceID = dev->id;
28524642e01fSmrg	ev.changedGroups = req->groups;
28534642e01fSmrg	ev.firstSI = req->firstSI;
28544642e01fSmrg	ev.nSI = req->nSI;
285505b261ecSmrg	ev.nTotalSI = compat->num_si;
285605b261ecSmrg	XkbSendCompatMapNotify(dev,&ev);
285705b261ecSmrg    }
285805b261ecSmrg
28594642e01fSmrg    if (req->recomputeActions) {
286005b261ecSmrg	XkbChangesRec		change;
286105b261ecSmrg	unsigned		check;
286205b261ecSmrg	XkbEventCauseRec	cause;
286305b261ecSmrg
286405b261ecSmrg	XkbSetCauseXkbReq(&cause,X_kbSetCompatMap,client);
28656747b715Smrg	memset(&change, 0, sizeof(XkbChangesRec));
286605b261ecSmrg	XkbUpdateActions(dev,xkb->min_key_code,XkbNumKeys(xkb),&change,&check,
286705b261ecSmrg									&cause);
286805b261ecSmrg	if (check)
286905b261ecSmrg	    XkbCheckSecondaryEffects(xkbi,check,&change,&cause);
287005b261ecSmrg	XkbSendNotification(dev,&change,&cause);
287105b261ecSmrg    }
28724642e01fSmrg    return Success;
28734642e01fSmrg}
28744642e01fSmrg
28754642e01fSmrgint
28764642e01fSmrgProcXkbSetCompatMap(ClientPtr client)
28774642e01fSmrg{
28784642e01fSmrg    DeviceIntPtr        dev;
28794642e01fSmrg    char                *data;
28804642e01fSmrg    int                 rc;
28814642e01fSmrg
28824642e01fSmrg    REQUEST(xkbSetCompatMapReq);
28834642e01fSmrg    REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq);
28844642e01fSmrg
28854642e01fSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
28864642e01fSmrg	return BadAccess;
28874642e01fSmrg
28884642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
28894642e01fSmrg
28904642e01fSmrg    data = (char *)&stuff[1];
28914642e01fSmrg
28924642e01fSmrg    /* check first using a dry-run */
28934642e01fSmrg    rc = _XkbSetCompatMap(client, dev, stuff, data, TRUE);
28944642e01fSmrg    if (rc != Success)
28954642e01fSmrg        return rc;
28964642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd)
28974642e01fSmrg    {
28984642e01fSmrg        DeviceIntPtr other;
28994642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
29004642e01fSmrg        {
29016747b715Smrg            if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev)
29024642e01fSmrg            {
29034642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
29044642e01fSmrg                if (rc == Success)
29054642e01fSmrg                {
29064642e01fSmrg                    /* dry-run */
29074642e01fSmrg                    rc = _XkbSetCompatMap(client, other, stuff, data, TRUE);
29084642e01fSmrg                    if (rc != Success)
29094642e01fSmrg                        return rc;
29104642e01fSmrg                }
29114642e01fSmrg            }
29124642e01fSmrg        }
29134642e01fSmrg    }
29144642e01fSmrg
29154642e01fSmrg    /* Yay, the dry-runs succeed. Let's apply */
29164642e01fSmrg    rc = _XkbSetCompatMap(client, dev, stuff, data, FALSE);
29174642e01fSmrg    if (rc != Success)
29184642e01fSmrg        return rc;
29194642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd)
29204642e01fSmrg    {
29214642e01fSmrg        DeviceIntPtr other;
29224642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
29234642e01fSmrg        {
29246747b715Smrg            if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev)
29254642e01fSmrg            {
29264642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
29274642e01fSmrg                if (rc == Success)
29284642e01fSmrg                {
29294642e01fSmrg                    rc = _XkbSetCompatMap(client, other, stuff, data, FALSE);
29304642e01fSmrg                    if (rc != Success)
29314642e01fSmrg                        return rc;
29324642e01fSmrg                }
29334642e01fSmrg            }
29344642e01fSmrg        }
29354642e01fSmrg    }
29364642e01fSmrg
29376747b715Smrg    return Success;
293805b261ecSmrg}
293905b261ecSmrg
294005b261ecSmrg/***====================================================================***/
294105b261ecSmrg
294205b261ecSmrgint
294305b261ecSmrgProcXkbGetIndicatorState(ClientPtr client)
294405b261ecSmrg{
294505b261ecSmrg    xkbGetIndicatorStateReply 	rep;
294605b261ecSmrg    XkbSrvLedInfoPtr		sli;
294705b261ecSmrg    DeviceIntPtr 		dev;
294805b261ecSmrg    register int 		i;
294905b261ecSmrg
295005b261ecSmrg    REQUEST(xkbGetIndicatorStateReq);
295105b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq);
295205b261ecSmrg
295305b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
295405b261ecSmrg	return BadAccess;
295505b261ecSmrg
29564642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
295705b261ecSmrg
295805b261ecSmrg    sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,
295905b261ecSmrg						XkbXI_IndicatorStateMask);
296005b261ecSmrg    if (!sli)
296105b261ecSmrg	return BadAlloc;
296205b261ecSmrg
296305b261ecSmrg    rep.type = X_Reply;
296405b261ecSmrg    rep.sequenceNumber = client->sequence;
296505b261ecSmrg    rep.length = 0;
296605b261ecSmrg    rep.deviceID = dev->id;
296705b261ecSmrg    rep.state = sli->effectiveState;
296805b261ecSmrg
296905b261ecSmrg    if (client->swapped) {
297005b261ecSmrg	swaps(&rep.sequenceNumber,i);
297105b261ecSmrg	swapl(&rep.state,i);
297205b261ecSmrg    }
297305b261ecSmrg    WriteToClient(client, SIZEOF(xkbGetIndicatorStateReply), (char *)&rep);
29746747b715Smrg    return Success;
297505b261ecSmrg}
297605b261ecSmrg
297705b261ecSmrg/***====================================================================***/
297805b261ecSmrg
297905b261ecSmrgstatic Status
298005b261ecSmrgXkbComputeGetIndicatorMapReplySize(
298105b261ecSmrg    XkbIndicatorPtr		indicators,
298205b261ecSmrg    xkbGetIndicatorMapReply	*rep)
298305b261ecSmrg{
298405b261ecSmrgregister int 	i,bit;
298505b261ecSmrgint		nIndicators;
298605b261ecSmrg
298705b261ecSmrg    rep->realIndicators = indicators->phys_indicators;
298805b261ecSmrg    for (i=nIndicators=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
298905b261ecSmrg	if (rep->which&bit)
299005b261ecSmrg	    nIndicators++;
299105b261ecSmrg    }
299205b261ecSmrg    rep->length = (nIndicators*SIZEOF(xkbIndicatorMapWireDesc))/4;
299305b261ecSmrg    return Success;
299405b261ecSmrg}
299505b261ecSmrg
299605b261ecSmrgstatic int
299705b261ecSmrgXkbSendIndicatorMap(	ClientPtr			client,
299805b261ecSmrg			XkbIndicatorPtr			indicators,
299905b261ecSmrg			xkbGetIndicatorMapReply *	rep)
300005b261ecSmrg{
300105b261ecSmrgint 			length;
300205b261ecSmrgCARD8 *			map;
300305b261ecSmrgregister int		i;
300405b261ecSmrgregister unsigned	bit;
300505b261ecSmrg
300605b261ecSmrg    length = rep->length*4;
300705b261ecSmrg    if (length>0) {
300805b261ecSmrg	CARD8 *to;
30096747b715Smrg	to= map= malloc(length);
301005b261ecSmrg	if (map) {
301105b261ecSmrg	    xkbIndicatorMapWireDesc  *wire = (xkbIndicatorMapWireDesc *)to;
301205b261ecSmrg	    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
301305b261ecSmrg		if (rep->which&bit) {
301405b261ecSmrg		    wire->flags= indicators->maps[i].flags;
301505b261ecSmrg		    wire->whichGroups= indicators->maps[i].which_groups;
301605b261ecSmrg		    wire->groups= indicators->maps[i].groups;
301705b261ecSmrg		    wire->whichMods= indicators->maps[i].which_mods;
301805b261ecSmrg		    wire->mods= indicators->maps[i].mods.mask;
301905b261ecSmrg		    wire->realMods= indicators->maps[i].mods.real_mods;
302005b261ecSmrg		    wire->virtualMods= indicators->maps[i].mods.vmods;
302105b261ecSmrg		    wire->ctrls= indicators->maps[i].ctrls;
302205b261ecSmrg		    if (client->swapped) {
302305b261ecSmrg			register int n;
302405b261ecSmrg			swaps(&wire->virtualMods,n);
302505b261ecSmrg			swapl(&wire->ctrls,n);
302605b261ecSmrg		    }
302705b261ecSmrg		    wire++;
302805b261ecSmrg		}
302905b261ecSmrg	    }
303005b261ecSmrg	    to = (CARD8 *)wire;
303105b261ecSmrg	    if ((to-map)!=length) {
303205b261ecSmrg		client->errorValue = _XkbErrCode2(0xff,length);
30336747b715Smrg		free(map);
303405b261ecSmrg		return BadLength;
303505b261ecSmrg	    }
303605b261ecSmrg	}
303705b261ecSmrg	else return BadAlloc;
303805b261ecSmrg    }
303905b261ecSmrg    else map = NULL;
304005b261ecSmrg    if (client->swapped) {
304105b261ecSmrg	swaps(&rep->sequenceNumber,i);
304205b261ecSmrg	swapl(&rep->length,i);
304305b261ecSmrg	swapl(&rep->which,i);
304405b261ecSmrg	swapl(&rep->realIndicators,i);
304505b261ecSmrg    }
304605b261ecSmrg    WriteToClient(client, SIZEOF(xkbGetIndicatorMapReply), (char *)rep);
304705b261ecSmrg    if (map) {
304805b261ecSmrg	WriteToClient(client, length, (char *)map);
30496747b715Smrg	free((char *)map);
305005b261ecSmrg    }
30516747b715Smrg    return Success;
305205b261ecSmrg}
305305b261ecSmrg
305405b261ecSmrgint
305505b261ecSmrgProcXkbGetIndicatorMap(ClientPtr client)
305605b261ecSmrg{
305705b261ecSmrgxkbGetIndicatorMapReply rep;
305805b261ecSmrgDeviceIntPtr		dev;
305905b261ecSmrgXkbDescPtr		xkb;
306005b261ecSmrgXkbIndicatorPtr		leds;
306105b261ecSmrg
306205b261ecSmrg    REQUEST(xkbGetIndicatorMapReq);
306305b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq);
306405b261ecSmrg
306505b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
306605b261ecSmrg	return BadAccess;
306705b261ecSmrg
30684642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
306905b261ecSmrg
307005b261ecSmrg    xkb= dev->key->xkbInfo->desc;
307105b261ecSmrg    leds= xkb->indicators;
307205b261ecSmrg
307305b261ecSmrg    rep.type = X_Reply;
307405b261ecSmrg    rep.sequenceNumber = client->sequence;
307505b261ecSmrg    rep.length = 0;
307605b261ecSmrg    rep.deviceID = dev->id;
307705b261ecSmrg    rep.which = stuff->which;
307805b261ecSmrg    XkbComputeGetIndicatorMapReplySize(leds,&rep);
307905b261ecSmrg    return XkbSendIndicatorMap(client,leds,&rep);
308005b261ecSmrg}
308105b261ecSmrg
30824642e01fSmrg/**
30834642e01fSmrg * Apply the given map to the given device. Which specifies which components
30844642e01fSmrg * to apply.
30854642e01fSmrg */
30864642e01fSmrgstatic int
30874642e01fSmrg_XkbSetIndicatorMap(ClientPtr client, DeviceIntPtr dev,
30884642e01fSmrg                    int which, xkbIndicatorMapWireDesc *desc)
30894642e01fSmrg{
30904642e01fSmrg    XkbSrvInfoPtr       xkbi;
30914642e01fSmrg    XkbSrvLedInfoPtr    sli;
30924642e01fSmrg    XkbEventCauseRec    cause;
30934642e01fSmrg    int                 i, bit;
30944642e01fSmrg
30954642e01fSmrg    xkbi = dev->key->xkbInfo;
30964642e01fSmrg
30974642e01fSmrg    sli= XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
30984642e01fSmrg						XkbXI_IndicatorMapsMask);
30994642e01fSmrg    if (!sli)
31004642e01fSmrg	return BadAlloc;
31014642e01fSmrg
31024642e01fSmrg    for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
31034642e01fSmrg	if (which & bit) {
31044642e01fSmrg	    sli->maps[i].flags = desc->flags;
31054642e01fSmrg	    sli->maps[i].which_groups = desc->whichGroups;
31064642e01fSmrg	    sli->maps[i].groups = desc->groups;
31074642e01fSmrg	    sli->maps[i].which_mods = desc->whichMods;
31084642e01fSmrg	    sli->maps[i].mods.mask = desc->mods;
31094642e01fSmrg	    sli->maps[i].mods.real_mods = desc->mods;
31104642e01fSmrg	    sli->maps[i].mods.vmods= desc->virtualMods;
31114642e01fSmrg	    sli->maps[i].ctrls = desc->ctrls;
31124642e01fSmrg	    if (desc->virtualMods!=0) {
31134642e01fSmrg		unsigned tmp;
31144642e01fSmrg		tmp= XkbMaskForVMask(xkbi->desc,desc->virtualMods);
31154642e01fSmrg		sli->maps[i].mods.mask= desc->mods|tmp;
31164642e01fSmrg	    }
31174642e01fSmrg	    desc++;
31184642e01fSmrg	}
31194642e01fSmrg    }
31204642e01fSmrg
31214642e01fSmrg    XkbSetCauseXkbReq(&cause,X_kbSetIndicatorMap,client);
31224642e01fSmrg    XkbApplyLedMapChanges(dev,sli,which,NULL,NULL,&cause);
31234642e01fSmrg
31244642e01fSmrg    return Success;
31254642e01fSmrg}
31264642e01fSmrg
312705b261ecSmrgint
312805b261ecSmrgProcXkbSetIndicatorMap(ClientPtr client)
312905b261ecSmrg{
31304642e01fSmrg    int                 i, bit;
31314642e01fSmrg    int                 nIndicators;
31324642e01fSmrg    DeviceIntPtr        dev;
31334642e01fSmrg    xkbIndicatorMapWireDesc     *from;
31344642e01fSmrg    int                 rc;
313505b261ecSmrg
313605b261ecSmrg    REQUEST(xkbSetIndicatorMapReq);
313705b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq);
313805b261ecSmrg
313905b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
314005b261ecSmrg	return BadAccess;
314105b261ecSmrg
31424642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
314305b261ecSmrg
314405b261ecSmrg    if (stuff->which==0)
31456747b715Smrg	return Success;
314605b261ecSmrg
314705b261ecSmrg    for (nIndicators=i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
314805b261ecSmrg	if (stuff->which&bit)
314905b261ecSmrg	    nIndicators++;
315005b261ecSmrg    }
315105b261ecSmrg    if (stuff->length!=((SIZEOF(xkbSetIndicatorMapReq)+
315205b261ecSmrg			(nIndicators*SIZEOF(xkbIndicatorMapWireDesc)))/4)) {
315305b261ecSmrg	return BadLength;
315405b261ecSmrg    }
315505b261ecSmrg
315605b261ecSmrg    from = (xkbIndicatorMapWireDesc *)&stuff[1];
315705b261ecSmrg    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
315805b261ecSmrg	if (stuff->which&bit) {
315905b261ecSmrg	    if (client->swapped) {
31604642e01fSmrg		int n;
316105b261ecSmrg		swaps(&from->virtualMods,n);
316205b261ecSmrg		swapl(&from->ctrls,n);
316305b261ecSmrg	    }
316405b261ecSmrg	    CHK_MASK_LEGAL(i,from->whichGroups,XkbIM_UseAnyGroup);
316505b261ecSmrg	    CHK_MASK_LEGAL(i,from->whichMods,XkbIM_UseAnyMods);
316605b261ecSmrg	    from++;
316705b261ecSmrg	}
316805b261ecSmrg    }
316905b261ecSmrg
317005b261ecSmrg    from = (xkbIndicatorMapWireDesc *)&stuff[1];
31714642e01fSmrg    rc = _XkbSetIndicatorMap(client, dev, stuff->which, from);
31724642e01fSmrg    if (rc != Success)
31734642e01fSmrg        return rc;
31744642e01fSmrg
31754642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd)
31764642e01fSmrg    {
31774642e01fSmrg        DeviceIntPtr other;
31784642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
31794642e01fSmrg        {
31806747b715Smrg            if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev)
31814642e01fSmrg            {
31824642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess);
31834642e01fSmrg                if (rc == Success)
31844642e01fSmrg                    _XkbSetIndicatorMap(client, other, stuff->which, from);
31854642e01fSmrg            }
31864642e01fSmrg        }
318705b261ecSmrg    }
318805b261ecSmrg
31894642e01fSmrg    return Success;
319005b261ecSmrg}
319105b261ecSmrg
319205b261ecSmrg/***====================================================================***/
319305b261ecSmrg
319405b261ecSmrgint
319505b261ecSmrgProcXkbGetNamedIndicator(ClientPtr client)
319605b261ecSmrg{
319705b261ecSmrg    DeviceIntPtr 		dev;
319805b261ecSmrg    xkbGetNamedIndicatorReply 	rep;
319905b261ecSmrg    register int		i = 0;
320005b261ecSmrg    XkbSrvLedInfoPtr		sli;
320105b261ecSmrg    XkbIndicatorMapPtr		map = NULL;
320205b261ecSmrg
320305b261ecSmrg    REQUEST(xkbGetNamedIndicatorReq);
320405b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq);
320505b261ecSmrg
320605b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
320705b261ecSmrg	return BadAccess;
320805b261ecSmrg
32094642e01fSmrg    CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
321005b261ecSmrg    CHK_ATOM_ONLY(stuff->indicator);
321105b261ecSmrg
321205b261ecSmrg    sli= XkbFindSrvLedInfo(dev,stuff->ledClass,stuff->ledID,0);
321305b261ecSmrg    if (!sli)
321405b261ecSmrg	return BadAlloc;
321505b261ecSmrg
321605b261ecSmrg    i= 0;
321705b261ecSmrg    map= NULL;
321805b261ecSmrg    if ((sli->names)&&(sli->maps)) {
321905b261ecSmrg        for (i=0;i<XkbNumIndicators;i++) {
322005b261ecSmrg            if (stuff->indicator==sli->names[i]) {
322105b261ecSmrg                map= &sli->maps[i];
322205b261ecSmrg                break;
322305b261ecSmrg            }
322405b261ecSmrg        }
322505b261ecSmrg    }
322605b261ecSmrg
322705b261ecSmrg    rep.type= X_Reply;
322805b261ecSmrg    rep.length = 0;
322905b261ecSmrg    rep.sequenceNumber = client->sequence;
323005b261ecSmrg    rep.deviceID = dev->id;
323105b261ecSmrg    rep.indicator= stuff->indicator;
323205b261ecSmrg    if (map!=NULL) {
32336747b715Smrg	rep.found= 		TRUE;
323405b261ecSmrg	rep.on=			((sli->effectiveState&(1<<i))!=0);
323505b261ecSmrg	rep.realIndicator=	((sli->physIndicators&(1<<i))!=0);
323605b261ecSmrg	rep.ndx= 		i;
323705b261ecSmrg	rep.flags= 		map->flags;
323805b261ecSmrg	rep.whichGroups= 	map->which_groups;
323905b261ecSmrg	rep.groups= 		map->groups;
324005b261ecSmrg	rep.whichMods= 		map->which_mods;
324105b261ecSmrg	rep.mods= 		map->mods.mask;
324205b261ecSmrg	rep.realMods= 		map->mods.real_mods;
324305b261ecSmrg	rep.virtualMods= 	map->mods.vmods;
324405b261ecSmrg	rep.ctrls= 		map->ctrls;
32456747b715Smrg	rep.supported= 		TRUE;
324605b261ecSmrg    }
324705b261ecSmrg    else  {
32486747b715Smrg	rep.found= 		FALSE;
32496747b715Smrg	rep.on= 		FALSE;
32506747b715Smrg	rep.realIndicator= 	FALSE;
325105b261ecSmrg	rep.ndx= 		XkbNoIndicator;
325205b261ecSmrg	rep.flags= 		0;
325305b261ecSmrg	rep.whichGroups= 	0;
325405b261ecSmrg	rep.groups= 		0;
325505b261ecSmrg	rep.whichMods= 		0;
325605b261ecSmrg	rep.mods=		0;
325705b261ecSmrg	rep.realMods= 		0;
325805b261ecSmrg	rep.virtualMods= 	0;
325905b261ecSmrg	rep.ctrls= 		0;
32606747b715Smrg	rep.supported= 		TRUE;
326105b261ecSmrg    }
326205b261ecSmrg    if ( client->swapped ) {
326305b261ecSmrg	register int n;
326405b261ecSmrg	swapl(&rep.length,n);
326505b261ecSmrg	swaps(&rep.sequenceNumber,n);
326605b261ecSmrg	swapl(&rep.indicator,n);
326705b261ecSmrg	swaps(&rep.virtualMods,n);
326805b261ecSmrg	swapl(&rep.ctrls,n);
326905b261ecSmrg    }
327005b261ecSmrg
327105b261ecSmrg    WriteToClient(client,SIZEOF(xkbGetNamedIndicatorReply), (char *)&rep);
32726747b715Smrg    return Success;
327305b261ecSmrg}
327405b261ecSmrg
327505b261ecSmrg
32764642e01fSmrg/**
32774642e01fSmrg * Find the IM on the device.
32784642e01fSmrg * Returns the map, or NULL if the map doesn't exist.
32794642e01fSmrg * If the return value is NULL, led_return is undefined. Otherwise, led_return
32804642e01fSmrg * is set to the led index of the map.
32814642e01fSmrg */
32824642e01fSmrgstatic XkbIndicatorMapPtr
32834642e01fSmrg_XkbFindNamedIndicatorMap(XkbSrvLedInfoPtr sli, Atom indicator,
32844642e01fSmrg                          int *led_return)
32854642e01fSmrg{
32864642e01fSmrg    XkbIndicatorMapPtr  map;
328705b261ecSmrg
32884642e01fSmrg    /* search for the right indicator */
32894642e01fSmrg    map = NULL;
329005b261ecSmrg    if (sli->names && sli->maps) {
32916747b715Smrg	int led;
32926747b715Smrg
32934642e01fSmrg	for (led = 0; (led < XkbNumIndicators) && (map == NULL); led++) {
32944642e01fSmrg	    if (sli->names[led] == indicator) {
329505b261ecSmrg		map= &sli->maps[led];
32966747b715Smrg		*led_return = led;
329705b261ecSmrg		break;
329805b261ecSmrg	    }
329905b261ecSmrg	}
330005b261ecSmrg    }
330105b261ecSmrg
33024642e01fSmrg    return map;
33034642e01fSmrg}
33044642e01fSmrg
33054642e01fSmrg/**
33066747b715Smrg * Creates an indicator map on the device. If dryRun is TRUE, it only checks
33074642e01fSmrg * if creation is possible, but doesn't actually create it.
33084642e01fSmrg */
33094642e01fSmrgstatic int
33104642e01fSmrg_XkbCreateIndicatorMap(DeviceIntPtr dev, Atom indicator,
33114642e01fSmrg                       int ledClass, int ledID,
33124642e01fSmrg                       XkbIndicatorMapPtr *map_return, int *led_return,
33134642e01fSmrg                       Bool dryRun)
33144642e01fSmrg{
33154642e01fSmrg    XkbSrvLedInfoPtr    sli;
33164642e01fSmrg    XkbIndicatorMapPtr  map;
33174642e01fSmrg    int                 led;
33184642e01fSmrg
33194642e01fSmrg    sli = XkbFindSrvLedInfo(dev, ledClass, ledID, XkbXI_IndicatorsMask);
33204642e01fSmrg    if (!sli)
33214642e01fSmrg        return BadAlloc;
33224642e01fSmrg
33234642e01fSmrg    map = _XkbFindNamedIndicatorMap(sli, indicator, &led);
33244642e01fSmrg
33254642e01fSmrg    if (!map)
33264642e01fSmrg    {
33274642e01fSmrg        /* find first unused indicator maps and assign the name to it */
33284642e01fSmrg        for (led = 0, map = NULL; (led < XkbNumIndicators) && (map == NULL); led++) {
33294642e01fSmrg            if ((sli->names) && (sli->maps) && (sli->names[led] == None) &&
33304642e01fSmrg                    (!XkbIM_InUse(&sli->maps[led])))
33314642e01fSmrg            {
33324642e01fSmrg                map = &sli->maps[led];
33334642e01fSmrg                if (!dryRun)
33344642e01fSmrg                    sli->names[led] = indicator;
33354642e01fSmrg                break;
33364642e01fSmrg            }
33374642e01fSmrg        }
33384642e01fSmrg    }
33394642e01fSmrg
33404642e01fSmrg    if (!map)
33414642e01fSmrg        return BadAlloc;
33424642e01fSmrg
33434642e01fSmrg    *led_return = led;
33444642e01fSmrg    *map_return = map;
33454642e01fSmrg    return Success;
33464642e01fSmrg}
33474642e01fSmrg
33484642e01fSmrgstatic int
33494642e01fSmrg_XkbSetNamedIndicator(ClientPtr client, DeviceIntPtr dev,
33504642e01fSmrg                      xkbSetNamedIndicatorReq *stuff)
33514642e01fSmrg{
33524642e01fSmrg    unsigned int                extDevReason;
33534642e01fSmrg    unsigned int                statec, namec, mapc;
33544642e01fSmrg    XkbSrvLedInfoPtr            sli;
33554642e01fSmrg    int                         led = 0;
33564642e01fSmrg    XkbIndicatorMapPtr          map;
33574642e01fSmrg    DeviceIntPtr                kbd;
33584642e01fSmrg    XkbEventCauseRec            cause;
33594642e01fSmrg    xkbExtensionDeviceNotify    ed;
33604642e01fSmrg    XkbChangesRec               changes;
33614642e01fSmrg    int                         rc;
33624642e01fSmrg
33634642e01fSmrg    rc = _XkbCreateIndicatorMap(dev, stuff->indicator, stuff->ledClass,
33644642e01fSmrg                                stuff->ledID, &map, &led, FALSE);
33654642e01fSmrg    if (rc != Success || !map) /* oh-oh */
33664642e01fSmrg        return rc;
33674642e01fSmrg
33684642e01fSmrg    sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID,
33694642e01fSmrg                            XkbXI_IndicatorsMask);
33704642e01fSmrg    if (!sli)
33714642e01fSmrg        return BadAlloc;
33724642e01fSmrg
33734642e01fSmrg    namec = mapc = statec = 0;
33744642e01fSmrg    extDevReason = 0;
33754642e01fSmrg
33764642e01fSmrg    namec |= (1<<led);
33774642e01fSmrg    sli->namesPresent |= ((stuff->indicator != None) ? (1 << led) : 0);
33784642e01fSmrg    extDevReason |= XkbXI_IndicatorNamesMask;
33794642e01fSmrg
33804642e01fSmrg    if (stuff->setMap) {
33814642e01fSmrg        map->flags = stuff->flags;
33824642e01fSmrg        map->which_groups = stuff->whichGroups;
33834642e01fSmrg        map->groups = stuff->groups;
33844642e01fSmrg        map->which_mods = stuff->whichMods;
33854642e01fSmrg        map->mods.mask = stuff->realMods;
33864642e01fSmrg        map->mods.real_mods = stuff->realMods;
33874642e01fSmrg        map->mods.vmods= stuff->virtualMods;
33884642e01fSmrg        map->ctrls = stuff->ctrls;
33894642e01fSmrg        mapc|= (1<<led);
33904642e01fSmrg    }
33914642e01fSmrg
33924642e01fSmrg    if ((stuff->setState) && ((map->flags & XkbIM_NoExplicit) == 0))
33934642e01fSmrg    {
33944642e01fSmrg        if (stuff->on)	sli->explicitState |=  (1<<led);
33954642e01fSmrg        else		sli->explicitState &= ~(1<<led);
33964642e01fSmrg        statec |= ((sli->effectiveState ^ sli->explicitState) & (1 << led));
339705b261ecSmrg    }
33984642e01fSmrg
33996747b715Smrg    memset((char *)&ed, 0, sizeof(xkbExtensionDeviceNotify));
34006747b715Smrg    memset((char *)&changes, 0, sizeof(XkbChangesRec));
340105b261ecSmrg    XkbSetCauseXkbReq(&cause,X_kbSetNamedIndicator,client);
340205b261ecSmrg    if (namec)
34034642e01fSmrg        XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause);
340405b261ecSmrg    if (mapc)
34054642e01fSmrg        XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause);
340605b261ecSmrg    if (statec)
34074642e01fSmrg        XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause);
340805b261ecSmrg
34094642e01fSmrg    kbd = dev;
341005b261ecSmrg    if ((sli->flags&XkbSLI_HasOwnState)==0)
34114642e01fSmrg        kbd = inputInfo.keyboard;
34124642e01fSmrg    XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause);
34134642e01fSmrg
34144642e01fSmrg    return Success;
34154642e01fSmrg}
34164642e01fSmrg
34174642e01fSmrgint
34184642e01fSmrgProcXkbSetNamedIndicator(ClientPtr client)
34194642e01fSmrg{
34204642e01fSmrg    int                         rc;
34214642e01fSmrg    DeviceIntPtr                dev;
34224642e01fSmrg    int                         led = 0;
34234642e01fSmrg    XkbIndicatorMapPtr          map;
34244642e01fSmrg
34254642e01fSmrg    REQUEST(xkbSetNamedIndicatorReq);
34264642e01fSmrg    REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq);
34274642e01fSmrg
34284642e01fSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
34294642e01fSmrg	return BadAccess;
34304642e01fSmrg
34314642e01fSmrg    CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
34324642e01fSmrg    CHK_ATOM_ONLY(stuff->indicator);
34334642e01fSmrg    CHK_MASK_LEGAL(0x10,stuff->whichGroups,XkbIM_UseAnyGroup);
34344642e01fSmrg    CHK_MASK_LEGAL(0x11,stuff->whichMods,XkbIM_UseAnyMods);
34354642e01fSmrg
34364642e01fSmrg    /* Dry-run for checks */
34374642e01fSmrg    rc = _XkbCreateIndicatorMap(dev, stuff->indicator,
34384642e01fSmrg                                stuff->ledClass, stuff->ledID,
34394642e01fSmrg                                &map, &led, TRUE);
34404642e01fSmrg    if (rc != Success || !map) /* couldn't be created or didn't exist */
34414642e01fSmrg        return rc;
34424642e01fSmrg
34434642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd ||
34444642e01fSmrg        stuff->deviceSpec == XkbUseCorePtr)
34454642e01fSmrg    {
34464642e01fSmrg        DeviceIntPtr other;
34474642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
34484642e01fSmrg        {
34496747b715Smrg            if ((other != dev) && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev &&
345052397711Smrg                (other->kbdfeed || other->leds) &&
34514642e01fSmrg                (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) == Success))
34524642e01fSmrg            {
34534642e01fSmrg                rc = _XkbCreateIndicatorMap(other, stuff->indicator,
34544642e01fSmrg                                            stuff->ledClass, stuff->ledID,
34554642e01fSmrg                                            &map, &led, TRUE);
34564642e01fSmrg                if (rc != Success || !map)
34574642e01fSmrg                    return rc;
34584642e01fSmrg            }
34594642e01fSmrg        }
34604642e01fSmrg    }
34614642e01fSmrg
34624642e01fSmrg    /* All checks passed, let's do it */
34634642e01fSmrg    rc = _XkbSetNamedIndicator(client, dev, stuff);
34644642e01fSmrg    if (rc != Success)
34654642e01fSmrg        return rc;
34664642e01fSmrg
34674642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd ||
34684642e01fSmrg        stuff->deviceSpec == XkbUseCorePtr)
34694642e01fSmrg    {
34704642e01fSmrg        DeviceIntPtr other;
34714642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
34724642e01fSmrg        {
34736747b715Smrg            if ((other != dev) && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev &&
347452397711Smrg                (other->kbdfeed || other->leds) &&
34754642e01fSmrg                (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) == Success))
34764642e01fSmrg            {
34774642e01fSmrg                _XkbSetNamedIndicator(client, other, stuff);
34784642e01fSmrg            }
34794642e01fSmrg        }
34804642e01fSmrg    }
34814642e01fSmrg
34826747b715Smrg    return Success;
348305b261ecSmrg}
348405b261ecSmrg
348505b261ecSmrg/***====================================================================***/
348605b261ecSmrg
348705b261ecSmrgstatic CARD32
348805b261ecSmrg_XkbCountAtoms(Atom *atoms,int maxAtoms,int *count)
348905b261ecSmrg{
349005b261ecSmrgregister unsigned int i,bit,nAtoms;
349105b261ecSmrgregister CARD32 atomsPresent;
349205b261ecSmrg
349305b261ecSmrg    for (i=nAtoms=atomsPresent=0,bit=1;i<maxAtoms;i++,bit<<=1) {
349405b261ecSmrg	if (atoms[i]!=None) {
349505b261ecSmrg	    atomsPresent|= bit;
349605b261ecSmrg	    nAtoms++;
349705b261ecSmrg	}
349805b261ecSmrg    }
349905b261ecSmrg    if (count)
350005b261ecSmrg	*count= nAtoms;
350105b261ecSmrg    return atomsPresent;
350205b261ecSmrg}
350305b261ecSmrg
350405b261ecSmrgstatic char *
350505b261ecSmrg_XkbWriteAtoms(char *wire,Atom *atoms,int maxAtoms,int swap)
350605b261ecSmrg{
350705b261ecSmrgregister unsigned int i;
350805b261ecSmrgAtom *atm;
350905b261ecSmrg
351005b261ecSmrg    atm = (Atom *)wire;
351105b261ecSmrg    for (i=0;i<maxAtoms;i++) {
351205b261ecSmrg	if (atoms[i]!=None) {
351305b261ecSmrg	    *atm= atoms[i];
351405b261ecSmrg	    if (swap) {
351505b261ecSmrg		register int n;
351605b261ecSmrg		swapl(atm,n);
351705b261ecSmrg	    }
351805b261ecSmrg	    atm++;
351905b261ecSmrg	}
352005b261ecSmrg    }
352105b261ecSmrg    return (char *)atm;
352205b261ecSmrg}
352305b261ecSmrg
352405b261ecSmrgstatic Status
352505b261ecSmrgXkbComputeGetNamesReplySize(XkbDescPtr xkb,xkbGetNamesReply *rep)
352605b261ecSmrg{
352705b261ecSmrgregister unsigned	which,length;
352805b261ecSmrgregister int		i;
352905b261ecSmrg
353005b261ecSmrg    rep->minKeyCode= xkb->min_key_code;
353105b261ecSmrg    rep->maxKeyCode= xkb->max_key_code;
353205b261ecSmrg    which= rep->which;
353305b261ecSmrg    length= 0;
353405b261ecSmrg    if (xkb->names!=NULL) {
353505b261ecSmrg	 if (which&XkbKeycodesNameMask)		length++;
353605b261ecSmrg	 if (which&XkbGeometryNameMask)		length++;
353705b261ecSmrg	 if (which&XkbSymbolsNameMask)		length++;
353805b261ecSmrg	 if (which&XkbPhysSymbolsNameMask)	length++;
353905b261ecSmrg	 if (which&XkbTypesNameMask)		length++;
354005b261ecSmrg	 if (which&XkbCompatNameMask)		length++;
354105b261ecSmrg    }
354205b261ecSmrg    else which&= ~XkbComponentNamesMask;
354305b261ecSmrg
354405b261ecSmrg    if (xkb->map!=NULL) {
354505b261ecSmrg	if (which&XkbKeyTypeNamesMask)
354605b261ecSmrg	    length+= xkb->map->num_types;
354705b261ecSmrg	rep->nTypes= xkb->map->num_types;
354805b261ecSmrg	if (which&XkbKTLevelNamesMask) {
354905b261ecSmrg	    XkbKeyTypePtr	pType = xkb->map->types;
355005b261ecSmrg	    int			nKTLevels = 0;
355105b261ecSmrg
355205b261ecSmrg	    length+= XkbPaddedSize(xkb->map->num_types)/4;
355305b261ecSmrg	    for (i=0;i<xkb->map->num_types;i++,pType++) {
355405b261ecSmrg		if (pType->level_names!=NULL)
355505b261ecSmrg		    nKTLevels+= pType->num_levels;
355605b261ecSmrg	    }
355705b261ecSmrg	    rep->nKTLevels= nKTLevels;
355805b261ecSmrg	    length+= nKTLevels;
355905b261ecSmrg	}
356005b261ecSmrg    }
356105b261ecSmrg    else {
356205b261ecSmrg	rep->nTypes=    0;
356305b261ecSmrg	rep->nKTLevels= 0;
356405b261ecSmrg	which&= ~(XkbKeyTypeNamesMask|XkbKTLevelNamesMask);
356505b261ecSmrg    }
356605b261ecSmrg
356705b261ecSmrg    rep->minKeyCode= xkb->min_key_code;
356805b261ecSmrg    rep->maxKeyCode= xkb->max_key_code;
356905b261ecSmrg    rep->indicators= 0;
357005b261ecSmrg    rep->virtualMods= 0;
357105b261ecSmrg    rep->groupNames= 0;
357205b261ecSmrg    if (xkb->names!=NULL) {
357305b261ecSmrg	if (which&XkbIndicatorNamesMask) {
357405b261ecSmrg	    int nLeds;
357505b261ecSmrg	    rep->indicators=
357605b261ecSmrg		_XkbCountAtoms(xkb->names->indicators,XkbNumIndicators,&nLeds);
357705b261ecSmrg	    length+= nLeds;
357805b261ecSmrg	    if (nLeds==0)
357905b261ecSmrg		which&= ~XkbIndicatorNamesMask;
358005b261ecSmrg	}
358105b261ecSmrg
358205b261ecSmrg	if (which&XkbVirtualModNamesMask) {
358305b261ecSmrg	    int nVMods;
358405b261ecSmrg	    rep->virtualMods=
358505b261ecSmrg		_XkbCountAtoms(xkb->names->vmods,XkbNumVirtualMods,&nVMods);
358605b261ecSmrg	    length+= nVMods;
358705b261ecSmrg	    if (nVMods==0)
358805b261ecSmrg		which&= ~XkbVirtualModNamesMask;
358905b261ecSmrg	}
359005b261ecSmrg
359105b261ecSmrg	if (which&XkbGroupNamesMask) {
359205b261ecSmrg	    int nGroups;
359305b261ecSmrg	    rep->groupNames=
359405b261ecSmrg		_XkbCountAtoms(xkb->names->groups,XkbNumKbdGroups,&nGroups);
359505b261ecSmrg	    length+= nGroups;
359605b261ecSmrg	    if (nGroups==0)
359705b261ecSmrg		which&= ~XkbGroupNamesMask;
359805b261ecSmrg	}
359905b261ecSmrg
360005b261ecSmrg	if ((which&XkbKeyNamesMask)&&(xkb->names->keys))
360105b261ecSmrg	     length+= rep->nKeys;
360205b261ecSmrg	else which&= ~XkbKeyNamesMask;
360305b261ecSmrg
360405b261ecSmrg	if ((which&XkbKeyAliasesMask)&&
360505b261ecSmrg	    (xkb->names->key_aliases)&&(xkb->names->num_key_aliases>0)) {
360605b261ecSmrg	    rep->nKeyAliases= xkb->names->num_key_aliases;
360705b261ecSmrg	    length+= rep->nKeyAliases*2;
360805b261ecSmrg	}
360905b261ecSmrg	else {
361005b261ecSmrg	    which&= ~XkbKeyAliasesMask;
361105b261ecSmrg	    rep->nKeyAliases= 0;
361205b261ecSmrg	}
361305b261ecSmrg
361405b261ecSmrg	if ((which&XkbRGNamesMask)&&(xkb->names->num_rg>0))
361505b261ecSmrg	     length+= xkb->names->num_rg;
361605b261ecSmrg	else which&= ~XkbRGNamesMask;
361705b261ecSmrg    }
361805b261ecSmrg    else {
361905b261ecSmrg	which&= ~(XkbIndicatorNamesMask|XkbVirtualModNamesMask);
362005b261ecSmrg	which&= ~(XkbGroupNamesMask|XkbKeyNamesMask|XkbKeyAliasesMask);
362105b261ecSmrg	which&= ~XkbRGNamesMask;
362205b261ecSmrg    }
362305b261ecSmrg
362405b261ecSmrg    rep->length= length;
362505b261ecSmrg    rep->which= which;
362605b261ecSmrg    return Success;
362705b261ecSmrg}
362805b261ecSmrg
362905b261ecSmrgstatic int
363005b261ecSmrgXkbSendNames(ClientPtr client,XkbDescPtr xkb,xkbGetNamesReply *rep)
363105b261ecSmrg{
363205b261ecSmrgregister unsigned 	i,length,which;
363305b261ecSmrgchar *			start;
363405b261ecSmrgchar *			desc;
363505b261ecSmrgregister int            n;
363605b261ecSmrg
363705b261ecSmrg    length= rep->length*4;
363805b261ecSmrg    which= rep->which;
363905b261ecSmrg    if (client->swapped) {
364005b261ecSmrg	swaps(&rep->sequenceNumber,n);
364105b261ecSmrg	swapl(&rep->length,n);
364205b261ecSmrg	swapl(&rep->which,n);
364305b261ecSmrg	swaps(&rep->virtualMods,n);
364405b261ecSmrg	swapl(&rep->indicators,n);
364505b261ecSmrg    }
364605b261ecSmrg
36479ace9065Smrg    start = desc = calloc(1, length);
364805b261ecSmrg    if ( !start )
364905b261ecSmrg	return BadAlloc;
365005b261ecSmrg    if (xkb->names) {
365105b261ecSmrg        if (which&XkbKeycodesNameMask) {
365205b261ecSmrg            *((CARD32 *)desc)= xkb->names->keycodes;
365305b261ecSmrg            if (client->swapped) {
365405b261ecSmrg                swapl(desc,n);
365505b261ecSmrg            }
365605b261ecSmrg            desc+= 4;
365705b261ecSmrg        }
365805b261ecSmrg        if (which&XkbGeometryNameMask)  {
365905b261ecSmrg            *((CARD32 *)desc)= xkb->names->geometry;
366005b261ecSmrg            if (client->swapped) {
366105b261ecSmrg                swapl(desc,n);
366205b261ecSmrg            }
366305b261ecSmrg            desc+= 4;
366405b261ecSmrg        }
366505b261ecSmrg        if (which&XkbSymbolsNameMask) {
366605b261ecSmrg            *((CARD32 *)desc)= xkb->names->symbols;
366705b261ecSmrg            if (client->swapped) {
366805b261ecSmrg                swapl(desc,n);
366905b261ecSmrg            }
367005b261ecSmrg            desc+= 4;
367105b261ecSmrg        }
367205b261ecSmrg        if (which&XkbPhysSymbolsNameMask) {
367305b261ecSmrg            register CARD32 *atm= (CARD32 *)desc;
367405b261ecSmrg            atm[0]= (CARD32)xkb->names->phys_symbols;
367505b261ecSmrg            if (client->swapped) {
367605b261ecSmrg                swapl(&atm[0],n);
367705b261ecSmrg            }
367805b261ecSmrg            desc+= 4;
367905b261ecSmrg        }
368005b261ecSmrg        if (which&XkbTypesNameMask) {
368105b261ecSmrg            *((CARD32 *)desc)= (CARD32)xkb->names->types;
368205b261ecSmrg            if (client->swapped) {
368305b261ecSmrg                swapl(desc,n);
368405b261ecSmrg            }
368505b261ecSmrg            desc+= 4;
368605b261ecSmrg        }
368705b261ecSmrg        if (which&XkbCompatNameMask) {
368805b261ecSmrg            *((CARD32 *)desc)= (CARD32)xkb->names->compat;
368905b261ecSmrg            if (client->swapped) {
369005b261ecSmrg                swapl(desc,n);
369105b261ecSmrg            }
369205b261ecSmrg            desc+= 4;
369305b261ecSmrg        }
369405b261ecSmrg        if (which&XkbKeyTypeNamesMask) {
369505b261ecSmrg            register CARD32 *atm= (CARD32 *)desc;
369605b261ecSmrg            register XkbKeyTypePtr type= xkb->map->types;
369705b261ecSmrg
369805b261ecSmrg            for (i=0;i<xkb->map->num_types;i++,atm++,type++) {
369905b261ecSmrg                *atm= (CARD32)type->name;
370005b261ecSmrg                if (client->swapped) {
370105b261ecSmrg                    swapl(atm,n);
370205b261ecSmrg                }
370305b261ecSmrg            }
370405b261ecSmrg            desc= (char *)atm;
370505b261ecSmrg        }
370605b261ecSmrg        if (which&XkbKTLevelNamesMask && xkb->map) {
370705b261ecSmrg            XkbKeyTypePtr type = xkb->map->types;
370805b261ecSmrg            register CARD32 *atm;
370905b261ecSmrg            for (i=0;i<rep->nTypes;i++,type++) {
371005b261ecSmrg                *desc++ = type->num_levels;
371105b261ecSmrg            }
371205b261ecSmrg            desc+= XkbPaddedSize(rep->nTypes)-rep->nTypes;
371305b261ecSmrg
371405b261ecSmrg            atm= (CARD32 *)desc;
371505b261ecSmrg            type = xkb->map->types;
371605b261ecSmrg            for (i=0;i<xkb->map->num_types;i++,type++) {
371705b261ecSmrg                register unsigned l;
371805b261ecSmrg                if (type->level_names) {
371905b261ecSmrg                    for (l=0;l<type->num_levels;l++,atm++) {
372005b261ecSmrg                        *atm= type->level_names[l];
372105b261ecSmrg                        if (client->swapped) {
372205b261ecSmrg                            swapl(atm,n);
372305b261ecSmrg                        }
372405b261ecSmrg                    }
372505b261ecSmrg                    desc+= type->num_levels*4;
372605b261ecSmrg                }
372705b261ecSmrg            }
372805b261ecSmrg        }
372905b261ecSmrg        if (which&XkbIndicatorNamesMask) {
373005b261ecSmrg            desc= _XkbWriteAtoms(desc,xkb->names->indicators,XkbNumIndicators,
373105b261ecSmrg                                 client->swapped);
373205b261ecSmrg        }
373305b261ecSmrg        if (which&XkbVirtualModNamesMask) {
373405b261ecSmrg            desc= _XkbWriteAtoms(desc,xkb->names->vmods,XkbNumVirtualMods,
373505b261ecSmrg                                 client->swapped);
373605b261ecSmrg        }
373705b261ecSmrg        if (which&XkbGroupNamesMask) {
373805b261ecSmrg            desc= _XkbWriteAtoms(desc,xkb->names->groups,XkbNumKbdGroups,
373905b261ecSmrg                                 client->swapped);
374005b261ecSmrg        }
374105b261ecSmrg        if (which&XkbKeyNamesMask) {
374205b261ecSmrg            for (i=0;i<rep->nKeys;i++,desc+= sizeof(XkbKeyNameRec)) {
374305b261ecSmrg                *((XkbKeyNamePtr)desc)= xkb->names->keys[i+rep->firstKey];
374405b261ecSmrg            }
374505b261ecSmrg        }
374605b261ecSmrg        if (which&XkbKeyAliasesMask) {
374705b261ecSmrg            XkbKeyAliasPtr	pAl;
374805b261ecSmrg            pAl= xkb->names->key_aliases;
374905b261ecSmrg            for (i=0;i<rep->nKeyAliases;i++,pAl++,desc+=2*XkbKeyNameLength) {
375005b261ecSmrg                *((XkbKeyAliasPtr)desc)= *pAl;
375105b261ecSmrg            }
375205b261ecSmrg        }
375305b261ecSmrg        if ((which&XkbRGNamesMask)&&(rep->nRadioGroups>0)) {
375405b261ecSmrg            register CARD32	*atm= (CARD32 *)desc;
375505b261ecSmrg            for (i=0;i<rep->nRadioGroups;i++,atm++) {
375605b261ecSmrg                *atm= (CARD32)xkb->names->radio_groups[i];
375705b261ecSmrg                if (client->swapped) {
375805b261ecSmrg                    swapl(atm,n);
375905b261ecSmrg                }
376005b261ecSmrg            }
376105b261ecSmrg            desc+= rep->nRadioGroups*4;
376205b261ecSmrg        }
376305b261ecSmrg    }
376405b261ecSmrg
376505b261ecSmrg    if ((desc-start)!=(length)) {
37664642e01fSmrg	ErrorF("[xkb] BOGUS LENGTH in write names, expected %d, got %ld\n",
376705b261ecSmrg					length, (unsigned long)(desc-start));
376805b261ecSmrg    }
376905b261ecSmrg    WriteToClient(client, SIZEOF(xkbGetNamesReply), (char *)rep);
377005b261ecSmrg    WriteToClient(client, length, start);
37716747b715Smrg    free((char *)start);
37726747b715Smrg    return Success;
377305b261ecSmrg}
377405b261ecSmrg
377505b261ecSmrgint
377605b261ecSmrgProcXkbGetNames(ClientPtr client)
377705b261ecSmrg{
377805b261ecSmrg    DeviceIntPtr	dev;
377905b261ecSmrg    XkbDescPtr		xkb;
378005b261ecSmrg    xkbGetNamesReply 	rep;
378105b261ecSmrg
378205b261ecSmrg    REQUEST(xkbGetNamesReq);
378305b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetNamesReq);
378405b261ecSmrg
378505b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
378605b261ecSmrg	return BadAccess;
378705b261ecSmrg
37884642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
378905b261ecSmrg    CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask);
379005b261ecSmrg
379105b261ecSmrg    xkb = dev->key->xkbInfo->desc;
37926747b715Smrg    memset(&rep, 0, sizeof(xkbGetNamesReply));
379305b261ecSmrg    rep.type= X_Reply;
379405b261ecSmrg    rep.sequenceNumber= client->sequence;
379505b261ecSmrg    rep.length = 0;
379605b261ecSmrg    rep.deviceID = dev->id;
379705b261ecSmrg    rep.which = stuff->which;
379805b261ecSmrg    rep.nTypes = xkb->map->num_types;
379905b261ecSmrg    rep.firstKey = xkb->min_key_code;
380005b261ecSmrg    rep.nKeys = XkbNumKeys(xkb);
380105b261ecSmrg    if (xkb->names!=NULL) {
380205b261ecSmrg	rep.nKeyAliases= xkb->names->num_key_aliases;
380305b261ecSmrg	rep.nRadioGroups = xkb->names->num_rg;
380405b261ecSmrg    }
380505b261ecSmrg    else {
380605b261ecSmrg	rep.nKeyAliases= rep.nRadioGroups= 0;
380705b261ecSmrg    }
380805b261ecSmrg    XkbComputeGetNamesReplySize(xkb,&rep);
380905b261ecSmrg    return XkbSendNames(client,xkb,&rep);
381005b261ecSmrg}
381105b261ecSmrg
381205b261ecSmrg/***====================================================================***/
381305b261ecSmrg
381405b261ecSmrgstatic CARD32 *
381505b261ecSmrg_XkbCheckAtoms(CARD32 *wire,int nAtoms,int swapped,Atom *pError)
381605b261ecSmrg{
381705b261ecSmrgregister int i;
381805b261ecSmrg
381905b261ecSmrg    for (i=0;i<nAtoms;i++,wire++) {
382005b261ecSmrg	if (swapped) {
382105b261ecSmrg	    register int n;
382205b261ecSmrg	    swapl(wire,n);
382305b261ecSmrg	}
382405b261ecSmrg	if ((((Atom)*wire)!=None)&&(!ValidAtom((Atom)*wire))) {
382505b261ecSmrg	    *pError= ((Atom)*wire);
382605b261ecSmrg	    return NULL;
382705b261ecSmrg	}
382805b261ecSmrg    }
382905b261ecSmrg    return wire;
383005b261ecSmrg}
383105b261ecSmrg
383205b261ecSmrgstatic CARD32 *
383305b261ecSmrg_XkbCheckMaskedAtoms(CARD32 *wire,int nAtoms,CARD32 present,int swapped,
383405b261ecSmrg								Atom *pError)
383505b261ecSmrg{
383605b261ecSmrgregister unsigned i,bit;
383705b261ecSmrg
383805b261ecSmrg    for (i=0,bit=1;(i<nAtoms)&&(present);i++,bit<<=1) {
383905b261ecSmrg	if ((present&bit)==0)
384005b261ecSmrg	    continue;
384105b261ecSmrg	if (swapped) {
384205b261ecSmrg	    register int n;
384305b261ecSmrg	    swapl(wire,n);
384405b261ecSmrg	}
384505b261ecSmrg	if ((((Atom)*wire)!=None)&&(!ValidAtom(((Atom)*wire)))) {
384605b261ecSmrg	    *pError= (Atom)*wire;
384705b261ecSmrg	    return NULL;
384805b261ecSmrg	}
384905b261ecSmrg	wire++;
385005b261ecSmrg    }
385105b261ecSmrg    return wire;
385205b261ecSmrg}
385305b261ecSmrg
385405b261ecSmrgstatic Atom *
385505b261ecSmrg_XkbCopyMaskedAtoms(	Atom	*wire,
385605b261ecSmrg    			Atom	*dest,
385705b261ecSmrg			int   	 nAtoms,
385805b261ecSmrg			CARD32	 present)
385905b261ecSmrg{
386005b261ecSmrgregister int i,bit;
386105b261ecSmrg
386205b261ecSmrg    for (i=0,bit=1;(i<nAtoms)&&(present);i++,bit<<=1) {
386305b261ecSmrg	if ((present&bit)==0)
386405b261ecSmrg	    continue;
386505b261ecSmrg	dest[i]= *wire++;
386605b261ecSmrg    }
386705b261ecSmrg    return wire;
386805b261ecSmrg}
386905b261ecSmrg
387005b261ecSmrgstatic Bool
387105b261ecSmrg_XkbCheckTypeName(Atom name,int typeNdx)
387205b261ecSmrg{
38736747b715Smrgconst char *	str;
387405b261ecSmrg
387505b261ecSmrg    str= NameForAtom(name);
387605b261ecSmrg    if ((strcmp(str,"ONE_LEVEL")==0)||(strcmp(str,"TWO_LEVEL")==0)||
387705b261ecSmrg	(strcmp(str,"ALPHABETIC")==0)||(strcmp(str,"KEYPAD")==0))
38786747b715Smrg	return FALSE;
38796747b715Smrg    return TRUE;
388005b261ecSmrg}
388105b261ecSmrg
38824642e01fSmrg/**
38834642e01fSmrg * Check the device-dependent data in the request against the device. Returns
38844642e01fSmrg * Success, or the appropriate error code.
38854642e01fSmrg */
38864642e01fSmrgstatic int
38874642e01fSmrg_XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
38884642e01fSmrg                  xkbSetNamesReq *stuff, CARD32 *data)
388905b261ecSmrg{
389005b261ecSmrg    XkbDescRec		*xkb;
389105b261ecSmrg    XkbNamesRec		*names;
389205b261ecSmrg    CARD32		*tmp;
389305b261ecSmrg    Atom		 bad;
389405b261ecSmrg
38954642e01fSmrg    tmp = data;
38964642e01fSmrg    xkb = dev->key->xkbInfo->desc;
38974642e01fSmrg    names = xkb->names;
38984642e01fSmrg
38994642e01fSmrg
39004642e01fSmrg    if (stuff->which & XkbKeyTypeNamesMask) {
39014642e01fSmrg        int i;
39024642e01fSmrg        CARD32	*old;
39034642e01fSmrg        if ( stuff->nTypes<1 ) {
39044642e01fSmrg            client->errorValue = _XkbErrCode2(0x02,stuff->nTypes);
39054642e01fSmrg            return BadValue;
39064642e01fSmrg        }
39074642e01fSmrg        if ((unsigned)(stuff->firstType+stuff->nTypes-1)>=xkb->map->num_types) {
39084642e01fSmrg            client->errorValue = _XkbErrCode4(0x03,stuff->firstType,
39094642e01fSmrg                    stuff->nTypes,
39104642e01fSmrg                    xkb->map->num_types);
39114642e01fSmrg            return BadValue;
39124642e01fSmrg        }
39134642e01fSmrg        if (((unsigned)stuff->firstType)<=XkbLastRequiredType) {
39144642e01fSmrg            client->errorValue = _XkbErrCode2(0x04,stuff->firstType);
39154642e01fSmrg            return BadAccess;
39164642e01fSmrg        }
39174642e01fSmrg        old= tmp;
39184642e01fSmrg        tmp= _XkbCheckAtoms(tmp,stuff->nTypes,client->swapped,&bad);
39194642e01fSmrg        if (!tmp) {
39204642e01fSmrg            client->errorValue= bad;
39214642e01fSmrg            return BadAtom;
39224642e01fSmrg        }
39234642e01fSmrg        for (i=0;i<stuff->nTypes;i++,old++) {
39244642e01fSmrg            if (!_XkbCheckTypeName((Atom)*old,stuff->firstType+i))
39254642e01fSmrg                client->errorValue= _XkbErrCode2(0x05,i);
39264642e01fSmrg        }
39274642e01fSmrg    }
39284642e01fSmrg    if (stuff->which&XkbKTLevelNamesMask) {
39294642e01fSmrg        unsigned i;
39304642e01fSmrg        XkbKeyTypePtr	type;
39314642e01fSmrg        CARD8 *		width;
39324642e01fSmrg        if ( stuff->nKTLevels<1 ) {
39334642e01fSmrg            client->errorValue = _XkbErrCode2(0x05,stuff->nKTLevels);
39344642e01fSmrg            return BadValue;
39354642e01fSmrg        }
39364642e01fSmrg        if ((unsigned)(stuff->firstKTLevel+stuff->nKTLevels-1)>=
39374642e01fSmrg                xkb->map->num_types) {
39384642e01fSmrg            client->errorValue = _XkbErrCode4(0x06,stuff->firstKTLevel,
39394642e01fSmrg                    stuff->nKTLevels,xkb->map->num_types);
39404642e01fSmrg            return BadValue;
39414642e01fSmrg        }
39424642e01fSmrg        width = (CARD8 *)tmp;
39434642e01fSmrg        tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels));
39444642e01fSmrg        type = &xkb->map->types[stuff->firstKTLevel];
39454642e01fSmrg        for (i=0;i<stuff->nKTLevels;i++,type++) {
39464642e01fSmrg            if (width[i]==0)
39474642e01fSmrg                continue;
39484642e01fSmrg            else if (width[i]!=type->num_levels) {
39494642e01fSmrg                client->errorValue= _XkbErrCode4(0x07,i+stuff->firstKTLevel,
39504642e01fSmrg                        type->num_levels,width[i]);
39514642e01fSmrg                return BadMatch;
39524642e01fSmrg            }
39534642e01fSmrg            tmp= _XkbCheckAtoms(tmp,width[i],client->swapped,&bad);
39544642e01fSmrg            if (!tmp) {
39554642e01fSmrg                client->errorValue= bad;
39564642e01fSmrg                return BadAtom;
39574642e01fSmrg            }
39584642e01fSmrg        }
39594642e01fSmrg    }
39604642e01fSmrg    if (stuff->which&XkbIndicatorNamesMask) {
39614642e01fSmrg        if (stuff->indicators==0) {
39624642e01fSmrg            client->errorValue= 0x08;
39634642e01fSmrg            return BadMatch;
39644642e01fSmrg        }
39654642e01fSmrg        tmp= _XkbCheckMaskedAtoms(tmp,XkbNumIndicators,stuff->indicators,
39664642e01fSmrg                client->swapped,&bad);
39674642e01fSmrg        if (!tmp) {
39684642e01fSmrg            client->errorValue= bad;
39694642e01fSmrg            return BadAtom;
39704642e01fSmrg        }
39714642e01fSmrg    }
39724642e01fSmrg    if (stuff->which&XkbVirtualModNamesMask) {
39734642e01fSmrg        if (stuff->virtualMods==0) {
39744642e01fSmrg            client->errorValue= 0x09;
39754642e01fSmrg            return BadMatch;
39764642e01fSmrg        }
39774642e01fSmrg        tmp= _XkbCheckMaskedAtoms(tmp,XkbNumVirtualMods,
39784642e01fSmrg                (CARD32)stuff->virtualMods,
39794642e01fSmrg                client->swapped,&bad);
39804642e01fSmrg        if (!tmp) {
39814642e01fSmrg            client->errorValue = bad;
39824642e01fSmrg            return BadAtom;
39834642e01fSmrg        }
39844642e01fSmrg    }
39854642e01fSmrg    if (stuff->which&XkbGroupNamesMask) {
39864642e01fSmrg        if (stuff->groupNames==0) {
39874642e01fSmrg            client->errorValue= 0x0a;
39884642e01fSmrg            return BadMatch;
39894642e01fSmrg        }
39904642e01fSmrg        tmp= _XkbCheckMaskedAtoms(tmp,XkbNumKbdGroups,
39914642e01fSmrg                (CARD32)stuff->groupNames,
39924642e01fSmrg                client->swapped,&bad);
39934642e01fSmrg        if (!tmp) {
39944642e01fSmrg            client->errorValue = bad;
39954642e01fSmrg            return BadAtom;
39964642e01fSmrg        }
39974642e01fSmrg    }
39984642e01fSmrg    if (stuff->which&XkbKeyNamesMask) {
39994642e01fSmrg        if (stuff->firstKey<(unsigned)xkb->min_key_code) {
40004642e01fSmrg            client->errorValue= _XkbErrCode3(0x0b,xkb->min_key_code,
40014642e01fSmrg                    stuff->firstKey);
40024642e01fSmrg            return BadValue;
40034642e01fSmrg        }
40044642e01fSmrg        if (((unsigned)(stuff->firstKey+stuff->nKeys-1)>xkb->max_key_code)||
40054642e01fSmrg                (stuff->nKeys<1)) {
40064642e01fSmrg            client->errorValue= _XkbErrCode4(0x0c,xkb->max_key_code,
40074642e01fSmrg                    stuff->firstKey,stuff->nKeys);
40084642e01fSmrg            return BadValue;
40094642e01fSmrg        }
40104642e01fSmrg        tmp+= stuff->nKeys;
40114642e01fSmrg    }
40124642e01fSmrg    if ((stuff->which&XkbKeyAliasesMask)&&(stuff->nKeyAliases>0)) {
40134642e01fSmrg        tmp+= stuff->nKeyAliases*2;
40144642e01fSmrg    }
40154642e01fSmrg    if (stuff->which&XkbRGNamesMask) {
40164642e01fSmrg        if ( stuff->nRadioGroups<1 ) {
40174642e01fSmrg            client->errorValue= _XkbErrCode2(0x0d,stuff->nRadioGroups);
40184642e01fSmrg            return BadValue;
40194642e01fSmrg        }
40204642e01fSmrg        tmp= _XkbCheckAtoms(tmp,stuff->nRadioGroups,client->swapped,&bad);
40214642e01fSmrg        if (!tmp) {
40224642e01fSmrg            client->errorValue= bad;
40234642e01fSmrg            return BadAtom;
40244642e01fSmrg        }
40254642e01fSmrg    }
40264642e01fSmrg    if ((tmp-((CARD32 *)stuff))!=stuff->length) {
40274642e01fSmrg        client->errorValue = stuff->length;
40284642e01fSmrg        return BadLength;
40294642e01fSmrg    }
40304642e01fSmrg
40314642e01fSmrg
40324642e01fSmrg
40334642e01fSmrg    return Success;
40344642e01fSmrg}
40354642e01fSmrg
40364642e01fSmrgstatic int
40374642e01fSmrg_XkbSetNames(ClientPtr client, DeviceIntPtr dev, xkbSetNamesReq *stuff)
40384642e01fSmrg{
40394642e01fSmrg    XkbDescRec		*xkb;
40404642e01fSmrg    XkbNamesRec		*names;
40414642e01fSmrg    CARD32		*tmp;
40424642e01fSmrg    xkbNamesNotify	 nn;
40434642e01fSmrg
40444642e01fSmrg    tmp = (CARD32 *)&stuff[1];
40454642e01fSmrg    xkb = dev->key->xkbInfo->desc;
40464642e01fSmrg    names = xkb->names;
40474642e01fSmrg
40484642e01fSmrg    if (XkbAllocNames(xkb,stuff->which,stuff->nRadioGroups,
40494642e01fSmrg                stuff->nKeyAliases)!=Success) {
40504642e01fSmrg        return BadAlloc;
40514642e01fSmrg    }
40524642e01fSmrg
40536747b715Smrg    memset(&nn, 0, sizeof(xkbNamesNotify));
40544642e01fSmrg    nn.changed= stuff->which;
40554642e01fSmrg    tmp = (CARD32 *)&stuff[1];
40564642e01fSmrg    if (stuff->which&XkbKeycodesNameMask)
40574642e01fSmrg        names->keycodes= *tmp++;
40584642e01fSmrg    if (stuff->which&XkbGeometryNameMask)
40594642e01fSmrg        names->geometry= *tmp++;
40604642e01fSmrg    if (stuff->which&XkbSymbolsNameMask)
40614642e01fSmrg        names->symbols= *tmp++;
40624642e01fSmrg    if (stuff->which&XkbPhysSymbolsNameMask)
40634642e01fSmrg        names->phys_symbols= *tmp++;
40644642e01fSmrg    if (stuff->which&XkbTypesNameMask)
40654642e01fSmrg        names->types= *tmp++;
40664642e01fSmrg    if (stuff->which&XkbCompatNameMask)
40674642e01fSmrg        names->compat= *tmp++;
40684642e01fSmrg    if ((stuff->which&XkbKeyTypeNamesMask)&&(stuff->nTypes>0)) {
40694642e01fSmrg        register unsigned i;
40704642e01fSmrg        register XkbKeyTypePtr type;
40714642e01fSmrg
40724642e01fSmrg        type= &xkb->map->types[stuff->firstType];
40734642e01fSmrg        for (i=0;i<stuff->nTypes;i++,type++) {
40744642e01fSmrg            type->name= *tmp++;
40754642e01fSmrg        }
40764642e01fSmrg        nn.firstType= stuff->firstType;
40774642e01fSmrg        nn.nTypes= stuff->nTypes;
40784642e01fSmrg    }
40794642e01fSmrg    if (stuff->which&XkbKTLevelNamesMask) {
40804642e01fSmrg        register XkbKeyTypePtr	type;
40814642e01fSmrg        register unsigned i;
40824642e01fSmrg        CARD8 *width;
40834642e01fSmrg
40844642e01fSmrg        width = (CARD8 *)tmp;
40854642e01fSmrg        tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels));
40864642e01fSmrg        type= &xkb->map->types[stuff->firstKTLevel];
40874642e01fSmrg        for (i=0;i<stuff->nKTLevels;i++,type++) {
40884642e01fSmrg            if (width[i]>0) {
40894642e01fSmrg                if (type->level_names) {
40904642e01fSmrg                    register unsigned n;
40914642e01fSmrg                    for (n=0;n<width[i];n++) {
40924642e01fSmrg                        type->level_names[n]= tmp[n];
40934642e01fSmrg                    }
40944642e01fSmrg                }
40954642e01fSmrg                tmp+= width[i];
40964642e01fSmrg            }
40974642e01fSmrg        }
40984642e01fSmrg        nn.firstLevelName= 0;
40994642e01fSmrg        nn.nLevelNames= stuff->nTypes;
41004642e01fSmrg    }
41014642e01fSmrg    if (stuff->which&XkbIndicatorNamesMask) {
41024642e01fSmrg        tmp= _XkbCopyMaskedAtoms(tmp,names->indicators,XkbNumIndicators,
41034642e01fSmrg                stuff->indicators);
41044642e01fSmrg        nn.changedIndicators= stuff->indicators;
41054642e01fSmrg    }
41064642e01fSmrg    if (stuff->which&XkbVirtualModNamesMask) {
41074642e01fSmrg        tmp= _XkbCopyMaskedAtoms(tmp,names->vmods,XkbNumVirtualMods,
41084642e01fSmrg                stuff->virtualMods);
41094642e01fSmrg        nn.changedVirtualMods= stuff->virtualMods;
41104642e01fSmrg    }
41114642e01fSmrg    if (stuff->which&XkbGroupNamesMask) {
41124642e01fSmrg        tmp= _XkbCopyMaskedAtoms(tmp,names->groups,XkbNumKbdGroups,
41134642e01fSmrg                stuff->groupNames);
41144642e01fSmrg        nn.changedVirtualMods= stuff->groupNames;
41154642e01fSmrg    }
41164642e01fSmrg    if (stuff->which&XkbKeyNamesMask) {
41174642e01fSmrg        memcpy((char*)&names->keys[stuff->firstKey],(char *)tmp,
41184642e01fSmrg                stuff->nKeys*XkbKeyNameLength);
41194642e01fSmrg        tmp+= stuff->nKeys;
41204642e01fSmrg        nn.firstKey= stuff->firstKey;
41214642e01fSmrg        nn.nKeys= stuff->nKeys;
41224642e01fSmrg    }
41234642e01fSmrg    if (stuff->which&XkbKeyAliasesMask) {
41244642e01fSmrg        if (stuff->nKeyAliases>0) {
41254642e01fSmrg            register int na= stuff->nKeyAliases;
41264642e01fSmrg            if (XkbAllocNames(xkb,XkbKeyAliasesMask,0,na)!=Success)
41274642e01fSmrg                return BadAlloc;
41284642e01fSmrg            memcpy((char *)names->key_aliases,(char *)tmp,
41294642e01fSmrg                    stuff->nKeyAliases*sizeof(XkbKeyAliasRec));
41304642e01fSmrg            tmp+= stuff->nKeyAliases*2;
41314642e01fSmrg        }
41324642e01fSmrg        else if (names->key_aliases!=NULL) {
41336747b715Smrg            free(names->key_aliases);
41344642e01fSmrg            names->key_aliases= NULL;
41354642e01fSmrg            names->num_key_aliases= 0;
41364642e01fSmrg        }
41374642e01fSmrg        nn.nAliases= names->num_key_aliases;
41384642e01fSmrg    }
41394642e01fSmrg    if (stuff->which&XkbRGNamesMask) {
41404642e01fSmrg        if (stuff->nRadioGroups>0) {
41414642e01fSmrg            register unsigned i,nrg;
41424642e01fSmrg            nrg= stuff->nRadioGroups;
41434642e01fSmrg            if (XkbAllocNames(xkb,XkbRGNamesMask,nrg,0)!=Success)
41444642e01fSmrg                return BadAlloc;
41454642e01fSmrg
41464642e01fSmrg            for (i=0;i<stuff->nRadioGroups;i++) {
41474642e01fSmrg                names->radio_groups[i]= tmp[i];
41484642e01fSmrg            }
41494642e01fSmrg            tmp+= stuff->nRadioGroups;
41504642e01fSmrg        }
41514642e01fSmrg        else if (names->radio_groups) {
41526747b715Smrg            free(names->radio_groups);
41534642e01fSmrg            names->radio_groups= NULL;
41544642e01fSmrg            names->num_rg= 0;
41554642e01fSmrg        }
41564642e01fSmrg        nn.nRadioGroups= names->num_rg;
41574642e01fSmrg    }
41584642e01fSmrg    if (nn.changed) {
41594642e01fSmrg        Bool needExtEvent;
41604642e01fSmrg        needExtEvent= (nn.changed&XkbIndicatorNamesMask)!=0;
41614642e01fSmrg        XkbSendNamesNotify(dev,&nn);
41624642e01fSmrg        if (needExtEvent) {
41634642e01fSmrg            XkbSrvLedInfoPtr		sli;
41644642e01fSmrg            xkbExtensionDeviceNotify	edev;
41654642e01fSmrg            register int		i;
41664642e01fSmrg            register unsigned		bit;
41674642e01fSmrg
41684642e01fSmrg            sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,
41694642e01fSmrg                    XkbXI_IndicatorsMask);
41704642e01fSmrg            sli->namesPresent= 0;
41714642e01fSmrg            for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
41724642e01fSmrg                if (names->indicators[i]!=None)
41734642e01fSmrg                    sli->namesPresent|= bit;
41744642e01fSmrg            }
41756747b715Smrg            memset(&edev, 0, sizeof(xkbExtensionDeviceNotify));
41764642e01fSmrg            edev.reason=	XkbXI_IndicatorNamesMask;
41774642e01fSmrg            edev.ledClass=	KbdFeedbackClass;
41784642e01fSmrg            edev.ledID=		dev->kbdfeed->ctrl.id;
41794642e01fSmrg            edev.ledsDefined= 	sli->namesPresent|sli->mapsPresent;
41804642e01fSmrg            edev.ledState=	sli->effectiveState;
41814642e01fSmrg            edev.firstBtn=	0;
41824642e01fSmrg            edev.nBtns=		0;
41834642e01fSmrg            edev.supported=	XkbXI_AllFeaturesMask;
41844642e01fSmrg            edev.unsupported=	0;
41854642e01fSmrg            XkbSendExtensionDeviceNotify(dev,client,&edev);
41864642e01fSmrg        }
41874642e01fSmrg    }
41884642e01fSmrg    return Success;
41894642e01fSmrg}
41904642e01fSmrg
41914642e01fSmrgint
41924642e01fSmrgProcXkbSetNames(ClientPtr client)
41934642e01fSmrg{
41944642e01fSmrg    DeviceIntPtr	 dev;
41954642e01fSmrg    CARD32		*tmp;
41964642e01fSmrg    Atom                 bad;
41974642e01fSmrg    int                  rc;
41984642e01fSmrg
419905b261ecSmrg    REQUEST(xkbSetNamesReq);
420005b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetNamesReq);
420105b261ecSmrg
420205b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
420305b261ecSmrg	return BadAccess;
420405b261ecSmrg
42054642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
420605b261ecSmrg    CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask);
420705b261ecSmrg
42084642e01fSmrg    /* check device-independent stuff */
420905b261ecSmrg    tmp = (CARD32 *)&stuff[1];
421005b261ecSmrg
421105b261ecSmrg    if (stuff->which&XkbKeycodesNameMask) {
421205b261ecSmrg	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
421305b261ecSmrg	if (!tmp) {
421405b261ecSmrg	    client->errorValue = bad;
421505b261ecSmrg	    return BadAtom;
421605b261ecSmrg	}
421705b261ecSmrg    }
421805b261ecSmrg    if (stuff->which&XkbGeometryNameMask) {
421905b261ecSmrg	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
422005b261ecSmrg	if (!tmp) {
422105b261ecSmrg	    client->errorValue = bad;
422205b261ecSmrg	    return BadAtom;
422305b261ecSmrg	}
422405b261ecSmrg    }
422505b261ecSmrg    if (stuff->which&XkbSymbolsNameMask) {
422605b261ecSmrg	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
422705b261ecSmrg	if (!tmp) {
422805b261ecSmrg	    client->errorValue = bad;
422905b261ecSmrg	    return BadAtom;
423005b261ecSmrg	}
423105b261ecSmrg    }
423205b261ecSmrg    if (stuff->which&XkbPhysSymbolsNameMask) {
423305b261ecSmrg	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
423405b261ecSmrg	if (!tmp) {
423505b261ecSmrg	    client->errorValue= bad;
423605b261ecSmrg	    return BadAtom;
423705b261ecSmrg	}
423805b261ecSmrg    }
423905b261ecSmrg    if (stuff->which&XkbTypesNameMask) {
424005b261ecSmrg	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
424105b261ecSmrg	if (!tmp) {
424205b261ecSmrg	    client->errorValue = bad;
424305b261ecSmrg	    return BadAtom;
424405b261ecSmrg	}
424505b261ecSmrg    }
424605b261ecSmrg    if (stuff->which&XkbCompatNameMask) {
424705b261ecSmrg	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
424805b261ecSmrg	if (!tmp) {
424905b261ecSmrg	    client->errorValue = bad;
425005b261ecSmrg	    return BadAtom;
425105b261ecSmrg	}
425205b261ecSmrg    }
42534642e01fSmrg
42544642e01fSmrg    /* start of device-dependent tests */
42554642e01fSmrg    rc = _XkbSetNamesCheck(client, dev, stuff, tmp);
42564642e01fSmrg    if (rc != Success)
42574642e01fSmrg        return rc;
42584642e01fSmrg
42594642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd)
42604642e01fSmrg    {
42614642e01fSmrg        DeviceIntPtr other;
42624642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
42634642e01fSmrg        {
42646747b715Smrg            if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev)
42654642e01fSmrg            {
42664642e01fSmrg
42674642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
42684642e01fSmrg                if (rc == Success)
42694642e01fSmrg                {
42704642e01fSmrg                    rc = _XkbSetNamesCheck(client, other, stuff, tmp);
42714642e01fSmrg                    if (rc != Success)
42724642e01fSmrg                        return rc;
42734642e01fSmrg                }
42744642e01fSmrg            }
42754642e01fSmrg        }
427605b261ecSmrg    }
427705b261ecSmrg
427805b261ecSmrg    /* everything is okay -- update names */
427905b261ecSmrg
42804642e01fSmrg    rc = _XkbSetNames(client, dev, stuff);
42814642e01fSmrg    if (rc != Success)
42824642e01fSmrg        return rc;
428305b261ecSmrg
42844642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd)
42854642e01fSmrg    {
42864642e01fSmrg        DeviceIntPtr other;
42874642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
42884642e01fSmrg        {
42896747b715Smrg            if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev)
42904642e01fSmrg            {
42914642e01fSmrg
42924642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
42934642e01fSmrg                if (rc == Success)
42944642e01fSmrg                    _XkbSetNames(client, other, stuff);
42954642e01fSmrg            }
42964642e01fSmrg        }
429705b261ecSmrg    }
42984642e01fSmrg
42994642e01fSmrg    /* everything is okay -- update names */
43004642e01fSmrg
43016747b715Smrg    return Success;
430205b261ecSmrg}
430305b261ecSmrg
430405b261ecSmrg/***====================================================================***/
430505b261ecSmrg
43064642e01fSmrg#include "xkbgeom.h"
430705b261ecSmrg
430805b261ecSmrg#define	XkbSizeCountedString(s)  ((s)?((((2+strlen(s))+3)/4)*4):4)
430905b261ecSmrg
431005b261ecSmrgstatic char *
431105b261ecSmrgXkbWriteCountedString(char *wire,char *str,Bool swap)
431205b261ecSmrg{
43139ace9065Smrg    CARD16 len,*pLen, paddedLen;
431405b261ecSmrg
43156747b715Smrg    if (!str)
43166747b715Smrg        return wire;
43176747b715Smrg
43186747b715Smrg    len= strlen(str);
431905b261ecSmrg    pLen= (CARD16 *)wire;
432005b261ecSmrg    *pLen= len;
432105b261ecSmrg    if (swap) {
432205b261ecSmrg	register int n;
432305b261ecSmrg	swaps(pLen,n);
432405b261ecSmrg    }
43259ace9065Smrg    paddedLen= pad_to_int32(sizeof(len)+len)-sizeof(len);
43269ace9065Smrg    strncpy(&wire[sizeof(len)],str,paddedLen);
43279ace9065Smrg    wire+= sizeof(len)+paddedLen;
432805b261ecSmrg    return wire;
432905b261ecSmrg}
433005b261ecSmrg
433105b261ecSmrgstatic int
433205b261ecSmrgXkbSizeGeomProperties(XkbGeometryPtr geom)
433305b261ecSmrg{
433405b261ecSmrgregister int 	i,size;
433505b261ecSmrgXkbPropertyPtr	prop;
433605b261ecSmrg
433705b261ecSmrg    for (size=i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
433805b261ecSmrg	size+= XkbSizeCountedString(prop->name);
433905b261ecSmrg	size+= XkbSizeCountedString(prop->value);
434005b261ecSmrg    }
434105b261ecSmrg    return size;
434205b261ecSmrg}
434305b261ecSmrg
434405b261ecSmrgstatic char *
434505b261ecSmrgXkbWriteGeomProperties(char *wire,XkbGeometryPtr geom,Bool swap)
434605b261ecSmrg{
434705b261ecSmrgregister int 	i;
434805b261ecSmrgregister XkbPropertyPtr	prop;
434905b261ecSmrg
435005b261ecSmrg    for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
435105b261ecSmrg	wire= XkbWriteCountedString(wire,prop->name,swap);
435205b261ecSmrg	wire= XkbWriteCountedString(wire,prop->value,swap);
435305b261ecSmrg    }
435405b261ecSmrg    return wire;
435505b261ecSmrg}
435605b261ecSmrg
435705b261ecSmrgstatic int
435805b261ecSmrgXkbSizeGeomKeyAliases(XkbGeometryPtr geom)
435905b261ecSmrg{
436005b261ecSmrg    return geom->num_key_aliases*(2*XkbKeyNameLength);
436105b261ecSmrg}
436205b261ecSmrg
436305b261ecSmrgstatic char *
436405b261ecSmrgXkbWriteGeomKeyAliases(char *wire,XkbGeometryPtr geom,Bool swap)
436505b261ecSmrg{
436605b261ecSmrgregister int sz;
436705b261ecSmrg
436805b261ecSmrg    sz= geom->num_key_aliases*(XkbKeyNameLength*2);
436905b261ecSmrg    if (sz>0) {
437005b261ecSmrg	memcpy(wire,(char *)geom->key_aliases,sz);
437105b261ecSmrg	wire+= sz;
437205b261ecSmrg    }
437305b261ecSmrg    return wire;
437405b261ecSmrg}
437505b261ecSmrg
437605b261ecSmrgstatic int
437705b261ecSmrgXkbSizeGeomColors(XkbGeometryPtr geom)
437805b261ecSmrg{
437905b261ecSmrgregister int 		i,size;
438005b261ecSmrgregister XkbColorPtr	color;
438105b261ecSmrg
438205b261ecSmrg    for (i=size=0,color=geom->colors;i<geom->num_colors;i++,color++) {
438305b261ecSmrg	size+= XkbSizeCountedString(color->spec);
438405b261ecSmrg    }
438505b261ecSmrg    return size;
438605b261ecSmrg}
438705b261ecSmrg
438805b261ecSmrgstatic char *
438905b261ecSmrgXkbWriteGeomColors(char *wire,XkbGeometryPtr geom,Bool swap)
439005b261ecSmrg{
439105b261ecSmrgregister int		i;
439205b261ecSmrgregister XkbColorPtr	color;
439305b261ecSmrg
439405b261ecSmrg    for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) {
439505b261ecSmrg	wire= XkbWriteCountedString(wire,color->spec,swap);
439605b261ecSmrg    }
439705b261ecSmrg    return wire;
439805b261ecSmrg}
439905b261ecSmrg
440005b261ecSmrgstatic int
440105b261ecSmrgXkbSizeGeomShapes(XkbGeometryPtr geom)
440205b261ecSmrg{
440305b261ecSmrgregister int		i,size;
440405b261ecSmrgregister XkbShapePtr	shape;
440505b261ecSmrg
440605b261ecSmrg    for (i=size=0,shape=geom->shapes;i<geom->num_shapes;i++,shape++) {
440705b261ecSmrg	register int		n;
440805b261ecSmrg	register XkbOutlinePtr	ol;
440905b261ecSmrg	size+= SIZEOF(xkbShapeWireDesc);
441005b261ecSmrg	for (n=0,ol=shape->outlines;n<shape->num_outlines;n++,ol++) {
441105b261ecSmrg	    size+= SIZEOF(xkbOutlineWireDesc);
441205b261ecSmrg	    size+= ol->num_points*SIZEOF(xkbPointWireDesc);
441305b261ecSmrg	}
441405b261ecSmrg    }
441505b261ecSmrg    return size;
441605b261ecSmrg}
441705b261ecSmrg
441805b261ecSmrgstatic char *
441905b261ecSmrgXkbWriteGeomShapes(char *wire,XkbGeometryPtr geom,Bool swap)
442005b261ecSmrg{
442105b261ecSmrgint			i;
442205b261ecSmrgXkbShapePtr		shape;
442305b261ecSmrgxkbShapeWireDesc *	shapeWire;
442405b261ecSmrg
442505b261ecSmrg    for (i=0,shape=geom->shapes;i<geom->num_shapes;i++,shape++) {
442605b261ecSmrg	register int 		o;
442705b261ecSmrg	XkbOutlinePtr		ol;
442805b261ecSmrg	xkbOutlineWireDesc *	olWire;
442905b261ecSmrg	shapeWire= (xkbShapeWireDesc *)wire;
443005b261ecSmrg	shapeWire->name= shape->name;
443105b261ecSmrg	shapeWire->nOutlines= shape->num_outlines;
443205b261ecSmrg	if (shape->primary!=NULL)
443305b261ecSmrg	     shapeWire->primaryNdx= XkbOutlineIndex(shape,shape->primary);
443405b261ecSmrg	else shapeWire->primaryNdx= XkbNoShape;
443505b261ecSmrg	if (shape->approx!=NULL)
443605b261ecSmrg	     shapeWire->approxNdx= XkbOutlineIndex(shape,shape->approx);
443705b261ecSmrg	else shapeWire->approxNdx= XkbNoShape;
44389ace9065Smrg	shapeWire->pad= 0;
443905b261ecSmrg	if (swap) {
444005b261ecSmrg	    register int n;
444105b261ecSmrg	    swapl(&shapeWire->name,n);
444205b261ecSmrg	}
444305b261ecSmrg	wire= (char *)&shapeWire[1];
444405b261ecSmrg	for (o=0,ol=shape->outlines;o<shape->num_outlines;o++,ol++) {
444505b261ecSmrg	    register int	p;
444605b261ecSmrg	    XkbPointPtr		pt;
444705b261ecSmrg	    xkbPointWireDesc *	ptWire;
444805b261ecSmrg	    olWire= (xkbOutlineWireDesc *)wire;
444905b261ecSmrg	    olWire->nPoints= ol->num_points;
445005b261ecSmrg	    olWire->cornerRadius= ol->corner_radius;
44519ace9065Smrg	    olWire->pad= 0;
445205b261ecSmrg	    wire= (char *)&olWire[1];
445305b261ecSmrg	    ptWire= (xkbPointWireDesc *)wire;
445405b261ecSmrg	    for (p=0,pt=ol->points;p<ol->num_points;p++,pt++) {
445505b261ecSmrg		ptWire[p].x= pt->x;
445605b261ecSmrg		ptWire[p].y= pt->y;
445705b261ecSmrg		if (swap) {
445805b261ecSmrg		    register int n;
445905b261ecSmrg		    swaps(&ptWire[p].x,n);
446005b261ecSmrg		    swaps(&ptWire[p].y,n);
446105b261ecSmrg		}
446205b261ecSmrg	    }
446305b261ecSmrg	    wire= (char *)&ptWire[ol->num_points];
446405b261ecSmrg	}
446505b261ecSmrg    }
446605b261ecSmrg    return wire;
446705b261ecSmrg}
446805b261ecSmrg
446905b261ecSmrgstatic int
447005b261ecSmrgXkbSizeGeomDoodads(int num_doodads,XkbDoodadPtr doodad)
447105b261ecSmrg{
447205b261ecSmrgregister int	i,size;
447305b261ecSmrg
447405b261ecSmrg    for (i=size=0;i<num_doodads;i++,doodad++) {
447505b261ecSmrg	size+= SIZEOF(xkbAnyDoodadWireDesc);
447605b261ecSmrg	if (doodad->any.type==XkbTextDoodad) {
447705b261ecSmrg	    size+= XkbSizeCountedString(doodad->text.text);
447805b261ecSmrg	    size+= XkbSizeCountedString(doodad->text.font);
447905b261ecSmrg	}
448005b261ecSmrg	else if (doodad->any.type==XkbLogoDoodad) {
448105b261ecSmrg	    size+= XkbSizeCountedString(doodad->logo.logo_name);
448205b261ecSmrg	}
448305b261ecSmrg    }
448405b261ecSmrg    return size;
448505b261ecSmrg}
448605b261ecSmrg
448705b261ecSmrgstatic char *
448805b261ecSmrgXkbWriteGeomDoodads(char *wire,int num_doodads,XkbDoodadPtr doodad,Bool swap)
448905b261ecSmrg{
449005b261ecSmrgregister int		i;
449105b261ecSmrgxkbDoodadWireDesc *	doodadWire;
449205b261ecSmrg
449305b261ecSmrg    for (i=0;i<num_doodads;i++,doodad++) {
449405b261ecSmrg	doodadWire= (xkbDoodadWireDesc *)wire;
449505b261ecSmrg	wire= (char *)&doodadWire[1];
44966747b715Smrg	memset(doodadWire, 0, SIZEOF(xkbDoodadWireDesc));
449705b261ecSmrg	doodadWire->any.name= doodad->any.name;
449805b261ecSmrg	doodadWire->any.type= doodad->any.type;
449905b261ecSmrg	doodadWire->any.priority= doodad->any.priority;
450005b261ecSmrg	doodadWire->any.top= doodad->any.top;
450105b261ecSmrg	doodadWire->any.left= doodad->any.left;
450205b261ecSmrg	if (swap) {
450305b261ecSmrg	    register int n;
450405b261ecSmrg	    swapl(&doodadWire->any.name,n);
450505b261ecSmrg	    swaps(&doodadWire->any.top,n);
450605b261ecSmrg	    swaps(&doodadWire->any.left,n);
450705b261ecSmrg	}
450805b261ecSmrg	switch (doodad->any.type) {
450905b261ecSmrg	    case XkbOutlineDoodad:
451005b261ecSmrg	    case XkbSolidDoodad:
451105b261ecSmrg		doodadWire->shape.angle= doodad->shape.angle;
451205b261ecSmrg		doodadWire->shape.colorNdx= doodad->shape.color_ndx;
451305b261ecSmrg		doodadWire->shape.shapeNdx= doodad->shape.shape_ndx;
451405b261ecSmrg		if (swap) {
451505b261ecSmrg		    register int n;
451605b261ecSmrg		    swaps(&doodadWire->shape.angle,n);
451705b261ecSmrg		}
451805b261ecSmrg		break;
451905b261ecSmrg	    case XkbTextDoodad:
452005b261ecSmrg		doodadWire->text.angle= doodad->text.angle;
452105b261ecSmrg		doodadWire->text.width= doodad->text.width;
452205b261ecSmrg		doodadWire->text.height= doodad->text.height;
452305b261ecSmrg		doodadWire->text.colorNdx= doodad->text.color_ndx;
452405b261ecSmrg		if (swap) {
452505b261ecSmrg		    register int n;
452605b261ecSmrg		    swaps(&doodadWire->text.angle,n);
452705b261ecSmrg		    swaps(&doodadWire->text.width,n);
452805b261ecSmrg		    swaps(&doodadWire->text.height,n);
452905b261ecSmrg		}
453005b261ecSmrg		wire= XkbWriteCountedString(wire,doodad->text.text,swap);
453105b261ecSmrg		wire= XkbWriteCountedString(wire,doodad->text.font,swap);
453205b261ecSmrg		break;
453305b261ecSmrg	    case XkbIndicatorDoodad:
453405b261ecSmrg		doodadWire->indicator.shapeNdx= doodad->indicator.shape_ndx;
453505b261ecSmrg		doodadWire->indicator.onColorNdx=doodad->indicator.on_color_ndx;
453605b261ecSmrg		doodadWire->indicator.offColorNdx=
453705b261ecSmrg						doodad->indicator.off_color_ndx;
453805b261ecSmrg		break;
453905b261ecSmrg	    case XkbLogoDoodad:
454005b261ecSmrg		doodadWire->logo.angle= doodad->logo.angle;
454105b261ecSmrg		doodadWire->logo.colorNdx= doodad->logo.color_ndx;
454205b261ecSmrg		doodadWire->logo.shapeNdx= doodad->logo.shape_ndx;
454305b261ecSmrg		wire= XkbWriteCountedString(wire,doodad->logo.logo_name,swap);
454405b261ecSmrg		break;
454505b261ecSmrg	    default:
45464642e01fSmrg		ErrorF("[xkb] Unknown doodad type %d in XkbWriteGeomDoodads\n",
454705b261ecSmrg			doodad->any.type);
45484642e01fSmrg		ErrorF("[xkb] Ignored\n");
454905b261ecSmrg		break;
455005b261ecSmrg	}
455105b261ecSmrg    }
455205b261ecSmrg    return wire;
455305b261ecSmrg}
455405b261ecSmrg
455505b261ecSmrgstatic char *
455605b261ecSmrgXkbWriteGeomOverlay(char *wire,XkbOverlayPtr ol,Bool swap)
455705b261ecSmrg{
455805b261ecSmrgregister int		r;
455905b261ecSmrgXkbOverlayRowPtr	row;
456005b261ecSmrgxkbOverlayWireDesc *	olWire;
456105b261ecSmrg
456205b261ecSmrg   olWire= (xkbOverlayWireDesc *)wire;
456305b261ecSmrg   olWire->name= ol->name;
456405b261ecSmrg   olWire->nRows= ol->num_rows;
45659ace9065Smrg   olWire->pad1= 0;
45669ace9065Smrg   olWire->pad2= 0;
456705b261ecSmrg   if (swap) {
456805b261ecSmrg	register int n;
456905b261ecSmrg	swapl(&olWire->name,n);
457005b261ecSmrg   }
457105b261ecSmrg   wire= (char *)&olWire[1];
457205b261ecSmrg   for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
457305b261ecSmrg   	unsigned int		k;
457405b261ecSmrg	XkbOverlayKeyPtr	key;
457505b261ecSmrg	xkbOverlayRowWireDesc *	rowWire;
457605b261ecSmrg	rowWire= (xkbOverlayRowWireDesc *)wire;
457705b261ecSmrg	rowWire->rowUnder= row->row_under;
457805b261ecSmrg	rowWire->nKeys= row->num_keys;
45799ace9065Smrg	rowWire->pad1= 0;
458005b261ecSmrg	wire= (char *)&rowWire[1];
458105b261ecSmrg	for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
458205b261ecSmrg	    xkbOverlayKeyWireDesc *	keyWire;
458305b261ecSmrg	    keyWire= (xkbOverlayKeyWireDesc *)wire;
458405b261ecSmrg	    memcpy(keyWire->over,key->over.name,XkbKeyNameLength);
458505b261ecSmrg	    memcpy(keyWire->under,key->under.name,XkbKeyNameLength);
458605b261ecSmrg	    wire= (char *)&keyWire[1];
458705b261ecSmrg	}
458805b261ecSmrg   }
458905b261ecSmrg   return wire;
459005b261ecSmrg}
459105b261ecSmrg
459205b261ecSmrgstatic int
459305b261ecSmrgXkbSizeGeomSections(XkbGeometryPtr geom)
459405b261ecSmrg{
459505b261ecSmrgregister int 	i,size;
459605b261ecSmrgXkbSectionPtr	section;
459705b261ecSmrg
459805b261ecSmrg    for (i=size=0,section=geom->sections;i<geom->num_sections;i++,section++) {
459905b261ecSmrg	size+= SIZEOF(xkbSectionWireDesc);
460005b261ecSmrg	if (section->rows) {
460105b261ecSmrg	    int		r;
460205b261ecSmrg	    XkbRowPtr	row;
460305b261ecSmrg	    for (r=0,row=section->rows;r<section->num_rows;row++,r++) {
460405b261ecSmrg		size+= SIZEOF(xkbRowWireDesc);
460505b261ecSmrg		size+= row->num_keys*SIZEOF(xkbKeyWireDesc);
460605b261ecSmrg	    }
460705b261ecSmrg	}
460805b261ecSmrg	if (section->doodads)
460905b261ecSmrg	    size+= XkbSizeGeomDoodads(section->num_doodads,section->doodads);
461005b261ecSmrg	if (section->overlays) {
461105b261ecSmrg	    int			o;
461205b261ecSmrg	    XkbOverlayPtr	ol;
461305b261ecSmrg	    for (o=0,ol=section->overlays;o<section->num_overlays;o++,ol++) {
461405b261ecSmrg		int			r;
461505b261ecSmrg		XkbOverlayRowPtr	row;
461605b261ecSmrg		size+= SIZEOF(xkbOverlayWireDesc);
461705b261ecSmrg		for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
461805b261ecSmrg		   size+= SIZEOF(xkbOverlayRowWireDesc);
461905b261ecSmrg		   size+= row->num_keys*SIZEOF(xkbOverlayKeyWireDesc);
462005b261ecSmrg		}
462105b261ecSmrg	    }
462205b261ecSmrg	}
462305b261ecSmrg    }
462405b261ecSmrg    return size;
462505b261ecSmrg}
462605b261ecSmrg
462705b261ecSmrgstatic char *
462805b261ecSmrgXkbWriteGeomSections(char *wire,XkbGeometryPtr geom,Bool swap)
462905b261ecSmrg{
463005b261ecSmrgregister int		i;
463105b261ecSmrgXkbSectionPtr		section;
463205b261ecSmrgxkbSectionWireDesc *	sectionWire;
463305b261ecSmrg
463405b261ecSmrg    for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) {
463505b261ecSmrg	sectionWire= (xkbSectionWireDesc *)wire;
463605b261ecSmrg	sectionWire->name= section->name;
463705b261ecSmrg	sectionWire->top= section->top;
463805b261ecSmrg	sectionWire->left= section->left;
463905b261ecSmrg	sectionWire->width= section->width;
464005b261ecSmrg	sectionWire->height= section->height;
464105b261ecSmrg	sectionWire->angle= section->angle;
464205b261ecSmrg	sectionWire->priority= section->priority;
464305b261ecSmrg	sectionWire->nRows= section->num_rows;
464405b261ecSmrg	sectionWire->nDoodads= section->num_doodads;
464505b261ecSmrg	sectionWire->nOverlays= section->num_overlays;
464605b261ecSmrg	sectionWire->pad= 0;
464705b261ecSmrg	if (swap) {
464805b261ecSmrg	    register int n;
464905b261ecSmrg	    swapl(&sectionWire->name,n);
465005b261ecSmrg	    swaps(&sectionWire->top,n);
465105b261ecSmrg	    swaps(&sectionWire->left,n);
465205b261ecSmrg	    swaps(&sectionWire->width,n);
465305b261ecSmrg	    swaps(&sectionWire->height,n);
465405b261ecSmrg	    swaps(&sectionWire->angle,n);
465505b261ecSmrg	}
465605b261ecSmrg	wire= (char *)&sectionWire[1];
465705b261ecSmrg	if (section->rows) {
465805b261ecSmrg	    int			r;
465905b261ecSmrg	    XkbRowPtr		row;
466005b261ecSmrg	    xkbRowWireDesc *	rowWire;
466105b261ecSmrg	    for (r=0,row=section->rows;r<section->num_rows;r++,row++) {
466205b261ecSmrg		rowWire= (xkbRowWireDesc *)wire;
466305b261ecSmrg		rowWire->top= row->top;
466405b261ecSmrg		rowWire->left= row->left;
466505b261ecSmrg		rowWire->nKeys= row->num_keys;
466605b261ecSmrg		rowWire->vertical= row->vertical;
466705b261ecSmrg		rowWire->pad= 0;
466805b261ecSmrg		if (swap) {
466905b261ecSmrg		    register int n;
467005b261ecSmrg		    swaps(&rowWire->top,n);
467105b261ecSmrg		    swaps(&rowWire->left,n);
467205b261ecSmrg		}
467305b261ecSmrg		wire= (char *)&rowWire[1];
467405b261ecSmrg		if (row->keys) {
467505b261ecSmrg		    int			k;
467605b261ecSmrg		    XkbKeyPtr		key;
467705b261ecSmrg		    xkbKeyWireDesc *	keyWire;
467805b261ecSmrg		    keyWire= (xkbKeyWireDesc *)wire;
467905b261ecSmrg		    for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
468005b261ecSmrg			memcpy(keyWire[k].name,key->name.name,XkbKeyNameLength);
468105b261ecSmrg			keyWire[k].gap= key->gap;
468205b261ecSmrg			keyWire[k].shapeNdx= key->shape_ndx;
468305b261ecSmrg			keyWire[k].colorNdx= key->color_ndx;
468405b261ecSmrg			if (swap) {
468505b261ecSmrg			    register int n;
468605b261ecSmrg			    swaps(&keyWire[k].gap,n);
468705b261ecSmrg			}
468805b261ecSmrg		    }
468905b261ecSmrg		    wire= (char *)&keyWire[row->num_keys];
469005b261ecSmrg		}
469105b261ecSmrg	    }
469205b261ecSmrg	}
469305b261ecSmrg	if (section->doodads) {
469405b261ecSmrg	    wire= XkbWriteGeomDoodads(wire,
469505b261ecSmrg	    			      section->num_doodads,section->doodads,
469605b261ecSmrg				      swap);
469705b261ecSmrg	}
469805b261ecSmrg	if (section->overlays) {
469905b261ecSmrg	    register int o;
470005b261ecSmrg	    for (o=0;o<section->num_overlays;o++) {
470105b261ecSmrg		wire= XkbWriteGeomOverlay(wire,&section->overlays[o],swap);
470205b261ecSmrg	    }
470305b261ecSmrg	}
470405b261ecSmrg    }
470505b261ecSmrg    return wire;
470605b261ecSmrg}
470705b261ecSmrg
470805b261ecSmrgstatic Status
470905b261ecSmrgXkbComputeGetGeometryReplySize(	XkbGeometryPtr		geom,
471005b261ecSmrg				xkbGetGeometryReply *	rep,
471105b261ecSmrg				Atom			name)
471205b261ecSmrg{
471305b261ecSmrgint	len;
471405b261ecSmrg
471505b261ecSmrg    if (geom!=NULL) {
471605b261ecSmrg	len= XkbSizeCountedString(geom->label_font);
471705b261ecSmrg	len+= XkbSizeGeomProperties(geom);
471805b261ecSmrg	len+= XkbSizeGeomColors(geom);
471905b261ecSmrg	len+= XkbSizeGeomShapes(geom);
472005b261ecSmrg	len+= XkbSizeGeomSections(geom);
472105b261ecSmrg	len+= XkbSizeGeomDoodads(geom->num_doodads,geom->doodads);
472205b261ecSmrg	len+= XkbSizeGeomKeyAliases(geom);
472305b261ecSmrg	rep->length= len/4;
47246747b715Smrg	rep->found= TRUE;
472505b261ecSmrg	rep->name= geom->name;
472605b261ecSmrg	rep->widthMM= geom->width_mm;
472705b261ecSmrg	rep->heightMM= geom->height_mm;
472805b261ecSmrg	rep->nProperties= geom->num_properties;
472905b261ecSmrg	rep->nColors= geom->num_colors;
473005b261ecSmrg	rep->nShapes= geom->num_shapes;
473105b261ecSmrg	rep->nSections= geom->num_sections;
473205b261ecSmrg	rep->nDoodads= geom->num_doodads;
473305b261ecSmrg	rep->nKeyAliases= geom->num_key_aliases;
473405b261ecSmrg	rep->baseColorNdx= XkbGeomColorIndex(geom,geom->base_color);
473505b261ecSmrg	rep->labelColorNdx= XkbGeomColorIndex(geom,geom->label_color);
473605b261ecSmrg    }
473705b261ecSmrg    else {
473805b261ecSmrg	rep->length= 0;
47396747b715Smrg	rep->found= FALSE;
474005b261ecSmrg	rep->name= name;
474105b261ecSmrg	rep->widthMM= rep->heightMM= 0;
474205b261ecSmrg	rep->nProperties= rep->nColors= rep->nShapes= 0;
474305b261ecSmrg	rep->nSections= rep->nDoodads= 0;
474405b261ecSmrg	rep->nKeyAliases= 0;
474505b261ecSmrg	rep->labelColorNdx= rep->baseColorNdx= 0;
474605b261ecSmrg    }
474705b261ecSmrg    return Success;
474805b261ecSmrg}
474905b261ecSmrg
475005b261ecSmrgstatic int
475105b261ecSmrgXkbSendGeometry(	ClientPtr		client,
475205b261ecSmrg			XkbGeometryPtr		geom,
475305b261ecSmrg			xkbGetGeometryReply *	rep,
475405b261ecSmrg			Bool			freeGeom)
475505b261ecSmrg{
475605b261ecSmrg    char	*desc,*start;
475705b261ecSmrg    int		 len;
475805b261ecSmrg
475905b261ecSmrg    if (geom!=NULL) {
476005b261ecSmrg	len= rep->length*4;
47616747b715Smrg	start= desc= malloc(len);
476205b261ecSmrg	if (!start)
476305b261ecSmrg	    return BadAlloc;
476405b261ecSmrg	desc=  XkbWriteCountedString(desc,geom->label_font,client->swapped);
476505b261ecSmrg	if ( rep->nProperties>0 )
476605b261ecSmrg	    desc = XkbWriteGeomProperties(desc,geom,client->swapped);
476705b261ecSmrg	if ( rep->nColors>0 )
476805b261ecSmrg	    desc = XkbWriteGeomColors(desc,geom,client->swapped);
476905b261ecSmrg	if ( rep->nShapes>0 )
477005b261ecSmrg	    desc = XkbWriteGeomShapes(desc,geom,client->swapped);
477105b261ecSmrg	if ( rep->nSections>0 )
477205b261ecSmrg	    desc = XkbWriteGeomSections(desc,geom,client->swapped);
477305b261ecSmrg	if ( rep->nDoodads>0 )
477405b261ecSmrg	    desc = XkbWriteGeomDoodads(desc,geom->num_doodads,geom->doodads,
477505b261ecSmrg							  client->swapped);
477605b261ecSmrg	if ( rep->nKeyAliases>0 )
477705b261ecSmrg	    desc = XkbWriteGeomKeyAliases(desc,geom,client->swapped);
477805b261ecSmrg	if ((desc-start)!=(len)) {
47794642e01fSmrg	    ErrorF("[xkb] BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n",
478005b261ecSmrg			len, (unsigned long)(desc-start));
478105b261ecSmrg	}
478205b261ecSmrg    }
478305b261ecSmrg    else {
478405b261ecSmrg	len= 0;
478505b261ecSmrg	start= NULL;
478605b261ecSmrg    }
478705b261ecSmrg    if (client->swapped) {
478805b261ecSmrg	register int n;
478905b261ecSmrg	swaps(&rep->sequenceNumber,n);
479005b261ecSmrg	swapl(&rep->length,n);
479105b261ecSmrg	swapl(&rep->name,n);
479205b261ecSmrg	swaps(&rep->widthMM,n);
479305b261ecSmrg	swaps(&rep->heightMM,n);
479405b261ecSmrg	swaps(&rep->nProperties,n);
479505b261ecSmrg	swaps(&rep->nColors,n);
479605b261ecSmrg	swaps(&rep->nShapes,n);
479705b261ecSmrg	swaps(&rep->nSections,n);
479805b261ecSmrg	swaps(&rep->nDoodads,n);
479905b261ecSmrg	swaps(&rep->nKeyAliases,n);
480005b261ecSmrg    }
480105b261ecSmrg    WriteToClient(client, SIZEOF(xkbGetGeometryReply), (char *)rep);
480205b261ecSmrg    if (len>0)
480305b261ecSmrg	WriteToClient(client, len, start);
480405b261ecSmrg    if (start!=NULL)
48056747b715Smrg	free((char *)start);
480605b261ecSmrg    if (freeGeom)
48076747b715Smrg	XkbFreeGeometry(geom,XkbGeomAllMask,TRUE);
48086747b715Smrg    return Success;
480905b261ecSmrg}
481005b261ecSmrg
481105b261ecSmrgint
481205b261ecSmrgProcXkbGetGeometry(ClientPtr client)
481305b261ecSmrg{
481405b261ecSmrg    DeviceIntPtr 	dev;
481505b261ecSmrg    xkbGetGeometryReply rep;
481605b261ecSmrg    XkbGeometryPtr	geom;
481705b261ecSmrg    Bool		shouldFree;
481805b261ecSmrg    Status		status;
481905b261ecSmrg
482005b261ecSmrg    REQUEST(xkbGetGeometryReq);
482105b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetGeometryReq);
482205b261ecSmrg
482305b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
482405b261ecSmrg	return BadAccess;
482505b261ecSmrg
48264642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
482705b261ecSmrg    CHK_ATOM_OR_NONE(stuff->name);
482805b261ecSmrg
482905b261ecSmrg    geom= XkbLookupNamedGeometry(dev,stuff->name,&shouldFree);
483005b261ecSmrg    rep.type= X_Reply;
483105b261ecSmrg    rep.deviceID= dev->id;
483205b261ecSmrg    rep.sequenceNumber= client->sequence;
483305b261ecSmrg    rep.length= 0;
483405b261ecSmrg    status= XkbComputeGetGeometryReplySize(geom,&rep,stuff->name);
483505b261ecSmrg    if (status!=Success)
483605b261ecSmrg	 return status;
483705b261ecSmrg    else return XkbSendGeometry(client,geom,&rep,shouldFree);
483805b261ecSmrg}
483905b261ecSmrg
484005b261ecSmrg/***====================================================================***/
484105b261ecSmrg
48421e26616aSmrgstatic Status
48431e26616aSmrg_GetCountedString(char **wire_inout, ClientPtr client, char **str)
484405b261ecSmrg{
48451e26616aSmrg    char *wire, *next;
48461e26616aSmrg    CARD16 len;
484705b261ecSmrg
48481e26616aSmrg    wire = *wire_inout;
48491e26616aSmrg    len = *(CARD16 *) wire;
48501e26616aSmrg    if (client->swapped) {
48511e26616aSmrg	int n;
48521e26616aSmrg        swaps(&len, n);
485305b261ecSmrg    }
48541e26616aSmrg    next = wire + XkbPaddedSize(len + 2);
48551e26616aSmrg    /* Check we're still within the size of the request */
48561e26616aSmrg    if (client->req_len <
48571e26616aSmrg        bytes_to_int32(next - (char *) client->requestBuffer))
48581e26616aSmrg        return BadValue;
48591e26616aSmrg    *str = malloc(len + 1);
48601e26616aSmrg    if (!*str)
48611e26616aSmrg        return BadAlloc;
48621e26616aSmrg    memcpy(*str, &wire[2], len);
48631e26616aSmrg    *(*str + len) = '\0';
48641e26616aSmrg    *wire_inout = next;
48651e26616aSmrg    return Success;
486605b261ecSmrg}
486705b261ecSmrg
486805b261ecSmrgstatic Status
486905b261ecSmrg_CheckSetDoodad(	char **		wire_inout,
487005b261ecSmrg			XkbGeometryPtr	geom,
487105b261ecSmrg			XkbSectionPtr	section,
487205b261ecSmrg			ClientPtr	client)
487305b261ecSmrg{
487405b261ecSmrgchar *			wire;
487505b261ecSmrgxkbDoodadWireDesc *	dWire;
487605b261ecSmrgXkbDoodadPtr		doodad;
48771e26616aSmrg    Status status;
487805b261ecSmrg
487905b261ecSmrg    dWire= (xkbDoodadWireDesc *)(*wire_inout);
488005b261ecSmrg    wire= (char *)&dWire[1];
488105b261ecSmrg    if (client->swapped) {
488205b261ecSmrg	register int n;
488305b261ecSmrg	swapl(&dWire->any.name,n);
488405b261ecSmrg	swaps(&dWire->any.top,n);
488505b261ecSmrg	swaps(&dWire->any.left,n);
488605b261ecSmrg	swaps(&dWire->any.angle,n);
488705b261ecSmrg    }
488805b261ecSmrg    CHK_ATOM_ONLY(dWire->any.name);
488905b261ecSmrg    doodad= XkbAddGeomDoodad(geom,section,dWire->any.name);
489005b261ecSmrg    if (!doodad)
489105b261ecSmrg	return BadAlloc;
489205b261ecSmrg    doodad->any.type= dWire->any.type;
489305b261ecSmrg    doodad->any.priority= dWire->any.priority;
489405b261ecSmrg    doodad->any.top= dWire->any.top;
489505b261ecSmrg    doodad->any.left= dWire->any.left;
489605b261ecSmrg    doodad->any.angle= dWire->any.angle;
489705b261ecSmrg    switch (doodad->any.type) {
489805b261ecSmrg	case XkbOutlineDoodad:
489905b261ecSmrg	case XkbSolidDoodad:
490005b261ecSmrg	    if (dWire->shape.colorNdx>=geom->num_colors) {
490105b261ecSmrg		client->errorValue= _XkbErrCode3(0x40,geom->num_colors,
490205b261ecSmrg							dWire->shape.colorNdx);
490305b261ecSmrg		return BadMatch;
490405b261ecSmrg	    }
490505b261ecSmrg	    if (dWire->shape.shapeNdx>=geom->num_shapes) {
490605b261ecSmrg		client->errorValue= _XkbErrCode3(0x41,geom->num_shapes,
490705b261ecSmrg							dWire->shape.shapeNdx);
490805b261ecSmrg		return BadMatch;
490905b261ecSmrg	    }
491005b261ecSmrg	    doodad->shape.color_ndx= dWire->shape.colorNdx;
491105b261ecSmrg	    doodad->shape.shape_ndx= dWire->shape.shapeNdx;
491205b261ecSmrg	    break;
491305b261ecSmrg	case XkbTextDoodad:
491405b261ecSmrg	    if (dWire->text.colorNdx>=geom->num_colors) {
491505b261ecSmrg		client->errorValue= _XkbErrCode3(0x42,geom->num_colors,
491605b261ecSmrg							dWire->text.colorNdx);
491705b261ecSmrg		return BadMatch;
491805b261ecSmrg	    }
491905b261ecSmrg	    if (client->swapped) {
492005b261ecSmrg		register int n;
492105b261ecSmrg		swaps(&dWire->text.width,n);
492205b261ecSmrg		swaps(&dWire->text.height,n);
492305b261ecSmrg	    }
492405b261ecSmrg	    doodad->text.width= dWire->text.width;
492505b261ecSmrg	    doodad->text.height= dWire->text.height;
492605b261ecSmrg	    doodad->text.color_ndx= dWire->text.colorNdx;
49271e26616aSmrg            status = _GetCountedString(&wire, client, &doodad->text.text);
49281e26616aSmrg            if (status != Success)
49291e26616aSmrg                return status;
49301e26616aSmrg            status = _GetCountedString(&wire, client, &doodad->text.font);
49311e26616aSmrg            if (status != Success) {
49321e26616aSmrg                free (doodad->text.text);
49331e26616aSmrg                return status;
49341e26616aSmrg            }
493505b261ecSmrg	    break;
493605b261ecSmrg	case XkbIndicatorDoodad:
493705b261ecSmrg	    if (dWire->indicator.onColorNdx>=geom->num_colors) {
493805b261ecSmrg		client->errorValue= _XkbErrCode3(0x43,geom->num_colors,
493905b261ecSmrg						dWire->indicator.onColorNdx);
494005b261ecSmrg		return BadMatch;
494105b261ecSmrg	    }
494205b261ecSmrg	    if (dWire->indicator.offColorNdx>=geom->num_colors) {
494305b261ecSmrg		client->errorValue= _XkbErrCode3(0x44,geom->num_colors,
494405b261ecSmrg						dWire->indicator.offColorNdx);
494505b261ecSmrg		return BadMatch;
494605b261ecSmrg	    }
494705b261ecSmrg	    if (dWire->indicator.shapeNdx>=geom->num_shapes) {
494805b261ecSmrg		client->errorValue= _XkbErrCode3(0x45,geom->num_shapes,
494905b261ecSmrg						dWire->indicator.shapeNdx);
495005b261ecSmrg		return BadMatch;
495105b261ecSmrg	    }
495205b261ecSmrg	    doodad->indicator.shape_ndx= dWire->indicator.shapeNdx;
495305b261ecSmrg	    doodad->indicator.on_color_ndx= dWire->indicator.onColorNdx;
495405b261ecSmrg	    doodad->indicator.off_color_ndx= dWire->indicator.offColorNdx;
495505b261ecSmrg	    break;
495605b261ecSmrg	case XkbLogoDoodad:
495705b261ecSmrg	    if (dWire->logo.colorNdx>=geom->num_colors) {
495805b261ecSmrg		client->errorValue= _XkbErrCode3(0x46,geom->num_colors,
495905b261ecSmrg							dWire->logo.colorNdx);
496005b261ecSmrg		return BadMatch;
496105b261ecSmrg	    }
496205b261ecSmrg	    if (dWire->logo.shapeNdx>=geom->num_shapes) {
496305b261ecSmrg		client->errorValue= _XkbErrCode3(0x47,geom->num_shapes,
496405b261ecSmrg							dWire->logo.shapeNdx);
496505b261ecSmrg		return BadMatch;
496605b261ecSmrg	    }
496705b261ecSmrg	    doodad->logo.color_ndx= dWire->logo.colorNdx;
496805b261ecSmrg	    doodad->logo.shape_ndx= dWire->logo.shapeNdx;
49691e26616aSmrg            status = _GetCountedString(&wire, client, &doodad->logo.logo_name);
49701e26616aSmrg            if (status != Success)
49711e26616aSmrg                return status;
497205b261ecSmrg	    break;
497305b261ecSmrg	default:
497405b261ecSmrg	    client->errorValue= _XkbErrCode2(0x4F,dWire->any.type);
497505b261ecSmrg	    return BadValue;
497605b261ecSmrg    }
497705b261ecSmrg    *wire_inout= wire;
497805b261ecSmrg    return Success;
497905b261ecSmrg}
498005b261ecSmrg
498105b261ecSmrgstatic Status
498205b261ecSmrg_CheckSetOverlay(	char **		wire_inout,
498305b261ecSmrg			XkbGeometryPtr	geom,
498405b261ecSmrg			XkbSectionPtr	section,
498505b261ecSmrg			ClientPtr	client)
498605b261ecSmrg{
498705b261ecSmrgregister int		r;
498805b261ecSmrgchar *			wire;
498905b261ecSmrgXkbOverlayPtr		ol;
499005b261ecSmrgxkbOverlayWireDesc *	olWire;
499105b261ecSmrgxkbOverlayRowWireDesc *	rWire;
499205b261ecSmrg
499305b261ecSmrg    wire= *wire_inout;
499405b261ecSmrg    olWire= (xkbOverlayWireDesc *)wire;
499505b261ecSmrg    if (client->swapped) {
499605b261ecSmrg	register int n;
499705b261ecSmrg	swapl(&olWire->name,n);
499805b261ecSmrg    }
499905b261ecSmrg    CHK_ATOM_ONLY(olWire->name);
500005b261ecSmrg    ol= XkbAddGeomOverlay(section,olWire->name,olWire->nRows);
500105b261ecSmrg    rWire= (xkbOverlayRowWireDesc *)&olWire[1];
500205b261ecSmrg    for (r=0;r<olWire->nRows;r++) {
500305b261ecSmrg	register int		k;
500405b261ecSmrg	xkbOverlayKeyWireDesc *	kWire;
500505b261ecSmrg	XkbOverlayRowPtr	row;
500605b261ecSmrg
500705b261ecSmrg	if (rWire->rowUnder>section->num_rows) {
500805b261ecSmrg	    client->errorValue= _XkbErrCode4(0x20,r,section->num_rows,
500905b261ecSmrg							rWire->rowUnder);
501005b261ecSmrg	    return BadMatch;
501105b261ecSmrg	}
501205b261ecSmrg	row= XkbAddGeomOverlayRow(ol,rWire->rowUnder,rWire->nKeys);
501305b261ecSmrg	kWire= (xkbOverlayKeyWireDesc *)&rWire[1];
501405b261ecSmrg	for (k=0;k<rWire->nKeys;k++,kWire++) {
501505b261ecSmrg	    if (XkbAddGeomOverlayKey(ol,row,
501605b261ecSmrg	    		(char *)kWire->over,(char *)kWire->under)==NULL) {
501705b261ecSmrg		client->errorValue= _XkbErrCode3(0x21,r,k);
501805b261ecSmrg		return BadMatch;
501905b261ecSmrg	    }
502005b261ecSmrg	}
502105b261ecSmrg	rWire= (xkbOverlayRowWireDesc *)kWire;
502205b261ecSmrg    }
502305b261ecSmrg    olWire= (xkbOverlayWireDesc *)rWire;
502405b261ecSmrg    wire= (char *)olWire;
502505b261ecSmrg    *wire_inout= wire;
502605b261ecSmrg    return Success;
502705b261ecSmrg}
502805b261ecSmrg
502905b261ecSmrgstatic Status
503005b261ecSmrg_CheckSetSections( 	XkbGeometryPtr		geom,
503105b261ecSmrg			xkbSetGeometryReq *	req,
503205b261ecSmrg			char **			wire_inout,
503305b261ecSmrg			ClientPtr		client)
503405b261ecSmrg{
503505b261ecSmrgStatus			status;
503605b261ecSmrgregister int		s;
503705b261ecSmrgchar *			wire;
503805b261ecSmrgxkbSectionWireDesc *	sWire;
503905b261ecSmrgXkbSectionPtr		section;
504005b261ecSmrg
504105b261ecSmrg    wire= *wire_inout;
504205b261ecSmrg    if (req->nSections<1)
504305b261ecSmrg	return Success;
504405b261ecSmrg    sWire= (xkbSectionWireDesc *)wire;
504505b261ecSmrg    for (s=0;s<req->nSections;s++) {
504605b261ecSmrg	register int		r;
504705b261ecSmrg	xkbRowWireDesc *	rWire;
504805b261ecSmrg	if (client->swapped) {
504905b261ecSmrg	    register int n;
505005b261ecSmrg	    swapl(&sWire->name,n);
505105b261ecSmrg	    swaps(&sWire->top,n);
505205b261ecSmrg	    swaps(&sWire->left,n);
505305b261ecSmrg	    swaps(&sWire->width,n);
505405b261ecSmrg	    swaps(&sWire->height,n);
505505b261ecSmrg	    swaps(&sWire->angle,n);
505605b261ecSmrg	}
505705b261ecSmrg	CHK_ATOM_ONLY(sWire->name);
505805b261ecSmrg	section= XkbAddGeomSection(geom,sWire->name,sWire->nRows,
505905b261ecSmrg					sWire->nDoodads,sWire->nOverlays);
506005b261ecSmrg	if (!section)
506105b261ecSmrg	    return BadAlloc;
506205b261ecSmrg	section->priority=	sWire->priority;
506305b261ecSmrg	section->top=		sWire->top;
506405b261ecSmrg	section->left=		sWire->left;
506505b261ecSmrg	section->width=		sWire->width;
506605b261ecSmrg	section->height=	sWire->height;
506705b261ecSmrg	section->angle=		sWire->angle;
506805b261ecSmrg	rWire= (xkbRowWireDesc *)&sWire[1];
506905b261ecSmrg	for (r=0;r<sWire->nRows;r++) {
507005b261ecSmrg	    register int	k;
507105b261ecSmrg	    XkbRowPtr		row;
507205b261ecSmrg	    xkbKeyWireDesc *	kWire;
507305b261ecSmrg	    if (client->swapped) {
507405b261ecSmrg		register int n;
507505b261ecSmrg		swaps(&rWire->top,n);
507605b261ecSmrg		swaps(&rWire->left,n);
507705b261ecSmrg	    }
507805b261ecSmrg	    row= XkbAddGeomRow(section,rWire->nKeys);
507905b261ecSmrg	    if (!row)
508005b261ecSmrg		return BadAlloc;
508105b261ecSmrg	    row->top= rWire->top;
508205b261ecSmrg	    row->left= rWire->left;
508305b261ecSmrg	    row->vertical= rWire->vertical;
508405b261ecSmrg	    kWire= (xkbKeyWireDesc *)&rWire[1];
508505b261ecSmrg	    for (k=0;k<rWire->nKeys;k++) {
508605b261ecSmrg		XkbKeyPtr	key;
508705b261ecSmrg		key= XkbAddGeomKey(row);
508805b261ecSmrg		if (!key)
508905b261ecSmrg		    return BadAlloc;
509005b261ecSmrg		memcpy(key->name.name,kWire[k].name,XkbKeyNameLength);
509105b261ecSmrg		key->gap= kWire[k].gap;
509205b261ecSmrg		key->shape_ndx= kWire[k].shapeNdx;
509305b261ecSmrg		key->color_ndx= kWire[k].colorNdx;
509405b261ecSmrg		if (key->shape_ndx>=geom->num_shapes) {
509505b261ecSmrg		    client->errorValue= _XkbErrCode3(0x10,key->shape_ndx,
509605b261ecSmrg							  geom->num_shapes);
509705b261ecSmrg		    return BadMatch;
509805b261ecSmrg		}
509905b261ecSmrg		if (key->color_ndx>=geom->num_colors) {
510005b261ecSmrg		    client->errorValue= _XkbErrCode3(0x11,key->color_ndx,
510105b261ecSmrg							  geom->num_colors);
510205b261ecSmrg		    return BadMatch;
510305b261ecSmrg		}
510405b261ecSmrg	    }
510505b261ecSmrg	    rWire= (xkbRowWireDesc *)&kWire[rWire->nKeys];
510605b261ecSmrg	}
510705b261ecSmrg	wire= (char *)rWire;
510805b261ecSmrg	if (sWire->nDoodads>0) {
510905b261ecSmrg	    register int d;
511005b261ecSmrg	    for (d=0;d<sWire->nDoodads;d++) {
511105b261ecSmrg		status=_CheckSetDoodad(&wire,geom,section,client);
511205b261ecSmrg		if (status!=Success)
511305b261ecSmrg		    return status;
511405b261ecSmrg	    }
511505b261ecSmrg	}
511605b261ecSmrg	if (sWire->nOverlays>0) {
511705b261ecSmrg	    register int o;
511805b261ecSmrg	    for (o=0;o<sWire->nOverlays;o++) {
511905b261ecSmrg		status= _CheckSetOverlay(&wire,geom,section,client);
512005b261ecSmrg		if (status!=Success)
512105b261ecSmrg		    return status;
512205b261ecSmrg	    }
512305b261ecSmrg	}
512405b261ecSmrg	sWire= (xkbSectionWireDesc *)wire;
512505b261ecSmrg    }
512605b261ecSmrg    wire= (char *)sWire;
512705b261ecSmrg    *wire_inout= wire;
512805b261ecSmrg    return Success;
512905b261ecSmrg}
513005b261ecSmrg
513105b261ecSmrgstatic Status
513205b261ecSmrg_CheckSetShapes( 	XkbGeometryPtr		geom,
513305b261ecSmrg			xkbSetGeometryReq *	req,
513405b261ecSmrg			char **			wire_inout,
513505b261ecSmrg			ClientPtr		client)
513605b261ecSmrg{
513705b261ecSmrgregister int	i;
513805b261ecSmrgchar *		wire;
513905b261ecSmrg
514005b261ecSmrg    wire= *wire_inout;
514105b261ecSmrg    if (req->nShapes<1) {
514205b261ecSmrg	client->errorValue= _XkbErrCode2(0x06,req->nShapes);
514305b261ecSmrg	return BadValue;
514405b261ecSmrg    }
514505b261ecSmrg    else {
514605b261ecSmrg	xkbShapeWireDesc *	shapeWire;
514705b261ecSmrg	XkbShapePtr		shape;
514805b261ecSmrg	register int		o;
514905b261ecSmrg	shapeWire= (xkbShapeWireDesc *)wire;
515005b261ecSmrg	for (i=0;i<req->nShapes;i++) {
515105b261ecSmrg	    xkbOutlineWireDesc *	olWire;
515205b261ecSmrg	    XkbOutlinePtr		ol;
515305b261ecSmrg	    shape= XkbAddGeomShape(geom,shapeWire->name,shapeWire->nOutlines);
515405b261ecSmrg	    if (!shape)
515505b261ecSmrg		return BadAlloc;
515605b261ecSmrg	    olWire= (xkbOutlineWireDesc *)(&shapeWire[1]);
515705b261ecSmrg	    for (o=0;o<shapeWire->nOutlines;o++) {
515805b261ecSmrg		register int		p;
515905b261ecSmrg		XkbPointPtr		pt;
516005b261ecSmrg		xkbPointWireDesc *	ptWire;
516105b261ecSmrg
516205b261ecSmrg		ol= XkbAddGeomOutline(shape,olWire->nPoints);
516305b261ecSmrg		if (!ol)
516405b261ecSmrg		    return BadAlloc;
516505b261ecSmrg		ol->corner_radius=	olWire->cornerRadius;
516605b261ecSmrg		ptWire= (xkbPointWireDesc *)&olWire[1];
516705b261ecSmrg		for (p=0,pt=ol->points;p<olWire->nPoints;p++,pt++) {
516805b261ecSmrg		    pt->x= ptWire[p].x;
516905b261ecSmrg		    pt->y= ptWire[p].y;
517005b261ecSmrg		    if (client->swapped) {
517105b261ecSmrg			register int n;
517205b261ecSmrg			swaps(&pt->x,n);
517305b261ecSmrg			swaps(&pt->y,n);
517405b261ecSmrg		    }
517505b261ecSmrg		}
517605b261ecSmrg		ol->num_points= olWire->nPoints;
517705b261ecSmrg		olWire= (xkbOutlineWireDesc *)(&ptWire[olWire->nPoints]);
517805b261ecSmrg	    }
517905b261ecSmrg	    if (shapeWire->primaryNdx!=XkbNoShape)
518005b261ecSmrg		shape->primary= &shape->outlines[shapeWire->primaryNdx];
518105b261ecSmrg	    if (shapeWire->approxNdx!=XkbNoShape)
518205b261ecSmrg		shape->approx= &shape->outlines[shapeWire->approxNdx];
518305b261ecSmrg	    shapeWire= (xkbShapeWireDesc *)olWire;
518405b261ecSmrg	}
518505b261ecSmrg	wire= (char *)shapeWire;
518605b261ecSmrg    }
518705b261ecSmrg    if (geom->num_shapes!=req->nShapes) {
518805b261ecSmrg	client->errorValue= _XkbErrCode3(0x07,geom->num_shapes,req->nShapes);
518905b261ecSmrg	return BadMatch;
519005b261ecSmrg    }
519105b261ecSmrg
519205b261ecSmrg    *wire_inout= wire;
519305b261ecSmrg    return Success;
519405b261ecSmrg}
519505b261ecSmrg
519605b261ecSmrgstatic Status
519705b261ecSmrg_CheckSetGeom(	XkbGeometryPtr		geom,
519805b261ecSmrg		xkbSetGeometryReq *	req,
519905b261ecSmrg		ClientPtr 		client)
520005b261ecSmrg{
520105b261ecSmrgregister int	i;
520205b261ecSmrgStatus		status;
520305b261ecSmrgchar *		wire;
520405b261ecSmrg
520505b261ecSmrg    wire= (char *)&req[1];
52061e26616aSmrg    status = _GetCountedString(&wire, client, &geom->label_font);
52071e26616aSmrg    if (status != Success)
52081e26616aSmrg        return status;
52091e26616aSmrg
52101e26616aSmrg    for (i = 0; i < req->nProperties; i++) {
52111e26616aSmrg	char *name, *val;
52121e26616aSmrg
52131e26616aSmrg        status = _GetCountedString(&wire, client, &name);
52141e26616aSmrg        if (status != Success)
52151e26616aSmrg            return status;
52161e26616aSmrg        status = _GetCountedString(&wire, client, &val);
52171e26616aSmrg        if (status != Success) {
52186747b715Smrg            free(name);
52191e26616aSmrg            return status;
522005b261ecSmrg        }
522105b261ecSmrg	if (XkbAddGeomProperty(geom,name,val)==NULL) {
52226747b715Smrg            free(name);
52236747b715Smrg            free(val);
522405b261ecSmrg	    return BadAlloc;
522505b261ecSmrg        }
52266747b715Smrg        free(name);
52276747b715Smrg        free(val);
522805b261ecSmrg    }
522905b261ecSmrg
523005b261ecSmrg    if (req->nColors<2) {
523105b261ecSmrg	client->errorValue= _XkbErrCode3(0x01,2,req->nColors);
523205b261ecSmrg	return BadValue;
523305b261ecSmrg    }
523405b261ecSmrg    if (req->baseColorNdx>req->nColors) {
523505b261ecSmrg	client->errorValue=_XkbErrCode3(0x03,req->nColors,req->baseColorNdx);
523605b261ecSmrg	return BadMatch;
523705b261ecSmrg    }
523805b261ecSmrg    if (req->labelColorNdx>req->nColors) {
523905b261ecSmrg	client->errorValue= _XkbErrCode3(0x03,req->nColors,req->labelColorNdx);
524005b261ecSmrg	return BadMatch;
524105b261ecSmrg    }
524205b261ecSmrg    if (req->labelColorNdx==req->baseColorNdx) {
524305b261ecSmrg	client->errorValue= _XkbErrCode3(0x04,req->baseColorNdx,
524405b261ecSmrg                                         req->labelColorNdx);
524505b261ecSmrg	return BadMatch;
524605b261ecSmrg    }
524705b261ecSmrg
52481e26616aSmrg    for (i = 0; i < req->nColors; i++) {
524905b261ecSmrg	char *name;
52501e26616aSmrg        status = _GetCountedString(&wire, client, &name);
52511e26616aSmrg        if (status != Success)
52521e26616aSmrg            return status;
525305b261ecSmrg        if (!XkbAddGeomColor(geom,name,geom->num_colors)) {
52546747b715Smrg            free(name);
525505b261ecSmrg	    return BadAlloc;
525605b261ecSmrg        }
52576747b715Smrg        free(name);
525805b261ecSmrg    }
525905b261ecSmrg    if (req->nColors!=geom->num_colors) {
526005b261ecSmrg	client->errorValue= _XkbErrCode3(0x05,req->nColors,geom->num_colors);
526105b261ecSmrg	return BadMatch;
526205b261ecSmrg    }
526305b261ecSmrg    geom->label_color= &geom->colors[req->labelColorNdx];
526405b261ecSmrg    geom->base_color= &geom->colors[req->baseColorNdx];
526505b261ecSmrg
526605b261ecSmrg    if ((status=_CheckSetShapes(geom,req,&wire,client))!=Success)
526705b261ecSmrg	return status;
526805b261ecSmrg
526905b261ecSmrg    if ((status=_CheckSetSections(geom,req,&wire,client))!=Success)
527005b261ecSmrg	return status;
527105b261ecSmrg
527205b261ecSmrg    for (i=0;i<req->nDoodads;i++) {
527305b261ecSmrg	status=_CheckSetDoodad(&wire,geom,NULL,client);
527405b261ecSmrg	if (status!=Success)
527505b261ecSmrg	    return status;
527605b261ecSmrg    }
527705b261ecSmrg
527805b261ecSmrg    for (i=0;i<req->nKeyAliases;i++) {
527905b261ecSmrg	if (XkbAddGeomKeyAlias(geom,&wire[XkbKeyNameLength],wire)==NULL)
528005b261ecSmrg	    return BadAlloc;
528105b261ecSmrg	wire+= 2*XkbKeyNameLength;
528205b261ecSmrg    }
528305b261ecSmrg    return Success;
528405b261ecSmrg}
528505b261ecSmrg
52864642e01fSmrgstatic int
52874642e01fSmrg_XkbSetGeometry(ClientPtr client, DeviceIntPtr dev, xkbSetGeometryReq *stuff)
528805b261ecSmrg{
528905b261ecSmrg    XkbDescPtr		xkb;
529005b261ecSmrg    Bool		new_name;
529105b261ecSmrg    xkbNewKeyboardNotify	nkn;
52924642e01fSmrg    XkbGeometryPtr	geom,old;
52934642e01fSmrg    XkbGeometrySizesRec	sizes;
52944642e01fSmrg    Status		status;
529505b261ecSmrg
529605b261ecSmrg    xkb= dev->key->xkbInfo->desc;
529705b261ecSmrg    old= xkb->geom;
529805b261ecSmrg    xkb->geom= NULL;
529905b261ecSmrg
53004642e01fSmrg    sizes.which=		XkbGeomAllMask;
530105b261ecSmrg    sizes.num_properties=	stuff->nProperties;
53024642e01fSmrg    sizes.num_colors=	stuff->nColors;
53034642e01fSmrg    sizes.num_shapes=	stuff->nShapes;
53044642e01fSmrg    sizes.num_sections=	stuff->nSections;
53054642e01fSmrg    sizes.num_doodads=	stuff->nDoodads;
530605b261ecSmrg    sizes.num_key_aliases=	stuff->nKeyAliases;
530705b261ecSmrg    if ((status= XkbAllocGeometry(xkb,&sizes))!=Success) {
53084642e01fSmrg        xkb->geom= old;
53094642e01fSmrg        return status;
531005b261ecSmrg    }
531105b261ecSmrg    geom= xkb->geom;
531205b261ecSmrg    geom->name= stuff->name;
531305b261ecSmrg    geom->width_mm= stuff->widthMM;
531405b261ecSmrg    geom->height_mm= stuff->heightMM;
531505b261ecSmrg    if ((status= _CheckSetGeom(geom,stuff,client))!=Success) {
53166747b715Smrg        XkbFreeGeometry(geom,XkbGeomAllMask,TRUE);
53174642e01fSmrg        xkb->geom= old;
53184642e01fSmrg        return status;
531905b261ecSmrg    }
532005b261ecSmrg    new_name= (xkb->names->geometry!=geom->name);
532105b261ecSmrg    xkb->names->geometry= geom->name;
532205b261ecSmrg    if (old)
53236747b715Smrg        XkbFreeGeometry(old,XkbGeomAllMask,TRUE);
532405b261ecSmrg    if (new_name) {
53254642e01fSmrg        xkbNamesNotify	nn;
53266747b715Smrg        memset(&nn, 0, sizeof(xkbNamesNotify));
53274642e01fSmrg        nn.changed= XkbGeometryNameMask;
53284642e01fSmrg        XkbSendNamesNotify(dev,&nn);
532905b261ecSmrg    }
533005b261ecSmrg    nkn.deviceID= nkn.oldDeviceID= dev->id;
533105b261ecSmrg    nkn.minKeyCode= nkn.oldMinKeyCode= xkb->min_key_code;
533205b261ecSmrg    nkn.maxKeyCode= nkn.oldMaxKeyCode= xkb->max_key_code;
533305b261ecSmrg    nkn.requestMajor=	XkbReqCode;
533405b261ecSmrg    nkn.requestMinor=	X_kbSetGeometry;
533505b261ecSmrg    nkn.changed=	XkbNKN_GeometryMask;
533605b261ecSmrg    XkbSendNewKeyboardNotify(dev,&nkn);
533705b261ecSmrg    return Success;
533805b261ecSmrg}
533905b261ecSmrg
53404642e01fSmrgint
53414642e01fSmrgProcXkbSetGeometry(ClientPtr client)
53424642e01fSmrg{
53434642e01fSmrg    DeviceIntPtr        dev;
53444642e01fSmrg    int                 rc;
53454642e01fSmrg
53464642e01fSmrg    REQUEST(xkbSetGeometryReq);
53474642e01fSmrg    REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq);
53484642e01fSmrg
53494642e01fSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
53504642e01fSmrg	return BadAccess;
53514642e01fSmrg
53524642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
53534642e01fSmrg    CHK_ATOM_OR_NONE(stuff->name);
53544642e01fSmrg
53554642e01fSmrg    rc = _XkbSetGeometry(client, dev, stuff);
53564642e01fSmrg    if (rc != Success)
53574642e01fSmrg        return rc;
53584642e01fSmrg
53594642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd)
53604642e01fSmrg    {
53614642e01fSmrg        DeviceIntPtr other;
53624642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
53634642e01fSmrg        {
53646747b715Smrg            if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev)
53654642e01fSmrg            {
53664642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
53674642e01fSmrg                if (rc == Success)
53684642e01fSmrg                    _XkbSetGeometry(client, other, stuff);
53694642e01fSmrg            }
53704642e01fSmrg        }
53714642e01fSmrg    }
53724642e01fSmrg
53734642e01fSmrg    return Success;
53744642e01fSmrg}
53754642e01fSmrg
537605b261ecSmrg/***====================================================================***/
537705b261ecSmrg
537805b261ecSmrgint
537905b261ecSmrgProcXkbPerClientFlags(ClientPtr client)
538005b261ecSmrg{
538105b261ecSmrg    DeviceIntPtr 		dev;
538205b261ecSmrg    xkbPerClientFlagsReply 	rep;
538305b261ecSmrg    XkbInterestPtr		interest;
53844642e01fSmrg    Mask access_mode = DixGetAttrAccess | DixSetAttrAccess;
538505b261ecSmrg
538605b261ecSmrg    REQUEST(xkbPerClientFlagsReq);
538705b261ecSmrg    REQUEST_SIZE_MATCH(xkbPerClientFlagsReq);
538805b261ecSmrg
538905b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
539005b261ecSmrg	return BadAccess;
539105b261ecSmrg
53924642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
539305b261ecSmrg    CHK_MASK_LEGAL(0x01,stuff->change,XkbPCF_AllFlagsMask);
539405b261ecSmrg    CHK_MASK_MATCH(0x02,stuff->change,stuff->value);
539505b261ecSmrg
539605b261ecSmrg    interest = XkbFindClientResource((DevicePtr)dev,client);
53976747b715Smrg    memset(&rep, 0, sizeof(xkbPerClientFlagsReply));
539805b261ecSmrg    rep.type= X_Reply;
539905b261ecSmrg    rep.length = 0;
540005b261ecSmrg    rep.sequenceNumber = client->sequence;
540105b261ecSmrg    if (stuff->change) {
540205b261ecSmrg	client->xkbClientFlags&= ~stuff->change;
540305b261ecSmrg	client->xkbClientFlags|= stuff->value;
540405b261ecSmrg    }
540505b261ecSmrg    if (stuff->change&XkbPCF_AutoResetControlsMask) {
540605b261ecSmrg	Bool	want;
540705b261ecSmrg	want= stuff->value&XkbPCF_AutoResetControlsMask;
540805b261ecSmrg	if (interest && !want) {
540905b261ecSmrg	    interest->autoCtrls= interest->autoCtrlValues= 0;
541005b261ecSmrg	}
541105b261ecSmrg	else if (want && (!interest)) {
541205b261ecSmrg	    XID id = FakeClientID(client->index);
54136747b715Smrg	    if (!AddResource(id,RT_XKBCLIENT,dev))
54146747b715Smrg		return BadAlloc;
541505b261ecSmrg	    interest= XkbAddClientResource((DevicePtr)dev,client,id);
541605b261ecSmrg	    if (!interest)
541705b261ecSmrg		return BadAlloc;
541805b261ecSmrg	}
541905b261ecSmrg	if (interest && want ) {
542005b261ecSmrg	    register unsigned affect;
542105b261ecSmrg	    affect= stuff->ctrlsToChange;
542205b261ecSmrg
542305b261ecSmrg	    CHK_MASK_LEGAL(0x03,affect,XkbAllBooleanCtrlsMask);
542405b261ecSmrg	    CHK_MASK_MATCH(0x04,affect,stuff->autoCtrls);
542505b261ecSmrg	    CHK_MASK_MATCH(0x05,stuff->autoCtrls,stuff->autoCtrlValues);
542605b261ecSmrg
542705b261ecSmrg	    interest->autoCtrls&= ~affect;
542805b261ecSmrg	    interest->autoCtrlValues&= ~affect;
542905b261ecSmrg	    interest->autoCtrls|= stuff->autoCtrls&affect;
543005b261ecSmrg	    interest->autoCtrlValues|= stuff->autoCtrlValues&affect;
543105b261ecSmrg	}
543205b261ecSmrg    }
543305b261ecSmrg    rep.supported = XkbPCF_AllFlagsMask;
543405b261ecSmrg    rep.value= client->xkbClientFlags&XkbPCF_AllFlagsMask;
543505b261ecSmrg    if (interest) {
543605b261ecSmrg	rep.autoCtrls= interest->autoCtrls;
543705b261ecSmrg	rep.autoCtrlValues= interest->autoCtrlValues;
543805b261ecSmrg    }
543905b261ecSmrg    else {
544005b261ecSmrg	rep.autoCtrls= rep.autoCtrlValues= 0;
544105b261ecSmrg    }
544205b261ecSmrg    if ( client->swapped ) {
544305b261ecSmrg	register int n;
544405b261ecSmrg	swaps(&rep.sequenceNumber, n);
544505b261ecSmrg	swapl(&rep.supported,n);
544605b261ecSmrg	swapl(&rep.value,n);
544705b261ecSmrg	swapl(&rep.autoCtrls,n);
544805b261ecSmrg	swapl(&rep.autoCtrlValues,n);
544905b261ecSmrg    }
545005b261ecSmrg    WriteToClient(client,SIZEOF(xkbPerClientFlagsReply), (char *)&rep);
54516747b715Smrg    return Success;
545205b261ecSmrg}
545305b261ecSmrg
545405b261ecSmrg/***====================================================================***/
545505b261ecSmrg
545605b261ecSmrg/* all latin-1 alphanumerics, plus parens, minus, underscore, slash */
545705b261ecSmrg/* and wildcards */
545805b261ecSmrgstatic unsigned char componentSpecLegal[] = {
545905b261ecSmrg        0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x87,
546005b261ecSmrg        0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07,
546105b261ecSmrg        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
546205b261ecSmrg        0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
546305b261ecSmrg};
546405b261ecSmrg
546505b261ecSmrg/* same as above but accepts percent, plus and bar too */
546605b261ecSmrgstatic unsigned char componentExprLegal[] = {
546705b261ecSmrg        0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0xff, 0x87,
546805b261ecSmrg        0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x17,
546905b261ecSmrg        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
547005b261ecSmrg        0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
547105b261ecSmrg};
547205b261ecSmrg
547305b261ecSmrgstatic char *
547405b261ecSmrgGetComponentSpec(unsigned char **pWire,Bool allowExpr,int *errRtrn)
547505b261ecSmrg{
547605b261ecSmrgint		len;
547705b261ecSmrgregister int	i;
547805b261ecSmrgunsigned char	*wire,*str,*tmp,*legal;
547905b261ecSmrg
548005b261ecSmrg    if (allowExpr)	legal= &componentExprLegal[0];
548105b261ecSmrg    else		legal= &componentSpecLegal[0];
548205b261ecSmrg
548305b261ecSmrg    wire= *pWire;
548405b261ecSmrg    len= (*(unsigned char *)wire++);
548505b261ecSmrg    if (len>0) {
54866747b715Smrg	str= calloc(1, len+1);
548705b261ecSmrg	if (str) {
548805b261ecSmrg	    tmp= str;
548905b261ecSmrg	    for (i=0;i<len;i++) {
549005b261ecSmrg		if (legal[(*wire)/8]&(1<<((*wire)%8)))
549105b261ecSmrg		    *tmp++= *wire++;
549205b261ecSmrg		else wire++;
549305b261ecSmrg	    }
549405b261ecSmrg	    if (tmp!=str)
549505b261ecSmrg		*tmp++= '\0';
549605b261ecSmrg	    else {
54976747b715Smrg		free(str);
549805b261ecSmrg		str= NULL;
549905b261ecSmrg	    }
550005b261ecSmrg	}
550105b261ecSmrg	else {
550205b261ecSmrg	    *errRtrn= BadAlloc;
550305b261ecSmrg	}
550405b261ecSmrg    }
550505b261ecSmrg    else {
550605b261ecSmrg	str= NULL;
550705b261ecSmrg    }
550805b261ecSmrg    *pWire= wire;
550905b261ecSmrg    return (char *)str;
551005b261ecSmrg}
551105b261ecSmrg
551205b261ecSmrg/***====================================================================***/
551305b261ecSmrg
551405b261ecSmrgint
551505b261ecSmrgProcXkbListComponents(ClientPtr client)
551605b261ecSmrg{
551705b261ecSmrg    DeviceIntPtr 		dev;
551805b261ecSmrg    xkbListComponentsReply 	rep;
551905b261ecSmrg    unsigned			len;
552005b261ecSmrg    int				status;
552105b261ecSmrg    unsigned char *		str;
552205b261ecSmrg    XkbSrvListInfoRec		list;
552305b261ecSmrg
552405b261ecSmrg    REQUEST(xkbListComponentsReq);
552505b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbListComponentsReq);
552605b261ecSmrg
552705b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
552805b261ecSmrg	return BadAccess;
552905b261ecSmrg
55304642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
553105b261ecSmrg
553205b261ecSmrg    status= Success;
553305b261ecSmrg    str= (unsigned char *)&stuff[1];
55346747b715Smrg    memset(&list, 0, sizeof(XkbSrvListInfoRec));
553505b261ecSmrg    list.maxRtrn= stuff->maxNames;
55366747b715Smrg    list.pattern[_XkbListKeycodes]= GetComponentSpec(&str,FALSE,&status);
55376747b715Smrg    list.pattern[_XkbListTypes]= GetComponentSpec(&str,FALSE,&status);
55386747b715Smrg    list.pattern[_XkbListCompat]= GetComponentSpec(&str,FALSE,&status);
55396747b715Smrg    list.pattern[_XkbListSymbols]= GetComponentSpec(&str,FALSE,&status);
55406747b715Smrg    list.pattern[_XkbListGeometry]= GetComponentSpec(&str,FALSE,&status);
554105b261ecSmrg    if (status!=Success)
554205b261ecSmrg	return status;
554305b261ecSmrg    len= str-((unsigned char *)stuff);
554405b261ecSmrg    if ((XkbPaddedSize(len)/4)!=stuff->length)
554505b261ecSmrg	return BadLength;
554605b261ecSmrg    if ((status=XkbDDXList(dev,&list,client))!=Success) {
55476747b715Smrg	free(list.pool);
55486747b715Smrg	list.pool = NULL;
554905b261ecSmrg	return status;
555005b261ecSmrg    }
55516747b715Smrg    memset(&rep, 0, sizeof(xkbListComponentsReply));
555205b261ecSmrg    rep.type= X_Reply;
555305b261ecSmrg    rep.deviceID = dev->id;
555405b261ecSmrg    rep.sequenceNumber = client->sequence;
555505b261ecSmrg    rep.length = XkbPaddedSize(list.nPool)/4;
55566747b715Smrg    rep.nKeymaps = 0;
555705b261ecSmrg    rep.nKeycodes = list.nFound[_XkbListKeycodes];
555805b261ecSmrg    rep.nTypes = list.nFound[_XkbListTypes];
555905b261ecSmrg    rep.nCompatMaps = list.nFound[_XkbListCompat];
556005b261ecSmrg    rep.nSymbols = list.nFound[_XkbListSymbols];
556105b261ecSmrg    rep.nGeometries = list.nFound[_XkbListGeometry];
556205b261ecSmrg    rep.extra=	0;
556305b261ecSmrg    if (list.nTotal>list.maxRtrn)
556405b261ecSmrg	rep.extra = (list.nTotal-list.maxRtrn);
556505b261ecSmrg    if (client->swapped) {
556605b261ecSmrg	register int n;
556705b261ecSmrg	swaps(&rep.sequenceNumber,n);
556805b261ecSmrg	swapl(&rep.length,n);
556905b261ecSmrg	swaps(&rep.nKeymaps,n);
557005b261ecSmrg	swaps(&rep.nKeycodes,n);
557105b261ecSmrg	swaps(&rep.nTypes,n);
557205b261ecSmrg	swaps(&rep.nCompatMaps,n);
557305b261ecSmrg	swaps(&rep.nSymbols,n);
557405b261ecSmrg	swaps(&rep.nGeometries,n);
557505b261ecSmrg	swaps(&rep.extra,n);
557605b261ecSmrg    }
557705b261ecSmrg    WriteToClient(client,SIZEOF(xkbListComponentsReply),(char *)&rep);
557805b261ecSmrg    if (list.nPool && list.pool) {
557905b261ecSmrg	WriteToClient(client,XkbPaddedSize(list.nPool), (char *)list.pool);
55806747b715Smrg	free(list.pool);
558105b261ecSmrg	list.pool= NULL;
558205b261ecSmrg    }
55836747b715Smrg    return Success;
558405b261ecSmrg}
558505b261ecSmrg
558605b261ecSmrg/***====================================================================***/
558705b261ecSmrg
558805b261ecSmrgint
558905b261ecSmrgProcXkbGetKbdByName(ClientPtr client)
559005b261ecSmrg{
559105b261ecSmrg    DeviceIntPtr 		dev;
559205b261ecSmrg    DeviceIntPtr                tmpd;
55939ace9065Smrg    xkbGetKbdByNameReply 	rep = {0};
55949ace9065Smrg    xkbGetMapReply		mrep = {0};
55959ace9065Smrg    xkbGetCompatMapReply	crep = {0};
55969ace9065Smrg    xkbGetIndicatorMapReply	irep = {0};
55979ace9065Smrg    xkbGetNamesReply		nrep = {0};
55989ace9065Smrg    xkbGetGeometryReply		grep = {0};
55999ace9065Smrg    XkbComponentNamesRec	names = {0};
56004642e01fSmrg    XkbDescPtr			xkb, new;
560105b261ecSmrg    unsigned char *		str;
560205b261ecSmrg    char 			mapFile[PATH_MAX];
560305b261ecSmrg    unsigned			len;
560405b261ecSmrg    unsigned			fwant,fneed,reported;
560505b261ecSmrg    int				status;
560605b261ecSmrg    Bool			geom_changed;
560705b261ecSmrg    XkbSrvLedInfoPtr            old_sli;
560805b261ecSmrg    XkbSrvLedInfoPtr            sli;
56094642e01fSmrg    Mask access_mode = DixGetAttrAccess | DixManageAccess;
561005b261ecSmrg
561105b261ecSmrg    REQUEST(xkbGetKbdByNameReq);
561205b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq);
561305b261ecSmrg
561405b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
561505b261ecSmrg	return BadAccess;
561605b261ecSmrg
56174642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
561805b261ecSmrg
561905b261ecSmrg    xkb = dev->key->xkbInfo->desc;
562005b261ecSmrg    status= Success;
562105b261ecSmrg    str= (unsigned char *)&stuff[1];
56226747b715Smrg    if (GetComponentSpec(&str,TRUE,&status)) /* keymap, unsupported */
56236747b715Smrg        return BadMatch;
56246747b715Smrg    names.keycodes= GetComponentSpec(&str,TRUE,&status);
56256747b715Smrg    names.types= GetComponentSpec(&str,TRUE,&status);
56266747b715Smrg    names.compat= GetComponentSpec(&str,TRUE,&status);
56276747b715Smrg    names.symbols= GetComponentSpec(&str,TRUE,&status);
56286747b715Smrg    names.geometry= GetComponentSpec(&str,TRUE,&status);
562905b261ecSmrg    if (status!=Success)
563005b261ecSmrg	return status;
563105b261ecSmrg    len= str-((unsigned char *)stuff);
563205b261ecSmrg    if ((XkbPaddedSize(len)/4)!=stuff->length)
563305b261ecSmrg	return BadLength;
563405b261ecSmrg
563505b261ecSmrg    CHK_MASK_LEGAL(0x01,stuff->want,XkbGBN_AllComponentsMask);
563605b261ecSmrg    CHK_MASK_LEGAL(0x02,stuff->need,XkbGBN_AllComponentsMask);
563705b261ecSmrg
563805b261ecSmrg    if (stuff->load)
563905b261ecSmrg	 fwant= XkbGBN_AllComponentsMask;
564005b261ecSmrg    else fwant= stuff->want|stuff->need;
56414642e01fSmrg    if ((!names.compat)&&
56424642e01fSmrg        (fwant&(XkbGBN_CompatMapMask|XkbGBN_IndicatorMapMask))) {
56434642e01fSmrg        names.compat= _XkbDupString("%");
564405b261ecSmrg    }
56454642e01fSmrg    if ((!names.types)&&(fwant&(XkbGBN_TypesMask))) {
56464642e01fSmrg        names.types= _XkbDupString("%");
56474642e01fSmrg    }
56484642e01fSmrg    if ((!names.symbols)&&(fwant&XkbGBN_SymbolsMask)) {
56494642e01fSmrg        names.symbols= _XkbDupString("%");
56504642e01fSmrg    }
56514642e01fSmrg    geom_changed= ((names.geometry!=NULL)&&(strcmp(names.geometry,"%")!=0));
56524642e01fSmrg    if ((!names.geometry)&&(fwant&XkbGBN_GeometryMask)) {
56534642e01fSmrg        names.geometry= _XkbDupString("%");
56546747b715Smrg        geom_changed= FALSE;
565505b261ecSmrg    }
565605b261ecSmrg
56576747b715Smrg    memset(mapFile, 0, PATH_MAX);
565805b261ecSmrg    rep.type= X_Reply;
565905b261ecSmrg    rep.deviceID = dev->id;
566005b261ecSmrg    rep.sequenceNumber = client->sequence;
566105b261ecSmrg    rep.length = 0;
566205b261ecSmrg    rep.minKeyCode = xkb->min_key_code;
566305b261ecSmrg    rep.maxKeyCode = xkb->max_key_code;
56646747b715Smrg    rep.loaded=	FALSE;
56656747b715Smrg    fwant= XkbConvertGetByNameComponents(TRUE,stuff->want)|XkmVirtualModsMask;
56666747b715Smrg    fneed= XkbConvertGetByNameComponents(TRUE,stuff->need);
56676747b715Smrg    rep.reported= XkbConvertGetByNameComponents(FALSE,fwant|fneed);
566805b261ecSmrg    if (stuff->load) {
566905b261ecSmrg	fneed|= XkmKeymapRequired;
567005b261ecSmrg	fwant|= XkmKeymapLegal;
567105b261ecSmrg    }
567205b261ecSmrg    if ((fwant|fneed)&XkmSymbolsMask) {
567305b261ecSmrg	fneed|= XkmKeyNamesIndex|XkmTypesIndex;
567405b261ecSmrg	fwant|= XkmIndicatorsIndex;
567505b261ecSmrg    }
567605b261ecSmrg
567705b261ecSmrg    /* We pass dev in here so we can get the old names out if needed. */
56784642e01fSmrg    rep.found = XkbDDXLoadKeymapByNames(dev,&names,fwant,fneed,&new,
567905b261ecSmrg                                        mapFile,PATH_MAX);
56806747b715Smrg    rep.newKeyboard= FALSE;
568105b261ecSmrg    rep.pad1= rep.pad2= rep.pad3= rep.pad4= 0;
568205b261ecSmrg
568305b261ecSmrg    stuff->want|= stuff->need;
56844642e01fSmrg    if (new==NULL)
568505b261ecSmrg	rep.reported= 0;
568605b261ecSmrg    else {
568705b261ecSmrg	if (stuff->load)
56886747b715Smrg	    rep.loaded= TRUE;
568905b261ecSmrg	if (stuff->load ||
56904642e01fSmrg		((rep.reported&XkbGBN_SymbolsMask) && (new->compat))) {
569105b261ecSmrg	    XkbChangesRec changes;
56926747b715Smrg	    memset(&changes, 0, sizeof(changes));
56934642e01fSmrg	    XkbUpdateDescActions(new,
56944642e01fSmrg			new->min_key_code,XkbNumKeys(new),
569505b261ecSmrg			&changes);
569605b261ecSmrg	}
569705b261ecSmrg
56984642e01fSmrg	if (new->map==NULL)
569905b261ecSmrg	    rep.reported&= ~(XkbGBN_SymbolsMask|XkbGBN_TypesMask);
570005b261ecSmrg	else if (rep.reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask)) {
570105b261ecSmrg	    mrep.type= X_Reply;
570205b261ecSmrg	    mrep.deviceID = dev->id;
570305b261ecSmrg	    mrep.sequenceNumber= client->sequence;
570405b261ecSmrg	    mrep.length = ((SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2);
57054642e01fSmrg	    mrep.minKeyCode = new->min_key_code;
57064642e01fSmrg	    mrep.maxKeyCode = new->max_key_code;
570705b261ecSmrg	    mrep.present = 0;
570805b261ecSmrg	    mrep.totalSyms = mrep.totalActs =
570905b261ecSmrg		mrep.totalKeyBehaviors= mrep.totalKeyExplicit=
571052397711Smrg		mrep.totalModMapKeys= mrep.totalVModMapKeys= 0;
571105b261ecSmrg	    if (rep.reported&(XkbGBN_TypesMask|XkbGBN_ClientSymbolsMask)) {
571205b261ecSmrg		mrep.present|= XkbKeyTypesMask;
571305b261ecSmrg		mrep.firstType = 0;
57144642e01fSmrg		mrep.nTypes = mrep.totalTypes= new->map->num_types;
571505b261ecSmrg	    }
571605b261ecSmrg	    else {
571705b261ecSmrg		mrep.firstType = mrep.nTypes= 0;
571805b261ecSmrg		mrep.totalTypes= 0;
571905b261ecSmrg	    }
572005b261ecSmrg	    if (rep.reported&XkbGBN_ClientSymbolsMask) {
572105b261ecSmrg		mrep.present|= (XkbKeySymsMask|XkbModifierMapMask);
57224642e01fSmrg		mrep.firstKeySym = mrep.firstModMapKey= new->min_key_code;
57234642e01fSmrg		mrep.nKeySyms = mrep.nModMapKeys= XkbNumKeys(new);
572405b261ecSmrg	    }
572505b261ecSmrg	    else {
572605b261ecSmrg		mrep.firstKeySym= mrep.firstModMapKey= 0;
572705b261ecSmrg		mrep.nKeySyms= mrep.nModMapKeys= 0;
572805b261ecSmrg	    }
572905b261ecSmrg	    if (rep.reported&XkbGBN_ServerSymbolsMask) {
573005b261ecSmrg		mrep.present|= XkbAllServerInfoMask;
573105b261ecSmrg		mrep.virtualMods= ~0;
573205b261ecSmrg		mrep.firstKeyAct = mrep.firstKeyBehavior =
57334642e01fSmrg			mrep.firstKeyExplicit = new->min_key_code;
573405b261ecSmrg		mrep.nKeyActs = mrep.nKeyBehaviors =
57354642e01fSmrg			mrep.nKeyExplicit = XkbNumKeys(new);
573652397711Smrg		mrep.firstVModMapKey= new->min_key_code;
573752397711Smrg		mrep.nVModMapKeys= XkbNumKeys(new);
573805b261ecSmrg	    }
573905b261ecSmrg	    else {
574005b261ecSmrg		mrep.virtualMods= 0;
574105b261ecSmrg		mrep.firstKeyAct= mrep.firstKeyBehavior=
574205b261ecSmrg			mrep.firstKeyExplicit = 0;
574305b261ecSmrg		mrep.nKeyActs= mrep.nKeyBehaviors= mrep.nKeyExplicit= 0;
574405b261ecSmrg	    }
57454642e01fSmrg	    XkbComputeGetMapReplySize(new,&mrep);
574605b261ecSmrg	    rep.length+= SIZEOF(xGenericReply)/4+mrep.length;
574705b261ecSmrg	}
57484642e01fSmrg	if (new->compat==NULL)
574905b261ecSmrg	    rep.reported&= ~XkbGBN_CompatMapMask;
575005b261ecSmrg	else if (rep.reported&XkbGBN_CompatMapMask) {
575105b261ecSmrg	    crep.type= X_Reply;
575205b261ecSmrg	    crep.deviceID= dev->id;
575305b261ecSmrg	    crep.sequenceNumber= client->sequence;
575405b261ecSmrg	    crep.length= 0;
575505b261ecSmrg	    crep.groups= XkbAllGroupsMask;
575605b261ecSmrg	    crep.firstSI= 0;
57574642e01fSmrg	    crep.nSI= crep.nTotalSI= new->compat->num_si;
57584642e01fSmrg	    XkbComputeGetCompatMapReplySize(new->compat,&crep);
575905b261ecSmrg	    rep.length+= SIZEOF(xGenericReply)/4+crep.length;
576005b261ecSmrg	}
57614642e01fSmrg	if (new->indicators==NULL)
576205b261ecSmrg	    rep.reported&= ~XkbGBN_IndicatorMapMask;
576305b261ecSmrg	else if (rep.reported&XkbGBN_IndicatorMapMask) {
576405b261ecSmrg	    irep.type= X_Reply;
576505b261ecSmrg	    irep.deviceID= dev->id;
576605b261ecSmrg	    irep.sequenceNumber= client->sequence;
576705b261ecSmrg	    irep.length= 0;
576805b261ecSmrg	    irep.which= XkbAllIndicatorsMask;
57694642e01fSmrg	    XkbComputeGetIndicatorMapReplySize(new->indicators,&irep);
577005b261ecSmrg	    rep.length+= SIZEOF(xGenericReply)/4+irep.length;
577105b261ecSmrg	}
57724642e01fSmrg	if (new->names==NULL)
577305b261ecSmrg	    rep.reported&= ~(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask);
577405b261ecSmrg	else if (rep.reported&(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask)) {
577505b261ecSmrg	    nrep.type= X_Reply;
577605b261ecSmrg	    nrep.deviceID= dev->id;
577705b261ecSmrg	    nrep.sequenceNumber= client->sequence;
577805b261ecSmrg	    nrep.length= 0;
57794642e01fSmrg	    nrep.minKeyCode= new->min_key_code;
57804642e01fSmrg	    nrep.maxKeyCode= new->max_key_code;
578105b261ecSmrg	    if (rep.reported&XkbGBN_OtherNamesMask) {
578205b261ecSmrg		nrep.which= XkbAllNamesMask;
57834642e01fSmrg		if (new->map!=NULL)
57844642e01fSmrg		     nrep.nTypes= new->map->num_types;
578505b261ecSmrg		else nrep.nTypes= 0;
578605b261ecSmrg		nrep.nKTLevels= 0;
578705b261ecSmrg		nrep.groupNames= XkbAllGroupsMask;
578805b261ecSmrg		nrep.virtualMods= XkbAllVirtualModsMask;
578905b261ecSmrg		nrep.indicators= XkbAllIndicatorsMask;
57904642e01fSmrg		nrep.nRadioGroups= new->names->num_rg;
579105b261ecSmrg	    }
579205b261ecSmrg	    else {
579305b261ecSmrg		nrep.which= 0;
579405b261ecSmrg		nrep.nTypes= 0;
579505b261ecSmrg		nrep.nKTLevels= 0;
579605b261ecSmrg		nrep.groupNames= 0;
579705b261ecSmrg		nrep.virtualMods= 0;
579805b261ecSmrg		nrep.indicators= 0;
579905b261ecSmrg		nrep.nRadioGroups= 0;
580005b261ecSmrg	    }
580105b261ecSmrg	    if (rep.reported&XkbGBN_KeyNamesMask) {
580205b261ecSmrg		nrep.which|= XkbKeyNamesMask;
58034642e01fSmrg		nrep.firstKey= new->min_key_code;
58044642e01fSmrg		nrep.nKeys= XkbNumKeys(new);
58054642e01fSmrg		nrep.nKeyAliases= new->names->num_key_aliases;
580605b261ecSmrg		if (nrep.nKeyAliases)
580705b261ecSmrg		    nrep.which|= XkbKeyAliasesMask;
580805b261ecSmrg	    }
580905b261ecSmrg	    else {
581005b261ecSmrg		nrep.which&= ~(XkbKeyNamesMask|XkbKeyAliasesMask);
581105b261ecSmrg		nrep.firstKey= nrep.nKeys= 0;
581205b261ecSmrg		nrep.nKeyAliases= 0;
581305b261ecSmrg	    }
58144642e01fSmrg	    XkbComputeGetNamesReplySize(new,&nrep);
581505b261ecSmrg	    rep.length+= SIZEOF(xGenericReply)/4+nrep.length;
581605b261ecSmrg	}
58174642e01fSmrg	if (new->geom==NULL)
581805b261ecSmrg	    rep.reported&= ~XkbGBN_GeometryMask;
581905b261ecSmrg	else if (rep.reported&XkbGBN_GeometryMask) {
582005b261ecSmrg	    grep.type= X_Reply;
582105b261ecSmrg	    grep.deviceID= dev->id;
582205b261ecSmrg	    grep.sequenceNumber= client->sequence;
582305b261ecSmrg	    grep.length= 0;
58246747b715Smrg	    grep.found= TRUE;
582505b261ecSmrg	    grep.pad= 0;
582605b261ecSmrg	    grep.widthMM= grep.heightMM= 0;
582705b261ecSmrg	    grep.nProperties= grep.nColors= grep.nShapes= 0;
582805b261ecSmrg	    grep.nSections= grep.nDoodads= 0;
582905b261ecSmrg	    grep.baseColorNdx= grep.labelColorNdx= 0;
58304642e01fSmrg	    XkbComputeGetGeometryReplySize(new->geom,&grep,None);
583105b261ecSmrg	    rep.length+= SIZEOF(xGenericReply)/4+grep.length;
583205b261ecSmrg	}
583305b261ecSmrg    }
583405b261ecSmrg
583505b261ecSmrg    reported= rep.reported;
583605b261ecSmrg    if ( client->swapped ) {
583705b261ecSmrg	register int n;
583805b261ecSmrg	swaps(&rep.sequenceNumber,n);
583905b261ecSmrg	swapl(&rep.length,n);
584005b261ecSmrg	swaps(&rep.found,n);
584105b261ecSmrg	swaps(&rep.reported,n);
584205b261ecSmrg    }
584305b261ecSmrg    WriteToClient(client,SIZEOF(xkbGetKbdByNameReply), (char *)&rep);
584405b261ecSmrg    if (reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask))
58454642e01fSmrg	XkbSendMap(client,new,&mrep);
584605b261ecSmrg    if (reported&XkbGBN_CompatMapMask)
58474642e01fSmrg	XkbSendCompatMap(client,new->compat,&crep);
584805b261ecSmrg    if (reported&XkbGBN_IndicatorMapMask)
58494642e01fSmrg	XkbSendIndicatorMap(client,new->indicators,&irep);
585005b261ecSmrg    if (reported&(XkbGBN_KeyNamesMask|XkbGBN_OtherNamesMask))
58514642e01fSmrg	XkbSendNames(client,new,&nrep);
585205b261ecSmrg    if (reported&XkbGBN_GeometryMask)
58536747b715Smrg	XkbSendGeometry(client,new->geom,&grep,FALSE);
585405b261ecSmrg    if (rep.loaded) {
585505b261ecSmrg	XkbDescPtr		old_xkb;
585605b261ecSmrg	xkbNewKeyboardNotify 	nkn;
585705b261ecSmrg	int 			i,nG,nTG;
585805b261ecSmrg	old_xkb= xkb;
58594642e01fSmrg	xkb= new;
586005b261ecSmrg	dev->key->xkbInfo->desc= xkb;
58614642e01fSmrg	new= old_xkb; /* so it'll get freed automatically */
586205b261ecSmrg
586305b261ecSmrg	*xkb->ctrls= *old_xkb->ctrls;
586405b261ecSmrg	for (nG=nTG=0,i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
586505b261ecSmrg	    nG= XkbKeyNumGroups(xkb,i);
586605b261ecSmrg	    if (nG>=XkbNumKbdGroups) {
586705b261ecSmrg		nTG= XkbNumKbdGroups;
586805b261ecSmrg		break;
586905b261ecSmrg	    }
587005b261ecSmrg	    if (nG>nTG) {
587105b261ecSmrg		nTG= nG;
587205b261ecSmrg	    }
587305b261ecSmrg	}
587405b261ecSmrg	xkb->ctrls->num_groups= nTG;
587505b261ecSmrg
587605b261ecSmrg        for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
58776747b715Smrg            if ((tmpd == dev) || (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) {
587805b261ecSmrg                if (tmpd != dev)
58796747b715Smrg                    XkbCopyDeviceKeymap(tmpd, dev);
588005b261ecSmrg
588105b261ecSmrg                if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) {
588205b261ecSmrg                    old_sli = tmpd->kbdfeed->xkb_sli;
588305b261ecSmrg                    tmpd->kbdfeed->xkb_sli = NULL;
588405b261ecSmrg                    sli = XkbAllocSrvLedInfo(tmpd, tmpd->kbdfeed, NULL, 0);
588505b261ecSmrg                    if (sli) {
588605b261ecSmrg                        sli->explicitState = old_sli->explicitState;
588705b261ecSmrg                        sli->effectiveState = old_sli->effectiveState;
588805b261ecSmrg                    }
588905b261ecSmrg                    tmpd->kbdfeed->xkb_sli = sli;
589005b261ecSmrg                    XkbFreeSrvLedInfo(old_sli);
589105b261ecSmrg                }
589205b261ecSmrg            }
589305b261ecSmrg        }
589405b261ecSmrg
589505b261ecSmrg	nkn.deviceID= nkn.oldDeviceID= dev->id;
58964642e01fSmrg	nkn.minKeyCode= new->min_key_code;
58974642e01fSmrg	nkn.maxKeyCode= new->max_key_code;
589805b261ecSmrg	nkn.oldMinKeyCode= xkb->min_key_code;
589905b261ecSmrg	nkn.oldMaxKeyCode= xkb->max_key_code;
590005b261ecSmrg	nkn.requestMajor= XkbReqCode;
590105b261ecSmrg	nkn.requestMinor= X_kbGetKbdByName;
590205b261ecSmrg	nkn.changed= XkbNKN_KeycodesMask;
590305b261ecSmrg	if (geom_changed)
590405b261ecSmrg	    nkn.changed|= XkbNKN_GeometryMask;
590505b261ecSmrg	XkbSendNewKeyboardNotify(dev,&nkn);
59066747b715Smrg
59076747b715Smrg	if (!IsMaster(dev) && dev->u.master)
59086747b715Smrg	{
59096747b715Smrg	    DeviceIntPtr master = dev->u.master;
59106747b715Smrg	    if (master->u.lastSlave == dev)
59116747b715Smrg	    {
59126747b715Smrg		XkbCopyDeviceKeymap(dev->u.master, dev);
59136747b715Smrg		XkbSendNewKeyboardNotify(dev,&nkn);
59146747b715Smrg	    }
59156747b715Smrg	}
591605b261ecSmrg    }
59174642e01fSmrg    if ((new!=NULL)&&(new!=xkb)) {
59186747b715Smrg	XkbFreeKeyboard(new,XkbAllComponentsMask,TRUE);
59194642e01fSmrg	new= NULL;
592005b261ecSmrg    }
59219ace9065Smrg    XkbFreeComponentNames(&names, FALSE);
59226747b715Smrg    return Success;
592305b261ecSmrg}
592405b261ecSmrg
592505b261ecSmrg/***====================================================================***/
592605b261ecSmrg
592705b261ecSmrgstatic int
592805b261ecSmrgComputeDeviceLedInfoSize(	DeviceIntPtr		dev,
592905b261ecSmrg				unsigned int		what,
593005b261ecSmrg				XkbSrvLedInfoPtr	sli)
593105b261ecSmrg{
593205b261ecSmrgint			nNames,nMaps;
593305b261ecSmrgregister unsigned 	n,bit;
593405b261ecSmrg
593505b261ecSmrg    if (sli==NULL)
593605b261ecSmrg	return 0;
593705b261ecSmrg    nNames= nMaps= 0;
593805b261ecSmrg    if ((what&XkbXI_IndicatorNamesMask)==0)
593905b261ecSmrg	sli->namesPresent= 0;
594005b261ecSmrg    if ((what&XkbXI_IndicatorMapsMask)==0)
594105b261ecSmrg	sli->mapsPresent= 0;
594205b261ecSmrg
594305b261ecSmrg    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
594405b261ecSmrg	if (sli->names && sli->names[n]!=None) {
594505b261ecSmrg	    sli->namesPresent|= bit;
594605b261ecSmrg	    nNames++;
594705b261ecSmrg	}
594805b261ecSmrg	if (sli->maps && XkbIM_InUse(&sli->maps[n])) {
594905b261ecSmrg	    sli->mapsPresent|= bit;
595005b261ecSmrg	    nMaps++;
595105b261ecSmrg	}
595205b261ecSmrg    }
595305b261ecSmrg    return (nNames*4)+(nMaps*SIZEOF(xkbIndicatorMapWireDesc));
595405b261ecSmrg}
595505b261ecSmrg
595605b261ecSmrgstatic int
595705b261ecSmrgCheckDeviceLedFBs(	DeviceIntPtr			dev,
595805b261ecSmrg			int				class,
595905b261ecSmrg			int				id,
596005b261ecSmrg			xkbGetDeviceInfoReply *		rep,
596105b261ecSmrg			ClientPtr			client)
596205b261ecSmrg{
596305b261ecSmrgint			nFBs= 0;
596405b261ecSmrgint			length= 0;
596505b261ecSmrgBool			classOk;
596605b261ecSmrg
596705b261ecSmrg    if (class==XkbDfltXIClass) {
596805b261ecSmrg	if (dev->kbdfeed)	class= KbdFeedbackClass;
596905b261ecSmrg	else if (dev->leds)	class= LedFeedbackClass;
597005b261ecSmrg	else {
597105b261ecSmrg	    client->errorValue= _XkbErrCode2(XkbErr_BadClass,class);
597205b261ecSmrg	    return XkbKeyboardErrorCode;
597305b261ecSmrg	}
597405b261ecSmrg    }
59756747b715Smrg    classOk= FALSE;
597605b261ecSmrg    if ((dev->kbdfeed)&&((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) {
597705b261ecSmrg	KbdFeedbackPtr kf;
59786747b715Smrg	classOk= TRUE;
597905b261ecSmrg	for (kf= dev->kbdfeed;(kf);kf=kf->next) {
598005b261ecSmrg	    if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=kf->ctrl.id))
598105b261ecSmrg		continue;
598205b261ecSmrg	    nFBs++;
598305b261ecSmrg	    length+= SIZEOF(xkbDeviceLedsWireDesc);
598405b261ecSmrg	    if (!kf->xkb_sli)
598505b261ecSmrg		kf->xkb_sli= XkbAllocSrvLedInfo(dev,kf,NULL,0);
598605b261ecSmrg	    length+= ComputeDeviceLedInfoSize(dev,rep->present,kf->xkb_sli);
598705b261ecSmrg	    if (id!=XkbAllXIIds)
598805b261ecSmrg		break;
598905b261ecSmrg	}
599005b261ecSmrg    }
599105b261ecSmrg    if ((dev->leds)&&((class==LedFeedbackClass)||(class==XkbAllXIClasses))) {
599205b261ecSmrg	LedFeedbackPtr lf;
59936747b715Smrg	classOk= TRUE;
599405b261ecSmrg	for (lf= dev->leds;(lf);lf=lf->next) {
599505b261ecSmrg	    if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=lf->ctrl.id))
599605b261ecSmrg		continue;
599705b261ecSmrg	    nFBs++;
599805b261ecSmrg	    length+= SIZEOF(xkbDeviceLedsWireDesc);
599905b261ecSmrg	    if (!lf->xkb_sli)
600005b261ecSmrg		lf->xkb_sli= XkbAllocSrvLedInfo(dev,NULL,lf,0);
600105b261ecSmrg	    length+= ComputeDeviceLedInfoSize(dev,rep->present,lf->xkb_sli);
600205b261ecSmrg	    if (id!=XkbAllXIIds)
600305b261ecSmrg		break;
600405b261ecSmrg	}
600505b261ecSmrg    }
600605b261ecSmrg    if (nFBs>0) {
60076747b715Smrg        rep->nDeviceLedFBs= nFBs;
60086747b715Smrg        rep->length+= (length/4);
600905b261ecSmrg	return Success;
601005b261ecSmrg    }
601105b261ecSmrg    if (classOk) client->errorValue= _XkbErrCode2(XkbErr_BadId,id);
601205b261ecSmrg    else	 client->errorValue= _XkbErrCode2(XkbErr_BadClass,class);
601305b261ecSmrg    return XkbKeyboardErrorCode;
601405b261ecSmrg}
601505b261ecSmrg
601605b261ecSmrgstatic int
601705b261ecSmrgSendDeviceLedInfo(	XkbSrvLedInfoPtr	sli,
601805b261ecSmrg			ClientPtr		client)
601905b261ecSmrg{
602005b261ecSmrgxkbDeviceLedsWireDesc	wire;
602105b261ecSmrgint			length;
602205b261ecSmrg
602305b261ecSmrg    length= 0;
602405b261ecSmrg    wire.ledClass= 		sli->class;
602505b261ecSmrg    wire.ledID= 		sli->id;
602605b261ecSmrg    wire.namesPresent= 		sli->namesPresent;
602705b261ecSmrg    wire.mapsPresent=   	sli->mapsPresent;
602805b261ecSmrg    wire.physIndicators= 	sli->physIndicators;
602905b261ecSmrg    wire.state=			sli->effectiveState;
603005b261ecSmrg    if (client->swapped) {
603105b261ecSmrg	register int n;
603205b261ecSmrg	swaps(&wire.ledClass,n);
603305b261ecSmrg	swaps(&wire.ledID,n);
603405b261ecSmrg	swapl(&wire.namesPresent,n);
603505b261ecSmrg	swapl(&wire.mapsPresent,n);
603605b261ecSmrg	swapl(&wire.physIndicators,n);
603705b261ecSmrg	swapl(&wire.state,n);
603805b261ecSmrg    }
603905b261ecSmrg    WriteToClient(client,SIZEOF(xkbDeviceLedsWireDesc),(char *)&wire);
604005b261ecSmrg    length+= SIZEOF(xkbDeviceLedsWireDesc);
604105b261ecSmrg    if (sli->namesPresent|sli->mapsPresent) {
604205b261ecSmrg	register unsigned i,bit;
604305b261ecSmrg	if (sli->namesPresent) {
604405b261ecSmrg	    CARD32	awire;
604505b261ecSmrg	    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
604605b261ecSmrg		if (sli->namesPresent&bit) {
604705b261ecSmrg		    awire= (CARD32)sli->names[i];
604805b261ecSmrg		    if (client->swapped) {
604905b261ecSmrg			register int n;
605005b261ecSmrg			swapl(&awire,n);
605105b261ecSmrg		    }
605205b261ecSmrg		    WriteToClient(client,4,(char *)&awire);
605305b261ecSmrg		    length+= 4;
605405b261ecSmrg		}
605505b261ecSmrg	    }
605605b261ecSmrg	}
605705b261ecSmrg	if (sli->mapsPresent) {
605805b261ecSmrg	    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
605905b261ecSmrg		xkbIndicatorMapWireDesc	iwire;
606005b261ecSmrg		if (sli->mapsPresent&bit) {
606105b261ecSmrg		    iwire.flags= 	sli->maps[i].flags;
606205b261ecSmrg		    iwire.whichGroups=	sli->maps[i].which_groups;
606305b261ecSmrg		    iwire.groups=	sli->maps[i].groups;
606405b261ecSmrg		    iwire.whichMods=	sli->maps[i].which_mods;
606505b261ecSmrg		    iwire.mods=		sli->maps[i].mods.mask;
606605b261ecSmrg		    iwire.realMods=	sli->maps[i].mods.real_mods;
606705b261ecSmrg		    iwire.virtualMods=	sli->maps[i].mods.vmods;
606805b261ecSmrg		    iwire.ctrls= 	sli->maps[i].ctrls;
606905b261ecSmrg		    if (client->swapped) {
607005b261ecSmrg			register int n;
607105b261ecSmrg			swaps(&iwire.virtualMods,n);
607205b261ecSmrg			swapl(&iwire.ctrls,n);
607305b261ecSmrg		    }
607405b261ecSmrg		    WriteToClient(client,SIZEOF(xkbIndicatorMapWireDesc),
607505b261ecSmrg								(char *)&iwire);
607605b261ecSmrg		    length+= SIZEOF(xkbIndicatorMapWireDesc);
607705b261ecSmrg		}
607805b261ecSmrg	    }
607905b261ecSmrg	}
608005b261ecSmrg    }
608105b261ecSmrg    return length;
608205b261ecSmrg}
608305b261ecSmrg
608405b261ecSmrgstatic int
608505b261ecSmrgSendDeviceLedFBs(	DeviceIntPtr	dev,
608605b261ecSmrg			int		class,
608705b261ecSmrg			int		id,
608805b261ecSmrg			unsigned	wantLength,
608905b261ecSmrg			ClientPtr	client)
609005b261ecSmrg{
609105b261ecSmrgint			length= 0;
609205b261ecSmrg
609305b261ecSmrg    if (class==XkbDfltXIClass) {
609405b261ecSmrg	if (dev->kbdfeed)	class= KbdFeedbackClass;
609505b261ecSmrg	else if (dev->leds)	class= LedFeedbackClass;
609605b261ecSmrg    }
609705b261ecSmrg    if ((dev->kbdfeed)&&
609805b261ecSmrg	((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) {
609905b261ecSmrg	KbdFeedbackPtr kf;
610005b261ecSmrg	for (kf= dev->kbdfeed;(kf);kf=kf->next) {
610105b261ecSmrg	    if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==kf->ctrl.id)) {
610205b261ecSmrg		length+= SendDeviceLedInfo(kf->xkb_sli,client);
610305b261ecSmrg		if (id!=XkbAllXIIds)
610405b261ecSmrg		    break;
610505b261ecSmrg	    }
610605b261ecSmrg	}
610705b261ecSmrg    }
610805b261ecSmrg    if ((dev->leds)&&
610905b261ecSmrg	((class==LedFeedbackClass)||(class==XkbAllXIClasses))) {
611005b261ecSmrg	LedFeedbackPtr lf;
611105b261ecSmrg	for (lf= dev->leds;(lf);lf=lf->next) {
611205b261ecSmrg	    if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==lf->ctrl.id)) {
611305b261ecSmrg		length+= SendDeviceLedInfo(lf->xkb_sli,client);
611405b261ecSmrg		if (id!=XkbAllXIIds)
611505b261ecSmrg		    break;
611605b261ecSmrg	    }
611705b261ecSmrg	}
611805b261ecSmrg    }
611905b261ecSmrg    if (length==wantLength)
612005b261ecSmrg	 return Success;
612105b261ecSmrg    else return BadLength;
612205b261ecSmrg}
612305b261ecSmrg
612405b261ecSmrgint
612505b261ecSmrgProcXkbGetDeviceInfo(ClientPtr client)
612605b261ecSmrg{
612705b261ecSmrgDeviceIntPtr		dev;
612805b261ecSmrgxkbGetDeviceInfoReply	rep;
612905b261ecSmrgint			status,nDeviceLedFBs;
613005b261ecSmrgunsigned		length,nameLen;
613105b261ecSmrgCARD16			ledClass,ledID;
61326747b715Smrgunsigned		wanted;
613305b261ecSmrgchar *			str;
613405b261ecSmrg
613505b261ecSmrg    REQUEST(xkbGetDeviceInfoReq);
613605b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq);
613705b261ecSmrg
613805b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
613905b261ecSmrg	return BadAccess;
614005b261ecSmrg
614105b261ecSmrg    wanted= stuff->wanted;
614205b261ecSmrg
61434642e01fSmrg    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
614405b261ecSmrg    CHK_MASK_LEGAL(0x01,wanted,XkbXI_AllDeviceFeaturesMask);
614505b261ecSmrg
614605b261ecSmrg    if ((!dev->button)||((stuff->nBtns<1)&&(!stuff->allBtns)))
614705b261ecSmrg	wanted&= ~XkbXI_ButtonActionsMask;
614805b261ecSmrg    if ((!dev->kbdfeed)&&(!dev->leds))
614905b261ecSmrg	wanted&= ~XkbXI_IndicatorsMask;
615005b261ecSmrg
615105b261ecSmrg    nameLen= XkbSizeCountedString(dev->name);
61526747b715Smrg    memset((char *)&rep, 0, SIZEOF(xkbGetDeviceInfoReply));
615305b261ecSmrg    rep.type = X_Reply;
615405b261ecSmrg    rep.deviceID= dev->id;
615505b261ecSmrg    rep.sequenceNumber = client->sequence;
615605b261ecSmrg    rep.length = nameLen/4;
615705b261ecSmrg    rep.present = wanted;
615805b261ecSmrg    rep.supported = XkbXI_AllDeviceFeaturesMask;
615905b261ecSmrg    rep.unsupported = 0;
616005b261ecSmrg    rep.firstBtnWanted = rep.nBtnsWanted = 0;
616105b261ecSmrg    rep.firstBtnRtrn = rep.nBtnsRtrn = 0;
616205b261ecSmrg    if (dev->button)
616305b261ecSmrg	 rep.totalBtns= dev->button->numButtons;
616405b261ecSmrg    else rep.totalBtns= 0;
61656747b715Smrg    rep.devType=	dev->xinput_type;
616605b261ecSmrg    rep.hasOwnState=	(dev->key && dev->key->xkbInfo);
616705b261ecSmrg    rep.nDeviceLedFBs = 0;
616805b261ecSmrg    if (dev->kbdfeed)	rep.dfltKbdFB= dev->kbdfeed->ctrl.id;
616905b261ecSmrg    else		rep.dfltKbdFB= XkbXINone;
617005b261ecSmrg    if (dev->leds)	rep.dfltLedFB= dev->leds->ctrl.id;
617105b261ecSmrg    else		rep.dfltLedFB= XkbXINone;
617205b261ecSmrg
617305b261ecSmrg    ledClass= stuff->ledClass;
617405b261ecSmrg    ledID= stuff->ledID;
617505b261ecSmrg
617605b261ecSmrg    rep.firstBtnWanted= rep.nBtnsWanted= 0;
617705b261ecSmrg    rep.firstBtnRtrn= rep.nBtnsRtrn= 0;
617805b261ecSmrg    if (wanted&XkbXI_ButtonActionsMask) {
617905b261ecSmrg	if (stuff->allBtns) {
618005b261ecSmrg	    stuff->firstBtn= 0;
618105b261ecSmrg	    stuff->nBtns= dev->button->numButtons;
618205b261ecSmrg	}
618305b261ecSmrg
618405b261ecSmrg	if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) {
618505b261ecSmrg	    client->errorValue = _XkbErrCode4(0x02,dev->button->numButtons,
618605b261ecSmrg							stuff->firstBtn,
618705b261ecSmrg							stuff->nBtns);
618805b261ecSmrg	    return BadValue;
618905b261ecSmrg	}
619005b261ecSmrg	else {
619105b261ecSmrg	    rep.firstBtnWanted= stuff->firstBtn;
619205b261ecSmrg	    rep.nBtnsWanted= stuff->nBtns;
619305b261ecSmrg	    if (dev->button->xkb_acts!=NULL) {
619405b261ecSmrg		XkbAction *act;
619505b261ecSmrg		register int i;
619605b261ecSmrg
619705b261ecSmrg		rep.firstBtnRtrn= stuff->firstBtn;
619805b261ecSmrg		rep.nBtnsRtrn= stuff->nBtns;
619905b261ecSmrg		act= &dev->button->xkb_acts[rep.firstBtnWanted];
620005b261ecSmrg		for (i=0;i<rep.nBtnsRtrn;i++,act++) {
620105b261ecSmrg		    if (act->type!=XkbSA_NoAction)
620205b261ecSmrg			break;
620305b261ecSmrg		}
620405b261ecSmrg		rep.firstBtnRtrn+=	i;
620505b261ecSmrg		rep.nBtnsRtrn-=		i;
620605b261ecSmrg		act= &dev->button->xkb_acts[rep.firstBtnRtrn+rep.nBtnsRtrn-1];
620705b261ecSmrg		for (i=0;i<rep.nBtnsRtrn;i++,act--) {
620805b261ecSmrg		    if (act->type!=XkbSA_NoAction)
620905b261ecSmrg			break;
621005b261ecSmrg		}
621105b261ecSmrg		rep.nBtnsRtrn-=		i;
621205b261ecSmrg	    }
621305b261ecSmrg	    rep.length+= (rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc))/4;
621405b261ecSmrg	}
621505b261ecSmrg    }
621605b261ecSmrg
621705b261ecSmrg    if (wanted&XkbXI_IndicatorsMask) {
621805b261ecSmrg	status= CheckDeviceLedFBs(dev,ledClass,ledID,&rep,client);
621905b261ecSmrg	if (status!=Success)
622005b261ecSmrg	    return status;
622105b261ecSmrg    }
622205b261ecSmrg    length= rep.length*4;
622305b261ecSmrg    nDeviceLedFBs = rep.nDeviceLedFBs;
622405b261ecSmrg    if (client->swapped) {
622505b261ecSmrg	register int n;
622605b261ecSmrg	swaps(&rep.sequenceNumber,n);
622705b261ecSmrg	swapl(&rep.length,n);
622805b261ecSmrg	swaps(&rep.present,n);
622905b261ecSmrg	swaps(&rep.supported,n);
623005b261ecSmrg	swaps(&rep.unsupported,n);
623105b261ecSmrg	swaps(&rep.nDeviceLedFBs,n);
623205b261ecSmrg	swapl(&rep.type,n);
6233475c125cSmrg	swaps(&rep.dfltKbdFB, n);
6234475c125cSmrg	swaps(&rep.dfltLedFB, n);
6235475c125cSmrg	swapl(&rep.devType, n);
623605b261ecSmrg    }
623705b261ecSmrg    WriteToClient(client,SIZEOF(xkbGetDeviceInfoReply), (char *)&rep);
623805b261ecSmrg
62396747b715Smrg    str= malloc(nameLen);
624005b261ecSmrg    if (!str)
624105b261ecSmrg	return BadAlloc;
624205b261ecSmrg    XkbWriteCountedString(str,dev->name,client->swapped);
624305b261ecSmrg    WriteToClient(client,nameLen,str);
62446747b715Smrg    free(str);
624505b261ecSmrg    length-= nameLen;
624605b261ecSmrg
624705b261ecSmrg    if (rep.nBtnsRtrn>0) {
624805b261ecSmrg	int			sz;
624905b261ecSmrg	xkbActionWireDesc *	awire;
625005b261ecSmrg	sz= rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc);
625105b261ecSmrg	awire= (xkbActionWireDesc *)&dev->button->xkb_acts[rep.firstBtnRtrn];
625205b261ecSmrg	WriteToClient(client,sz,(char *)awire);
625305b261ecSmrg	length-= sz;
625405b261ecSmrg    }
625505b261ecSmrg    if (nDeviceLedFBs>0) {
625605b261ecSmrg	status= SendDeviceLedFBs(dev,ledClass,ledID,length,client);
625705b261ecSmrg	if (status!=Success)
625805b261ecSmrg	    return status;
625905b261ecSmrg    }
626005b261ecSmrg    else if (length!=0)  {
62614642e01fSmrg	ErrorF("[xkb] Internal Error!  BadLength in ProcXkbGetDeviceInfo\n");
62624642e01fSmrg	ErrorF("[xkb]                  Wrote %d fewer bytes than expected\n",length);
626305b261ecSmrg	return BadLength;
626405b261ecSmrg    }
62656747b715Smrg    return Success;
626605b261ecSmrg}
626705b261ecSmrg
626805b261ecSmrgstatic char *
626905b261ecSmrgCheckSetDeviceIndicators(	char *		wire,
627005b261ecSmrg				DeviceIntPtr	dev,
627105b261ecSmrg				int		num,
627205b261ecSmrg				int *		status_rtrn,
627305b261ecSmrg				ClientPtr	client)
627405b261ecSmrg{
627505b261ecSmrgxkbDeviceLedsWireDesc *	ledWire;
627605b261ecSmrgint			i;
627705b261ecSmrgXkbSrvLedInfoPtr 	sli;
627805b261ecSmrg
627905b261ecSmrg    ledWire= (xkbDeviceLedsWireDesc *)wire;
628005b261ecSmrg    for (i=0;i<num;i++) {
628105b261ecSmrg	if (client->swapped) {
628205b261ecSmrg	   register int n;
628305b261ecSmrg	   swaps(&ledWire->ledClass,n);
628405b261ecSmrg	   swaps(&ledWire->ledID,n);
628505b261ecSmrg	   swapl(&ledWire->namesPresent,n);
628605b261ecSmrg	   swapl(&ledWire->mapsPresent,n);
628705b261ecSmrg	   swapl(&ledWire->physIndicators,n);
628805b261ecSmrg	}
628905b261ecSmrg
629005b261ecSmrg        sli= XkbFindSrvLedInfo(dev,ledWire->ledClass,ledWire->ledID,
629105b261ecSmrg							XkbXI_IndicatorsMask);
629205b261ecSmrg	if (sli!=NULL) {
629305b261ecSmrg	    register int n;
629405b261ecSmrg	    register unsigned bit;
629505b261ecSmrg	    int nMaps,nNames;
629605b261ecSmrg	    CARD32 *atomWire;
629705b261ecSmrg	    xkbIndicatorMapWireDesc *mapWire;
629805b261ecSmrg
629905b261ecSmrg	    nMaps= nNames= 0;
630005b261ecSmrg	    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
630105b261ecSmrg		if (ledWire->namesPresent&bit)
630205b261ecSmrg		    nNames++;
630305b261ecSmrg		if (ledWire->mapsPresent&bit)
630405b261ecSmrg		    nMaps++;
630505b261ecSmrg	    }
630605b261ecSmrg	    atomWire= (CARD32 *)&ledWire[1];
630705b261ecSmrg	    if (nNames>0) {
630805b261ecSmrg		for (n=0;n<nNames;n++) {
630905b261ecSmrg		    if (client->swapped) {
631005b261ecSmrg			register int t;
631105b261ecSmrg			swapl(atomWire,t);
631205b261ecSmrg		    }
631305b261ecSmrg		    CHK_ATOM_OR_NONE3(((Atom)(*atomWire)),client->errorValue,
631405b261ecSmrg							*status_rtrn,NULL);
631505b261ecSmrg		    atomWire++;
631605b261ecSmrg		}
631705b261ecSmrg	    }
631805b261ecSmrg	    mapWire= (xkbIndicatorMapWireDesc *)atomWire;
631905b261ecSmrg	    if (nMaps>0) {
632005b261ecSmrg		for (n=0;n<nMaps;n++) {
632105b261ecSmrg		    if (client->swapped) {
632205b261ecSmrg			register int t;
632305b261ecSmrg			swaps(&mapWire->virtualMods,t);
632405b261ecSmrg			swapl(&mapWire->ctrls,t);
632505b261ecSmrg		    }
632605b261ecSmrg		    CHK_MASK_LEGAL3(0x21,mapWire->whichGroups,
632705b261ecSmrg						XkbIM_UseAnyGroup,
632805b261ecSmrg						client->errorValue,
632905b261ecSmrg						*status_rtrn,NULL);
633005b261ecSmrg		    CHK_MASK_LEGAL3(0x22,mapWire->whichMods,XkbIM_UseAnyMods,
633105b261ecSmrg						client->errorValue,
633205b261ecSmrg						*status_rtrn,NULL);
633305b261ecSmrg		    mapWire++;
633405b261ecSmrg		}
633505b261ecSmrg	    }
633605b261ecSmrg	    ledWire= (xkbDeviceLedsWireDesc *)mapWire;
633705b261ecSmrg	}
633805b261ecSmrg	else {
633905b261ecSmrg	    /* SHOULD NEVER HAPPEN */
634005b261ecSmrg	    return (char *)ledWire;
634105b261ecSmrg	}
634205b261ecSmrg    }
634305b261ecSmrg    return (char *)ledWire;
634405b261ecSmrg}
634505b261ecSmrg
634605b261ecSmrgstatic char *
634705b261ecSmrgSetDeviceIndicators(	char *			wire,
634805b261ecSmrg			DeviceIntPtr		dev,
634905b261ecSmrg			unsigned		changed,
635005b261ecSmrg			int			num,
635105b261ecSmrg			int *			status_rtrn,
635205b261ecSmrg			ClientPtr		client,
635305b261ecSmrg			xkbExtensionDeviceNotify *ev)
635405b261ecSmrg{
635505b261ecSmrgxkbDeviceLedsWireDesc *		ledWire;
635605b261ecSmrgint				i;
635705b261ecSmrgXkbEventCauseRec		cause;
635805b261ecSmrgunsigned			namec,mapc,statec;
635905b261ecSmrgxkbExtensionDeviceNotify	ed;
636005b261ecSmrgXkbChangesRec			changes;
636105b261ecSmrgDeviceIntPtr			kbd;
636205b261ecSmrg
63636747b715Smrg    memset((char *)&ed, 0, sizeof(xkbExtensionDeviceNotify));
63646747b715Smrg    memset((char *)&changes, 0, sizeof(XkbChangesRec));
636505b261ecSmrg    XkbSetCauseXkbReq(&cause,X_kbSetDeviceInfo,client);
636605b261ecSmrg    ledWire= (xkbDeviceLedsWireDesc *)wire;
636705b261ecSmrg    for (i=0;i<num;i++) {
636805b261ecSmrg	register int			n;
636905b261ecSmrg	register unsigned 		bit;
637005b261ecSmrg	CARD32 *			atomWire;
637105b261ecSmrg	xkbIndicatorMapWireDesc *	mapWire;
637205b261ecSmrg	XkbSrvLedInfoPtr		sli;
637305b261ecSmrg
637405b261ecSmrg	namec= mapc= statec= 0;
637505b261ecSmrg    	sli= XkbFindSrvLedInfo(dev,ledWire->ledClass,ledWire->ledID,
637605b261ecSmrg						XkbXI_IndicatorMapsMask);
637705b261ecSmrg	if (!sli) {
637805b261ecSmrg	    /* SHOULD NEVER HAPPEN!! */
637905b261ecSmrg	    return (char *)ledWire;
638005b261ecSmrg	}
638105b261ecSmrg
638205b261ecSmrg	atomWire= (CARD32 *)&ledWire[1];
638305b261ecSmrg	if (changed&XkbXI_IndicatorNamesMask) {
638405b261ecSmrg	    namec= sli->namesPresent|ledWire->namesPresent;
63856747b715Smrg	    memset((char *)sli->names, 0, XkbNumIndicators*sizeof(Atom));
638605b261ecSmrg	}
638705b261ecSmrg	if (ledWire->namesPresent) {
638805b261ecSmrg	    sli->namesPresent= ledWire->namesPresent;
63896747b715Smrg	    memset((char *)sli->names, 0, XkbNumIndicators*sizeof(Atom));
639005b261ecSmrg	    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
639105b261ecSmrg		if (ledWire->namesPresent&bit) {
639205b261ecSmrg		     sli->names[n]= (Atom)*atomWire;
639305b261ecSmrg		     if (sli->names[n]==None)
639405b261ecSmrg			ledWire->namesPresent&= ~bit;
639505b261ecSmrg		     atomWire++;
639605b261ecSmrg		}
639705b261ecSmrg	    }
639805b261ecSmrg	}
639905b261ecSmrg	mapWire= (xkbIndicatorMapWireDesc *)atomWire;
640005b261ecSmrg	if (changed&XkbXI_IndicatorMapsMask) {
640105b261ecSmrg	    mapc= sli->mapsPresent|ledWire->mapsPresent;
640205b261ecSmrg	    sli->mapsPresent= ledWire->mapsPresent;
64036747b715Smrg	    memset((char*)sli->maps, 0, XkbNumIndicators*sizeof(XkbIndicatorMapRec));
640405b261ecSmrg	}
640505b261ecSmrg	if (ledWire->mapsPresent) {
640605b261ecSmrg	    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
640705b261ecSmrg		if (ledWire->mapsPresent&bit) {
640805b261ecSmrg		    sli->maps[n].flags=		mapWire->flags;
640905b261ecSmrg		    sli->maps[n].which_groups=	mapWire->whichGroups;
641005b261ecSmrg		    sli->maps[n].groups=	mapWire->groups;
641105b261ecSmrg		    sli->maps[n].which_mods=	mapWire->whichMods;
641205b261ecSmrg		    sli->maps[n].mods.mask=	mapWire->mods;
641305b261ecSmrg		    sli->maps[n].mods.real_mods=mapWire->realMods;
641405b261ecSmrg		    sli->maps[n].mods.vmods=	mapWire->virtualMods;
641505b261ecSmrg		    sli->maps[n].ctrls=		mapWire->ctrls;
641605b261ecSmrg		    mapWire++;
641705b261ecSmrg		}
641805b261ecSmrg	    }
641905b261ecSmrg	}
642005b261ecSmrg	if (changed&XkbXI_IndicatorStateMask) {
642105b261ecSmrg	    statec= sli->effectiveState^ledWire->state;
642205b261ecSmrg	    sli->explicitState&= ~statec;
642305b261ecSmrg	    sli->explicitState|= (ledWire->state&statec);
642405b261ecSmrg	}
642505b261ecSmrg	if (namec)
642605b261ecSmrg	    XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause);
642705b261ecSmrg	if (mapc)
642805b261ecSmrg	    XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause);
642905b261ecSmrg	if (statec)
643005b261ecSmrg	    XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause);
643105b261ecSmrg
643205b261ecSmrg	kbd= dev;
643305b261ecSmrg	if ((sli->flags&XkbSLI_HasOwnState)==0)
64344642e01fSmrg	    kbd = inputInfo.keyboard;
643505b261ecSmrg
643605b261ecSmrg	XkbFlushLedEvents(dev,kbd,sli,&ed,&changes,&cause);
643705b261ecSmrg	ledWire= (xkbDeviceLedsWireDesc *)mapWire;
643805b261ecSmrg    }
643905b261ecSmrg    return (char *)ledWire;
644005b261ecSmrg}
644105b261ecSmrg
644205b261ecSmrg
64434642e01fSmrgstatic int
64444642e01fSmrg_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev,
64454642e01fSmrg                  xkbSetDeviceInfoReq *stuff)
64464642e01fSmrg{
64474642e01fSmrg    char                       *wire;
644805b261ecSmrg
644905b261ecSmrg    wire= (char *)&stuff[1];
64504642e01fSmrg    if (stuff->change&XkbXI_ButtonActionsMask) {
645105b261ecSmrg	if (!dev->button) {
645205b261ecSmrg	    client->errorValue = _XkbErrCode2(XkbErr_BadClass,ButtonClass);
645305b261ecSmrg	    return XkbKeyboardErrorCode;
645405b261ecSmrg	}
645505b261ecSmrg	if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) {
645605b261ecSmrg	    client->errorValue= _XkbErrCode4(0x02,stuff->firstBtn,stuff->nBtns,
645705b261ecSmrg						dev->button->numButtons);
645805b261ecSmrg	    return BadMatch;
645905b261ecSmrg	}
646005b261ecSmrg	wire+= (stuff->nBtns*SIZEOF(xkbActionWireDesc));
646105b261ecSmrg    }
646205b261ecSmrg    if (stuff->change&XkbXI_IndicatorsMask) {
646305b261ecSmrg	int status= Success;
646405b261ecSmrg	wire= CheckSetDeviceIndicators(wire,dev,stuff->nDeviceLedFBs,
646505b261ecSmrg							&status,client);
646605b261ecSmrg	if (status!=Success)
646705b261ecSmrg	    return status;
646805b261ecSmrg    }
646905b261ecSmrg    if (((wire-((char *)stuff))/4)!=stuff->length)
647005b261ecSmrg	return BadLength;
647105b261ecSmrg
64724642e01fSmrg    return Success;
64734642e01fSmrg}
64744642e01fSmrg
64754642e01fSmrgstatic int
64764642e01fSmrg_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev,
64774642e01fSmrg                       xkbSetDeviceInfoReq *stuff)
64784642e01fSmrg{
64794642e01fSmrg    char                       *wire;
64804642e01fSmrg    xkbExtensionDeviceNotify    ed;
64814642e01fSmrg
64826747b715Smrg    memset((char *)&ed, 0, SIZEOF(xkbExtensionDeviceNotify));
648305b261ecSmrg    ed.deviceID=	dev->id;
648405b261ecSmrg    wire= (char *)&stuff[1];
64854642e01fSmrg    if (stuff->change&XkbXI_ButtonActionsMask) {
648605b261ecSmrg	int			nBtns,sz,i;
648705b261ecSmrg	XkbAction *		acts;
648805b261ecSmrg	DeviceIntPtr		kbd;
648905b261ecSmrg
649005b261ecSmrg	nBtns= dev->button->numButtons;
649105b261ecSmrg	acts= dev->button->xkb_acts;
649205b261ecSmrg	if (acts==NULL) {
64936747b715Smrg	    acts= calloc(nBtns, sizeof(XkbAction));
649405b261ecSmrg	    if (!acts)
649505b261ecSmrg		return BadAlloc;
649605b261ecSmrg	    dev->button->xkb_acts= acts;
649705b261ecSmrg	}
649805b261ecSmrg	sz= stuff->nBtns*SIZEOF(xkbActionWireDesc);
649905b261ecSmrg	memcpy((char *)&acts[stuff->firstBtn],(char *)wire,sz);
650005b261ecSmrg	wire+= sz;
650105b261ecSmrg	ed.reason|=	XkbXI_ButtonActionsMask;
650205b261ecSmrg	ed.firstBtn=	stuff->firstBtn;
650305b261ecSmrg	ed.nBtns=	stuff->nBtns;
650405b261ecSmrg
650505b261ecSmrg	if (dev->key)	kbd= dev;
65064642e01fSmrg	else		kbd= inputInfo.keyboard;
650705b261ecSmrg	acts= &dev->button->xkb_acts[stuff->firstBtn];
650805b261ecSmrg	for (i=0;i<stuff->nBtns;i++,acts++) {
650905b261ecSmrg	    if (acts->type!=XkbSA_NoAction)
651005b261ecSmrg		XkbSetActionKeyMods(kbd->key->xkbInfo->desc,acts,0);
651105b261ecSmrg	}
651205b261ecSmrg    }
651305b261ecSmrg    if (stuff->change&XkbXI_IndicatorsMask) {
651405b261ecSmrg	int status= Success;
65154642e01fSmrg	wire= SetDeviceIndicators(wire,dev,stuff->change,
65164642e01fSmrg				  stuff->nDeviceLedFBs, &status,client,&ed);
651705b261ecSmrg	if (status!=Success)
651805b261ecSmrg	    return status;
651905b261ecSmrg    }
652005b261ecSmrg    if ((stuff->change)&&(ed.reason))
652105b261ecSmrg	XkbSendExtensionDeviceNotify(dev,client,&ed);
65224642e01fSmrg    return Success;
65234642e01fSmrg}
65244642e01fSmrg
65254642e01fSmrgint
65264642e01fSmrgProcXkbSetDeviceInfo(ClientPtr client)
65274642e01fSmrg{
65284642e01fSmrg    DeviceIntPtr        dev;
65294642e01fSmrg    int                 rc;
65304642e01fSmrg
65314642e01fSmrg    REQUEST(xkbSetDeviceInfoReq);
65324642e01fSmrg    REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq);
65334642e01fSmrg
65344642e01fSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
65354642e01fSmrg	return BadAccess;
65364642e01fSmrg
65374642e01fSmrg    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
65384642e01fSmrg    CHK_MASK_LEGAL(0x01,stuff->change,XkbXI_AllFeaturesMask);
65394642e01fSmrg
65404642e01fSmrg    rc = _XkbSetDeviceInfoCheck(client, dev, stuff);
65414642e01fSmrg
65424642e01fSmrg    if (rc != Success)
65434642e01fSmrg        return rc;
65444642e01fSmrg
65454642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd || stuff->deviceSpec == XkbUseCorePtr)
65464642e01fSmrg    {
65474642e01fSmrg        DeviceIntPtr other;
65484642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
65494642e01fSmrg        {
65506747b715Smrg            if (((other != dev) && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) &&
65514642e01fSmrg                ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
65524642e01fSmrg                (stuff->deviceSpec == XkbUseCorePtr && other->button)))
65534642e01fSmrg            {
65544642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
65554642e01fSmrg                if (rc == Success)
65564642e01fSmrg                {
65574642e01fSmrg                    rc = _XkbSetDeviceInfoCheck(client, other, stuff);
65584642e01fSmrg                    if (rc != Success)
65594642e01fSmrg                        return rc;
65604642e01fSmrg                }
65614642e01fSmrg            }
65624642e01fSmrg        }
65634642e01fSmrg    }
65644642e01fSmrg
65654642e01fSmrg    /* checks done, apply */
65664642e01fSmrg    rc = _XkbSetDeviceInfo(client, dev, stuff);
65674642e01fSmrg    if (rc != Success)
65684642e01fSmrg        return rc;
65694642e01fSmrg
65704642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd || stuff->deviceSpec == XkbUseCorePtr)
65714642e01fSmrg    {
65724642e01fSmrg        DeviceIntPtr other;
65734642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
65744642e01fSmrg        {
65756747b715Smrg            if (((other != dev) && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) &&
65764642e01fSmrg                ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
65774642e01fSmrg                (stuff->deviceSpec == XkbUseCorePtr && other->button)))
65784642e01fSmrg            {
65794642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
65804642e01fSmrg                if (rc == Success)
65814642e01fSmrg                {
65824642e01fSmrg                    rc = _XkbSetDeviceInfo(client, other, stuff);
65834642e01fSmrg                    if (rc != Success)
65844642e01fSmrg                        return rc;
65854642e01fSmrg                }
65864642e01fSmrg            }
65874642e01fSmrg        }
65884642e01fSmrg    }
65894642e01fSmrg
65906747b715Smrg    return Success;
659105b261ecSmrg}
659205b261ecSmrg
659305b261ecSmrg/***====================================================================***/
659405b261ecSmrg
659505b261ecSmrgint
659605b261ecSmrgProcXkbSetDebuggingFlags(ClientPtr client)
659705b261ecSmrg{
659805b261ecSmrgCARD32 				newFlags,newCtrls,extraLength;
659905b261ecSmrgxkbSetDebuggingFlagsReply 	rep;
66004642e01fSmrgint rc;
660105b261ecSmrg
660205b261ecSmrg    REQUEST(xkbSetDebuggingFlagsReq);
660305b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq);
660405b261ecSmrg
66054642e01fSmrg    rc = XaceHook(XACE_SERVER_ACCESS, client, DixDebugAccess);
66064642e01fSmrg    if (rc != Success)
66074642e01fSmrg	return rc;
66084642e01fSmrg
660905b261ecSmrg    newFlags=  xkbDebugFlags&(~stuff->affectFlags);
661005b261ecSmrg    newFlags|= (stuff->flags&stuff->affectFlags);
661105b261ecSmrg    newCtrls=  xkbDebugCtrls&(~stuff->affectCtrls);
661205b261ecSmrg    newCtrls|= (stuff->ctrls&stuff->affectCtrls);
661305b261ecSmrg    if (xkbDebugFlags || newFlags || stuff->msgLength) {
66144642e01fSmrg	ErrorF("[xkb] XkbDebug: Setting debug flags to 0x%lx\n",(long)newFlags);
661505b261ecSmrg	if (newCtrls!=xkbDebugCtrls)
66164642e01fSmrg	    ErrorF("[xkb] XkbDebug: Setting debug controls to 0x%lx\n",(long)newCtrls);
661705b261ecSmrg    }
661805b261ecSmrg    extraLength= (stuff->length<<2)-sz_xkbSetDebuggingFlagsReq;
661905b261ecSmrg    if (stuff->msgLength>0) {
662005b261ecSmrg	char *msg;
662105b261ecSmrg	if (extraLength<XkbPaddedSize(stuff->msgLength)) {
66224642e01fSmrg	    ErrorF("[xkb] XkbDebug: msgLength= %d, length= %ld (should be %d)\n",
662305b261ecSmrg			stuff->msgLength,(long)extraLength,
662405b261ecSmrg			XkbPaddedSize(stuff->msgLength));
662505b261ecSmrg	    return BadLength;
662605b261ecSmrg	}
662705b261ecSmrg	msg= (char *)&stuff[1];
662805b261ecSmrg	if (msg[stuff->msgLength-1]!='\0') {
66294642e01fSmrg	    ErrorF("[xkb] XkbDebug: message not null-terminated\n");
663005b261ecSmrg	    return BadValue;
663105b261ecSmrg	}
66324642e01fSmrg	ErrorF("[xkb] XkbDebug: %s\n",msg);
663305b261ecSmrg    }
663405b261ecSmrg    xkbDebugFlags = newFlags;
663505b261ecSmrg    xkbDebugCtrls = newCtrls;
663605b261ecSmrg
663705b261ecSmrg    rep.type= X_Reply;
663805b261ecSmrg    rep.length = 0;
663905b261ecSmrg    rep.sequenceNumber = client->sequence;
664005b261ecSmrg    rep.currentFlags = newFlags;
664105b261ecSmrg    rep.currentCtrls = newCtrls;
664205b261ecSmrg    rep.supportedFlags = ~0;
664305b261ecSmrg    rep.supportedCtrls = ~0;
664405b261ecSmrg    if ( client->swapped ) {
664505b261ecSmrg	register int n;
664605b261ecSmrg	swaps(&rep.sequenceNumber, n);
664705b261ecSmrg	swapl(&rep.currentFlags, n);
664805b261ecSmrg	swapl(&rep.currentCtrls, n);
664905b261ecSmrg	swapl(&rep.supportedFlags, n);
665005b261ecSmrg	swapl(&rep.supportedCtrls, n);
665105b261ecSmrg    }
665205b261ecSmrg    WriteToClient(client,SIZEOF(xkbSetDebuggingFlagsReply), (char *)&rep);
66536747b715Smrg    return Success;
665405b261ecSmrg}
665505b261ecSmrg
665605b261ecSmrg/***====================================================================***/
665705b261ecSmrg
665805b261ecSmrgstatic int
665905b261ecSmrgProcXkbDispatch (ClientPtr client)
666005b261ecSmrg{
666105b261ecSmrg    REQUEST(xReq);
666205b261ecSmrg    switch (stuff->data)
666305b261ecSmrg    {
666405b261ecSmrg    case X_kbUseExtension:
666505b261ecSmrg	return ProcXkbUseExtension(client);
666605b261ecSmrg    case X_kbSelectEvents:
666705b261ecSmrg	return ProcXkbSelectEvents(client);
666805b261ecSmrg    case X_kbBell:
666905b261ecSmrg	return ProcXkbBell(client);
667005b261ecSmrg    case X_kbGetState:
667105b261ecSmrg	return ProcXkbGetState(client);
667205b261ecSmrg    case X_kbLatchLockState:
667305b261ecSmrg	return ProcXkbLatchLockState(client);
667405b261ecSmrg    case X_kbGetControls:
667505b261ecSmrg	return ProcXkbGetControls(client);
667605b261ecSmrg    case X_kbSetControls:
667705b261ecSmrg	return ProcXkbSetControls(client);
667805b261ecSmrg    case X_kbGetMap:
667905b261ecSmrg	return ProcXkbGetMap(client);
668005b261ecSmrg    case X_kbSetMap:
668105b261ecSmrg	return ProcXkbSetMap(client);
668205b261ecSmrg    case X_kbGetCompatMap:
668305b261ecSmrg	return ProcXkbGetCompatMap(client);
668405b261ecSmrg    case X_kbSetCompatMap:
668505b261ecSmrg	return ProcXkbSetCompatMap(client);
668605b261ecSmrg    case X_kbGetIndicatorState:
668705b261ecSmrg	return ProcXkbGetIndicatorState(client);
668805b261ecSmrg    case X_kbGetIndicatorMap:
668905b261ecSmrg	return ProcXkbGetIndicatorMap(client);
669005b261ecSmrg    case X_kbSetIndicatorMap:
669105b261ecSmrg	return ProcXkbSetIndicatorMap(client);
669205b261ecSmrg    case X_kbGetNamedIndicator:
669305b261ecSmrg	return ProcXkbGetNamedIndicator(client);
669405b261ecSmrg    case X_kbSetNamedIndicator:
669505b261ecSmrg	return ProcXkbSetNamedIndicator(client);
669605b261ecSmrg    case X_kbGetNames:
669705b261ecSmrg	return ProcXkbGetNames(client);
669805b261ecSmrg    case X_kbSetNames:
669905b261ecSmrg	return ProcXkbSetNames(client);
670005b261ecSmrg    case X_kbGetGeometry:
670105b261ecSmrg	return ProcXkbGetGeometry(client);
670205b261ecSmrg    case X_kbSetGeometry:
670305b261ecSmrg	return ProcXkbSetGeometry(client);
670405b261ecSmrg    case X_kbPerClientFlags:
670505b261ecSmrg	return ProcXkbPerClientFlags(client);
670605b261ecSmrg    case X_kbListComponents:
670705b261ecSmrg	return ProcXkbListComponents(client);
670805b261ecSmrg    case X_kbGetKbdByName:
670905b261ecSmrg	return ProcXkbGetKbdByName(client);
671005b261ecSmrg    case X_kbGetDeviceInfo:
671105b261ecSmrg	return ProcXkbGetDeviceInfo(client);
671205b261ecSmrg    case X_kbSetDeviceInfo:
671305b261ecSmrg	return ProcXkbSetDeviceInfo(client);
671405b261ecSmrg    case X_kbSetDebuggingFlags:
671505b261ecSmrg	return ProcXkbSetDebuggingFlags(client);
671605b261ecSmrg    default:
671705b261ecSmrg	return BadRequest;
671805b261ecSmrg    }
671905b261ecSmrg}
672005b261ecSmrg
672105b261ecSmrgstatic int
672205b261ecSmrgXkbClientGone(pointer data,XID id)
672305b261ecSmrg{
672405b261ecSmrg    DevicePtr	pXDev = (DevicePtr)data;
672505b261ecSmrg
672605b261ecSmrg    if (!XkbRemoveResourceClient(pXDev,id)) {
67274642e01fSmrg	ErrorF("[xkb] Internal Error! bad RemoveResourceClient in XkbClientGone\n");
672805b261ecSmrg    }
672905b261ecSmrg    return 1;
673005b261ecSmrg}
673105b261ecSmrg
673205b261ecSmrgvoid
673305b261ecSmrgXkbExtensionInit(void)
673405b261ecSmrg{
673505b261ecSmrg    ExtensionEntry *extEntry;
673605b261ecSmrg
67376747b715Smrg    RT_XKBCLIENT = CreateNewResourceType(XkbClientGone, "XkbClient");
67386747b715Smrg    if (!RT_XKBCLIENT)
67396747b715Smrg	return;
67406747b715Smrg
67416747b715Smrg    if (!XkbInitPrivates())
67426747b715Smrg	return;
67436747b715Smrg
674405b261ecSmrg    if ((extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors,
674505b261ecSmrg				 ProcXkbDispatch, SProcXkbDispatch,
67464642e01fSmrg				 NULL, StandardMinorOpcode))) {
674705b261ecSmrg	XkbReqCode = (unsigned char)extEntry->base;
674805b261ecSmrg	XkbEventBase = (unsigned char)extEntry->eventBase;
674905b261ecSmrg	XkbErrorBase = (unsigned char)extEntry->errorBase;
675005b261ecSmrg	XkbKeyboardErrorCode = XkbErrorBase+XkbKeyboard;
675105b261ecSmrg    }
675205b261ecSmrg    return;
675305b261ecSmrg}
675405b261ecSmrg
675505b261ecSmrg
6756