xkb.c revision 05b261ec
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#define	NEED_EVENTS
3405b261ecSmrg#define	NEED_REPLIES
3505b261ecSmrg#include <X11/Xproto.h>
3605b261ecSmrg#include "misc.h"
3705b261ecSmrg#include "inputstr.h"
3805b261ecSmrg#define	XKBSRV_NEED_FILE_FUNCS
3905b261ecSmrg#include <xkbsrv.h>
4005b261ecSmrg#include "extnsionst.h"
4105b261ecSmrg#include "xkb.h"
4205b261ecSmrg
4305b261ecSmrg#include <X11/extensions/XI.h>
4405b261ecSmrg
4505b261ecSmrg	int	XkbEventBase;
4605b261ecSmrgstatic	int	XkbErrorBase;
4705b261ecSmrg	int	XkbReqCode;
4805b261ecSmrgstatic  int	XkbKeyboardErrorCode;
4905b261ecSmrgCARD32	xkbDebugFlags = 0;
5005b261ecSmrgstatic CARD32	xkbDebugCtrls = 0;
5105b261ecSmrg
5205b261ecSmrgstatic RESTYPE	RT_XKBCLIENT;
5305b261ecSmrg
5405b261ecSmrg/***====================================================================***/
5505b261ecSmrg
5605b261ecSmrg#define	CHK_DEVICE(d,sp,lf) {\
5705b261ecSmrg    int why;\
5805b261ecSmrg    d = (DeviceIntPtr)lf((sp),&why);\
5905b261ecSmrg    if  (!dev) {\
6005b261ecSmrg	client->errorValue = _XkbErrCode2(why,(sp));\
6105b261ecSmrg	return XkbKeyboardErrorCode;\
6205b261ecSmrg    }\
6305b261ecSmrg}
6405b261ecSmrg
6505b261ecSmrg#define	CHK_KBD_DEVICE(d,sp) 	CHK_DEVICE(d,sp,_XkbLookupKeyboard)
6605b261ecSmrg#define	CHK_LED_DEVICE(d,sp) 	CHK_DEVICE(d,sp,_XkbLookupLedDevice)
6705b261ecSmrg#define	CHK_BELL_DEVICE(d,sp) 	CHK_DEVICE(d,sp,_XkbLookupBellDevice)
6805b261ecSmrg#define	CHK_ANY_DEVICE(d,sp) 	CHK_DEVICE(d,sp,_XkbLookupAnyDevice)
6905b261ecSmrg
7005b261ecSmrg#define	CHK_ATOM_ONLY2(a,ev,er) {\
7105b261ecSmrg	if (((a)==None)||(!ValidAtom((a)))) {\
7205b261ecSmrg	    (ev)= (XID)(a);\
7305b261ecSmrg	    return er;\
7405b261ecSmrg	}\
7505b261ecSmrg}
7605b261ecSmrg#define	CHK_ATOM_ONLY(a) \
7705b261ecSmrg	CHK_ATOM_ONLY2(a,client->errorValue,BadAtom)
7805b261ecSmrg
7905b261ecSmrg#define	CHK_ATOM_OR_NONE3(a,ev,er,ret) {\
8005b261ecSmrg	if (((a)!=None)&&(!ValidAtom((a)))) {\
8105b261ecSmrg	    (ev)= (XID)(a);\
8205b261ecSmrg	    (er)= BadAtom;\
8305b261ecSmrg	    return ret;\
8405b261ecSmrg	}\
8505b261ecSmrg}
8605b261ecSmrg#define	CHK_ATOM_OR_NONE2(a,ev,er) {\
8705b261ecSmrg	if (((a)!=None)&&(!ValidAtom((a)))) {\
8805b261ecSmrg	    (ev)= (XID)(a);\
8905b261ecSmrg	    return er;\
9005b261ecSmrg	}\
9105b261ecSmrg}
9205b261ecSmrg#define	CHK_ATOM_OR_NONE(a) \
9305b261ecSmrg	CHK_ATOM_OR_NONE2(a,client->errorValue,BadAtom)
9405b261ecSmrg
9505b261ecSmrg#define	CHK_MASK_LEGAL3(err,mask,legal,ev,er,ret)	{\
9605b261ecSmrg	if ((mask)&(~(legal))) { \
9705b261ecSmrg	    (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\
9805b261ecSmrg	    (er)= BadValue;\
9905b261ecSmrg	    return ret;\
10005b261ecSmrg	}\
10105b261ecSmrg}
10205b261ecSmrg#define	CHK_MASK_LEGAL2(err,mask,legal,ev,er)	{\
10305b261ecSmrg	if ((mask)&(~(legal))) { \
10405b261ecSmrg	    (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\
10505b261ecSmrg	    return er;\
10605b261ecSmrg	}\
10705b261ecSmrg}
10805b261ecSmrg#define	CHK_MASK_LEGAL(err,mask,legal) \
10905b261ecSmrg	CHK_MASK_LEGAL2(err,mask,legal,client->errorValue,BadValue)
11005b261ecSmrg
11105b261ecSmrg#define	CHK_MASK_MATCH(err,affect,value) {\
11205b261ecSmrg	if ((value)&(~(affect))) { \
11305b261ecSmrg	    client->errorValue= _XkbErrCode2((err),((value)&(~(affect))));\
11405b261ecSmrg	    return BadMatch;\
11505b261ecSmrg	}\
11605b261ecSmrg}
11705b261ecSmrg#define	CHK_MASK_OVERLAP(err,m1,m2) {\
11805b261ecSmrg	if ((m1)&(m2)) { \
11905b261ecSmrg	    client->errorValue= _XkbErrCode2((err),((m1)&(m2)));\
12005b261ecSmrg	    return BadMatch;\
12105b261ecSmrg	}\
12205b261ecSmrg}
12305b261ecSmrg#define	CHK_KEY_RANGE2(err,first,num,x,ev,er) {\
12405b261ecSmrg	if (((unsigned)(first)+(num)-1)>(x)->max_key_code) {\
12505b261ecSmrg	    (ev)=_XkbErrCode4(err,(first),(num),(x)->max_key_code);\
12605b261ecSmrg	    return er;\
12705b261ecSmrg	}\
12805b261ecSmrg	else if ( (first)<(x)->min_key_code ) {\
12905b261ecSmrg	    (ev)=_XkbErrCode3(err+1,(first),xkb->min_key_code);\
13005b261ecSmrg	    return er;\
13105b261ecSmrg	}\
13205b261ecSmrg}
13305b261ecSmrg#define	CHK_KEY_RANGE(err,first,num,x)  \
13405b261ecSmrg	CHK_KEY_RANGE2(err,first,num,x,client->errorValue,BadValue)
13505b261ecSmrg
13605b261ecSmrg#define	CHK_REQ_KEY_RANGE2(err,first,num,r,ev,er) {\
13705b261ecSmrg	if (((unsigned)(first)+(num)-1)>(r)->maxKeyCode) {\
13805b261ecSmrg	    (ev)=_XkbErrCode4(err,(first),(num),(r)->maxKeyCode);\
13905b261ecSmrg	    return er;\
14005b261ecSmrg	}\
14105b261ecSmrg	else if ( (first)<(r)->minKeyCode ) {\
14205b261ecSmrg	    (ev)=_XkbErrCode3(err+1,(first),(r)->minKeyCode);\
14305b261ecSmrg	    return er;\
14405b261ecSmrg	}\
14505b261ecSmrg}
14605b261ecSmrg#define	CHK_REQ_KEY_RANGE(err,first,num,r)  \
14705b261ecSmrg	CHK_REQ_KEY_RANGE2(err,first,num,r,client->errorValue,BadValue)
14805b261ecSmrg
14905b261ecSmrg/***====================================================================***/
15005b261ecSmrg
15105b261ecSmrgint
15205b261ecSmrgProcXkbUseExtension(ClientPtr client)
15305b261ecSmrg{
15405b261ecSmrg    REQUEST(xkbUseExtensionReq);
15505b261ecSmrg    xkbUseExtensionReply	rep;
15605b261ecSmrg    register int n;
15705b261ecSmrg    int	supported;
15805b261ecSmrg
15905b261ecSmrg    REQUEST_SIZE_MATCH(xkbUseExtensionReq);
16005b261ecSmrg    if (stuff->wantedMajor != XkbMajorVersion) {
16105b261ecSmrg	/* pre-release version 0.65 is compatible with 1.00 */
16205b261ecSmrg	supported= ((XkbMajorVersion==1)&&
16305b261ecSmrg		    (stuff->wantedMajor==0)&&(stuff->wantedMinor==65));
16405b261ecSmrg    }
16505b261ecSmrg    else supported = 1;
16605b261ecSmrg
16705b261ecSmrg    if ((supported) && (!(client->xkbClientFlags&_XkbClientInitialized))) {
16805b261ecSmrg	client->xkbClientFlags= _XkbClientInitialized;
16905b261ecSmrg	client->vMajor= stuff->wantedMajor;
17005b261ecSmrg	client->vMinor= stuff->wantedMinor;
17105b261ecSmrg    }
17205b261ecSmrg    else if (xkbDebugFlags&0x1) {
17305b261ecSmrg	ErrorF("Rejecting client %d (0x%lx) (wants %d.%02d, have %d.%02d)\n",
17405b261ecSmrg					client->index,
17505b261ecSmrg					(long)client->clientAsMask,
17605b261ecSmrg					stuff->wantedMajor,stuff->wantedMinor,
17705b261ecSmrg					XkbMajorVersion,XkbMinorVersion);
17805b261ecSmrg    }
17905b261ecSmrg    rep.type = X_Reply;
18005b261ecSmrg    rep.supported = supported;
18105b261ecSmrg    rep.length = 0;
18205b261ecSmrg    rep.sequenceNumber = client->sequence;
18305b261ecSmrg    rep.serverMajor = XkbMajorVersion;
18405b261ecSmrg    rep.serverMinor = XkbMinorVersion;
18505b261ecSmrg    if ( client->swapped ) {
18605b261ecSmrg	swaps(&rep.sequenceNumber, n);
18705b261ecSmrg	swaps(&rep.serverMajor, n);
18805b261ecSmrg	swaps(&rep.serverMinor, n);
18905b261ecSmrg    }
19005b261ecSmrg    WriteToClient(client,SIZEOF(xkbUseExtensionReply), (char *)&rep);
19105b261ecSmrg    return client->noClientException;
19205b261ecSmrg}
19305b261ecSmrg
19405b261ecSmrg/***====================================================================***/
19505b261ecSmrg
19605b261ecSmrgint
19705b261ecSmrgProcXkbSelectEvents(ClientPtr client)
19805b261ecSmrg{
19905b261ecSmrg    unsigned		legal;
20005b261ecSmrg    DeviceIntPtr 	dev;
20105b261ecSmrg    XkbInterestPtr	masks;
20205b261ecSmrg    REQUEST(xkbSelectEventsReq);
20305b261ecSmrg
20405b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSelectEventsReq);
20505b261ecSmrg
20605b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
20705b261ecSmrg	return BadAccess;
20805b261ecSmrg
20905b261ecSmrg    CHK_ANY_DEVICE(dev,stuff->deviceSpec);
21005b261ecSmrg
21105b261ecSmrg    if (((stuff->affectWhich&XkbMapNotifyMask)!=0)&&(stuff->affectMap)) {
21205b261ecSmrg	client->mapNotifyMask&= ~stuff->affectMap;
21305b261ecSmrg	client->mapNotifyMask|= (stuff->affectMap&stuff->map);
21405b261ecSmrg    }
21505b261ecSmrg    if ((stuff->affectWhich&(~XkbMapNotifyMask))==0)
21605b261ecSmrg	return client->noClientException;
21705b261ecSmrg
21805b261ecSmrg    masks = XkbFindClientResource((DevicePtr)dev,client);
21905b261ecSmrg    if (!masks){
22005b261ecSmrg	XID id = FakeClientID(client->index);
22105b261ecSmrg	AddResource(id,RT_XKBCLIENT,dev);
22205b261ecSmrg	masks= XkbAddClientResource((DevicePtr)dev,client,id);
22305b261ecSmrg    }
22405b261ecSmrg    if (masks) {
22505b261ecSmrg	union {
22605b261ecSmrg	    CARD8	*c8;
22705b261ecSmrg	    CARD16	*c16;
22805b261ecSmrg	    CARD32	*c32;
22905b261ecSmrg	} from,to;
23005b261ecSmrg	register unsigned bit,ndx,maskLeft,dataLeft,size;
23105b261ecSmrg
23205b261ecSmrg	from.c8= (CARD8 *)&stuff[1];
23305b261ecSmrg	dataLeft= (stuff->length*4)-SIZEOF(xkbSelectEventsReq);
23405b261ecSmrg	maskLeft= (stuff->affectWhich&(~XkbMapNotifyMask));
23505b261ecSmrg	for (ndx=0,bit=1; (maskLeft!=0); ndx++, bit<<=1) {
23605b261ecSmrg	    if ((bit&maskLeft)==0)
23705b261ecSmrg		continue;
23805b261ecSmrg	    maskLeft&= ~bit;
23905b261ecSmrg	    switch (ndx) {
24005b261ecSmrg		case XkbNewKeyboardNotify:
24105b261ecSmrg		    to.c16= &client->newKeyboardNotifyMask;
24205b261ecSmrg		    legal= XkbAllNewKeyboardEventsMask;
24305b261ecSmrg		    size= 2;
24405b261ecSmrg		    break;
24505b261ecSmrg		case XkbStateNotify:
24605b261ecSmrg		    to.c16= &masks->stateNotifyMask;
24705b261ecSmrg		    legal= XkbAllStateEventsMask;
24805b261ecSmrg		    size= 2;
24905b261ecSmrg		    break;
25005b261ecSmrg		case XkbControlsNotify:
25105b261ecSmrg		    to.c32= &masks->ctrlsNotifyMask;
25205b261ecSmrg		    legal= XkbAllControlEventsMask;
25305b261ecSmrg		    size= 4;
25405b261ecSmrg		    break;
25505b261ecSmrg		case XkbIndicatorStateNotify:
25605b261ecSmrg		    to.c32= &masks->iStateNotifyMask;
25705b261ecSmrg		    legal= XkbAllIndicatorEventsMask;
25805b261ecSmrg		    size= 4;
25905b261ecSmrg		    break;
26005b261ecSmrg		case XkbIndicatorMapNotify:
26105b261ecSmrg		    to.c32= &masks->iMapNotifyMask;
26205b261ecSmrg		    legal= XkbAllIndicatorEventsMask;
26305b261ecSmrg		    size= 4;
26405b261ecSmrg		    break;
26505b261ecSmrg		case XkbNamesNotify:
26605b261ecSmrg		    to.c16= &masks->namesNotifyMask;
26705b261ecSmrg		    legal= XkbAllNameEventsMask;
26805b261ecSmrg		    size= 2;
26905b261ecSmrg		    break;
27005b261ecSmrg		case XkbCompatMapNotify:
27105b261ecSmrg		    to.c8= &masks->compatNotifyMask;
27205b261ecSmrg		    legal= XkbAllCompatMapEventsMask;
27305b261ecSmrg		    size= 1;
27405b261ecSmrg		    break;
27505b261ecSmrg		case XkbBellNotify:
27605b261ecSmrg		    to.c8= &masks->bellNotifyMask;
27705b261ecSmrg		    legal= XkbAllBellEventsMask;
27805b261ecSmrg		    size= 1;
27905b261ecSmrg		    break;
28005b261ecSmrg		case XkbActionMessage:
28105b261ecSmrg		    to.c8= &masks->actionMessageMask;
28205b261ecSmrg		    legal= XkbAllActionMessagesMask;
28305b261ecSmrg		    size= 1;
28405b261ecSmrg		    break;
28505b261ecSmrg		case XkbAccessXNotify:
28605b261ecSmrg		    to.c16= &masks->accessXNotifyMask;
28705b261ecSmrg		    legal= XkbAllAccessXEventsMask;
28805b261ecSmrg		    size= 2;
28905b261ecSmrg		    break;
29005b261ecSmrg		case XkbExtensionDeviceNotify:
29105b261ecSmrg		    to.c16= &masks->extDevNotifyMask;
29205b261ecSmrg		    legal= XkbAllExtensionDeviceEventsMask;
29305b261ecSmrg		    size= 2;
29405b261ecSmrg		    break;
29505b261ecSmrg		default:
29605b261ecSmrg		    client->errorValue = _XkbErrCode2(33,bit);
29705b261ecSmrg		    return BadValue;
29805b261ecSmrg	    }
29905b261ecSmrg
30005b261ecSmrg	    if (stuff->clear&bit) {
30105b261ecSmrg		if (size==2)		to.c16[0]= 0;
30205b261ecSmrg		else if (size==4)	to.c32[0]= 0;
30305b261ecSmrg		else			to.c8[0]=  0;
30405b261ecSmrg	    }
30505b261ecSmrg	    else if (stuff->selectAll&bit) {
30605b261ecSmrg		if (size==2)		to.c16[0]= ~0;
30705b261ecSmrg		else if (size==4)	to.c32[0]= ~0;
30805b261ecSmrg		else			to.c8[0]=  ~0;
30905b261ecSmrg	    }
31005b261ecSmrg	    else {
31105b261ecSmrg		if (dataLeft<(size*2))
31205b261ecSmrg		    return BadLength;
31305b261ecSmrg		if (size==2) {
31405b261ecSmrg		    CHK_MASK_MATCH(ndx,from.c16[0],from.c16[1]);
31505b261ecSmrg		    CHK_MASK_LEGAL(ndx,from.c16[0],legal);
31605b261ecSmrg		    to.c16[0]&= ~from.c16[0];
31705b261ecSmrg		    to.c16[0]|= (from.c16[0]&from.c16[1]);
31805b261ecSmrg		}
31905b261ecSmrg		else if (size==4) {
32005b261ecSmrg		    CHK_MASK_MATCH(ndx,from.c32[0],from.c32[1]);
32105b261ecSmrg		    CHK_MASK_LEGAL(ndx,from.c32[0],legal);
32205b261ecSmrg		    to.c32[0]&= ~from.c32[0];
32305b261ecSmrg		    to.c32[0]|= (from.c32[0]&from.c32[1]);
32405b261ecSmrg		}
32505b261ecSmrg		else  {
32605b261ecSmrg		    CHK_MASK_MATCH(ndx,from.c8[0],from.c8[1]);
32705b261ecSmrg		    CHK_MASK_LEGAL(ndx,from.c8[0],legal);
32805b261ecSmrg		    to.c8[0]&= ~from.c8[0];
32905b261ecSmrg		    to.c8[0]|= (from.c8[0]&from.c8[1]);
33005b261ecSmrg		    size= 2;
33105b261ecSmrg		}
33205b261ecSmrg		from.c8+= (size*2);
33305b261ecSmrg		dataLeft-= (size*2);
33405b261ecSmrg	    }
33505b261ecSmrg	}
33605b261ecSmrg	if (dataLeft>2) {
33705b261ecSmrg	    ErrorF("Extra data (%d bytes) after SelectEvents\n",dataLeft);
33805b261ecSmrg	    return BadLength;
33905b261ecSmrg	}
34005b261ecSmrg	return client->noClientException;
34105b261ecSmrg    }
34205b261ecSmrg    return BadAlloc;
34305b261ecSmrg}
34405b261ecSmrg
34505b261ecSmrg/***====================================================================***/
34605b261ecSmrg
34705b261ecSmrg/* FIXME: Needs to ding on all core-sending devices. */
34805b261ecSmrgint
34905b261ecSmrgProcXkbBell(ClientPtr client)
35005b261ecSmrg{
35105b261ecSmrg    REQUEST(xkbBellReq);
35205b261ecSmrg    DeviceIntPtr dev;
35305b261ecSmrg    WindowPtr	 pWin;
35405b261ecSmrg    int base;
35505b261ecSmrg    int newPercent,oldPitch,oldDuration;
35605b261ecSmrg    pointer ctrl;
35705b261ecSmrg
35805b261ecSmrg    REQUEST_SIZE_MATCH(xkbBellReq);
35905b261ecSmrg
36005b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
36105b261ecSmrg	return BadAccess;
36205b261ecSmrg
36305b261ecSmrg    CHK_BELL_DEVICE(dev,stuff->deviceSpec);
36405b261ecSmrg    CHK_ATOM_OR_NONE(stuff->name);
36505b261ecSmrg
36605b261ecSmrg    if ((stuff->forceSound)&&(stuff->eventOnly)) {
36705b261ecSmrg	client->errorValue=_XkbErrCode3(0x1,stuff->forceSound,stuff->eventOnly);
36805b261ecSmrg	return BadMatch;
36905b261ecSmrg    }
37005b261ecSmrg    if (stuff->percent < -100 || stuff->percent > 100) {
37105b261ecSmrg	client->errorValue = _XkbErrCode2(0x2,stuff->percent);
37205b261ecSmrg	return BadValue;
37305b261ecSmrg    }
37405b261ecSmrg    if (stuff->duration<-1) {
37505b261ecSmrg	client->errorValue = _XkbErrCode2(0x3,stuff->duration);
37605b261ecSmrg	return BadValue;
37705b261ecSmrg    }
37805b261ecSmrg    if (stuff->pitch<-1) {
37905b261ecSmrg	client->errorValue = _XkbErrCode2(0x4,stuff->pitch);
38005b261ecSmrg	return BadValue;
38105b261ecSmrg    }
38205b261ecSmrg
38305b261ecSmrg    if (stuff->bellClass == XkbDfltXIClass) {
38405b261ecSmrg	if (dev->kbdfeed!=NULL)
38505b261ecSmrg	     stuff->bellClass= KbdFeedbackClass;
38605b261ecSmrg	else stuff->bellClass= BellFeedbackClass;
38705b261ecSmrg    }
38805b261ecSmrg    if (stuff->bellClass == KbdFeedbackClass) {
38905b261ecSmrg	KbdFeedbackPtr	k;
39005b261ecSmrg	if (stuff->bellID==XkbDfltXIId)
39105b261ecSmrg	    k= dev->kbdfeed;
39205b261ecSmrg	else {
39305b261ecSmrg	    for (k=dev->kbdfeed; k; k=k->next) {
39405b261ecSmrg		if (k->ctrl.id == stuff->bellID)
39505b261ecSmrg		    break;
39605b261ecSmrg	    }
39705b261ecSmrg	}
39805b261ecSmrg	if (!k) {
39905b261ecSmrg	    client->errorValue= _XkbErrCode2(0x5,stuff->bellID);
40005b261ecSmrg	    return BadValue;
40105b261ecSmrg	}
40205b261ecSmrg	base = k->ctrl.bell;
40305b261ecSmrg	ctrl = (pointer) &(k->ctrl);
40405b261ecSmrg	oldPitch= k->ctrl.bell_pitch;
40505b261ecSmrg	oldDuration= k->ctrl.bell_duration;
40605b261ecSmrg	if (stuff->pitch!=0) {
40705b261ecSmrg	    if (stuff->pitch==-1)
40805b261ecSmrg		 k->ctrl.bell_pitch= defaultKeyboardControl.bell_pitch;
40905b261ecSmrg	    else k->ctrl.bell_pitch= stuff->pitch;
41005b261ecSmrg	}
41105b261ecSmrg	if (stuff->duration!=0) {
41205b261ecSmrg	    if (stuff->duration==-1)
41305b261ecSmrg		 k->ctrl.bell_duration= defaultKeyboardControl.bell_duration;
41405b261ecSmrg	    else k->ctrl.bell_duration= stuff->duration;
41505b261ecSmrg	}
41605b261ecSmrg    }
41705b261ecSmrg    else if (stuff->bellClass == BellFeedbackClass) {
41805b261ecSmrg	BellFeedbackPtr	b;
41905b261ecSmrg	if (stuff->bellID==XkbDfltXIId)
42005b261ecSmrg	    b= dev->bell;
42105b261ecSmrg	else {
42205b261ecSmrg	    for (b=dev->bell; b; b=b->next) {
42305b261ecSmrg		if (b->ctrl.id == stuff->bellID)
42405b261ecSmrg		    break;
42505b261ecSmrg	    }
42605b261ecSmrg	}
42705b261ecSmrg	if (!b) {
42805b261ecSmrg	    client->errorValue = _XkbErrCode2(0x6,stuff->bellID);
42905b261ecSmrg	    return BadValue;
43005b261ecSmrg	}
43105b261ecSmrg	base = b->ctrl.percent;
43205b261ecSmrg	ctrl = (pointer) &(b->ctrl);
43305b261ecSmrg	oldPitch= b->ctrl.pitch;
43405b261ecSmrg	oldDuration= b->ctrl.duration;
43505b261ecSmrg	if (stuff->pitch!=0) {
43605b261ecSmrg	    if (stuff->pitch==-1)
43705b261ecSmrg		 b->ctrl.pitch= defaultKeyboardControl.bell_pitch;
43805b261ecSmrg	    else b->ctrl.pitch= stuff->pitch;
43905b261ecSmrg	}
44005b261ecSmrg	if (stuff->duration!=0) {
44105b261ecSmrg	    if (stuff->duration==-1)
44205b261ecSmrg		 b->ctrl.duration= defaultKeyboardControl.bell_duration;
44305b261ecSmrg	    else b->ctrl.duration= stuff->duration;
44405b261ecSmrg	}
44505b261ecSmrg    }
44605b261ecSmrg    else {
44705b261ecSmrg	client->errorValue = _XkbErrCode2(0x7,stuff->bellClass);;
44805b261ecSmrg	return BadValue;
44905b261ecSmrg    }
45005b261ecSmrg    if (stuff->window!=None) {
45105b261ecSmrg	pWin= (WindowPtr)LookupIDByType(stuff->window,RT_WINDOW);
45205b261ecSmrg	if (pWin==NULL) {
45305b261ecSmrg	    client->errorValue= stuff->window;
45405b261ecSmrg	    return BadValue;
45505b261ecSmrg	}
45605b261ecSmrg    }
45705b261ecSmrg    else pWin= NULL;
45805b261ecSmrg
45905b261ecSmrg    newPercent= (base*stuff->percent)/100;
46005b261ecSmrg    if (stuff->percent < 0)
46105b261ecSmrg         newPercent= base+newPercent;
46205b261ecSmrg    else newPercent= base-newPercent+stuff->percent;
46305b261ecSmrg    XkbHandleBell(stuff->forceSound, stuff->eventOnly,
46405b261ecSmrg				dev, newPercent, ctrl, stuff->bellClass,
46505b261ecSmrg				stuff->name, pWin, client);
46605b261ecSmrg    if ((stuff->pitch!=0)||(stuff->duration!=0)) {
46705b261ecSmrg	if (stuff->bellClass == KbdFeedbackClass) {
46805b261ecSmrg	    KbdFeedbackPtr	k;
46905b261ecSmrg	    k= (KbdFeedbackPtr)ctrl;
47005b261ecSmrg	    if (stuff->pitch!=0)
47105b261ecSmrg		k->ctrl.bell_pitch= oldPitch;
47205b261ecSmrg	    if (stuff->duration!=0)
47305b261ecSmrg		k->ctrl.bell_duration= oldDuration;
47405b261ecSmrg	}
47505b261ecSmrg	else {
47605b261ecSmrg	    BellFeedbackPtr	b;
47705b261ecSmrg	    b= (BellFeedbackPtr)ctrl;
47805b261ecSmrg	    if (stuff->pitch!=0)
47905b261ecSmrg		b->ctrl.pitch= oldPitch;
48005b261ecSmrg	    if (stuff->duration!=0)
48105b261ecSmrg		b->ctrl.duration= oldDuration;
48205b261ecSmrg	}
48305b261ecSmrg    }
48405b261ecSmrg    return Success;
48505b261ecSmrg}
48605b261ecSmrg
48705b261ecSmrg/***====================================================================***/
48805b261ecSmrg
48905b261ecSmrgint
49005b261ecSmrgProcXkbGetState(ClientPtr client)
49105b261ecSmrg{
49205b261ecSmrg    REQUEST(xkbGetStateReq);
49305b261ecSmrg    DeviceIntPtr	dev;
49405b261ecSmrg    xkbGetStateReply	 rep;
49505b261ecSmrg    XkbStateRec		*xkb;
49605b261ecSmrg
49705b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetStateReq);
49805b261ecSmrg
49905b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
50005b261ecSmrg	return BadAccess;
50105b261ecSmrg
50205b261ecSmrg    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
50305b261ecSmrg
50405b261ecSmrg    xkb= &dev->key->xkbInfo->state;
50505b261ecSmrg    bzero(&rep,sizeof(xkbGetStateReply));
50605b261ecSmrg    rep.type= X_Reply;
50705b261ecSmrg    rep.sequenceNumber= client->sequence;
50805b261ecSmrg    rep.length = 0;
50905b261ecSmrg    rep.deviceID = dev->id;
51005b261ecSmrg    rep.mods = dev->key->state&0xff;
51105b261ecSmrg    rep.baseMods = xkb->base_mods;
51205b261ecSmrg    rep.lockedMods = xkb->locked_mods;
51305b261ecSmrg    rep.latchedMods = xkb->latched_mods;
51405b261ecSmrg    rep.group = xkb->group;
51505b261ecSmrg    rep.baseGroup = xkb->base_group;
51605b261ecSmrg    rep.latchedGroup = xkb->latched_group;
51705b261ecSmrg    rep.lockedGroup = xkb->locked_group;
51805b261ecSmrg    rep.compatState = xkb->compat_state;
51905b261ecSmrg    rep.ptrBtnState = xkb->ptr_buttons;
52005b261ecSmrg    if (client->swapped) {
52105b261ecSmrg	register int n;
52205b261ecSmrg	swaps(&rep.sequenceNumber,n);
52305b261ecSmrg	swaps(&rep.ptrBtnState,n);
52405b261ecSmrg    }
52505b261ecSmrg    WriteToClient(client, SIZEOF(xkbGetStateReply), (char *)&rep);
52605b261ecSmrg    return client->noClientException;
52705b261ecSmrg}
52805b261ecSmrg
52905b261ecSmrg/***====================================================================***/
53005b261ecSmrg
53105b261ecSmrgint
53205b261ecSmrgProcXkbLatchLockState(ClientPtr client)
53305b261ecSmrg{
53405b261ecSmrg    int status;
53505b261ecSmrg    DeviceIntPtr dev, tmpd;
53605b261ecSmrg    XkbStateRec	oldState,*newState;
53705b261ecSmrg    CARD16 changed;
53805b261ecSmrg    xkbStateNotify sn;
53905b261ecSmrg    XkbEventCauseRec cause;
54005b261ecSmrg
54105b261ecSmrg    REQUEST(xkbLatchLockStateReq);
54205b261ecSmrg    REQUEST_SIZE_MATCH(xkbLatchLockStateReq);
54305b261ecSmrg
54405b261ecSmrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
54505b261ecSmrg	return BadAccess;
54605b261ecSmrg
54705b261ecSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec);
54805b261ecSmrg    CHK_MASK_MATCH(0x01, stuff->affectModLocks, stuff->modLocks);
54905b261ecSmrg    CHK_MASK_MATCH(0x01, stuff->affectModLatches, stuff->modLatches);
55005b261ecSmrg
55105b261ecSmrg    status = Success;
55205b261ecSmrg
55305b261ecSmrg    for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
55405b261ecSmrg        if ((dev == inputInfo.keyboard && tmpd->key && tmpd->coreEvents) ||
55505b261ecSmrg            tmpd == dev) {
55605b261ecSmrg            if (!tmpd->key->xkbInfo)
55705b261ecSmrg                continue;
55805b261ecSmrg
55905b261ecSmrg            oldState = tmpd->key->xkbInfo->state;
56005b261ecSmrg            newState = &tmpd->key->xkbInfo->state;
56105b261ecSmrg            if (stuff->affectModLocks) {
56205b261ecSmrg                newState->locked_mods &= ~stuff->affectModLocks;
56305b261ecSmrg                newState->locked_mods |= (stuff->affectModLocks & stuff->modLocks);
56405b261ecSmrg            }
56505b261ecSmrg            if (status == Success && stuff->lockGroup)
56605b261ecSmrg                newState->locked_group = stuff->groupLock;
56705b261ecSmrg            if (status == Success && stuff->affectModLatches)
56805b261ecSmrg                status = XkbLatchModifiers(tmpd, stuff->affectModLatches,
56905b261ecSmrg                                           stuff->modLatches);
57005b261ecSmrg            if (status == Success && stuff->latchGroup)
57105b261ecSmrg                status = XkbLatchGroup(tmpd, stuff->groupLatch);
57205b261ecSmrg
57305b261ecSmrg            if (status != Success)
57405b261ecSmrg                return status;
57505b261ecSmrg
57605b261ecSmrg            XkbComputeDerivedState(tmpd->key->xkbInfo);
57705b261ecSmrg            tmpd->key->state = XkbStateFieldFromRec(newState);
57805b261ecSmrg
57905b261ecSmrg            changed = XkbStateChangedFlags(&oldState, newState);
58005b261ecSmrg            if (changed) {
58105b261ecSmrg                sn.keycode = 0;
58205b261ecSmrg                sn.eventType = 0;
58305b261ecSmrg                sn.requestMajor = XkbReqCode;
58405b261ecSmrg                sn.requestMinor = X_kbLatchLockState;
58505b261ecSmrg                sn.changed = changed;
58605b261ecSmrg                XkbSendStateNotify(tmpd, &sn);
58705b261ecSmrg                changed = XkbIndicatorsToUpdate(tmpd, changed, False);
58805b261ecSmrg                if (changed) {
58905b261ecSmrg                    XkbSetCauseXkbReq(&cause, X_kbLatchLockState, client);
59005b261ecSmrg                    XkbUpdateIndicators(tmpd, changed, True, NULL, &cause);
59105b261ecSmrg	        }
59205b261ecSmrg            }
59305b261ecSmrg        }
59405b261ecSmrg    }
59505b261ecSmrg
59605b261ecSmrg    return client->noClientException;
59705b261ecSmrg}
59805b261ecSmrg
59905b261ecSmrg/***====================================================================***/
60005b261ecSmrg
60105b261ecSmrgint
60205b261ecSmrgProcXkbGetControls(ClientPtr client)
60305b261ecSmrg{
60405b261ecSmrg    xkbGetControlsReply rep;
60505b261ecSmrg    XkbControlsPtr	xkb;
60605b261ecSmrg    DeviceIntPtr 	dev;
60705b261ecSmrg    register int 	n;
60805b261ecSmrg
60905b261ecSmrg    REQUEST(xkbGetControlsReq);
61005b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetControlsReq);
61105b261ecSmrg
61205b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
61305b261ecSmrg	return BadAccess;
61405b261ecSmrg
61505b261ecSmrg    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
61605b261ecSmrg
61705b261ecSmrg    xkb = dev->key->xkbInfo->desc->ctrls;
61805b261ecSmrg    rep.type = X_Reply;
61905b261ecSmrg    rep.length = (SIZEOF(xkbGetControlsReply)-
62005b261ecSmrg		  SIZEOF(xGenericReply)) >> 2;
62105b261ecSmrg    rep.sequenceNumber = client->sequence;
62205b261ecSmrg    rep.deviceID = ((DeviceIntPtr)dev)->id;
62305b261ecSmrg    rep.numGroups = xkb->num_groups;
62405b261ecSmrg    rep.groupsWrap = xkb->groups_wrap;
62505b261ecSmrg    rep.internalMods = xkb->internal.mask;
62605b261ecSmrg    rep.ignoreLockMods = xkb->ignore_lock.mask;
62705b261ecSmrg    rep.internalRealMods = xkb->internal.real_mods;
62805b261ecSmrg    rep.ignoreLockRealMods = xkb->ignore_lock.real_mods;
62905b261ecSmrg    rep.internalVMods = xkb->internal.vmods;
63005b261ecSmrg    rep.ignoreLockVMods = xkb->ignore_lock.vmods;
63105b261ecSmrg    rep.enabledCtrls = xkb->enabled_ctrls;
63205b261ecSmrg    rep.repeatDelay = xkb->repeat_delay;
63305b261ecSmrg    rep.repeatInterval = xkb->repeat_interval;
63405b261ecSmrg    rep.slowKeysDelay = xkb->slow_keys_delay;
63505b261ecSmrg    rep.debounceDelay = xkb->debounce_delay;
63605b261ecSmrg    rep.mkDelay = xkb->mk_delay;
63705b261ecSmrg    rep.mkInterval = xkb->mk_interval;
63805b261ecSmrg    rep.mkTimeToMax = xkb->mk_time_to_max;
63905b261ecSmrg    rep.mkMaxSpeed = xkb->mk_max_speed;
64005b261ecSmrg    rep.mkCurve = xkb->mk_curve;
64105b261ecSmrg    rep.mkDfltBtn = xkb->mk_dflt_btn;
64205b261ecSmrg    rep.axTimeout = xkb->ax_timeout;
64305b261ecSmrg    rep.axtCtrlsMask = xkb->axt_ctrls_mask;
64405b261ecSmrg    rep.axtCtrlsValues = xkb->axt_ctrls_values;
64505b261ecSmrg    rep.axtOptsMask = xkb->axt_opts_mask;
64605b261ecSmrg    rep.axtOptsValues = xkb->axt_opts_values;
64705b261ecSmrg    rep.axOptions = xkb->ax_options;
64805b261ecSmrg    memcpy(rep.perKeyRepeat,xkb->per_key_repeat,XkbPerKeyBitArraySize);
64905b261ecSmrg    if (client->swapped) {
65005b261ecSmrg    	swaps(&rep.sequenceNumber, n);
65105b261ecSmrg	swapl(&rep.length,n);
65205b261ecSmrg	swaps(&rep.internalVMods, n);
65305b261ecSmrg	swaps(&rep.ignoreLockVMods, n);
65405b261ecSmrg	swapl(&rep.enabledCtrls, n);
65505b261ecSmrg	swaps(&rep.repeatDelay, n);
65605b261ecSmrg	swaps(&rep.repeatInterval, n);
65705b261ecSmrg	swaps(&rep.slowKeysDelay, n);
65805b261ecSmrg	swaps(&rep.debounceDelay, n);
65905b261ecSmrg	swaps(&rep.mkDelay, n);
66005b261ecSmrg	swaps(&rep.mkInterval, n);
66105b261ecSmrg	swaps(&rep.mkTimeToMax, n);
66205b261ecSmrg	swaps(&rep.mkMaxSpeed, n);
66305b261ecSmrg	swaps(&rep.mkCurve, n);
66405b261ecSmrg	swaps(&rep.axTimeout, n);
66505b261ecSmrg	swapl(&rep.axtCtrlsMask, n);
66605b261ecSmrg	swapl(&rep.axtCtrlsValues, n);
66705b261ecSmrg	swaps(&rep.axtOptsMask, n);
66805b261ecSmrg	swaps(&rep.axtOptsValues, n);
66905b261ecSmrg	swaps(&rep.axOptions, n);
67005b261ecSmrg    }
67105b261ecSmrg    WriteToClient(client, SIZEOF(xkbGetControlsReply), (char *)&rep);
67205b261ecSmrg    return(client->noClientException);
67305b261ecSmrg}
67405b261ecSmrg
67505b261ecSmrgint
67605b261ecSmrgProcXkbSetControls(ClientPtr client)
67705b261ecSmrg{
67805b261ecSmrg    DeviceIntPtr 	dev, tmpd;
67905b261ecSmrg    XkbSrvInfoPtr	xkbi;
68005b261ecSmrg    XkbControlsPtr	ctrl;
68105b261ecSmrg    XkbControlsRec	new,old;
68205b261ecSmrg    xkbControlsNotify	cn;
68305b261ecSmrg    XkbEventCauseRec	cause;
68405b261ecSmrg    XkbSrvLedInfoPtr	sli;
68505b261ecSmrg
68605b261ecSmrg    REQUEST(xkbSetControlsReq);
68705b261ecSmrg    REQUEST_SIZE_MATCH(xkbSetControlsReq);
68805b261ecSmrg
68905b261ecSmrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
69005b261ecSmrg	return BadAccess;
69105b261ecSmrg
69205b261ecSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec);
69305b261ecSmrg    CHK_MASK_LEGAL(0x01, stuff->changeCtrls, XkbAllControlsMask);
69405b261ecSmrg
69505b261ecSmrg    for (tmpd = inputInfo.keyboard; tmpd; tmpd = tmpd->next) {
69605b261ecSmrg        if ((dev == inputInfo.keyboard && tmpd->key && tmpd->coreEvents) ||
69705b261ecSmrg            tmpd == dev) {
69805b261ecSmrg
69905b261ecSmrg            xkbi = tmpd->key->xkbInfo;
70005b261ecSmrg            ctrl = xkbi->desc->ctrls;
70105b261ecSmrg            new = *ctrl;
70205b261ecSmrg            XkbSetCauseXkbReq(&cause, X_kbSetControls, client);
70305b261ecSmrg
70405b261ecSmrg            if (stuff->changeCtrls & XkbInternalModsMask) {
70505b261ecSmrg                CHK_MASK_MATCH(0x02, stuff->affectInternalMods,
70605b261ecSmrg                               stuff->internalMods);
70705b261ecSmrg                CHK_MASK_MATCH(0x03, stuff->affectInternalVMods,
70805b261ecSmrg                               stuff->internalVMods);
70905b261ecSmrg
71005b261ecSmrg                new.internal.real_mods &= ~(stuff->affectInternalMods);
71105b261ecSmrg                new.internal.real_mods |= (stuff->affectInternalMods &
71205b261ecSmrg                                           stuff->internalMods);
71305b261ecSmrg                new.internal.vmods &= ~(stuff->affectInternalVMods);
71405b261ecSmrg                new.internal.vmods |= (stuff->affectInternalVMods &
71505b261ecSmrg                                       stuff->internalVMods);
71605b261ecSmrg                new.internal.mask = new.internal.real_mods |
71705b261ecSmrg                                    XkbMaskForVMask(xkbi->desc,
71805b261ecSmrg                                                    new.internal.vmods);
71905b261ecSmrg            }
72005b261ecSmrg
72105b261ecSmrg            if (stuff->changeCtrls & XkbIgnoreLockModsMask) {
72205b261ecSmrg                CHK_MASK_MATCH(0x4, stuff->affectIgnoreLockMods,
72305b261ecSmrg                               stuff->ignoreLockMods);
72405b261ecSmrg                CHK_MASK_MATCH(0x5, stuff->affectIgnoreLockVMods,
72505b261ecSmrg                               stuff->ignoreLockVMods);
72605b261ecSmrg
72705b261ecSmrg                new.ignore_lock.real_mods &= ~(stuff->affectIgnoreLockMods);
72805b261ecSmrg                new.ignore_lock.real_mods |= (stuff->affectIgnoreLockMods &
72905b261ecSmrg                                              stuff->ignoreLockMods);
73005b261ecSmrg                new.ignore_lock.vmods &= ~(stuff->affectIgnoreLockVMods);
73105b261ecSmrg                new.ignore_lock.vmods |= (stuff->affectIgnoreLockVMods &
73205b261ecSmrg                                          stuff->ignoreLockVMods);
73305b261ecSmrg                new.ignore_lock.mask = new.ignore_lock.real_mods |
73405b261ecSmrg                                       XkbMaskForVMask(xkbi->desc,
73505b261ecSmrg                                                       new.ignore_lock.vmods);
73605b261ecSmrg            }
73705b261ecSmrg
73805b261ecSmrg            CHK_MASK_MATCH(0x06, stuff->affectEnabledCtrls,
73905b261ecSmrg                           stuff->enabledCtrls);
74005b261ecSmrg            if (stuff->affectEnabledCtrls) {
74105b261ecSmrg                CHK_MASK_LEGAL(0x07, stuff->affectEnabledCtrls,
74205b261ecSmrg                               XkbAllBooleanCtrlsMask);
74305b261ecSmrg
74405b261ecSmrg                new.enabled_ctrls &= ~(stuff->affectEnabledCtrls);
74505b261ecSmrg                new.enabled_ctrls |= (stuff->affectEnabledCtrls &
74605b261ecSmrg                                      stuff->enabledCtrls);
74705b261ecSmrg            }
74805b261ecSmrg
74905b261ecSmrg            if (stuff->changeCtrls & XkbRepeatKeysMask) {
75005b261ecSmrg                if (stuff->repeatDelay < 1 || stuff->repeatInterval < 1) {
75105b261ecSmrg                    client->errorValue = _XkbErrCode3(0x08, stuff->repeatDelay,
75205b261ecSmrg                                                      stuff->repeatInterval);
75305b261ecSmrg                    return BadValue;
75405b261ecSmrg                }
75505b261ecSmrg
75605b261ecSmrg                new.repeat_delay = stuff->repeatDelay;
75705b261ecSmrg                new.repeat_interval = stuff->repeatInterval;
75805b261ecSmrg            }
75905b261ecSmrg
76005b261ecSmrg            if (stuff->changeCtrls & XkbSlowKeysMask) {
76105b261ecSmrg                if (stuff->slowKeysDelay < 1) {
76205b261ecSmrg                    client->errorValue = _XkbErrCode2(0x09,
76305b261ecSmrg                                                      stuff->slowKeysDelay);
76405b261ecSmrg                    return BadValue;
76505b261ecSmrg                }
76605b261ecSmrg
76705b261ecSmrg                new.slow_keys_delay = stuff->slowKeysDelay;
76805b261ecSmrg            }
76905b261ecSmrg
77005b261ecSmrg            if (stuff->changeCtrls & XkbBounceKeysMask) {
77105b261ecSmrg                if (stuff->debounceDelay < 1) {
77205b261ecSmrg                    client->errorValue = _XkbErrCode2(0x0A,
77305b261ecSmrg                                                      stuff->debounceDelay);
77405b261ecSmrg                    return BadValue;
77505b261ecSmrg                }
77605b261ecSmrg
77705b261ecSmrg                new.debounce_delay = stuff->debounceDelay;
77805b261ecSmrg            }
77905b261ecSmrg
78005b261ecSmrg            if (stuff->changeCtrls & XkbMouseKeysMask) {
78105b261ecSmrg                if (stuff->mkDfltBtn > XkbMaxMouseKeysBtn) {
78205b261ecSmrg                    client->errorValue = _XkbErrCode2(0x0B, stuff->mkDfltBtn);
78305b261ecSmrg                    return BadValue;
78405b261ecSmrg                }
78505b261ecSmrg
78605b261ecSmrg                new.mk_dflt_btn = stuff->mkDfltBtn;
78705b261ecSmrg            }
78805b261ecSmrg
78905b261ecSmrg            if (stuff->changeCtrls & XkbMouseKeysAccelMask) {
79005b261ecSmrg                if (stuff->mkDelay < 1 || stuff->mkInterval < 1 ||
79105b261ecSmrg                    stuff->mkTimeToMax < 1 || stuff->mkMaxSpeed < 1 ||
79205b261ecSmrg                    stuff->mkCurve < -1000) {
79305b261ecSmrg                    client->errorValue = _XkbErrCode2(0x0C,0);
79405b261ecSmrg                    return BadValue;
79505b261ecSmrg                }
79605b261ecSmrg
79705b261ecSmrg                new.mk_delay = stuff->mkDelay;
79805b261ecSmrg                new.mk_interval = stuff->mkInterval;
79905b261ecSmrg                new.mk_time_to_max = stuff->mkTimeToMax;
80005b261ecSmrg                new.mk_max_speed = stuff->mkMaxSpeed;
80105b261ecSmrg                new.mk_curve = stuff->mkCurve;
80205b261ecSmrg                AccessXComputeCurveFactor(xkbi, &new);
80305b261ecSmrg            }
80405b261ecSmrg
80505b261ecSmrg            if (stuff->changeCtrls & XkbGroupsWrapMask) {
80605b261ecSmrg                unsigned act, num;
80705b261ecSmrg
80805b261ecSmrg                act = XkbOutOfRangeGroupAction(stuff->groupsWrap);
80905b261ecSmrg                switch (act) {
81005b261ecSmrg                case XkbRedirectIntoRange:
81105b261ecSmrg                    num = XkbOutOfRangeGroupNumber(stuff->groupsWrap);
81205b261ecSmrg                    if (num >= new.num_groups) {
81305b261ecSmrg                        client->errorValue = _XkbErrCode3(0x0D, new.num_groups,
81405b261ecSmrg                                                          num);
81505b261ecSmrg                        return BadValue;
81605b261ecSmrg                    }
81705b261ecSmrg                case XkbWrapIntoRange:
81805b261ecSmrg                case XkbClampIntoRange:
81905b261ecSmrg                    break;
82005b261ecSmrg                default:
82105b261ecSmrg                    client->errorValue = _XkbErrCode2(0x0E, act);
82205b261ecSmrg                    return BadValue;
82305b261ecSmrg                }
82405b261ecSmrg
82505b261ecSmrg                new.groups_wrap= stuff->groupsWrap;
82605b261ecSmrg            }
82705b261ecSmrg
82805b261ecSmrg            CHK_MASK_LEGAL(0x0F, stuff->axOptions, XkbAX_AllOptionsMask);
82905b261ecSmrg            if (stuff->changeCtrls & XkbAccessXKeysMask) {
83005b261ecSmrg                new.ax_options = stuff->axOptions & XkbAX_AllOptionsMask;
83105b261ecSmrg            }
83205b261ecSmrg            else {
83305b261ecSmrg                if (stuff->changeCtrls & XkbStickyKeysMask) {
83405b261ecSmrg                    new.ax_options &= ~(XkbAX_SKOptionsMask);
83505b261ecSmrg                    new.ax_options |= (stuff->axOptions & XkbAX_SKOptionsMask);
83605b261ecSmrg                }
83705b261ecSmrg
83805b261ecSmrg                if (stuff->changeCtrls & XkbAccessXFeedbackMask) {
83905b261ecSmrg                    new.ax_options &= ~(XkbAX_FBOptionsMask);
84005b261ecSmrg                    new.ax_options |= (stuff->axOptions & XkbAX_FBOptionsMask);
84105b261ecSmrg                }
84205b261ecSmrg            }
84305b261ecSmrg
84405b261ecSmrg            if (stuff->changeCtrls & XkbAccessXTimeoutMask) {
84505b261ecSmrg                if (stuff->axTimeout < 1) {
84605b261ecSmrg                    client->errorValue = _XkbErrCode2(0x10, stuff->axTimeout);
84705b261ecSmrg                    return BadValue;
84805b261ecSmrg                }
84905b261ecSmrg                CHK_MASK_MATCH(0x11, stuff->axtCtrlsMask,
85005b261ecSmrg                               stuff->axtCtrlsValues);
85105b261ecSmrg                CHK_MASK_LEGAL(0x12, stuff->axtCtrlsMask,
85205b261ecSmrg                               XkbAllBooleanCtrlsMask);
85305b261ecSmrg                CHK_MASK_MATCH(0x13, stuff->axtOptsMask, stuff->axtOptsValues);
85405b261ecSmrg                CHK_MASK_LEGAL(0x14, stuff->axtOptsMask, XkbAX_AllOptionsMask);
85505b261ecSmrg                new.ax_timeout = stuff->axTimeout;
85605b261ecSmrg                new.axt_ctrls_mask = stuff->axtCtrlsMask;
85705b261ecSmrg                new.axt_ctrls_values = (stuff->axtCtrlsValues &
85805b261ecSmrg                                        stuff->axtCtrlsMask);
85905b261ecSmrg                new.axt_opts_mask = stuff->axtOptsMask;
86005b261ecSmrg                new.axt_opts_values = (stuff->axtOptsValues &
86105b261ecSmrg                                       stuff->axtOptsMask);
86205b261ecSmrg            }
86305b261ecSmrg
86405b261ecSmrg            if (stuff->changeCtrls & XkbPerKeyRepeatMask)
86505b261ecSmrg                memcpy(new.per_key_repeat, stuff->perKeyRepeat,
86605b261ecSmrg                       XkbPerKeyBitArraySize);
86705b261ecSmrg
86805b261ecSmrg            old= *ctrl;
86905b261ecSmrg            *ctrl= new;
87005b261ecSmrg            XkbDDXChangeControls(tmpd, &old, ctrl);
87105b261ecSmrg
87205b261ecSmrg            if (XkbComputeControlsNotify(tmpd, &old, ctrl, &cn, False)) {
87305b261ecSmrg                cn.keycode = 0;
87405b261ecSmrg                cn.eventType = 0;
87505b261ecSmrg                cn.requestMajor = XkbReqCode;
87605b261ecSmrg                cn.requestMinor = X_kbSetControls;
87705b261ecSmrg                XkbSendControlsNotify(tmpd, &cn);
87805b261ecSmrg            }
87905b261ecSmrg
88005b261ecSmrg            sli = XkbFindSrvLedInfo(tmpd, XkbDfltXIClass, XkbDfltXIId, 0);
88105b261ecSmrg            if (sli)
88205b261ecSmrg                XkbUpdateIndicators(tmpd, sli->usesControls, True, NULL,
88305b261ecSmrg                                    &cause);
88405b261ecSmrg
88505b261ecSmrg            /* If sticky keys were disabled, clear all locks and latches */
88605b261ecSmrg            if ((old.enabled_ctrls & XkbStickyKeysMask) &&
88705b261ecSmrg                !(ctrl->enabled_ctrls & XkbStickyKeysMask))
88805b261ecSmrg                XkbClearAllLatchesAndLocks(tmpd, xkbi, True, &cause);
88905b261ecSmrg        }
89005b261ecSmrg    }
89105b261ecSmrg
89205b261ecSmrg    return client->noClientException;
89305b261ecSmrg}
89405b261ecSmrg
89505b261ecSmrg/***====================================================================***/
89605b261ecSmrg
89705b261ecSmrgstatic int
89805b261ecSmrgXkbSizeKeyTypes(XkbDescPtr xkb,xkbGetMapReply *rep)
89905b261ecSmrg{
90005b261ecSmrg    XkbKeyTypeRec 	*type;
90105b261ecSmrg    unsigned		i,len;
90205b261ecSmrg
90305b261ecSmrg    len= 0;
90405b261ecSmrg    if (((rep->present&XkbKeyTypesMask)==0)||(rep->nTypes<1)||
90505b261ecSmrg	(!xkb)||(!xkb->map)||(!xkb->map->types)) {
90605b261ecSmrg	rep->present&= ~XkbKeyTypesMask;
90705b261ecSmrg	rep->firstType= rep->nTypes= 0;
90805b261ecSmrg	return 0;
90905b261ecSmrg    }
91005b261ecSmrg    type= &xkb->map->types[rep->firstType];
91105b261ecSmrg    for (i=0;i<rep->nTypes;i++,type++){
91205b261ecSmrg	len+= SIZEOF(xkbKeyTypeWireDesc);
91305b261ecSmrg	if (type->map_count>0) {
91405b261ecSmrg	    len+= (type->map_count*SIZEOF(xkbKTMapEntryWireDesc));
91505b261ecSmrg	    if (type->preserve)
91605b261ecSmrg		len+= (type->map_count*SIZEOF(xkbModsWireDesc));
91705b261ecSmrg	}
91805b261ecSmrg    }
91905b261ecSmrg    return len;
92005b261ecSmrg}
92105b261ecSmrg
92205b261ecSmrgstatic char *
92305b261ecSmrgXkbWriteKeyTypes(	XkbDescPtr		xkb,
92405b261ecSmrg			xkbGetMapReply *	rep,
92505b261ecSmrg			char *			buf,
92605b261ecSmrg			ClientPtr 		client)
92705b261ecSmrg{
92805b261ecSmrg    XkbKeyTypePtr	type;
92905b261ecSmrg    unsigned		i;
93005b261ecSmrg    xkbKeyTypeWireDesc *wire;
93105b261ecSmrg
93205b261ecSmrg    type= &xkb->map->types[rep->firstType];
93305b261ecSmrg    for (i=0;i<rep->nTypes;i++,type++) {
93405b261ecSmrg	register unsigned n;
93505b261ecSmrg	wire= (xkbKeyTypeWireDesc *)buf;
93605b261ecSmrg	wire->mask = type->mods.mask;
93705b261ecSmrg	wire->realMods = type->mods.real_mods;
93805b261ecSmrg	wire->virtualMods = type->mods.vmods;
93905b261ecSmrg	wire->numLevels = type->num_levels;
94005b261ecSmrg	wire->nMapEntries = type->map_count;
94105b261ecSmrg	wire->preserve = (type->preserve!=NULL);
94205b261ecSmrg	if (client->swapped) {
94305b261ecSmrg	    register int n;
94405b261ecSmrg	    swaps(&wire->virtualMods,n);
94505b261ecSmrg	}
94605b261ecSmrg
94705b261ecSmrg	buf= (char *)&wire[1];
94805b261ecSmrg	if (wire->nMapEntries>0) {
94905b261ecSmrg	    xkbKTMapEntryWireDesc *	wire;
95005b261ecSmrg	    XkbKTMapEntryPtr		entry;
95105b261ecSmrg	    wire= (xkbKTMapEntryWireDesc *)buf;
95205b261ecSmrg	    entry= type->map;
95305b261ecSmrg	    for (n=0;n<type->map_count;n++,wire++,entry++) {
95405b261ecSmrg		wire->active= entry->active;
95505b261ecSmrg		wire->mask= entry->mods.mask;
95605b261ecSmrg		wire->level= entry->level;
95705b261ecSmrg		wire->realMods= entry->mods.real_mods;
95805b261ecSmrg		wire->virtualMods= entry->mods.vmods;
95905b261ecSmrg		if (client->swapped) {
96005b261ecSmrg		    register int n;
96105b261ecSmrg		    swaps(&wire->virtualMods,n);
96205b261ecSmrg		}
96305b261ecSmrg	    }
96405b261ecSmrg	    buf= (char *)wire;
96505b261ecSmrg	    if (type->preserve!=NULL) {
96605b261ecSmrg		xkbModsWireDesc *	pwire;
96705b261ecSmrg		XkbModsPtr		preserve;
96805b261ecSmrg		pwire= (xkbModsWireDesc *)buf;
96905b261ecSmrg		preserve= type->preserve;
97005b261ecSmrg		for (n=0;n<type->map_count;n++,pwire++,preserve++) {
97105b261ecSmrg		    pwire->mask= preserve->mask;
97205b261ecSmrg		    pwire->realMods= preserve->real_mods;
97305b261ecSmrg		    pwire->virtualMods= preserve->vmods;
97405b261ecSmrg		    if (client->swapped) {
97505b261ecSmrg			register int n;
97605b261ecSmrg			swaps(&pwire->virtualMods,n);
97705b261ecSmrg		    }
97805b261ecSmrg		}
97905b261ecSmrg		buf= (char *)pwire;
98005b261ecSmrg	    }
98105b261ecSmrg	}
98205b261ecSmrg    }
98305b261ecSmrg    return buf;
98405b261ecSmrg}
98505b261ecSmrg
98605b261ecSmrgstatic int
98705b261ecSmrgXkbSizeKeySyms(XkbDescPtr xkb,xkbGetMapReply *rep)
98805b261ecSmrg{
98905b261ecSmrg    XkbSymMapPtr	symMap;
99005b261ecSmrg    unsigned		i,len;
99105b261ecSmrg    unsigned		nSyms,nSymsThisKey;
99205b261ecSmrg
99305b261ecSmrg    if (((rep->present&XkbKeySymsMask)==0)||(rep->nKeySyms<1)||
99405b261ecSmrg	(!xkb)||(!xkb->map)||(!xkb->map->key_sym_map)) {
99505b261ecSmrg	rep->present&= ~XkbKeySymsMask;
99605b261ecSmrg	rep->firstKeySym= rep->nKeySyms= 0;
99705b261ecSmrg	rep->totalSyms= 0;
99805b261ecSmrg	return 0;
99905b261ecSmrg    }
100005b261ecSmrg    len= rep->nKeySyms*SIZEOF(xkbSymMapWireDesc);
100105b261ecSmrg    symMap = &xkb->map->key_sym_map[rep->firstKeySym];
100205b261ecSmrg    for (i=nSyms=0;i<rep->nKeySyms;i++,symMap++) {
100305b261ecSmrg	if (symMap->offset!=0) {
100405b261ecSmrg	    nSymsThisKey= XkbNumGroups(symMap->group_info)*symMap->width;
100505b261ecSmrg	    nSyms+= nSymsThisKey;
100605b261ecSmrg	}
100705b261ecSmrg    }
100805b261ecSmrg    len+= nSyms*4;
100905b261ecSmrg    rep->totalSyms= nSyms;
101005b261ecSmrg    return len;
101105b261ecSmrg}
101205b261ecSmrg
101305b261ecSmrgstatic int
101405b261ecSmrgXkbSizeVirtualMods(XkbDescPtr xkb,xkbGetMapReply *rep)
101505b261ecSmrg{
101605b261ecSmrgregister unsigned i,nMods,bit;
101705b261ecSmrg
101805b261ecSmrg    if (((rep->present&XkbVirtualModsMask)==0)||(rep->virtualMods==0)||
101905b261ecSmrg	(!xkb)||(!xkb->server)) {
102005b261ecSmrg	rep->present&= ~XkbVirtualModsMask;
102105b261ecSmrg	rep->virtualMods= 0;
102205b261ecSmrg	return 0;
102305b261ecSmrg    }
102405b261ecSmrg    for (i=nMods=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
102505b261ecSmrg        if (rep->virtualMods&bit)
102605b261ecSmrg	    nMods++;
102705b261ecSmrg    }
102805b261ecSmrg    return XkbPaddedSize(nMods);
102905b261ecSmrg}
103005b261ecSmrg
103105b261ecSmrgstatic char *
103205b261ecSmrgXkbWriteKeySyms(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,ClientPtr client)
103305b261ecSmrg{
103405b261ecSmrgregister KeySym *	pSym;
103505b261ecSmrgXkbSymMapPtr		symMap;
103605b261ecSmrgxkbSymMapWireDesc *	outMap;
103705b261ecSmrgregister unsigned	i;
103805b261ecSmrg
103905b261ecSmrg    symMap = &xkb->map->key_sym_map[rep->firstKeySym];
104005b261ecSmrg    for (i=0;i<rep->nKeySyms;i++,symMap++) {
104105b261ecSmrg	outMap = (xkbSymMapWireDesc *)buf;
104205b261ecSmrg	outMap->ktIndex[0] = symMap->kt_index[0];
104305b261ecSmrg	outMap->ktIndex[1] = symMap->kt_index[1];
104405b261ecSmrg	outMap->ktIndex[2] = symMap->kt_index[2];
104505b261ecSmrg	outMap->ktIndex[3] = symMap->kt_index[3];
104605b261ecSmrg	outMap->groupInfo = symMap->group_info;
104705b261ecSmrg	outMap->width= symMap->width;
104805b261ecSmrg	outMap->nSyms = symMap->width*XkbNumGroups(symMap->group_info);
104905b261ecSmrg	buf= (char *)&outMap[1];
105005b261ecSmrg	if (outMap->nSyms==0)
105105b261ecSmrg	    continue;
105205b261ecSmrg
105305b261ecSmrg	pSym = &xkb->map->syms[symMap->offset];
105405b261ecSmrg	memcpy((char *)buf,(char *)pSym,outMap->nSyms*4);
105505b261ecSmrg	if (client->swapped) {
105605b261ecSmrg	    register int n,nSyms= outMap->nSyms;
105705b261ecSmrg	    swaps(&outMap->nSyms,n);
105805b261ecSmrg	    while (nSyms-->0) {
105905b261ecSmrg		swapl(buf,n);
106005b261ecSmrg		buf+= 4;
106105b261ecSmrg	    }
106205b261ecSmrg	}
106305b261ecSmrg	else buf+= outMap->nSyms*4;
106405b261ecSmrg    }
106505b261ecSmrg    return buf;
106605b261ecSmrg}
106705b261ecSmrg
106805b261ecSmrgstatic int
106905b261ecSmrgXkbSizeKeyActions(XkbDescPtr xkb,xkbGetMapReply *rep)
107005b261ecSmrg{
107105b261ecSmrg    unsigned		i,len,nActs;
107205b261ecSmrg    register KeyCode	firstKey;
107305b261ecSmrg
107405b261ecSmrg    if (((rep->present&XkbKeyActionsMask)==0)||(rep->nKeyActs<1)||
107505b261ecSmrg	(!xkb)||(!xkb->server)||(!xkb->server->key_acts)) {
107605b261ecSmrg	rep->present&= ~XkbKeyActionsMask;
107705b261ecSmrg	rep->firstKeyAct= rep->nKeyActs= 0;
107805b261ecSmrg	rep->totalActs= 0;
107905b261ecSmrg	return 0;
108005b261ecSmrg    }
108105b261ecSmrg    firstKey= rep->firstKeyAct;
108205b261ecSmrg    for (nActs=i=0;i<rep->nKeyActs;i++) {
108305b261ecSmrg	if (xkb->server->key_acts[i+firstKey]!=0)
108405b261ecSmrg	    nActs+= XkbKeyNumActions(xkb,i+firstKey);
108505b261ecSmrg    }
108605b261ecSmrg    len= XkbPaddedSize(rep->nKeyActs)+(nActs*SIZEOF(xkbActionWireDesc));
108705b261ecSmrg    rep->totalActs= nActs;
108805b261ecSmrg    return len;
108905b261ecSmrg}
109005b261ecSmrg
109105b261ecSmrgstatic char *
109205b261ecSmrgXkbWriteKeyActions(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
109305b261ecSmrg							ClientPtr client)
109405b261ecSmrg{
109505b261ecSmrg    unsigned		i;
109605b261ecSmrg    CARD8 *		numDesc;
109705b261ecSmrg    XkbAnyAction *	actDesc;
109805b261ecSmrg
109905b261ecSmrg    numDesc = (CARD8 *)buf;
110005b261ecSmrg    for (i=0;i<rep->nKeyActs;i++) {
110105b261ecSmrg	if (xkb->server->key_acts[i+rep->firstKeyAct]==0)
110205b261ecSmrg	     numDesc[i] = 0;
110305b261ecSmrg	else numDesc[i] = XkbKeyNumActions(xkb,(i+rep->firstKeyAct));
110405b261ecSmrg    }
110505b261ecSmrg    buf+= XkbPaddedSize(rep->nKeyActs);
110605b261ecSmrg
110705b261ecSmrg    actDesc = (XkbAnyAction *)buf;
110805b261ecSmrg    for (i=0;i<rep->nKeyActs;i++) {
110905b261ecSmrg	if (xkb->server->key_acts[i+rep->firstKeyAct]!=0) {
111005b261ecSmrg	    unsigned int num;
111105b261ecSmrg	    num = XkbKeyNumActions(xkb,(i+rep->firstKeyAct));
111205b261ecSmrg	    memcpy((char *)actDesc,
111305b261ecSmrg		   (char*)XkbKeyActionsPtr(xkb,(i+rep->firstKeyAct)),
111405b261ecSmrg		   num*SIZEOF(xkbActionWireDesc));
111505b261ecSmrg	    actDesc+= num;
111605b261ecSmrg	}
111705b261ecSmrg    }
111805b261ecSmrg    buf = (char *)actDesc;
111905b261ecSmrg    return buf;
112005b261ecSmrg}
112105b261ecSmrg
112205b261ecSmrgstatic int
112305b261ecSmrgXkbSizeKeyBehaviors(XkbDescPtr xkb,xkbGetMapReply *rep)
112405b261ecSmrg{
112505b261ecSmrg    unsigned		i,len,nBhvr;
112605b261ecSmrg    XkbBehavior *	bhv;
112705b261ecSmrg
112805b261ecSmrg    if (((rep->present&XkbKeyBehaviorsMask)==0)||(rep->nKeyBehaviors<1)||
112905b261ecSmrg	(!xkb)||(!xkb->server)||(!xkb->server->behaviors)) {
113005b261ecSmrg	rep->present&= ~XkbKeyBehaviorsMask;
113105b261ecSmrg	rep->firstKeyBehavior= rep->nKeyBehaviors= 0;
113205b261ecSmrg	rep->totalKeyBehaviors= 0;
113305b261ecSmrg	return 0;
113405b261ecSmrg    }
113505b261ecSmrg    bhv= &xkb->server->behaviors[rep->firstKeyBehavior];
113605b261ecSmrg    for (nBhvr=i=0;i<rep->nKeyBehaviors;i++,bhv++) {
113705b261ecSmrg	if (bhv->type!=XkbKB_Default)
113805b261ecSmrg	    nBhvr++;
113905b261ecSmrg    }
114005b261ecSmrg    len= nBhvr*SIZEOF(xkbBehaviorWireDesc);
114105b261ecSmrg    rep->totalKeyBehaviors= nBhvr;
114205b261ecSmrg    return len;
114305b261ecSmrg}
114405b261ecSmrg
114505b261ecSmrgstatic char *
114605b261ecSmrgXkbWriteKeyBehaviors(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
114705b261ecSmrg							ClientPtr client)
114805b261ecSmrg{
114905b261ecSmrg    unsigned		i;
115005b261ecSmrg    xkbBehaviorWireDesc	*wire;
115105b261ecSmrg    XkbBehavior		*pBhvr;
115205b261ecSmrg
115305b261ecSmrg    wire = (xkbBehaviorWireDesc *)buf;
115405b261ecSmrg    pBhvr= &xkb->server->behaviors[rep->firstKeyBehavior];
115505b261ecSmrg    for (i=0;i<rep->nKeyBehaviors;i++,pBhvr++) {
115605b261ecSmrg	if (pBhvr->type!=XkbKB_Default) {
115705b261ecSmrg	    wire->key=  i+rep->firstKeyBehavior;
115805b261ecSmrg	    wire->type= pBhvr->type;
115905b261ecSmrg	    wire->data= pBhvr->data;
116005b261ecSmrg	    wire++;
116105b261ecSmrg	}
116205b261ecSmrg    }
116305b261ecSmrg    buf = (char *)wire;
116405b261ecSmrg    return buf;
116505b261ecSmrg}
116605b261ecSmrg
116705b261ecSmrgstatic int
116805b261ecSmrgXkbSizeExplicit(XkbDescPtr xkb,xkbGetMapReply *rep)
116905b261ecSmrg{
117005b261ecSmrg    unsigned	i,len,nRtrn;
117105b261ecSmrg
117205b261ecSmrg    if (((rep->present&XkbExplicitComponentsMask)==0)||(rep->nKeyExplicit<1)||
117305b261ecSmrg	(!xkb)||(!xkb->server)||(!xkb->server->explicit)) {
117405b261ecSmrg	rep->present&= ~XkbExplicitComponentsMask;
117505b261ecSmrg	rep->firstKeyExplicit= rep->nKeyExplicit= 0;
117605b261ecSmrg	rep->totalKeyExplicit= 0;
117705b261ecSmrg	return 0;
117805b261ecSmrg    }
117905b261ecSmrg    for (nRtrn=i=0;i<rep->nKeyExplicit;i++) {
118005b261ecSmrg	if (xkb->server->explicit[i+rep->firstKeyExplicit]!=0)
118105b261ecSmrg	    nRtrn++;
118205b261ecSmrg    }
118305b261ecSmrg    rep->totalKeyExplicit= nRtrn;
118405b261ecSmrg    len= XkbPaddedSize(nRtrn*2); /* two bytes per non-zero explicit component */
118505b261ecSmrg    return len;
118605b261ecSmrg}
118705b261ecSmrg
118805b261ecSmrgstatic char *
118905b261ecSmrgXkbWriteExplicit(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,ClientPtr client)
119005b261ecSmrg{
119105b261ecSmrgunsigned	i;
119205b261ecSmrgchar *		start;
119305b261ecSmrgunsigned char *	pExp;
119405b261ecSmrg
119505b261ecSmrg    start= buf;
119605b261ecSmrg    pExp= &xkb->server->explicit[rep->firstKeyExplicit];
119705b261ecSmrg    for (i=0;i<rep->nKeyExplicit;i++,pExp++) {
119805b261ecSmrg	if (*pExp!=0) {
119905b261ecSmrg	    *buf++= i+rep->firstKeyExplicit;
120005b261ecSmrg	    *buf++= *pExp;
120105b261ecSmrg	}
120205b261ecSmrg    }
120305b261ecSmrg    i= XkbPaddedSize(buf-start)-(buf-start); /* pad to word boundary */
120405b261ecSmrg    return buf+i;
120505b261ecSmrg}
120605b261ecSmrg
120705b261ecSmrgstatic int
120805b261ecSmrgXkbSizeModifierMap(XkbDescPtr xkb,xkbGetMapReply *rep)
120905b261ecSmrg{
121005b261ecSmrg    unsigned	i,len,nRtrn;
121105b261ecSmrg
121205b261ecSmrg    if (((rep->present&XkbModifierMapMask)==0)||(rep->nModMapKeys<1)||
121305b261ecSmrg	(!xkb)||(!xkb->map)||(!xkb->map->modmap)) {
121405b261ecSmrg	rep->present&= ~XkbModifierMapMask;
121505b261ecSmrg	rep->firstModMapKey= rep->nModMapKeys= 0;
121605b261ecSmrg	rep->totalModMapKeys= 0;
121705b261ecSmrg	return 0;
121805b261ecSmrg    }
121905b261ecSmrg    for (nRtrn=i=0;i<rep->nModMapKeys;i++) {
122005b261ecSmrg	if (xkb->map->modmap[i+rep->firstModMapKey]!=0)
122105b261ecSmrg	    nRtrn++;
122205b261ecSmrg    }
122305b261ecSmrg    rep->totalModMapKeys= nRtrn;
122405b261ecSmrg    len= XkbPaddedSize(nRtrn*2); /* two bytes per non-zero modmap component */
122505b261ecSmrg    return len;
122605b261ecSmrg}
122705b261ecSmrg
122805b261ecSmrgstatic char *
122905b261ecSmrgXkbWriteModifierMap(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
123005b261ecSmrg							ClientPtr client)
123105b261ecSmrg{
123205b261ecSmrgunsigned	i;
123305b261ecSmrgchar *		start;
123405b261ecSmrgunsigned char *	pMap;
123505b261ecSmrg
123605b261ecSmrg    start= buf;
123705b261ecSmrg    pMap= &xkb->map->modmap[rep->firstModMapKey];
123805b261ecSmrg    for (i=0;i<rep->nModMapKeys;i++,pMap++) {
123905b261ecSmrg	if (*pMap!=0) {
124005b261ecSmrg	    *buf++= i+rep->firstModMapKey;
124105b261ecSmrg	    *buf++= *pMap;
124205b261ecSmrg	}
124305b261ecSmrg    }
124405b261ecSmrg    i= XkbPaddedSize(buf-start)-(buf-start); /* pad to word boundary */
124505b261ecSmrg    return buf+i;
124605b261ecSmrg}
124705b261ecSmrg
124805b261ecSmrgstatic int
124905b261ecSmrgXkbSizeVirtualModMap(XkbDescPtr xkb,xkbGetMapReply *rep)
125005b261ecSmrg{
125105b261ecSmrg    unsigned	i,len,nRtrn;
125205b261ecSmrg
125305b261ecSmrg    if (((rep->present&XkbVirtualModMapMask)==0)||(rep->nVModMapKeys<1)||
125405b261ecSmrg	(!xkb)||(!xkb->server)||(!xkb->server->vmodmap)) {
125505b261ecSmrg	rep->present&= ~XkbVirtualModMapMask;
125605b261ecSmrg	rep->firstVModMapKey= rep->nVModMapKeys= 0;
125705b261ecSmrg	rep->totalVModMapKeys= 0;
125805b261ecSmrg	return 0;
125905b261ecSmrg    }
126005b261ecSmrg    for (nRtrn=i=0;i<rep->nVModMapKeys-1;i++) {
126105b261ecSmrg	if (xkb->server->vmodmap[i+rep->firstVModMapKey]!=0)
126205b261ecSmrg	    nRtrn++;
126305b261ecSmrg    }
126405b261ecSmrg    rep->totalVModMapKeys= nRtrn;
126505b261ecSmrg    len= nRtrn*SIZEOF(xkbVModMapWireDesc);
126605b261ecSmrg    return len;
126705b261ecSmrg}
126805b261ecSmrg
126905b261ecSmrgstatic char *
127005b261ecSmrgXkbWriteVirtualModMap(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
127105b261ecSmrg							ClientPtr client)
127205b261ecSmrg{
127305b261ecSmrgunsigned		i;
127405b261ecSmrgxkbVModMapWireDesc *	wire;
127505b261ecSmrgunsigned short *	pMap;
127605b261ecSmrg
127705b261ecSmrg    wire= (xkbVModMapWireDesc *)buf;
127805b261ecSmrg    pMap= &xkb->server->vmodmap[rep->firstVModMapKey];
127905b261ecSmrg    for (i=0;i<rep->nVModMapKeys-1;i++,pMap++) {
128005b261ecSmrg	if (*pMap!=0) {
128105b261ecSmrg	    wire->key= i+rep->firstVModMapKey;
128205b261ecSmrg	    wire->vmods= *pMap;
128305b261ecSmrg	    wire++;
128405b261ecSmrg	}
128505b261ecSmrg    }
128605b261ecSmrg    return (char *)wire;
128705b261ecSmrg}
128805b261ecSmrg
128905b261ecSmrgstatic Status
129005b261ecSmrgXkbComputeGetMapReplySize(XkbDescPtr xkb,xkbGetMapReply *rep)
129105b261ecSmrg{
129205b261ecSmrgint	len;
129305b261ecSmrg
129405b261ecSmrg    rep->minKeyCode= xkb->min_key_code;
129505b261ecSmrg    rep->maxKeyCode= xkb->max_key_code;
129605b261ecSmrg    len= XkbSizeKeyTypes(xkb,rep);
129705b261ecSmrg    len+= XkbSizeKeySyms(xkb,rep);
129805b261ecSmrg    len+= XkbSizeKeyActions(xkb,rep);
129905b261ecSmrg    len+= XkbSizeKeyBehaviors(xkb,rep);
130005b261ecSmrg    len+= XkbSizeVirtualMods(xkb,rep);
130105b261ecSmrg    len+= XkbSizeExplicit(xkb,rep);
130205b261ecSmrg    len+= XkbSizeModifierMap(xkb,rep);
130305b261ecSmrg    len+= XkbSizeVirtualModMap(xkb,rep);
130405b261ecSmrg    rep->length+= (len/4);
130505b261ecSmrg    return Success;
130605b261ecSmrg}
130705b261ecSmrg
130805b261ecSmrgstatic int
130905b261ecSmrgXkbSendMap(ClientPtr client,XkbDescPtr xkb,xkbGetMapReply *rep)
131005b261ecSmrg{
131105b261ecSmrgunsigned	i,len;
131205b261ecSmrgchar		*desc,*start;
131305b261ecSmrg
131405b261ecSmrg    len= (rep->length*4)-(SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply));
131505b261ecSmrg    start= desc= (char *)ALLOCATE_LOCAL(len);
131605b261ecSmrg    if (!start)
131705b261ecSmrg	return BadAlloc;
131805b261ecSmrg    if ( rep->nTypes>0 )
131905b261ecSmrg	desc = XkbWriteKeyTypes(xkb,rep,desc,client);
132005b261ecSmrg    if ( rep->nKeySyms>0 )
132105b261ecSmrg	desc = XkbWriteKeySyms(xkb,rep,desc,client);
132205b261ecSmrg    if ( rep->nKeyActs>0 )
132305b261ecSmrg	desc = XkbWriteKeyActions(xkb,rep,desc,client);
132405b261ecSmrg    if ( rep->totalKeyBehaviors>0 )
132505b261ecSmrg	desc = XkbWriteKeyBehaviors(xkb,rep,desc,client);
132605b261ecSmrg    if ( rep->virtualMods ) {
132705b261ecSmrg	register int sz,bit;
132805b261ecSmrg	for (i=sz=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
132905b261ecSmrg	    if (rep->virtualMods&bit) {
133005b261ecSmrg		desc[sz++]= xkb->server->vmods[i];
133105b261ecSmrg	    }
133205b261ecSmrg	}
133305b261ecSmrg	desc+= XkbPaddedSize(sz);
133405b261ecSmrg    }
133505b261ecSmrg    if ( rep->totalKeyExplicit>0 )
133605b261ecSmrg	desc= XkbWriteExplicit(xkb,rep,desc,client);
133705b261ecSmrg    if ( rep->totalModMapKeys>0 )
133805b261ecSmrg	desc= XkbWriteModifierMap(xkb,rep,desc,client);
133905b261ecSmrg    if ( rep->totalVModMapKeys>0 )
134005b261ecSmrg	desc= XkbWriteVirtualModMap(xkb,rep,desc,client);
134105b261ecSmrg    if ((desc-start)!=(len)) {
134205b261ecSmrg	ErrorF("BOGUS LENGTH in write keyboard desc, expected %d, got %ld\n",
134305b261ecSmrg					len, (unsigned long)(desc-start));
134405b261ecSmrg    }
134505b261ecSmrg    if (client->swapped) {
134605b261ecSmrg	register int n;
134705b261ecSmrg	swaps(&rep->sequenceNumber,n);
134805b261ecSmrg	swapl(&rep->length,n);
134905b261ecSmrg	swaps(&rep->present,n);
135005b261ecSmrg	swaps(&rep->totalSyms,n);
135105b261ecSmrg	swaps(&rep->totalActs,n);
135205b261ecSmrg    }
135305b261ecSmrg    WriteToClient(client, (i=SIZEOF(xkbGetMapReply)), (char *)rep);
135405b261ecSmrg    WriteToClient(client, len, start);
135505b261ecSmrg    DEALLOCATE_LOCAL((char *)start);
135605b261ecSmrg    return client->noClientException;
135705b261ecSmrg}
135805b261ecSmrg
135905b261ecSmrgint
136005b261ecSmrgProcXkbGetMap(ClientPtr client)
136105b261ecSmrg{
136205b261ecSmrg    DeviceIntPtr	 dev;
136305b261ecSmrg    xkbGetMapReply	 rep;
136405b261ecSmrg    XkbDescRec		*xkb;
136505b261ecSmrg    int			 n,status;
136605b261ecSmrg
136705b261ecSmrg    REQUEST(xkbGetMapReq);
136805b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetMapReq);
136905b261ecSmrg
137005b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
137105b261ecSmrg	return BadAccess;
137205b261ecSmrg
137305b261ecSmrg    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
137405b261ecSmrg    CHK_MASK_OVERLAP(0x01,stuff->full,stuff->partial);
137505b261ecSmrg    CHK_MASK_LEGAL(0x02,stuff->full,XkbAllMapComponentsMask);
137605b261ecSmrg    CHK_MASK_LEGAL(0x03,stuff->partial,XkbAllMapComponentsMask);
137705b261ecSmrg
137805b261ecSmrg    xkb= dev->key->xkbInfo->desc;
137905b261ecSmrg    bzero(&rep,sizeof(xkbGetMapReply));
138005b261ecSmrg    rep.type= X_Reply;
138105b261ecSmrg    rep.sequenceNumber= client->sequence;
138205b261ecSmrg    rep.length = (SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2;
138305b261ecSmrg    rep.deviceID = dev->id;
138405b261ecSmrg    rep.present = stuff->partial|stuff->full;
138505b261ecSmrg    rep.minKeyCode = xkb->min_key_code;
138605b261ecSmrg    rep.maxKeyCode = xkb->max_key_code;
138705b261ecSmrg    if ( stuff->full&XkbKeyTypesMask ) {
138805b261ecSmrg	rep.firstType = 0;
138905b261ecSmrg	rep.nTypes = xkb->map->num_types;
139005b261ecSmrg    }
139105b261ecSmrg    else if (stuff->partial&XkbKeyTypesMask) {
139205b261ecSmrg	if (((unsigned)stuff->firstType+stuff->nTypes)>xkb->map->num_types) {
139305b261ecSmrg	    client->errorValue = _XkbErrCode4(0x04,xkb->map->num_types,
139405b261ecSmrg					stuff->firstType,stuff->nTypes);
139505b261ecSmrg	    return BadValue;
139605b261ecSmrg	}
139705b261ecSmrg	rep.firstType = stuff->firstType;
139805b261ecSmrg	rep.nTypes = stuff->nTypes;
139905b261ecSmrg    }
140005b261ecSmrg    else rep.nTypes = 0;
140105b261ecSmrg    rep.totalTypes = xkb->map->num_types;
140205b261ecSmrg
140305b261ecSmrg    n= XkbNumKeys(xkb);
140405b261ecSmrg    if ( stuff->full&XkbKeySymsMask ) {
140505b261ecSmrg	rep.firstKeySym = xkb->min_key_code;
140605b261ecSmrg	rep.nKeySyms = n;
140705b261ecSmrg    }
140805b261ecSmrg    else if (stuff->partial&XkbKeySymsMask) {
140905b261ecSmrg	CHK_KEY_RANGE(0x05,stuff->firstKeySym,stuff->nKeySyms,xkb);
141005b261ecSmrg	rep.firstKeySym = stuff->firstKeySym;
141105b261ecSmrg	rep.nKeySyms = stuff->nKeySyms;
141205b261ecSmrg    }
141305b261ecSmrg    else rep.nKeySyms = 0;
141405b261ecSmrg    rep.totalSyms= 0;
141505b261ecSmrg
141605b261ecSmrg    if ( stuff->full&XkbKeyActionsMask ) {
141705b261ecSmrg	rep.firstKeyAct= xkb->min_key_code;
141805b261ecSmrg	rep.nKeyActs= n;
141905b261ecSmrg    }
142005b261ecSmrg    else if (stuff->partial&XkbKeyActionsMask) {
142105b261ecSmrg	CHK_KEY_RANGE(0x07,stuff->firstKeyAct,stuff->nKeyActs,xkb);
142205b261ecSmrg	rep.firstKeyAct= stuff->firstKeyAct;
142305b261ecSmrg	rep.nKeyActs= stuff->nKeyActs;
142405b261ecSmrg    }
142505b261ecSmrg    else rep.nKeyActs= 0;
142605b261ecSmrg    rep.totalActs= 0;
142705b261ecSmrg
142805b261ecSmrg    if ( stuff->full&XkbKeyBehaviorsMask ) {
142905b261ecSmrg	rep.firstKeyBehavior = xkb->min_key_code;
143005b261ecSmrg	rep.nKeyBehaviors = n;
143105b261ecSmrg    }
143205b261ecSmrg    else if (stuff->partial&XkbKeyBehaviorsMask) {
143305b261ecSmrg	CHK_KEY_RANGE(0x09,stuff->firstKeyBehavior,stuff->nKeyBehaviors,xkb);
143405b261ecSmrg	rep.firstKeyBehavior= stuff->firstKeyBehavior;
143505b261ecSmrg	rep.nKeyBehaviors= stuff->nKeyBehaviors;
143605b261ecSmrg    }
143705b261ecSmrg    else rep.nKeyBehaviors = 0;
143805b261ecSmrg    rep.totalKeyBehaviors= 0;
143905b261ecSmrg
144005b261ecSmrg    if (stuff->full&XkbVirtualModsMask)
144105b261ecSmrg	rep.virtualMods= ~0;
144205b261ecSmrg    else if (stuff->partial&XkbVirtualModsMask)
144305b261ecSmrg	rep.virtualMods= stuff->virtualMods;
144405b261ecSmrg
144505b261ecSmrg    if (stuff->full&XkbExplicitComponentsMask) {
144605b261ecSmrg	rep.firstKeyExplicit= xkb->min_key_code;
144705b261ecSmrg	rep.nKeyExplicit= n;
144805b261ecSmrg    }
144905b261ecSmrg    else if (stuff->partial&XkbExplicitComponentsMask) {
145005b261ecSmrg	CHK_KEY_RANGE(0x0B,stuff->firstKeyExplicit,stuff->nKeyExplicit,xkb);
145105b261ecSmrg	rep.firstKeyExplicit= stuff->firstKeyExplicit;
145205b261ecSmrg	rep.nKeyExplicit= stuff->nKeyExplicit;
145305b261ecSmrg    }
145405b261ecSmrg    else rep.nKeyExplicit = 0;
145505b261ecSmrg    rep.totalKeyExplicit=  0;
145605b261ecSmrg
145705b261ecSmrg    if (stuff->full&XkbModifierMapMask) {
145805b261ecSmrg	rep.firstModMapKey= xkb->min_key_code;
145905b261ecSmrg	rep.nModMapKeys= n;
146005b261ecSmrg    }
146105b261ecSmrg    else if (stuff->partial&XkbModifierMapMask) {
146205b261ecSmrg	CHK_KEY_RANGE(0x0D,stuff->firstModMapKey,stuff->nModMapKeys,xkb);
146305b261ecSmrg	rep.firstModMapKey= stuff->firstModMapKey;
146405b261ecSmrg	rep.nModMapKeys= stuff->nModMapKeys;
146505b261ecSmrg    }
146605b261ecSmrg    else rep.nModMapKeys = 0;
146705b261ecSmrg    rep.totalModMapKeys= 0;
146805b261ecSmrg
146905b261ecSmrg    if (stuff->full&XkbVirtualModMapMask) {
147005b261ecSmrg	rep.firstVModMapKey= xkb->min_key_code;
147105b261ecSmrg	rep.nVModMapKeys= n;
147205b261ecSmrg    }
147305b261ecSmrg    else if (stuff->partial&XkbVirtualModMapMask) {
147405b261ecSmrg	CHK_KEY_RANGE(0x0F,stuff->firstVModMapKey,stuff->nVModMapKeys,xkb);
147505b261ecSmrg	rep.firstVModMapKey= stuff->firstVModMapKey;
147605b261ecSmrg	rep.nVModMapKeys= stuff->nVModMapKeys;
147705b261ecSmrg    }
147805b261ecSmrg    else rep.nVModMapKeys = 0;
147905b261ecSmrg    rep.totalVModMapKeys= 0;
148005b261ecSmrg
148105b261ecSmrg    if ((status=XkbComputeGetMapReplySize(xkb,&rep))!=Success)
148205b261ecSmrg	return status;
148305b261ecSmrg    return XkbSendMap(client,xkb,&rep);
148405b261ecSmrg}
148505b261ecSmrg
148605b261ecSmrg/***====================================================================***/
148705b261ecSmrg
148805b261ecSmrgstatic int
148905b261ecSmrgCheckKeyTypes(	ClientPtr	client,
149005b261ecSmrg		XkbDescPtr	xkb,
149105b261ecSmrg		xkbSetMapReq *	req,
149205b261ecSmrg		xkbKeyTypeWireDesc **wireRtrn,
149305b261ecSmrg		int	 *	nMapsRtrn,
149405b261ecSmrg		CARD8 *		mapWidthRtrn)
149505b261ecSmrg{
149605b261ecSmrgunsigned		nMaps;
149705b261ecSmrgregister unsigned	i,n;
149805b261ecSmrgregister CARD8 *	map;
149905b261ecSmrgregister xkbKeyTypeWireDesc	*wire = *wireRtrn;
150005b261ecSmrg
150105b261ecSmrg    if (req->firstType>((unsigned)xkb->map->num_types)) {
150205b261ecSmrg	*nMapsRtrn = _XkbErrCode3(0x01,req->firstType,xkb->map->num_types);
150305b261ecSmrg	return 0;
150405b261ecSmrg    }
150505b261ecSmrg    if (req->flags&XkbSetMapResizeTypes) {
150605b261ecSmrg	nMaps = req->firstType+req->nTypes;
150705b261ecSmrg	if (nMaps<XkbNumRequiredTypes) {  /* canonical types must be there */
150805b261ecSmrg	    *nMapsRtrn= _XkbErrCode4(0x02,req->firstType,req->nTypes,4);
150905b261ecSmrg	    return 0;
151005b261ecSmrg	}
151105b261ecSmrg    }
151205b261ecSmrg    else if (req->present&XkbKeyTypesMask) {
151305b261ecSmrg	nMaps = xkb->map->num_types;
151405b261ecSmrg	if ((req->firstType+req->nTypes)>nMaps) {
151505b261ecSmrg	    *nMapsRtrn = req->firstType+req->nTypes;
151605b261ecSmrg	    return 0;
151705b261ecSmrg	}
151805b261ecSmrg    }
151905b261ecSmrg    else {
152005b261ecSmrg	*nMapsRtrn = xkb->map->num_types;
152105b261ecSmrg	for (i=0;i<xkb->map->num_types;i++) {
152205b261ecSmrg	    mapWidthRtrn[i] = xkb->map->types[i].num_levels;
152305b261ecSmrg	}
152405b261ecSmrg	return 1;
152505b261ecSmrg    }
152605b261ecSmrg
152705b261ecSmrg    for (i=0;i<req->firstType;i++) {
152805b261ecSmrg	mapWidthRtrn[i] = xkb->map->types[i].num_levels;
152905b261ecSmrg    }
153005b261ecSmrg    for (i=0;i<req->nTypes;i++) {
153105b261ecSmrg	unsigned	width;
153205b261ecSmrg	if (client->swapped) {
153305b261ecSmrg	    register int s;
153405b261ecSmrg	    swaps(&wire->virtualMods,s);
153505b261ecSmrg	}
153605b261ecSmrg	n= i+req->firstType;
153705b261ecSmrg	width= wire->numLevels;
153805b261ecSmrg	if (width<1) {
153905b261ecSmrg	    *nMapsRtrn= _XkbErrCode3(0x04,n,width);
154005b261ecSmrg	    return 0;
154105b261ecSmrg	}
154205b261ecSmrg	else if ((n==XkbOneLevelIndex)&&(width!=1)) { /* must be width 1 */
154305b261ecSmrg	    *nMapsRtrn= _XkbErrCode3(0x05,n,width);
154405b261ecSmrg	    return 0;
154505b261ecSmrg	}
154605b261ecSmrg	else if ((width!=2)&&
154705b261ecSmrg		 ((n==XkbTwoLevelIndex)||(n==XkbKeypadIndex)||
154805b261ecSmrg		  (n==XkbAlphabeticIndex))) {
154905b261ecSmrg	    /* TWO_LEVEL, ALPHABETIC and KEYPAD must be width 2 */
155005b261ecSmrg	    *nMapsRtrn= _XkbErrCode3(0x05,n,width);
155105b261ecSmrg	    return 0;
155205b261ecSmrg	}
155305b261ecSmrg	if (wire->nMapEntries>0) {
155405b261ecSmrg	    xkbKTSetMapEntryWireDesc *	mapWire;
155505b261ecSmrg	    xkbModsWireDesc *		preWire;
155605b261ecSmrg	    mapWire= (xkbKTSetMapEntryWireDesc *)&wire[1];
155705b261ecSmrg	    preWire= (xkbModsWireDesc *)&mapWire[wire->nMapEntries];
155805b261ecSmrg	    for (n=0;n<wire->nMapEntries;n++) {
155905b261ecSmrg		if (client->swapped) {
156005b261ecSmrg		    register int s;
156105b261ecSmrg		    swaps(&mapWire[n].virtualMods,s);
156205b261ecSmrg		}
156305b261ecSmrg		if (mapWire[n].realMods&(~wire->realMods)) {
156405b261ecSmrg		    *nMapsRtrn= _XkbErrCode4(0x06,n,mapWire[n].realMods,
156505b261ecSmrg						 wire->realMods);
156605b261ecSmrg		    return 0;
156705b261ecSmrg		}
156805b261ecSmrg		if (mapWire[n].virtualMods&(~wire->virtualMods)) {
156905b261ecSmrg		    *nMapsRtrn= _XkbErrCode3(0x07,n,mapWire[n].virtualMods);
157005b261ecSmrg		    return 0;
157105b261ecSmrg		}
157205b261ecSmrg		if (mapWire[n].level>=wire->numLevels) {
157305b261ecSmrg		    *nMapsRtrn= _XkbErrCode4(0x08,n,wire->numLevels,
157405b261ecSmrg						 mapWire[n].level);
157505b261ecSmrg		    return 0;
157605b261ecSmrg		}
157705b261ecSmrg		if (wire->preserve) {
157805b261ecSmrg		    if (client->swapped) {
157905b261ecSmrg			register int s;
158005b261ecSmrg			swaps(&preWire[n].virtualMods,s);
158105b261ecSmrg		    }
158205b261ecSmrg		    if (preWire[n].realMods&(~mapWire[n].realMods)) {
158305b261ecSmrg			*nMapsRtrn= _XkbErrCode4(0x09,n,preWire[n].realMods,
158405b261ecSmrg							mapWire[n].realMods);
158505b261ecSmrg			return 0;
158605b261ecSmrg		    }
158705b261ecSmrg		    if (preWire[n].virtualMods&(~mapWire[n].virtualMods)) {
158805b261ecSmrg			*nMapsRtrn=_XkbErrCode3(0x0a,n,preWire[n].virtualMods);
158905b261ecSmrg			return 0;
159005b261ecSmrg		    }
159105b261ecSmrg		}
159205b261ecSmrg	    }
159305b261ecSmrg	    if (wire->preserve)
159405b261ecSmrg		 map= (CARD8 *)&preWire[wire->nMapEntries];
159505b261ecSmrg	    else map= (CARD8 *)&mapWire[wire->nMapEntries];
159605b261ecSmrg	}
159705b261ecSmrg	else map= (CARD8 *)&wire[1];
159805b261ecSmrg	mapWidthRtrn[i+req->firstType] = wire->numLevels;
159905b261ecSmrg	wire= (xkbKeyTypeWireDesc *)map;
160005b261ecSmrg    }
160105b261ecSmrg    for (i=req->firstType+req->nTypes;i<nMaps;i++) {
160205b261ecSmrg	mapWidthRtrn[i] = xkb->map->types[i].num_levels;
160305b261ecSmrg    }
160405b261ecSmrg    *nMapsRtrn = nMaps;
160505b261ecSmrg    *wireRtrn = wire;
160605b261ecSmrg    return 1;
160705b261ecSmrg}
160805b261ecSmrg
160905b261ecSmrgstatic int
161005b261ecSmrgCheckKeySyms(	ClientPtr		client,
161105b261ecSmrg		XkbDescPtr		xkb,
161205b261ecSmrg		xkbSetMapReq *		req,
161305b261ecSmrg		int			nTypes,
161405b261ecSmrg		CARD8 *	 		mapWidths,
161505b261ecSmrg		CARD16 *	 	symsPerKey,
161605b261ecSmrg		xkbSymMapWireDesc **	wireRtrn,
161705b261ecSmrg		int *			errorRtrn)
161805b261ecSmrg{
161905b261ecSmrgregister unsigned	i;
162005b261ecSmrgXkbSymMapPtr		map;
162105b261ecSmrgxkbSymMapWireDesc*	wire = *wireRtrn;
162205b261ecSmrg
162305b261ecSmrg    if (!(XkbKeySymsMask&req->present))
162405b261ecSmrg	return 1;
162505b261ecSmrg    CHK_REQ_KEY_RANGE2(0x11,req->firstKeySym,req->nKeySyms,req,(*errorRtrn),0);
162605b261ecSmrg    map = &xkb->map->key_sym_map[xkb->min_key_code];
162705b261ecSmrg    for (i=xkb->min_key_code;i<(unsigned)req->firstKeySym;i++,map++) {
162805b261ecSmrg	register int g,ng,w;
162905b261ecSmrg	ng= XkbNumGroups(map->group_info);
163005b261ecSmrg	for (w=g=0;g<ng;g++) {
163105b261ecSmrg	    if (map->kt_index[g]>=(unsigned)nTypes) {
163205b261ecSmrg		*errorRtrn = _XkbErrCode4(0x13,i,g,map->kt_index[g]);
163305b261ecSmrg		return 0;
163405b261ecSmrg	    }
163505b261ecSmrg	    if (mapWidths[map->kt_index[g]]>w)
163605b261ecSmrg		w= mapWidths[map->kt_index[g]];
163705b261ecSmrg	}
163805b261ecSmrg	symsPerKey[i] = w*ng;
163905b261ecSmrg    }
164005b261ecSmrg    for (i=0;i<req->nKeySyms;i++) {
164105b261ecSmrg	KeySym *pSyms;
164205b261ecSmrg	register unsigned nG;
164305b261ecSmrg	if (client->swapped) {
164405b261ecSmrg	    swaps(&wire->nSyms,nG);
164505b261ecSmrg	}
164605b261ecSmrg	nG = XkbNumGroups(wire->groupInfo);
164705b261ecSmrg	if (nG>XkbNumKbdGroups) {
164805b261ecSmrg	    *errorRtrn = _XkbErrCode3(0x14,i+req->firstKeySym,nG);
164905b261ecSmrg	    return 0;
165005b261ecSmrg	}
165105b261ecSmrg	if (nG>0) {
165205b261ecSmrg	    register int g,w;
165305b261ecSmrg	    for (g=w=0;g<nG;g++) {
165405b261ecSmrg		if (wire->ktIndex[g]>=(unsigned)nTypes) {
165505b261ecSmrg		    *errorRtrn= _XkbErrCode4(0x15,i+req->firstKeySym,g,
165605b261ecSmrg		    					   wire->ktIndex[g]);
165705b261ecSmrg		    return 0;
165805b261ecSmrg		}
165905b261ecSmrg		if (mapWidths[wire->ktIndex[g]]>w)
166005b261ecSmrg		    w= mapWidths[wire->ktIndex[g]];
166105b261ecSmrg	    }
166205b261ecSmrg	    if (wire->width!=w) {
166305b261ecSmrg		*errorRtrn= _XkbErrCode3(0x16,i+req->firstKeySym,wire->width);
166405b261ecSmrg		return 0;
166505b261ecSmrg	    }
166605b261ecSmrg	    w*= nG;
166705b261ecSmrg	    symsPerKey[i+req->firstKeySym] = w;
166805b261ecSmrg	    if (w!=wire->nSyms) {
166905b261ecSmrg		*errorRtrn=_XkbErrCode4(0x16,i+req->firstKeySym,wire->nSyms,w);
167005b261ecSmrg		return 0;
167105b261ecSmrg	    }
167205b261ecSmrg	}
167305b261ecSmrg	else if (wire->nSyms!=0) {
167405b261ecSmrg	    *errorRtrn = _XkbErrCode3(0x17,i+req->firstKeySym,wire->nSyms);
167505b261ecSmrg	    return 0;
167605b261ecSmrg	}
167705b261ecSmrg	pSyms = (KeySym *)&wire[1];
167805b261ecSmrg	wire = (xkbSymMapWireDesc *)&pSyms[wire->nSyms];
167905b261ecSmrg    }
168005b261ecSmrg
168105b261ecSmrg    map = &xkb->map->key_sym_map[i];
168205b261ecSmrg    for (;i<=(unsigned)xkb->max_key_code;i++,map++) {
168305b261ecSmrg	register int g,nG,w;
168405b261ecSmrg	nG= XkbKeyNumGroups(xkb,i);
168505b261ecSmrg	for (w=g=0;g<nG;g++)  {
168605b261ecSmrg	    if (map->kt_index[g]>=(unsigned)nTypes) {
168705b261ecSmrg		*errorRtrn = _XkbErrCode4(0x18,i,g,map->kt_index[g]);
168805b261ecSmrg		return 0;
168905b261ecSmrg	    }
169005b261ecSmrg	    if (mapWidths[map->kt_index[g]]>w)
169105b261ecSmrg		    w= mapWidths[map->kt_index[g]];
169205b261ecSmrg	}
169305b261ecSmrg	symsPerKey[i] = w*nG;
169405b261ecSmrg    }
169505b261ecSmrg    *wireRtrn = wire;
169605b261ecSmrg    return 1;
169705b261ecSmrg}
169805b261ecSmrg
169905b261ecSmrgstatic int
170005b261ecSmrgCheckKeyActions(	XkbDescPtr	xkb,
170105b261ecSmrg			xkbSetMapReq *	req,
170205b261ecSmrg			int		nTypes,
170305b261ecSmrg			CARD8 *		mapWidths,
170405b261ecSmrg			CARD16 *	symsPerKey,
170505b261ecSmrg			CARD8 **	wireRtrn,
170605b261ecSmrg			int *		nActsRtrn)
170705b261ecSmrg{
170805b261ecSmrgint			 nActs;
170905b261ecSmrgCARD8 *			 wire = *wireRtrn;
171005b261ecSmrgregister unsigned	 i;
171105b261ecSmrg
171205b261ecSmrg    if (!(XkbKeyActionsMask&req->present))
171305b261ecSmrg	return 1;
171405b261ecSmrg    CHK_REQ_KEY_RANGE2(0x21,req->firstKeyAct,req->nKeyActs,req,(*nActsRtrn),0);
171505b261ecSmrg    for (nActs=i=0;i<req->nKeyActs;i++) {
171605b261ecSmrg	if (wire[0]!=0) {
171705b261ecSmrg	    if (wire[0]==symsPerKey[i+req->firstKeyAct])
171805b261ecSmrg		nActs+= wire[0];
171905b261ecSmrg	    else {
172005b261ecSmrg		*nActsRtrn= _XkbErrCode3(0x23,i+req->firstKeyAct,wire[0]);
172105b261ecSmrg		return 0;
172205b261ecSmrg	    }
172305b261ecSmrg	}
172405b261ecSmrg	wire++;
172505b261ecSmrg    }
172605b261ecSmrg    if (req->nKeyActs%4)
172705b261ecSmrg	wire+= 4-(req->nKeyActs%4);
172805b261ecSmrg    *wireRtrn = (CARD8 *)(((XkbAnyAction *)wire)+nActs);
172905b261ecSmrg    *nActsRtrn = nActs;
173005b261ecSmrg    return 1;
173105b261ecSmrg}
173205b261ecSmrg
173305b261ecSmrgstatic int
173405b261ecSmrgCheckKeyBehaviors(	XkbDescPtr 		xkb,
173505b261ecSmrg			xkbSetMapReq *		req,
173605b261ecSmrg			xkbBehaviorWireDesc **	wireRtrn,
173705b261ecSmrg			int *			errorRtrn)
173805b261ecSmrg{
173905b261ecSmrgregister xkbBehaviorWireDesc *	wire = *wireRtrn;
174005b261ecSmrgregister XkbServerMapPtr	server = xkb->server;
174105b261ecSmrgregister unsigned	 	i;
174205b261ecSmrgunsigned			first,last;
174305b261ecSmrg
174405b261ecSmrg    if (((req->present&XkbKeyBehaviorsMask)==0)||(req->nKeyBehaviors<1)) {
174505b261ecSmrg	req->present&= ~XkbKeyBehaviorsMask;
174605b261ecSmrg	req->nKeyBehaviors= 0;
174705b261ecSmrg	return 1;
174805b261ecSmrg    }
174905b261ecSmrg    first= req->firstKeyBehavior;
175005b261ecSmrg    last=  req->firstKeyBehavior+req->nKeyBehaviors-1;
175105b261ecSmrg    if (first<req->minKeyCode) {
175205b261ecSmrg	*errorRtrn = _XkbErrCode3(0x31,first,req->minKeyCode);
175305b261ecSmrg	return 0;
175405b261ecSmrg    }
175505b261ecSmrg    if (last>req->maxKeyCode) {
175605b261ecSmrg	*errorRtrn = _XkbErrCode3(0x32,last,req->maxKeyCode);
175705b261ecSmrg	return 0;
175805b261ecSmrg    }
175905b261ecSmrg
176005b261ecSmrg    for (i=0;i<req->totalKeyBehaviors;i++,wire++) {
176105b261ecSmrg	if ((wire->key<first)||(wire->key>last)) {
176205b261ecSmrg	    *errorRtrn = _XkbErrCode4(0x33,first,last,wire->key);
176305b261ecSmrg	    return 0;
176405b261ecSmrg	}
176505b261ecSmrg	if ((wire->type&XkbKB_Permanent)&&
176605b261ecSmrg	    ((server->behaviors[wire->key].type!=wire->type)||
176705b261ecSmrg	     (server->behaviors[wire->key].data!=wire->data))) {
176805b261ecSmrg	    *errorRtrn = _XkbErrCode3(0x33,wire->key,wire->type);
176905b261ecSmrg	    return 0;
177005b261ecSmrg	}
177105b261ecSmrg	if ((wire->type==XkbKB_RadioGroup)&&
177205b261ecSmrg		((wire->data&(~XkbKB_RGAllowNone))>XkbMaxRadioGroups)) {
177305b261ecSmrg	    *errorRtrn= _XkbErrCode4(0x34,wire->key,wire->data,
177405b261ecSmrg							XkbMaxRadioGroups);
177505b261ecSmrg	    return 0;
177605b261ecSmrg	}
177705b261ecSmrg	if ((wire->type==XkbKB_Overlay1)||(wire->type==XkbKB_Overlay2)) {
177805b261ecSmrg	    CHK_KEY_RANGE2(0x35,wire->key,1,xkb,*errorRtrn,0);
177905b261ecSmrg	}
178005b261ecSmrg    }
178105b261ecSmrg    *wireRtrn = wire;
178205b261ecSmrg    return 1;
178305b261ecSmrg}
178405b261ecSmrg
178505b261ecSmrgstatic int
178605b261ecSmrgCheckVirtualMods(	XkbDescRec *	xkb,
178705b261ecSmrg			xkbSetMapReq *	req,
178805b261ecSmrg			CARD8 **	wireRtrn,
178905b261ecSmrg			int *		errorRtrn)
179005b261ecSmrg{
179105b261ecSmrgregister CARD8		*wire = *wireRtrn;
179205b261ecSmrgregister unsigned 	 i,nMods,bit;
179305b261ecSmrg
179405b261ecSmrg    if (((req->present&XkbVirtualModsMask)==0)||(req->virtualMods==0))
179505b261ecSmrg	return 1;
179605b261ecSmrg    for (i=nMods=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
179705b261ecSmrg	if (req->virtualMods&bit)
179805b261ecSmrg	    nMods++;
179905b261ecSmrg    }
180005b261ecSmrg    *wireRtrn= (wire+XkbPaddedSize(nMods));
180105b261ecSmrg    return 1;
180205b261ecSmrg}
180305b261ecSmrg
180405b261ecSmrgstatic int
180505b261ecSmrgCheckKeyExplicit(	XkbDescPtr	xkb,
180605b261ecSmrg			xkbSetMapReq *	req,
180705b261ecSmrg			CARD8 **	wireRtrn,
180805b261ecSmrg			int	*	errorRtrn)
180905b261ecSmrg{
181005b261ecSmrgregister CARD8 *	wire = *wireRtrn;
181105b261ecSmrgCARD8	*		start;
181205b261ecSmrgregister unsigned 	i;
181305b261ecSmrgint			first,last;
181405b261ecSmrg
181505b261ecSmrg    if (((req->present&XkbExplicitComponentsMask)==0)||(req->nKeyExplicit<1)) {
181605b261ecSmrg	req->present&= ~XkbExplicitComponentsMask;
181705b261ecSmrg	req->nKeyExplicit= 0;
181805b261ecSmrg	return 1;
181905b261ecSmrg    }
182005b261ecSmrg    first= req->firstKeyExplicit;
182105b261ecSmrg    last=  first+req->nKeyExplicit-1;
182205b261ecSmrg    if (first<req->minKeyCode) {
182305b261ecSmrg	*errorRtrn = _XkbErrCode3(0x51,first,req->minKeyCode);
182405b261ecSmrg	return 0;
182505b261ecSmrg    }
182605b261ecSmrg    if (last>req->maxKeyCode) {
182705b261ecSmrg	*errorRtrn = _XkbErrCode3(0x52,last,req->maxKeyCode);
182805b261ecSmrg	return 0;
182905b261ecSmrg    }
183005b261ecSmrg    start= wire;
183105b261ecSmrg    for (i=0;i<req->totalKeyExplicit;i++,wire+=2) {
183205b261ecSmrg	if ((wire[0]<first)||(wire[0]>last)) {
183305b261ecSmrg	    *errorRtrn = _XkbErrCode4(0x53,first,last,wire[0]);
183405b261ecSmrg	    return 0;
183505b261ecSmrg	}
183605b261ecSmrg	if (wire[1]&(~XkbAllExplicitMask)) {
183705b261ecSmrg	     *errorRtrn= _XkbErrCode3(0x52,~XkbAllExplicitMask,wire[1]);
183805b261ecSmrg	     return 0;
183905b261ecSmrg	}
184005b261ecSmrg    }
184105b261ecSmrg    wire+= XkbPaddedSize(wire-start)-(wire-start);
184205b261ecSmrg    *wireRtrn= wire;
184305b261ecSmrg    return 1;
184405b261ecSmrg}
184505b261ecSmrg
184605b261ecSmrgstatic int
184705b261ecSmrgCheckModifierMap(XkbDescPtr xkb,xkbSetMapReq *req,CARD8 **wireRtrn,int *errRtrn)
184805b261ecSmrg{
184905b261ecSmrgregister CARD8 *	wire = *wireRtrn;
185005b261ecSmrgCARD8	*		start;
185105b261ecSmrgregister unsigned 	i;
185205b261ecSmrgint			first,last;
185305b261ecSmrg
185405b261ecSmrg    if (((req->present&XkbModifierMapMask)==0)||(req->nModMapKeys<1)) {
185505b261ecSmrg	req->present&= ~XkbModifierMapMask;
185605b261ecSmrg	req->nModMapKeys= 0;
185705b261ecSmrg	return 1;
185805b261ecSmrg    }
185905b261ecSmrg    first= req->firstModMapKey;
186005b261ecSmrg    last=  first+req->nModMapKeys-1;
186105b261ecSmrg    if (first<req->minKeyCode) {
186205b261ecSmrg	*errRtrn = _XkbErrCode3(0x61,first,req->minKeyCode);
186305b261ecSmrg	return 0;
186405b261ecSmrg    }
186505b261ecSmrg    if (last>req->maxKeyCode) {
186605b261ecSmrg	*errRtrn = _XkbErrCode3(0x62,last,req->maxKeyCode);
186705b261ecSmrg	return 0;
186805b261ecSmrg    }
186905b261ecSmrg    start= wire;
187005b261ecSmrg    for (i=0;i<req->totalModMapKeys;i++,wire+=2) {
187105b261ecSmrg	if ((wire[0]<first)||(wire[0]>last)) {
187205b261ecSmrg	    *errRtrn = _XkbErrCode4(0x63,first,last,wire[0]);
187305b261ecSmrg	    return 0;
187405b261ecSmrg	}
187505b261ecSmrg    }
187605b261ecSmrg    wire+= XkbPaddedSize(wire-start)-(wire-start);
187705b261ecSmrg    *wireRtrn= wire;
187805b261ecSmrg    return 1;
187905b261ecSmrg}
188005b261ecSmrg
188105b261ecSmrgstatic int
188205b261ecSmrgCheckVirtualModMap(	XkbDescPtr xkb,
188305b261ecSmrg			xkbSetMapReq *req,
188405b261ecSmrg			xkbVModMapWireDesc **wireRtrn,
188505b261ecSmrg			int *errRtrn)
188605b261ecSmrg{
188705b261ecSmrgregister xkbVModMapWireDesc *	wire = *wireRtrn;
188805b261ecSmrgregister unsigned 		i;
188905b261ecSmrgint				first,last;
189005b261ecSmrg
189105b261ecSmrg    if (((req->present&XkbVirtualModMapMask)==0)||(req->nVModMapKeys<1)) {
189205b261ecSmrg	req->present&= ~XkbVirtualModMapMask;
189305b261ecSmrg	req->nVModMapKeys= 0;
189405b261ecSmrg	return 1;
189505b261ecSmrg    }
189605b261ecSmrg    first= req->firstVModMapKey;
189705b261ecSmrg    last=  first+req->nVModMapKeys-1;
189805b261ecSmrg    if (first<req->minKeyCode) {
189905b261ecSmrg	*errRtrn = _XkbErrCode3(0x71,first,req->minKeyCode);
190005b261ecSmrg	return 0;
190105b261ecSmrg    }
190205b261ecSmrg    if (last>req->maxKeyCode) {
190305b261ecSmrg	*errRtrn = _XkbErrCode3(0x72,last,req->maxKeyCode);
190405b261ecSmrg	return 0;
190505b261ecSmrg    }
190605b261ecSmrg    for (i=0;i<req->totalVModMapKeys;i++,wire++) {
190705b261ecSmrg	if ((wire->key<first)||(wire->key>last)) {
190805b261ecSmrg	    *errRtrn = _XkbErrCode4(0x73,first,last,wire->key);
190905b261ecSmrg	    return 0;
191005b261ecSmrg	}
191105b261ecSmrg    }
191205b261ecSmrg    *wireRtrn= wire;
191305b261ecSmrg    return 1;
191405b261ecSmrg}
191505b261ecSmrg
191605b261ecSmrgstatic char *
191705b261ecSmrgSetKeyTypes(	XkbDescPtr		xkb,
191805b261ecSmrg		xkbSetMapReq *		req,
191905b261ecSmrg		xkbKeyTypeWireDesc *	wire,
192005b261ecSmrg		XkbChangesPtr		changes)
192105b261ecSmrg{
192205b261ecSmrgregister unsigned	i;
192305b261ecSmrgunsigned		first,last;
192405b261ecSmrgCARD8			*map;
192505b261ecSmrg
192605b261ecSmrg    if ((unsigned)(req->firstType+req->nTypes)>xkb->map->size_types) {
192705b261ecSmrg	i= req->firstType+req->nTypes;
192805b261ecSmrg	if (XkbAllocClientMap(xkb,XkbKeyTypesMask,i)!=Success) {
192905b261ecSmrg	    return NULL;
193005b261ecSmrg	}
193105b261ecSmrg    }
193205b261ecSmrg    if ((unsigned)(req->firstType+req->nTypes)>xkb->map->num_types)
193305b261ecSmrg	xkb->map->num_types= req->firstType+req->nTypes;
193405b261ecSmrg
193505b261ecSmrg    for (i=0;i<req->nTypes;i++) {
193605b261ecSmrg	XkbKeyTypePtr		pOld;
193705b261ecSmrg	register unsigned 	n;
193805b261ecSmrg
193905b261ecSmrg	if (XkbResizeKeyType(xkb,i+req->firstType,wire->nMapEntries,
194005b261ecSmrg				wire->preserve,wire->numLevels)!=Success) {
194105b261ecSmrg	    return NULL;
194205b261ecSmrg	}
194305b261ecSmrg	pOld = &xkb->map->types[i+req->firstType];
194405b261ecSmrg	map = (CARD8 *)&wire[1];
194505b261ecSmrg
194605b261ecSmrg	pOld->mods.real_mods = wire->realMods;
194705b261ecSmrg	pOld->mods.vmods= wire->virtualMods;
194805b261ecSmrg	pOld->num_levels = wire->numLevels;
194905b261ecSmrg	pOld->map_count= wire->nMapEntries;
195005b261ecSmrg
195105b261ecSmrg	pOld->mods.mask= pOld->mods.real_mods|
195205b261ecSmrg					XkbMaskForVMask(xkb,pOld->mods.vmods);
195305b261ecSmrg
195405b261ecSmrg	if (wire->nMapEntries) {
195505b261ecSmrg	    xkbKTSetMapEntryWireDesc *mapWire;
195605b261ecSmrg	    xkbModsWireDesc *preWire;
195705b261ecSmrg	    unsigned tmp;
195805b261ecSmrg	    mapWire= (xkbKTSetMapEntryWireDesc *)map;
195905b261ecSmrg	    preWire= (xkbModsWireDesc *)&mapWire[wire->nMapEntries];
196005b261ecSmrg	    for (n=0;n<wire->nMapEntries;n++) {
196105b261ecSmrg		pOld->map[n].active= 1;
196205b261ecSmrg		pOld->map[n].mods.mask= mapWire[n].realMods;
196305b261ecSmrg		pOld->map[n].mods.real_mods= mapWire[n].realMods;
196405b261ecSmrg		pOld->map[n].mods.vmods= mapWire[n].virtualMods;
196505b261ecSmrg		pOld->map[n].level= mapWire[n].level;
196605b261ecSmrg		if (mapWire[n].virtualMods!=0) {
196705b261ecSmrg		    tmp= XkbMaskForVMask(xkb,mapWire[n].virtualMods);
196805b261ecSmrg		    pOld->map[n].active= (tmp!=0);
196905b261ecSmrg		    pOld->map[n].mods.mask|= tmp;
197005b261ecSmrg		}
197105b261ecSmrg		if (wire->preserve) {
197205b261ecSmrg		    pOld->preserve[n].real_mods= preWire[n].realMods;
197305b261ecSmrg		    pOld->preserve[n].vmods= preWire[n].virtualMods;
197405b261ecSmrg		    tmp= XkbMaskForVMask(xkb,preWire[n].virtualMods);
197505b261ecSmrg		    pOld->preserve[n].mask= preWire[n].realMods|tmp;
197605b261ecSmrg		}
197705b261ecSmrg	    }
197805b261ecSmrg	    if (wire->preserve)
197905b261ecSmrg		 map= (CARD8 *)&preWire[wire->nMapEntries];
198005b261ecSmrg	    else map= (CARD8 *)&mapWire[wire->nMapEntries];
198105b261ecSmrg	}
198205b261ecSmrg	else map= (CARD8 *)&wire[1];
198305b261ecSmrg	wire = (xkbKeyTypeWireDesc *)map;
198405b261ecSmrg    }
198505b261ecSmrg    first= req->firstType;
198605b261ecSmrg    last= first+req->nTypes-1; /* last changed type */
198705b261ecSmrg    if (changes->map.changed&XkbKeyTypesMask) {
198805b261ecSmrg	int oldLast;
198905b261ecSmrg	oldLast= changes->map.first_type+changes->map.num_types-1;
199005b261ecSmrg	if (changes->map.first_type<first)
199105b261ecSmrg	    first= changes->map.first_type;
199205b261ecSmrg	if (oldLast>last)
199305b261ecSmrg	    last= oldLast;
199405b261ecSmrg    }
199505b261ecSmrg    changes->map.changed|= XkbKeyTypesMask;
199605b261ecSmrg    changes->map.first_type = first;
199705b261ecSmrg    changes->map.num_types = (last-first)+1;
199805b261ecSmrg    return (char *)wire;
199905b261ecSmrg}
200005b261ecSmrg
200105b261ecSmrgstatic char *
200205b261ecSmrgSetKeySyms(	ClientPtr		client,
200305b261ecSmrg		XkbDescPtr		xkb,
200405b261ecSmrg		xkbSetMapReq *		req,
200505b261ecSmrg		xkbSymMapWireDesc *	wire,
200605b261ecSmrg		XkbChangesPtr 		changes,
200705b261ecSmrg		DeviceIntPtr		dev)
200805b261ecSmrg{
200905b261ecSmrgregister unsigned 	i,s;
201005b261ecSmrgXkbSymMapPtr		oldMap;
201105b261ecSmrgKeySym *		newSyms;
201205b261ecSmrgKeySym *		pSyms;
201305b261ecSmrgunsigned		first,last;
201405b261ecSmrg
201505b261ecSmrg    oldMap = &xkb->map->key_sym_map[req->firstKeySym];
201605b261ecSmrg    for (i=0;i<req->nKeySyms;i++,oldMap++) {
201705b261ecSmrg	pSyms = (KeySym *)&wire[1];
201805b261ecSmrg	if (wire->nSyms>0) {
201905b261ecSmrg	    newSyms = XkbResizeKeySyms(xkb,i+req->firstKeySym,wire->nSyms);
202005b261ecSmrg	    for (s=0;s<wire->nSyms;s++) {
202105b261ecSmrg		newSyms[s]= pSyms[s];
202205b261ecSmrg	    }
202305b261ecSmrg	    if (client->swapped) {
202405b261ecSmrg		int n;
202505b261ecSmrg		for (s=0;s<wire->nSyms;s++) {
202605b261ecSmrg		    swapl(&newSyms[s],n);
202705b261ecSmrg		}
202805b261ecSmrg	    }
202905b261ecSmrg	}
203005b261ecSmrg	oldMap->kt_index[0] = wire->ktIndex[0];
203105b261ecSmrg	oldMap->kt_index[1] = wire->ktIndex[1];
203205b261ecSmrg	oldMap->kt_index[2] = wire->ktIndex[2];
203305b261ecSmrg	oldMap->kt_index[3] = wire->ktIndex[3];
203405b261ecSmrg	oldMap->group_info = wire->groupInfo;
203505b261ecSmrg	oldMap->width = wire->width;
203605b261ecSmrg	wire= (xkbSymMapWireDesc *)&pSyms[wire->nSyms];
203705b261ecSmrg    }
203805b261ecSmrg    first= req->firstKeySym;
203905b261ecSmrg    last= first+req->nKeySyms-1;
204005b261ecSmrg    if (changes->map.changed&XkbKeySymsMask) {
204105b261ecSmrg	int oldLast= (changes->map.first_key_sym+changes->map.num_key_syms-1);
204205b261ecSmrg	if (changes->map.first_key_sym<first)
204305b261ecSmrg	    first= changes->map.first_key_sym;
204405b261ecSmrg	if (oldLast>last)
204505b261ecSmrg	    last= oldLast;
204605b261ecSmrg    }
204705b261ecSmrg    changes->map.changed|= XkbKeySymsMask;
204805b261ecSmrg    changes->map.first_key_sym = first;
204905b261ecSmrg    changes->map.num_key_syms = (last-first+1);
205005b261ecSmrg
205105b261ecSmrg    s= 0;
205205b261ecSmrg    for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
205305b261ecSmrg	if (XkbKeyNumGroups(xkb,i)>s)
205405b261ecSmrg	    s= XkbKeyNumGroups(xkb,i);
205505b261ecSmrg    }
205605b261ecSmrg    if (s!=xkb->ctrls->num_groups) {
205705b261ecSmrg	xkbControlsNotify	cn;
205805b261ecSmrg	XkbControlsRec		old;
205905b261ecSmrg	cn.keycode= 0;
206005b261ecSmrg	cn.eventType= 0;
206105b261ecSmrg	cn.requestMajor= XkbReqCode;
206205b261ecSmrg	cn.requestMinor= X_kbSetMap;
206305b261ecSmrg	old= *xkb->ctrls;
206405b261ecSmrg	xkb->ctrls->num_groups= s;
206505b261ecSmrg	if (XkbComputeControlsNotify(dev,&old,xkb->ctrls,&cn,False))
206605b261ecSmrg	    XkbSendControlsNotify(dev,&cn);
206705b261ecSmrg    }
206805b261ecSmrg    return (char *)wire;
206905b261ecSmrg}
207005b261ecSmrg
207105b261ecSmrgstatic char *
207205b261ecSmrgSetKeyActions(	XkbDescPtr	xkb,
207305b261ecSmrg		xkbSetMapReq *	req,
207405b261ecSmrg		CARD8 *		wire,
207505b261ecSmrg		XkbChangesPtr	changes)
207605b261ecSmrg{
207705b261ecSmrgregister unsigned	i,first,last;
207805b261ecSmrgCARD8 *			nActs = wire;
207905b261ecSmrgXkbAction *		newActs;
208005b261ecSmrg
208105b261ecSmrg    wire+= XkbPaddedSize(req->nKeyActs);
208205b261ecSmrg    for (i=0;i<req->nKeyActs;i++) {
208305b261ecSmrg	if (nActs[i]==0)
208405b261ecSmrg	    xkb->server->key_acts[i+req->firstKeyAct]= 0;
208505b261ecSmrg	else {
208605b261ecSmrg	    newActs= XkbResizeKeyActions(xkb,i+req->firstKeyAct,nActs[i]);
208705b261ecSmrg	    memcpy((char *)newActs,(char *)wire,
208805b261ecSmrg					nActs[i]*SIZEOF(xkbActionWireDesc));
208905b261ecSmrg	    wire+= nActs[i]*SIZEOF(xkbActionWireDesc);
209005b261ecSmrg	}
209105b261ecSmrg    }
209205b261ecSmrg    first= req->firstKeyAct;
209305b261ecSmrg    last= (first+req->nKeyActs-1);
209405b261ecSmrg    if (changes->map.changed&XkbKeyActionsMask) {
209505b261ecSmrg	int oldLast;
209605b261ecSmrg	oldLast= changes->map.first_key_act+changes->map.num_key_acts-1;
209705b261ecSmrg	if (changes->map.first_key_act<first)
209805b261ecSmrg	    first= changes->map.first_key_act;
209905b261ecSmrg	if (oldLast>last)
210005b261ecSmrg	    last= oldLast;
210105b261ecSmrg    }
210205b261ecSmrg    changes->map.changed|= XkbKeyActionsMask;
210305b261ecSmrg    changes->map.first_key_act= first;
210405b261ecSmrg    changes->map.num_key_acts= (last-first+1);
210505b261ecSmrg    return (char *)wire;
210605b261ecSmrg}
210705b261ecSmrg
210805b261ecSmrgstatic char *
210905b261ecSmrgSetKeyBehaviors(	XkbSrvInfoPtr	 xkbi,
211005b261ecSmrg    			xkbSetMapReq	*req,
211105b261ecSmrg    			xkbBehaviorWireDesc	*wire,
211205b261ecSmrg    			XkbChangesPtr	 changes)
211305b261ecSmrg{
211405b261ecSmrgregister unsigned i;
211505b261ecSmrgint maxRG = -1;
211605b261ecSmrgXkbDescPtr       xkb = xkbi->desc;
211705b261ecSmrgXkbServerMapPtr	 server = xkb->server;
211805b261ecSmrgunsigned	 first,last;
211905b261ecSmrg
212005b261ecSmrg    first= req->firstKeyBehavior;
212105b261ecSmrg    last= req->firstKeyBehavior+req->nKeyBehaviors-1;
212205b261ecSmrg    bzero(&server->behaviors[first],req->nKeyBehaviors*sizeof(XkbBehavior));
212305b261ecSmrg    for (i=0;i<req->totalKeyBehaviors;i++) {
212405b261ecSmrg	if ((server->behaviors[wire->key].type&XkbKB_Permanent)==0) {
212505b261ecSmrg	    server->behaviors[wire->key].type= wire->type;
212605b261ecSmrg	    server->behaviors[wire->key].data= wire->data;
212705b261ecSmrg	    if ((wire->type==XkbKB_RadioGroup)&&(((int)wire->data)>maxRG))
212805b261ecSmrg		maxRG= wire->data + 1;
212905b261ecSmrg	}
213005b261ecSmrg	wire++;
213105b261ecSmrg    }
213205b261ecSmrg
213305b261ecSmrg    if (maxRG>(int)xkbi->nRadioGroups) {
213405b261ecSmrg        int sz = maxRG*sizeof(XkbRadioGroupRec);
213505b261ecSmrg        if (xkbi->radioGroups)
213605b261ecSmrg             xkbi->radioGroups=(XkbRadioGroupPtr)_XkbRealloc(xkbi->radioGroups,sz);
213705b261ecSmrg        else xkbi->radioGroups= (XkbRadioGroupPtr)_XkbCalloc(1, sz);
213805b261ecSmrg        if (xkbi->radioGroups) {
213905b261ecSmrg             if (xkbi->nRadioGroups)
214005b261ecSmrg                bzero(&xkbi->radioGroups[xkbi->nRadioGroups],
214105b261ecSmrg                        (maxRG-xkbi->nRadioGroups)*sizeof(XkbRadioGroupRec));
214205b261ecSmrg             xkbi->nRadioGroups= maxRG;
214305b261ecSmrg        }
214405b261ecSmrg        else xkbi->nRadioGroups= 0;
214505b261ecSmrg        /* should compute members here */
214605b261ecSmrg    }
214705b261ecSmrg    if (changes->map.changed&XkbKeyBehaviorsMask) {
214805b261ecSmrg	unsigned oldLast;
214905b261ecSmrg	oldLast= changes->map.first_key_behavior+
215005b261ecSmrg					changes->map.num_key_behaviors-1;
215105b261ecSmrg        if (changes->map.first_key_behavior<req->firstKeyBehavior)
215205b261ecSmrg             first= changes->map.first_key_behavior;
215305b261ecSmrg        if (oldLast>last)
215405b261ecSmrg            last= oldLast;
215505b261ecSmrg    }
215605b261ecSmrg    changes->map.changed|= XkbKeyBehaviorsMask;
215705b261ecSmrg    changes->map.first_key_behavior = first;
215805b261ecSmrg    changes->map.num_key_behaviors = (last-first+1);
215905b261ecSmrg    return (char *)wire;
216005b261ecSmrg}
216105b261ecSmrg
216205b261ecSmrgstatic char *
216305b261ecSmrgSetVirtualMods(XkbSrvInfoPtr xkbi,xkbSetMapReq *req,CARD8 *wire,
216405b261ecSmrg						XkbChangesPtr changes)
216505b261ecSmrg{
216605b261ecSmrgregister int 		i,bit,nMods;
216705b261ecSmrgXkbServerMapPtr		srv = xkbi->desc->server;
216805b261ecSmrg
216905b261ecSmrg    if (((req->present&XkbVirtualModsMask)==0)||(req->virtualMods==0))
217005b261ecSmrg	return (char *)wire;
217105b261ecSmrg    for (i=nMods=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
217205b261ecSmrg	if (req->virtualMods&bit) {
217305b261ecSmrg	    if (srv->vmods[i]!=wire[nMods]) {
217405b261ecSmrg		changes->map.changed|= XkbVirtualModsMask;
217505b261ecSmrg		changes->map.vmods|= bit;
217605b261ecSmrg		srv->vmods[i]= wire[nMods];
217705b261ecSmrg	    }
217805b261ecSmrg	    nMods++;
217905b261ecSmrg	}
218005b261ecSmrg    }
218105b261ecSmrg    return (char *)(wire+XkbPaddedSize(nMods));
218205b261ecSmrg}
218305b261ecSmrg
218405b261ecSmrgstatic char *
218505b261ecSmrgSetKeyExplicit(XkbSrvInfoPtr xkbi,xkbSetMapReq *req,CARD8 *wire,
218605b261ecSmrg							XkbChangesPtr changes)
218705b261ecSmrg{
218805b261ecSmrgregister unsigned	i,first,last;
218905b261ecSmrgXkbServerMapPtr		xkb = xkbi->desc->server;
219005b261ecSmrgCARD8 *			start;
219105b261ecSmrg
219205b261ecSmrg    start= wire;
219305b261ecSmrg    first= req->firstKeyExplicit;
219405b261ecSmrg    last=  req->firstKeyExplicit+req->nKeyExplicit-1;
219505b261ecSmrg    bzero(&xkb->explicit[first],req->nKeyExplicit);
219605b261ecSmrg    for (i=0;i<req->totalKeyExplicit;i++,wire+= 2) {
219705b261ecSmrg	xkb->explicit[wire[0]]= wire[1];
219805b261ecSmrg    }
219905b261ecSmrg    if (first>0) {
220005b261ecSmrg	if (changes->map.changed&XkbExplicitComponentsMask) {
220105b261ecSmrg	    int oldLast;
220205b261ecSmrg	    oldLast= changes->map.first_key_explicit+
220305b261ecSmrg					changes->map.num_key_explicit-1;
220405b261ecSmrg	    if (changes->map.first_key_explicit<first)
220505b261ecSmrg		first= changes->map.first_key_explicit;
220605b261ecSmrg	    if (oldLast>last)
220705b261ecSmrg		last= oldLast;
220805b261ecSmrg	}
220905b261ecSmrg	changes->map.first_key_explicit= first;
221005b261ecSmrg	changes->map.num_key_explicit= (last-first)+1;
221105b261ecSmrg    }
221205b261ecSmrg    wire+= XkbPaddedSize(wire-start)-(wire-start);
221305b261ecSmrg    return (char *)wire;
221405b261ecSmrg}
221505b261ecSmrg
221605b261ecSmrgstatic char *
221705b261ecSmrgSetModifierMap(	XkbSrvInfoPtr	xkbi,
221805b261ecSmrg		xkbSetMapReq *	req,
221905b261ecSmrg		CARD8 *		wire,
222005b261ecSmrg		XkbChangesPtr	changes)
222105b261ecSmrg{
222205b261ecSmrgregister unsigned	i,first,last;
222305b261ecSmrgXkbClientMapPtr		xkb = xkbi->desc->map;
222405b261ecSmrgCARD8 *			start;
222505b261ecSmrg
222605b261ecSmrg    start= wire;
222705b261ecSmrg    first= req->firstModMapKey;
222805b261ecSmrg    last=  req->firstModMapKey+req->nModMapKeys-1;
222905b261ecSmrg    bzero(&xkb->modmap[first],req->nModMapKeys);
223005b261ecSmrg    for (i=0;i<req->totalModMapKeys;i++,wire+= 2) {
223105b261ecSmrg	xkb->modmap[wire[0]]= wire[1];
223205b261ecSmrg    }
223305b261ecSmrg    if (first>0) {
223405b261ecSmrg	if (changes->map.changed&XkbModifierMapMask) {
223505b261ecSmrg	    int oldLast;
223605b261ecSmrg	    oldLast= changes->map.first_modmap_key+
223705b261ecSmrg						changes->map.num_modmap_keys-1;
223805b261ecSmrg	    if (changes->map.first_modmap_key<first)
223905b261ecSmrg		first= changes->map.first_modmap_key;
224005b261ecSmrg	    if (oldLast>last)
224105b261ecSmrg		last= oldLast;
224205b261ecSmrg	}
224305b261ecSmrg	changes->map.first_modmap_key= first;
224405b261ecSmrg	changes->map.num_modmap_keys= (last-first)+1;
224505b261ecSmrg    }
224605b261ecSmrg    wire+= XkbPaddedSize(wire-start)-(wire-start);
224705b261ecSmrg    return (char *)wire;
224805b261ecSmrg}
224905b261ecSmrg
225005b261ecSmrgstatic char *
225105b261ecSmrgSetVirtualModMap(	XkbSrvInfoPtr		xkbi,
225205b261ecSmrg			xkbSetMapReq *		req,
225305b261ecSmrg			xkbVModMapWireDesc *	wire,
225405b261ecSmrg			XkbChangesPtr 		changes)
225505b261ecSmrg{
225605b261ecSmrgregister unsigned	i,first,last;
225705b261ecSmrgXkbServerMapPtr		srv = xkbi->desc->server;
225805b261ecSmrg
225905b261ecSmrg    first= req->firstVModMapKey;
226005b261ecSmrg    last=  req->firstVModMapKey+req->nVModMapKeys-1;
226105b261ecSmrg    bzero(&srv->vmodmap[first],req->nVModMapKeys*sizeof(unsigned short));
226205b261ecSmrg    for (i=0;i<req->totalVModMapKeys;i++,wire++) {
226305b261ecSmrg	srv->vmodmap[wire->key]= wire->vmods;
226405b261ecSmrg    }
226505b261ecSmrg    if (first>0) {
226605b261ecSmrg	if (changes->map.changed&XkbVirtualModMapMask) {
226705b261ecSmrg	    int oldLast;
226805b261ecSmrg	    oldLast= changes->map.first_vmodmap_key+
226905b261ecSmrg					changes->map.num_vmodmap_keys-1;
227005b261ecSmrg	    if (changes->map.first_vmodmap_key<first)
227105b261ecSmrg		first= changes->map.first_vmodmap_key;
227205b261ecSmrg	    if (oldLast>last)
227305b261ecSmrg		last= oldLast;
227405b261ecSmrg	}
227505b261ecSmrg	changes->map.first_vmodmap_key= first;
227605b261ecSmrg	changes->map.num_vmodmap_keys= (last-first)+1;
227705b261ecSmrg    }
227805b261ecSmrg    return (char *)wire;
227905b261ecSmrg}
228005b261ecSmrg
228105b261ecSmrg/* FIXME: Needs to set map on all core-sending devices. */
228205b261ecSmrgint
228305b261ecSmrgProcXkbSetMap(ClientPtr client)
228405b261ecSmrg{
228505b261ecSmrg    DeviceIntPtr	dev;
228605b261ecSmrg    XkbSrvInfoPtr	xkbi;
228705b261ecSmrg    XkbDescPtr		xkb;
228805b261ecSmrg    XkbChangesRec	change;
228905b261ecSmrg    XkbEventCauseRec	cause;
229005b261ecSmrg    int			nTypes = 0,nActions,error;
229105b261ecSmrg    char *		tmp;
229205b261ecSmrg    CARD8	 	mapWidths[XkbMaxLegalKeyCode+1];
229305b261ecSmrg    CARD16	 	symsPerKey[XkbMaxLegalKeyCode+1];
229405b261ecSmrg    Bool		sentNKN;
229505b261ecSmrg
229605b261ecSmrg    REQUEST(xkbSetMapReq);
229705b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetMapReq);
229805b261ecSmrg
229905b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
230005b261ecSmrg	return BadAccess;
230105b261ecSmrg
230205b261ecSmrg    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
230305b261ecSmrg    CHK_MASK_LEGAL(0x01,stuff->present,XkbAllMapComponentsMask);
230405b261ecSmrg
230505b261ecSmrg    XkbSetCauseXkbReq(&cause,X_kbSetMap,client);
230605b261ecSmrg    xkbi= dev->key->xkbInfo;
230705b261ecSmrg    xkb = xkbi->desc;
230805b261ecSmrg
230905b261ecSmrg    if ((xkb->min_key_code!=stuff->minKeyCode)||
231005b261ecSmrg    				(xkb->max_key_code!=stuff->maxKeyCode)) {
231105b261ecSmrg	if (client->vMajor!=1) { /* pre 1.0 versions of Xlib have a bug */
231205b261ecSmrg	    stuff->minKeyCode= xkb->min_key_code;
231305b261ecSmrg	    stuff->maxKeyCode= xkb->max_key_code;
231405b261ecSmrg	}
231505b261ecSmrg	else {
231605b261ecSmrg	    if (!XkbIsLegalKeycode(stuff->minKeyCode)) {
231705b261ecSmrg		client->errorValue= _XkbErrCode3(2,stuff->minKeyCode,
231805b261ecSmrg							stuff->maxKeyCode);
231905b261ecSmrg		return BadValue;
232005b261ecSmrg	    }
232105b261ecSmrg	    if (stuff->minKeyCode>stuff->maxKeyCode) {
232205b261ecSmrg		client->errorValue= _XkbErrCode3(3,stuff->minKeyCode,
232305b261ecSmrg							stuff->maxKeyCode);
232405b261ecSmrg		return BadMatch;
232505b261ecSmrg	    }
232605b261ecSmrg	}
232705b261ecSmrg    }
232805b261ecSmrg
232905b261ecSmrg    tmp = (char *)&stuff[1];
233005b261ecSmrg    if ((stuff->present&XkbKeyTypesMask)&&
233105b261ecSmrg	(!CheckKeyTypes(client,xkb,stuff,(xkbKeyTypeWireDesc **)&tmp,
233205b261ecSmrg						&nTypes,mapWidths))) {
233305b261ecSmrg	client->errorValue = nTypes;
233405b261ecSmrg	return BadValue;
233505b261ecSmrg    }
233605b261ecSmrg    if ((stuff->present&XkbKeySymsMask)&&
233705b261ecSmrg	(!CheckKeySyms(client,xkb,stuff,nTypes,mapWidths,symsPerKey,
233805b261ecSmrg					(xkbSymMapWireDesc **)&tmp,&error))) {
233905b261ecSmrg	client->errorValue = error;
234005b261ecSmrg	return BadValue;
234105b261ecSmrg    }
234205b261ecSmrg
234305b261ecSmrg    if ((stuff->present&XkbKeyActionsMask)&&
234405b261ecSmrg	(!CheckKeyActions(xkb,stuff,nTypes,mapWidths,symsPerKey,
234505b261ecSmrg						(CARD8 **)&tmp,&nActions))) {
234605b261ecSmrg	client->errorValue = nActions;
234705b261ecSmrg	return BadValue;
234805b261ecSmrg    }
234905b261ecSmrg
235005b261ecSmrg    if ((stuff->present&XkbKeyBehaviorsMask)&&
235105b261ecSmrg	(!CheckKeyBehaviors(xkb,stuff,(xkbBehaviorWireDesc**)&tmp,&error))) {
235205b261ecSmrg	client->errorValue = error;
235305b261ecSmrg	return BadValue;
235405b261ecSmrg    }
235505b261ecSmrg
235605b261ecSmrg    if ((stuff->present&XkbVirtualModsMask)&&
235705b261ecSmrg	(!CheckVirtualMods(xkb,stuff,(CARD8 **)&tmp,&error))) {
235805b261ecSmrg	client->errorValue= error;
235905b261ecSmrg	return BadValue;
236005b261ecSmrg    }
236105b261ecSmrg    if ((stuff->present&XkbExplicitComponentsMask)&&
236205b261ecSmrg	(!CheckKeyExplicit(xkb,stuff,(CARD8 **)&tmp,&error))) {
236305b261ecSmrg	client->errorValue= error;
236405b261ecSmrg	return BadValue;
236505b261ecSmrg    }
236605b261ecSmrg    if ((stuff->present&XkbModifierMapMask)&&
236705b261ecSmrg	(!CheckModifierMap(xkb,stuff,(CARD8 **)&tmp,&error))) {
236805b261ecSmrg	client->errorValue= error;
236905b261ecSmrg	return BadValue;
237005b261ecSmrg    }
237105b261ecSmrg    if ((stuff->present&XkbVirtualModMapMask)&&
237205b261ecSmrg	(!CheckVirtualModMap(xkb,stuff,(xkbVModMapWireDesc **)&tmp,&error))) {
237305b261ecSmrg	client->errorValue= error;
237405b261ecSmrg	return BadValue;
237505b261ecSmrg    }
237605b261ecSmrg    if (((tmp-((char *)stuff))/4)!=stuff->length) {
237705b261ecSmrg	ErrorF("Internal error! Bad length in XkbSetMap (after check)\n");
237805b261ecSmrg	client->errorValue = tmp-((char *)&stuff[1]);
237905b261ecSmrg	return BadLength;
238005b261ecSmrg    }
238105b261ecSmrg    bzero(&change,sizeof(change));
238205b261ecSmrg    sentNKN= False;
238305b261ecSmrg    if ((xkb->min_key_code!=stuff->minKeyCode)||
238405b261ecSmrg    				(xkb->max_key_code!=stuff->maxKeyCode)) {
238505b261ecSmrg	Status			status;
238605b261ecSmrg	xkbNewKeyboardNotify	nkn;
238705b261ecSmrg	nkn.deviceID= nkn.oldDeviceID= dev->id;
238805b261ecSmrg	nkn.oldMinKeyCode= xkb->min_key_code;
238905b261ecSmrg	nkn.oldMaxKeyCode= xkb->max_key_code;
239005b261ecSmrg	status= XkbChangeKeycodeRange(xkb,stuff->minKeyCode,stuff->maxKeyCode,
239105b261ecSmrg								&change);
239205b261ecSmrg	if (status!=Success)
239305b261ecSmrg	    return status;
239405b261ecSmrg	nkn.minKeyCode= xkb->min_key_code;
239505b261ecSmrg	nkn.maxKeyCode= xkb->max_key_code;
239605b261ecSmrg	nkn.requestMajor= XkbReqCode;
239705b261ecSmrg	nkn.requestMinor= X_kbSetMap;
239805b261ecSmrg	nkn.changed= XkbNKN_KeycodesMask;
239905b261ecSmrg	XkbSendNewKeyboardNotify(dev,&nkn);
240005b261ecSmrg	sentNKN= True;
240105b261ecSmrg    }
240205b261ecSmrg    tmp = (char *)&stuff[1];
240305b261ecSmrg    if (stuff->present&XkbKeyTypesMask) {
240405b261ecSmrg	tmp = SetKeyTypes(xkb,stuff,(xkbKeyTypeWireDesc *)tmp,&change);
240505b261ecSmrg	if (!tmp)	goto allocFailure;
240605b261ecSmrg    }
240705b261ecSmrg    if (stuff->present&XkbKeySymsMask) {
240805b261ecSmrg	tmp = SetKeySyms(client,xkb,stuff,(xkbSymMapWireDesc *)tmp,&change,dev);
240905b261ecSmrg	if (!tmp)	goto allocFailure;
241005b261ecSmrg    }
241105b261ecSmrg    if (stuff->present&XkbKeyActionsMask) {
241205b261ecSmrg	tmp = SetKeyActions(xkb,stuff,(CARD8 *)tmp,&change);
241305b261ecSmrg	if (!tmp)	goto allocFailure;
241405b261ecSmrg    }
241505b261ecSmrg    if (stuff->present&XkbKeyBehaviorsMask) {
241605b261ecSmrg	tmp= SetKeyBehaviors(xkbi,stuff,(xkbBehaviorWireDesc *)tmp,&change);
241705b261ecSmrg	if (!tmp)	goto allocFailure;
241805b261ecSmrg    }
241905b261ecSmrg    if (stuff->present&XkbVirtualModsMask)
242005b261ecSmrg	tmp= SetVirtualMods(xkbi,stuff,(CARD8 *)tmp,&change);
242105b261ecSmrg    if (stuff->present&XkbExplicitComponentsMask)
242205b261ecSmrg	tmp= SetKeyExplicit(xkbi,stuff,(CARD8 *)tmp,&change);
242305b261ecSmrg    if (stuff->present&XkbModifierMapMask)
242405b261ecSmrg	tmp= SetModifierMap(xkbi,stuff,(CARD8 *)tmp,&change);
242505b261ecSmrg    if (stuff->present&XkbVirtualModMapMask)
242605b261ecSmrg	tmp= SetVirtualModMap(xkbi,stuff,(xkbVModMapWireDesc *)tmp,&change);
242705b261ecSmrg    if (((tmp-((char *)stuff))/4)!=stuff->length) {
242805b261ecSmrg	ErrorF("Internal error! Bad length in XkbSetMap (after set)\n");
242905b261ecSmrg	client->errorValue = tmp-((char *)&stuff[1]);
243005b261ecSmrg	return BadLength;
243105b261ecSmrg    }
243205b261ecSmrg    if (stuff->flags&XkbSetMapRecomputeActions) {
243305b261ecSmrg	KeyCode		first,last,firstMM,lastMM;
243405b261ecSmrg	if (change.map.num_key_syms>0) {
243505b261ecSmrg	    first= change.map.first_key_sym;
243605b261ecSmrg	    last= first+change.map.num_key_syms-1;
243705b261ecSmrg	}
243805b261ecSmrg	else first= last= 0;
243905b261ecSmrg	if (change.map.num_modmap_keys>0) {
244005b261ecSmrg	    firstMM= change.map.first_modmap_key;
244105b261ecSmrg	    lastMM= first+change.map.num_modmap_keys-1;
244205b261ecSmrg	}
244305b261ecSmrg	else firstMM= lastMM= 0;
244405b261ecSmrg	if ((last>0) && (lastMM>0)) {
244505b261ecSmrg	    if (firstMM<first)
244605b261ecSmrg		first= firstMM;
244705b261ecSmrg	    if (lastMM>last)
244805b261ecSmrg		last= lastMM;
244905b261ecSmrg	}
245005b261ecSmrg	else if (lastMM>0) {
245105b261ecSmrg	    first= firstMM;
245205b261ecSmrg	    last= lastMM;
245305b261ecSmrg	}
245405b261ecSmrg	if (last>0) {
245505b261ecSmrg	    unsigned check= 0;
245605b261ecSmrg	    XkbUpdateActions(dev,first,(last-first+1),&change,&check,&cause);
245705b261ecSmrg	    if (check)
245805b261ecSmrg		XkbCheckSecondaryEffects(xkbi,check,&change,&cause);
245905b261ecSmrg	}
246005b261ecSmrg    }
246105b261ecSmrg    if (!sentNKN)
246205b261ecSmrg	XkbSendNotification(dev,&change,&cause);
246305b261ecSmrg
246405b261ecSmrg    XkbUpdateCoreDescription(dev,False);
246505b261ecSmrg    return client->noClientException;
246605b261ecSmrgallocFailure:
246705b261ecSmrg    return BadAlloc;
246805b261ecSmrg}
246905b261ecSmrg
247005b261ecSmrg/***====================================================================***/
247105b261ecSmrg
247205b261ecSmrgstatic Status
247305b261ecSmrgXkbComputeGetCompatMapReplySize(	XkbCompatMapPtr 	compat,
247405b261ecSmrg					xkbGetCompatMapReply *	rep)
247505b261ecSmrg{
247605b261ecSmrgunsigned	 size,nGroups;
247705b261ecSmrg
247805b261ecSmrg    nGroups= 0;
247905b261ecSmrg    if (rep->groups!=0) {
248005b261ecSmrg	register int i,bit;
248105b261ecSmrg	for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
248205b261ecSmrg	    if (rep->groups&bit)
248305b261ecSmrg		nGroups++;
248405b261ecSmrg	}
248505b261ecSmrg    }
248605b261ecSmrg    size= nGroups*SIZEOF(xkbModsWireDesc);
248705b261ecSmrg    size+= (rep->nSI*SIZEOF(xkbSymInterpretWireDesc));
248805b261ecSmrg    rep->length= size/4;
248905b261ecSmrg    return Success;
249005b261ecSmrg}
249105b261ecSmrg
249205b261ecSmrgstatic int
249305b261ecSmrgXkbSendCompatMap(	ClientPtr 		client,
249405b261ecSmrg			XkbCompatMapPtr 	compat,
249505b261ecSmrg			xkbGetCompatMapReply *	rep)
249605b261ecSmrg{
249705b261ecSmrgchar	*	data;
249805b261ecSmrgint		size;
249905b261ecSmrg
250005b261ecSmrg    size= rep->length*4;
250105b261ecSmrg    if (size>0) {
250205b261ecSmrg	data = (char *)ALLOCATE_LOCAL(size);
250305b261ecSmrg	if (data) {
250405b261ecSmrg	    register unsigned i,bit;
250505b261ecSmrg	    xkbModsWireDesc *	grp;
250605b261ecSmrg	    XkbSymInterpretPtr	sym= &compat->sym_interpret[rep->firstSI];
250705b261ecSmrg	    xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data;
250805b261ecSmrg	    for (i=0;i<rep->nSI;i++,sym++,wire++) {
250905b261ecSmrg		wire->sym= sym->sym;
251005b261ecSmrg		wire->mods= sym->mods;
251105b261ecSmrg		wire->match= sym->match;
251205b261ecSmrg		wire->virtualMod= sym->virtual_mod;
251305b261ecSmrg		wire->flags= sym->flags;
251405b261ecSmrg		memcpy((char*)&wire->act,(char*)&sym->act,sz_xkbActionWireDesc);
251505b261ecSmrg		if (client->swapped) {
251605b261ecSmrg		    register int n;
251705b261ecSmrg		    swapl(&wire->sym,n);
251805b261ecSmrg		}
251905b261ecSmrg	    }
252005b261ecSmrg	    if (rep->groups) {
252105b261ecSmrg		grp = (xkbModsWireDesc *)wire;
252205b261ecSmrg		for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
252305b261ecSmrg		    if (rep->groups&bit) {
252405b261ecSmrg			grp->mask= compat->groups[i].mask;
252505b261ecSmrg			grp->realMods= compat->groups[i].real_mods;
252605b261ecSmrg			grp->virtualMods= compat->groups[i].vmods;
252705b261ecSmrg			if (client->swapped) {
252805b261ecSmrg			    register int n;
252905b261ecSmrg			    swaps(&grp->virtualMods,n);
253005b261ecSmrg			}
253105b261ecSmrg			grp++;
253205b261ecSmrg		    }
253305b261ecSmrg		}
253405b261ecSmrg		wire= (xkbSymInterpretWireDesc*)grp;
253505b261ecSmrg	    }
253605b261ecSmrg	}
253705b261ecSmrg	else return BadAlloc;
253805b261ecSmrg    }
253905b261ecSmrg    else data= NULL;
254005b261ecSmrg
254105b261ecSmrg    if (client->swapped) {
254205b261ecSmrg	register int n;
254305b261ecSmrg	swaps(&rep->sequenceNumber,n);
254405b261ecSmrg	swapl(&rep->length,n);
254505b261ecSmrg	swaps(&rep->firstSI,n);
254605b261ecSmrg	swaps(&rep->nSI,n);
254705b261ecSmrg	swaps(&rep->nTotalSI,n);
254805b261ecSmrg    }
254905b261ecSmrg
255005b261ecSmrg    WriteToClient(client, SIZEOF(xkbGetCompatMapReply), (char *)rep);
255105b261ecSmrg    if (data) {
255205b261ecSmrg	WriteToClient(client, size, data);
255305b261ecSmrg	DEALLOCATE_LOCAL((char *)data);
255405b261ecSmrg    }
255505b261ecSmrg    return client->noClientException;
255605b261ecSmrg}
255705b261ecSmrg
255805b261ecSmrgint
255905b261ecSmrgProcXkbGetCompatMap(ClientPtr client)
256005b261ecSmrg{
256105b261ecSmrg    xkbGetCompatMapReply 	rep;
256205b261ecSmrg    DeviceIntPtr 		dev;
256305b261ecSmrg    XkbDescPtr			xkb;
256405b261ecSmrg    XkbCompatMapPtr		compat;
256505b261ecSmrg
256605b261ecSmrg    REQUEST(xkbGetCompatMapReq);
256705b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetCompatMapReq);
256805b261ecSmrg
256905b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
257005b261ecSmrg	return BadAccess;
257105b261ecSmrg
257205b261ecSmrg    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
257305b261ecSmrg
257405b261ecSmrg    xkb = dev->key->xkbInfo->desc;
257505b261ecSmrg    compat= xkb->compat;
257605b261ecSmrg
257705b261ecSmrg    rep.type = X_Reply;
257805b261ecSmrg    rep.deviceID = dev->id;
257905b261ecSmrg    rep.sequenceNumber = client->sequence;
258005b261ecSmrg    rep.length = 0;
258105b261ecSmrg    rep.firstSI = stuff->firstSI;
258205b261ecSmrg    rep.nSI = stuff->nSI;
258305b261ecSmrg    if (stuff->getAllSI) {
258405b261ecSmrg	rep.firstSI = 0;
258505b261ecSmrg	rep.nSI = compat->num_si;
258605b261ecSmrg    }
258705b261ecSmrg    else if ((((unsigned)stuff->nSI)>0)&&
258805b261ecSmrg		((unsigned)(stuff->firstSI+stuff->nSI-1)>=compat->num_si)) {
258905b261ecSmrg	client->errorValue = _XkbErrCode2(0x05,compat->num_si);
259005b261ecSmrg	return BadValue;
259105b261ecSmrg    }
259205b261ecSmrg    rep.nTotalSI = compat->num_si;
259305b261ecSmrg    rep.groups= stuff->groups;
259405b261ecSmrg    XkbComputeGetCompatMapReplySize(compat,&rep);
259505b261ecSmrg    return XkbSendCompatMap(client,compat,&rep);
259605b261ecSmrg}
259705b261ecSmrg
259805b261ecSmrg/* FIXME: Needs to set compat map on all core-sending devices. */
259905b261ecSmrgint
260005b261ecSmrgProcXkbSetCompatMap(ClientPtr client)
260105b261ecSmrg{
260205b261ecSmrg    DeviceIntPtr 	dev;
260305b261ecSmrg    XkbSrvInfoPtr 	xkbi;
260405b261ecSmrg    XkbDescPtr		xkb;
260505b261ecSmrg    XkbCompatMapPtr 	compat;
260605b261ecSmrg    char	*	data;
260705b261ecSmrg    int		 	nGroups;
260805b261ecSmrg    register unsigned	i,bit;
260905b261ecSmrg
261005b261ecSmrg    REQUEST(xkbSetCompatMapReq);
261105b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq);
261205b261ecSmrg
261305b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
261405b261ecSmrg	return BadAccess;
261505b261ecSmrg
261605b261ecSmrg    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
261705b261ecSmrg
261805b261ecSmrg    data = (char *)&stuff[1];
261905b261ecSmrg    xkbi = dev->key->xkbInfo;
262005b261ecSmrg    xkb= xkbi->desc;
262105b261ecSmrg    compat= xkb->compat;
262205b261ecSmrg    if ((stuff->nSI>0)||(stuff->truncateSI)) {
262305b261ecSmrg	xkbSymInterpretWireDesc *wire;
262405b261ecSmrg	if (stuff->firstSI>compat->num_si) {
262505b261ecSmrg	    client->errorValue = _XkbErrCode2(0x02,compat->num_si);
262605b261ecSmrg	    return BadValue;
262705b261ecSmrg	}
262805b261ecSmrg	wire= (xkbSymInterpretWireDesc *)data;
262905b261ecSmrg	wire+= stuff->nSI;
263005b261ecSmrg	data = (char *)wire;
263105b261ecSmrg    }
263205b261ecSmrg    nGroups= 0;
263305b261ecSmrg    if (stuff->groups!=0) {
263405b261ecSmrg	for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
263505b261ecSmrg	    if ( stuff->groups&bit )
263605b261ecSmrg		nGroups++;
263705b261ecSmrg	}
263805b261ecSmrg    }
263905b261ecSmrg    data+= nGroups*SIZEOF(xkbModsWireDesc);
264005b261ecSmrg    if (((data-((char *)stuff))/4)!=stuff->length) {
264105b261ecSmrg	return BadLength;
264205b261ecSmrg    }
264305b261ecSmrg    data = (char *)&stuff[1];
264405b261ecSmrg    if (stuff->nSI>0) {
264505b261ecSmrg	xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data;
264605b261ecSmrg	XkbSymInterpretPtr	sym;
264705b261ecSmrg	if ((unsigned)(stuff->firstSI+stuff->nSI)>compat->num_si) {
264805b261ecSmrg	    compat->num_si= stuff->firstSI+stuff->nSI;
264905b261ecSmrg	    compat->sym_interpret= _XkbTypedRealloc(compat->sym_interpret,
265005b261ecSmrg						   compat->num_si,
265105b261ecSmrg						   XkbSymInterpretRec);
265205b261ecSmrg	    if (!compat->sym_interpret) {
265305b261ecSmrg		compat->num_si= 0;
265405b261ecSmrg		return BadAlloc;
265505b261ecSmrg	    }
265605b261ecSmrg	}
265705b261ecSmrg	else if (stuff->truncateSI) {
265805b261ecSmrg	    compat->num_si = stuff->firstSI+stuff->nSI;
265905b261ecSmrg	}
266005b261ecSmrg	sym = &compat->sym_interpret[stuff->firstSI];
266105b261ecSmrg	for (i=0;i<stuff->nSI;i++,wire++,sym++) {
266205b261ecSmrg	    if (client->swapped) {
266305b261ecSmrg		register int n;
266405b261ecSmrg		swapl(&wire->sym,n);
266505b261ecSmrg	    }
266605b261ecSmrg	    sym->sym= wire->sym;
266705b261ecSmrg	    sym->mods= wire->mods;
266805b261ecSmrg	    sym->match= wire->match;
266905b261ecSmrg	    sym->flags= wire->flags;
267005b261ecSmrg	    sym->virtual_mod= wire->virtualMod;
267105b261ecSmrg	    memcpy((char *)&sym->act,(char *)&wire->act,
267205b261ecSmrg	    					SIZEOF(xkbActionWireDesc));
267305b261ecSmrg	}
267405b261ecSmrg	data = (char *)wire;
267505b261ecSmrg    }
267605b261ecSmrg    else if (stuff->truncateSI) {
267705b261ecSmrg	compat->num_si = stuff->firstSI;
267805b261ecSmrg    }
267905b261ecSmrg
268005b261ecSmrg    if (stuff->groups!=0) {
268105b261ecSmrg	register unsigned i,bit;
268205b261ecSmrg	xkbModsWireDesc *wire = (xkbModsWireDesc *)data;
268305b261ecSmrg	for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
268405b261ecSmrg	    if (stuff->groups&bit) {
268505b261ecSmrg		if (client->swapped) {
268605b261ecSmrg		    register int n;
268705b261ecSmrg		    swaps(&wire->virtualMods,n);
268805b261ecSmrg		}
268905b261ecSmrg		compat->groups[i].mask= wire->realMods;
269005b261ecSmrg		compat->groups[i].real_mods= wire->realMods;
269105b261ecSmrg		compat->groups[i].vmods= wire->virtualMods;
269205b261ecSmrg		if (wire->virtualMods!=0) {
269305b261ecSmrg		    unsigned tmp;
269405b261ecSmrg		    tmp= XkbMaskForVMask(xkb,wire->virtualMods);
269505b261ecSmrg		    compat->groups[i].mask|= tmp;
269605b261ecSmrg		}
269705b261ecSmrg		data+= SIZEOF(xkbModsWireDesc);
269805b261ecSmrg		wire= (xkbModsWireDesc *)data;
269905b261ecSmrg	    }
270005b261ecSmrg	}
270105b261ecSmrg    }
270205b261ecSmrg    i= XkbPaddedSize((data-((char *)stuff)));
270305b261ecSmrg    if ((i/4)!=stuff->length) {
270405b261ecSmrg	ErrorF("Internal length error on read in ProcXkbSetCompatMap\n");
270505b261ecSmrg	return BadLength;
270605b261ecSmrg    }
270705b261ecSmrg
270805b261ecSmrg    if (dev->xkb_interest) {
270905b261ecSmrg	xkbCompatMapNotify ev;
271005b261ecSmrg	ev.deviceID = dev->id;
271105b261ecSmrg	ev.changedGroups = stuff->groups;
271205b261ecSmrg	ev.firstSI = stuff->firstSI;
271305b261ecSmrg	ev.nSI = stuff->nSI;
271405b261ecSmrg	ev.nTotalSI = compat->num_si;
271505b261ecSmrg	XkbSendCompatMapNotify(dev,&ev);
271605b261ecSmrg    }
271705b261ecSmrg
271805b261ecSmrg    if (stuff->recomputeActions) {
271905b261ecSmrg	XkbChangesRec		change;
272005b261ecSmrg	unsigned		check;
272105b261ecSmrg	XkbEventCauseRec	cause;
272205b261ecSmrg
272305b261ecSmrg	XkbSetCauseXkbReq(&cause,X_kbSetCompatMap,client);
272405b261ecSmrg	bzero(&change,sizeof(XkbChangesRec));
272505b261ecSmrg	XkbUpdateActions(dev,xkb->min_key_code,XkbNumKeys(xkb),&change,&check,
272605b261ecSmrg									&cause);
272705b261ecSmrg	if (check)
272805b261ecSmrg	    XkbCheckSecondaryEffects(xkbi,check,&change,&cause);
272905b261ecSmrg	XkbUpdateCoreDescription(dev,False);
273005b261ecSmrg	XkbSendNotification(dev,&change,&cause);
273105b261ecSmrg    }
273205b261ecSmrg    return client->noClientException;
273305b261ecSmrg}
273405b261ecSmrg
273505b261ecSmrg/***====================================================================***/
273605b261ecSmrg
273705b261ecSmrgint
273805b261ecSmrgProcXkbGetIndicatorState(ClientPtr client)
273905b261ecSmrg{
274005b261ecSmrg    xkbGetIndicatorStateReply 	rep;
274105b261ecSmrg    XkbSrvLedInfoPtr		sli;
274205b261ecSmrg    DeviceIntPtr 		dev;
274305b261ecSmrg    register int 		i;
274405b261ecSmrg
274505b261ecSmrg    REQUEST(xkbGetIndicatorStateReq);
274605b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq);
274705b261ecSmrg
274805b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
274905b261ecSmrg	return BadAccess;
275005b261ecSmrg
275105b261ecSmrg    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
275205b261ecSmrg
275305b261ecSmrg    sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,
275405b261ecSmrg						XkbXI_IndicatorStateMask);
275505b261ecSmrg    if (!sli)
275605b261ecSmrg	return BadAlloc;
275705b261ecSmrg
275805b261ecSmrg    rep.type = X_Reply;
275905b261ecSmrg    rep.sequenceNumber = client->sequence;
276005b261ecSmrg    rep.length = 0;
276105b261ecSmrg    rep.deviceID = dev->id;
276205b261ecSmrg    rep.state = sli->effectiveState;
276305b261ecSmrg
276405b261ecSmrg    if (client->swapped) {
276505b261ecSmrg	swaps(&rep.sequenceNumber,i);
276605b261ecSmrg	swapl(&rep.state,i);
276705b261ecSmrg    }
276805b261ecSmrg    WriteToClient(client, SIZEOF(xkbGetIndicatorStateReply), (char *)&rep);
276905b261ecSmrg    return client->noClientException;
277005b261ecSmrg}
277105b261ecSmrg
277205b261ecSmrg/***====================================================================***/
277305b261ecSmrg
277405b261ecSmrgstatic Status
277505b261ecSmrgXkbComputeGetIndicatorMapReplySize(
277605b261ecSmrg    XkbIndicatorPtr		indicators,
277705b261ecSmrg    xkbGetIndicatorMapReply	*rep)
277805b261ecSmrg{
277905b261ecSmrgregister int 	i,bit;
278005b261ecSmrgint		nIndicators;
278105b261ecSmrg
278205b261ecSmrg    rep->realIndicators = indicators->phys_indicators;
278305b261ecSmrg    for (i=nIndicators=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
278405b261ecSmrg	if (rep->which&bit)
278505b261ecSmrg	    nIndicators++;
278605b261ecSmrg    }
278705b261ecSmrg    rep->length = (nIndicators*SIZEOF(xkbIndicatorMapWireDesc))/4;
278805b261ecSmrg    return Success;
278905b261ecSmrg}
279005b261ecSmrg
279105b261ecSmrgstatic int
279205b261ecSmrgXkbSendIndicatorMap(	ClientPtr			client,
279305b261ecSmrg			XkbIndicatorPtr			indicators,
279405b261ecSmrg			xkbGetIndicatorMapReply *	rep)
279505b261ecSmrg{
279605b261ecSmrgint 			length;
279705b261ecSmrgCARD8 *			map;
279805b261ecSmrgregister int		i;
279905b261ecSmrgregister unsigned	bit;
280005b261ecSmrg
280105b261ecSmrg    length = rep->length*4;
280205b261ecSmrg    if (length>0) {
280305b261ecSmrg	CARD8 *to;
280405b261ecSmrg	to= map= (CARD8 *)ALLOCATE_LOCAL(length);
280505b261ecSmrg	if (map) {
280605b261ecSmrg	    xkbIndicatorMapWireDesc  *wire = (xkbIndicatorMapWireDesc *)to;
280705b261ecSmrg	    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
280805b261ecSmrg		if (rep->which&bit) {
280905b261ecSmrg		    wire->flags= indicators->maps[i].flags;
281005b261ecSmrg		    wire->whichGroups= indicators->maps[i].which_groups;
281105b261ecSmrg		    wire->groups= indicators->maps[i].groups;
281205b261ecSmrg		    wire->whichMods= indicators->maps[i].which_mods;
281305b261ecSmrg		    wire->mods= indicators->maps[i].mods.mask;
281405b261ecSmrg		    wire->realMods= indicators->maps[i].mods.real_mods;
281505b261ecSmrg		    wire->virtualMods= indicators->maps[i].mods.vmods;
281605b261ecSmrg		    wire->ctrls= indicators->maps[i].ctrls;
281705b261ecSmrg		    if (client->swapped) {
281805b261ecSmrg			register int n;
281905b261ecSmrg			swaps(&wire->virtualMods,n);
282005b261ecSmrg			swapl(&wire->ctrls,n);
282105b261ecSmrg		    }
282205b261ecSmrg		    wire++;
282305b261ecSmrg		}
282405b261ecSmrg	    }
282505b261ecSmrg	    to = (CARD8 *)wire;
282605b261ecSmrg	    if ((to-map)!=length) {
282705b261ecSmrg		client->errorValue = _XkbErrCode2(0xff,length);
282805b261ecSmrg		return BadLength;
282905b261ecSmrg	    }
283005b261ecSmrg	}
283105b261ecSmrg	else return BadAlloc;
283205b261ecSmrg    }
283305b261ecSmrg    else map = NULL;
283405b261ecSmrg    if (client->swapped) {
283505b261ecSmrg	swaps(&rep->sequenceNumber,i);
283605b261ecSmrg	swapl(&rep->length,i);
283705b261ecSmrg	swapl(&rep->which,i);
283805b261ecSmrg	swapl(&rep->realIndicators,i);
283905b261ecSmrg    }
284005b261ecSmrg    WriteToClient(client, SIZEOF(xkbGetIndicatorMapReply), (char *)rep);
284105b261ecSmrg    if (map) {
284205b261ecSmrg	WriteToClient(client, length, (char *)map);
284305b261ecSmrg	DEALLOCATE_LOCAL((char *)map);
284405b261ecSmrg    }
284505b261ecSmrg    return client->noClientException;
284605b261ecSmrg}
284705b261ecSmrg
284805b261ecSmrgint
284905b261ecSmrgProcXkbGetIndicatorMap(ClientPtr client)
285005b261ecSmrg{
285105b261ecSmrgxkbGetIndicatorMapReply rep;
285205b261ecSmrgDeviceIntPtr		dev;
285305b261ecSmrgXkbDescPtr		xkb;
285405b261ecSmrgXkbIndicatorPtr		leds;
285505b261ecSmrg
285605b261ecSmrg    REQUEST(xkbGetIndicatorMapReq);
285705b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq);
285805b261ecSmrg
285905b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
286005b261ecSmrg	return BadAccess;
286105b261ecSmrg
286205b261ecSmrg    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
286305b261ecSmrg
286405b261ecSmrg    xkb= dev->key->xkbInfo->desc;
286505b261ecSmrg    leds= xkb->indicators;
286605b261ecSmrg
286705b261ecSmrg    rep.type = X_Reply;
286805b261ecSmrg    rep.sequenceNumber = client->sequence;
286905b261ecSmrg    rep.length = 0;
287005b261ecSmrg    rep.deviceID = dev->id;
287105b261ecSmrg    rep.which = stuff->which;
287205b261ecSmrg    XkbComputeGetIndicatorMapReplySize(leds,&rep);
287305b261ecSmrg    return XkbSendIndicatorMap(client,leds,&rep);
287405b261ecSmrg}
287505b261ecSmrg
287605b261ecSmrg/* FIXME: Needs to set indicator map on all core-sending devices. */
287705b261ecSmrgint
287805b261ecSmrgProcXkbSetIndicatorMap(ClientPtr client)
287905b261ecSmrg{
288005b261ecSmrg    register int 	i,bit;
288105b261ecSmrg    int			nIndicators,why;
288205b261ecSmrg    DeviceIntPtr 	dev;
288305b261ecSmrg    XkbSrvInfoPtr	xkbi;
288405b261ecSmrg    xkbIndicatorMapWireDesc *from;
288505b261ecSmrg    XkbSrvLedInfoPtr	sli;
288605b261ecSmrg    XkbEventCauseRec	cause;
288705b261ecSmrg
288805b261ecSmrg    REQUEST(xkbSetIndicatorMapReq);
288905b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq);
289005b261ecSmrg
289105b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
289205b261ecSmrg	return BadAccess;
289305b261ecSmrg
289405b261ecSmrg    dev = _XkbLookupKeyboard(stuff->deviceSpec,&why);
289505b261ecSmrg    if (!dev) {
289605b261ecSmrg	client->errorValue = _XkbErrCode2(why,stuff->deviceSpec);
289705b261ecSmrg	return XkbKeyboardErrorCode;
289805b261ecSmrg    }
289905b261ecSmrg    xkbi= dev->key->xkbInfo;
290005b261ecSmrg
290105b261ecSmrg    if (stuff->which==0)
290205b261ecSmrg	return client->noClientException;
290305b261ecSmrg
290405b261ecSmrg    for (nIndicators=i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
290505b261ecSmrg	if (stuff->which&bit)
290605b261ecSmrg	    nIndicators++;
290705b261ecSmrg    }
290805b261ecSmrg    if (stuff->length!=((SIZEOF(xkbSetIndicatorMapReq)+
290905b261ecSmrg			(nIndicators*SIZEOF(xkbIndicatorMapWireDesc)))/4)) {
291005b261ecSmrg	return BadLength;
291105b261ecSmrg    }
291205b261ecSmrg
291305b261ecSmrg    sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,
291405b261ecSmrg						XkbXI_IndicatorMapsMask);
291505b261ecSmrg    if (!sli)
291605b261ecSmrg	return BadAlloc;
291705b261ecSmrg
291805b261ecSmrg    from = (xkbIndicatorMapWireDesc *)&stuff[1];
291905b261ecSmrg    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
292005b261ecSmrg	if (stuff->which&bit) {
292105b261ecSmrg	    if (client->swapped) {
292205b261ecSmrg		register int n;
292305b261ecSmrg		swaps(&from->virtualMods,n);
292405b261ecSmrg		swapl(&from->ctrls,n);
292505b261ecSmrg	    }
292605b261ecSmrg	    CHK_MASK_LEGAL(i,from->whichGroups,XkbIM_UseAnyGroup);
292705b261ecSmrg	    CHK_MASK_LEGAL(i,from->whichMods,XkbIM_UseAnyMods);
292805b261ecSmrg	    from++;
292905b261ecSmrg	}
293005b261ecSmrg    }
293105b261ecSmrg
293205b261ecSmrg    from = (xkbIndicatorMapWireDesc *)&stuff[1];
293305b261ecSmrg    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
293405b261ecSmrg	if (stuff->which&bit) {
293505b261ecSmrg	    sli->maps[i].flags = from->flags;
293605b261ecSmrg	    sli->maps[i].which_groups = from->whichGroups;
293705b261ecSmrg	    sli->maps[i].groups = from->groups;
293805b261ecSmrg	    sli->maps[i].which_mods = from->whichMods;
293905b261ecSmrg	    sli->maps[i].mods.mask = from->mods;
294005b261ecSmrg	    sli->maps[i].mods.real_mods = from->mods;
294105b261ecSmrg	    sli->maps[i].mods.vmods= from->virtualMods;
294205b261ecSmrg	    sli->maps[i].ctrls = from->ctrls;
294305b261ecSmrg	    if (from->virtualMods!=0) {
294405b261ecSmrg		unsigned tmp;
294505b261ecSmrg		tmp= XkbMaskForVMask(xkbi->desc,from->virtualMods);
294605b261ecSmrg		sli->maps[i].mods.mask= from->mods|tmp;
294705b261ecSmrg	    }
294805b261ecSmrg	    from++;
294905b261ecSmrg	}
295005b261ecSmrg    }
295105b261ecSmrg
295205b261ecSmrg    XkbSetCauseXkbReq(&cause,X_kbSetIndicatorMap,client);
295305b261ecSmrg    XkbApplyLedMapChanges(dev,sli,stuff->which,NULL,NULL,&cause);
295405b261ecSmrg    return client->noClientException;
295505b261ecSmrg}
295605b261ecSmrg
295705b261ecSmrg/***====================================================================***/
295805b261ecSmrg
295905b261ecSmrgint
296005b261ecSmrgProcXkbGetNamedIndicator(ClientPtr client)
296105b261ecSmrg{
296205b261ecSmrg    DeviceIntPtr 		dev;
296305b261ecSmrg    xkbGetNamedIndicatorReply 	rep;
296405b261ecSmrg    register int		i = 0;
296505b261ecSmrg    XkbSrvLedInfoPtr		sli;
296605b261ecSmrg    XkbIndicatorMapPtr		map = NULL;
296705b261ecSmrg
296805b261ecSmrg    REQUEST(xkbGetNamedIndicatorReq);
296905b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq);
297005b261ecSmrg
297105b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
297205b261ecSmrg	return BadAccess;
297305b261ecSmrg
297405b261ecSmrg    CHK_LED_DEVICE(dev,stuff->deviceSpec);
297505b261ecSmrg    CHK_ATOM_ONLY(stuff->indicator);
297605b261ecSmrg
297705b261ecSmrg    sli= XkbFindSrvLedInfo(dev,stuff->ledClass,stuff->ledID,0);
297805b261ecSmrg    if (!sli)
297905b261ecSmrg	return BadAlloc;
298005b261ecSmrg
298105b261ecSmrg    i= 0;
298205b261ecSmrg    map= NULL;
298305b261ecSmrg    if ((sli->names)&&(sli->maps)) {
298405b261ecSmrg        for (i=0;i<XkbNumIndicators;i++) {
298505b261ecSmrg            if (stuff->indicator==sli->names[i]) {
298605b261ecSmrg                map= &sli->maps[i];
298705b261ecSmrg                break;
298805b261ecSmrg            }
298905b261ecSmrg        }
299005b261ecSmrg    }
299105b261ecSmrg
299205b261ecSmrg    rep.type= X_Reply;
299305b261ecSmrg    rep.length = 0;
299405b261ecSmrg    rep.sequenceNumber = client->sequence;
299505b261ecSmrg    rep.deviceID = dev->id;
299605b261ecSmrg    rep.indicator= stuff->indicator;
299705b261ecSmrg    if (map!=NULL) {
299805b261ecSmrg	rep.found= 		True;
299905b261ecSmrg	rep.on=			((sli->effectiveState&(1<<i))!=0);
300005b261ecSmrg	rep.realIndicator=	((sli->physIndicators&(1<<i))!=0);
300105b261ecSmrg	rep.ndx= 		i;
300205b261ecSmrg	rep.flags= 		map->flags;
300305b261ecSmrg	rep.whichGroups= 	map->which_groups;
300405b261ecSmrg	rep.groups= 		map->groups;
300505b261ecSmrg	rep.whichMods= 		map->which_mods;
300605b261ecSmrg	rep.mods= 		map->mods.mask;
300705b261ecSmrg	rep.realMods= 		map->mods.real_mods;
300805b261ecSmrg	rep.virtualMods= 	map->mods.vmods;
300905b261ecSmrg	rep.ctrls= 		map->ctrls;
301005b261ecSmrg	rep.supported= 		True;
301105b261ecSmrg    }
301205b261ecSmrg    else  {
301305b261ecSmrg	rep.found= 		False;
301405b261ecSmrg	rep.on= 		False;
301505b261ecSmrg	rep.realIndicator= 	False;
301605b261ecSmrg	rep.ndx= 		XkbNoIndicator;
301705b261ecSmrg	rep.flags= 		0;
301805b261ecSmrg	rep.whichGroups= 	0;
301905b261ecSmrg	rep.groups= 		0;
302005b261ecSmrg	rep.whichMods= 		0;
302105b261ecSmrg	rep.mods=		0;
302205b261ecSmrg	rep.realMods= 		0;
302305b261ecSmrg	rep.virtualMods= 	0;
302405b261ecSmrg	rep.ctrls= 		0;
302505b261ecSmrg	rep.supported= 		True;
302605b261ecSmrg    }
302705b261ecSmrg    if ( client->swapped ) {
302805b261ecSmrg	register int n;
302905b261ecSmrg	swapl(&rep.length,n);
303005b261ecSmrg	swaps(&rep.sequenceNumber,n);
303105b261ecSmrg	swapl(&rep.indicator,n);
303205b261ecSmrg	swaps(&rep.virtualMods,n);
303305b261ecSmrg	swapl(&rep.ctrls,n);
303405b261ecSmrg    }
303505b261ecSmrg
303605b261ecSmrg    WriteToClient(client,SIZEOF(xkbGetNamedIndicatorReply), (char *)&rep);
303705b261ecSmrg    return client->noClientException;
303805b261ecSmrg}
303905b261ecSmrg
304005b261ecSmrg/* FIXME: Needs to set indicator on all core-sending devices. */
304105b261ecSmrgint
304205b261ecSmrgProcXkbSetNamedIndicator(ClientPtr client)
304305b261ecSmrg{
304405b261ecSmrg    DeviceIntPtr 		dev,kbd;
304505b261ecSmrg    XkbIndicatorMapPtr		map;
304605b261ecSmrg    XkbSrvLedInfoPtr 		sli;
304705b261ecSmrg    register int		led = 0;
304805b261ecSmrg    unsigned			extDevReason;
304905b261ecSmrg    unsigned			statec,namec,mapc;
305005b261ecSmrg    XkbEventCauseRec		cause;
305105b261ecSmrg    xkbExtensionDeviceNotify	ed;
305205b261ecSmrg    XkbChangesRec		changes;
305305b261ecSmrg
305405b261ecSmrg    REQUEST(xkbSetNamedIndicatorReq);
305505b261ecSmrg    REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq);
305605b261ecSmrg
305705b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
305805b261ecSmrg	return BadAccess;
305905b261ecSmrg
306005b261ecSmrg    CHK_LED_DEVICE(dev,stuff->deviceSpec);
306105b261ecSmrg    CHK_ATOM_ONLY(stuff->indicator);
306205b261ecSmrg    CHK_MASK_LEGAL(0x10,stuff->whichGroups,XkbIM_UseAnyGroup);
306305b261ecSmrg    CHK_MASK_LEGAL(0x11,stuff->whichMods,XkbIM_UseAnyMods);
306405b261ecSmrg
306505b261ecSmrg    extDevReason= 0;
306605b261ecSmrg
306705b261ecSmrg    sli= XkbFindSrvLedInfo(dev,stuff->ledClass,stuff->ledID,
306805b261ecSmrg							XkbXI_IndicatorsMask);
306905b261ecSmrg    if (!sli)
307005b261ecSmrg	return BadAlloc;
307105b261ecSmrg
307205b261ecSmrg    statec= mapc= namec= 0;
307305b261ecSmrg    map= NULL;
307405b261ecSmrg    if (sli->names && sli->maps) {
307505b261ecSmrg	for (led=0;(led<XkbNumIndicators)&&(map==NULL);led++) {
307605b261ecSmrg	    if (sli->names[led]==stuff->indicator) {
307705b261ecSmrg		map= &sli->maps[led];
307805b261ecSmrg		break;
307905b261ecSmrg	    }
308005b261ecSmrg	}
308105b261ecSmrg    }
308205b261ecSmrg    if (map==NULL) {
308305b261ecSmrg	if (!stuff->createMap)
308405b261ecSmrg	    return client->noClientException;
308505b261ecSmrg	for (led=0,map=NULL;(led<XkbNumIndicators)&&(map==NULL);led++) {
308605b261ecSmrg	    if ((sli->names)&&(sli->maps)&&(sli->names[led]==None)&&
308705b261ecSmrg                (!XkbIM_InUse(&sli->maps[led]))) {
308805b261ecSmrg		map= &sli->maps[led];
308905b261ecSmrg		sli->names[led]= stuff->indicator;
309005b261ecSmrg		break;
309105b261ecSmrg	    }
309205b261ecSmrg	}
309305b261ecSmrg	if (map==NULL)
309405b261ecSmrg	    return client->noClientException;
309505b261ecSmrg	namec|= (1<<led);
309605b261ecSmrg	sli->namesPresent|= ((stuff->indicator!=None)?(1<<led):0);
309705b261ecSmrg	extDevReason|= XkbXI_IndicatorNamesMask;
309805b261ecSmrg    }
309905b261ecSmrg
310005b261ecSmrg    if (stuff->setMap) {
310105b261ecSmrg	map->flags = stuff->flags;
310205b261ecSmrg	map->which_groups = stuff->whichGroups;
310305b261ecSmrg	map->groups = stuff->groups;
310405b261ecSmrg	map->which_mods = stuff->whichMods;
310505b261ecSmrg	map->mods.mask = stuff->realMods;
310605b261ecSmrg	map->mods.real_mods = stuff->realMods;
310705b261ecSmrg	map->mods.vmods= stuff->virtualMods;
310805b261ecSmrg	map->ctrls = stuff->ctrls;
310905b261ecSmrg	mapc|= (1<<led);
311005b261ecSmrg    }
311105b261ecSmrg    if ((stuff->setState)&&((map->flags&XkbIM_NoExplicit)==0)) {
311205b261ecSmrg	if (stuff->on)	sli->explicitState|=  (1<<led);
311305b261ecSmrg	else		sli->explicitState&= ~(1<<led);
311405b261ecSmrg	statec|= ((sli->effectiveState^sli->explicitState)&(1<<led));
311505b261ecSmrg    }
311605b261ecSmrg    bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify));
311705b261ecSmrg    bzero((char *)&changes,sizeof(XkbChangesRec));
311805b261ecSmrg    XkbSetCauseXkbReq(&cause,X_kbSetNamedIndicator,client);
311905b261ecSmrg    if (namec)
312005b261ecSmrg	XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause);
312105b261ecSmrg    if (mapc)
312205b261ecSmrg	XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause);
312305b261ecSmrg    if (statec)
312405b261ecSmrg	XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause);
312505b261ecSmrg
312605b261ecSmrg    kbd= dev;
312705b261ecSmrg    if ((sli->flags&XkbSLI_HasOwnState)==0)
312805b261ecSmrg	kbd= (DeviceIntPtr)LookupKeyboardDevice();
312905b261ecSmrg    XkbFlushLedEvents(dev,kbd,sli,&ed,&changes,&cause);
313005b261ecSmrg    return client->noClientException;
313105b261ecSmrg}
313205b261ecSmrg
313305b261ecSmrg/***====================================================================***/
313405b261ecSmrg
313505b261ecSmrgstatic CARD32
313605b261ecSmrg_XkbCountAtoms(Atom *atoms,int maxAtoms,int *count)
313705b261ecSmrg{
313805b261ecSmrgregister unsigned int i,bit,nAtoms;
313905b261ecSmrgregister CARD32 atomsPresent;
314005b261ecSmrg
314105b261ecSmrg    for (i=nAtoms=atomsPresent=0,bit=1;i<maxAtoms;i++,bit<<=1) {
314205b261ecSmrg	if (atoms[i]!=None) {
314305b261ecSmrg	    atomsPresent|= bit;
314405b261ecSmrg	    nAtoms++;
314505b261ecSmrg	}
314605b261ecSmrg    }
314705b261ecSmrg    if (count)
314805b261ecSmrg	*count= nAtoms;
314905b261ecSmrg    return atomsPresent;
315005b261ecSmrg}
315105b261ecSmrg
315205b261ecSmrgstatic char *
315305b261ecSmrg_XkbWriteAtoms(char *wire,Atom *atoms,int maxAtoms,int swap)
315405b261ecSmrg{
315505b261ecSmrgregister unsigned int i;
315605b261ecSmrgAtom *atm;
315705b261ecSmrg
315805b261ecSmrg    atm = (Atom *)wire;
315905b261ecSmrg    for (i=0;i<maxAtoms;i++) {
316005b261ecSmrg	if (atoms[i]!=None) {
316105b261ecSmrg	    *atm= atoms[i];
316205b261ecSmrg	    if (swap) {
316305b261ecSmrg		register int n;
316405b261ecSmrg		swapl(atm,n);
316505b261ecSmrg	    }
316605b261ecSmrg	    atm++;
316705b261ecSmrg	}
316805b261ecSmrg    }
316905b261ecSmrg    return (char *)atm;
317005b261ecSmrg}
317105b261ecSmrg
317205b261ecSmrgstatic Status
317305b261ecSmrgXkbComputeGetNamesReplySize(XkbDescPtr xkb,xkbGetNamesReply *rep)
317405b261ecSmrg{
317505b261ecSmrgregister unsigned	which,length;
317605b261ecSmrgregister int		i;
317705b261ecSmrg
317805b261ecSmrg    rep->minKeyCode= xkb->min_key_code;
317905b261ecSmrg    rep->maxKeyCode= xkb->max_key_code;
318005b261ecSmrg    which= rep->which;
318105b261ecSmrg    length= 0;
318205b261ecSmrg    if (xkb->names!=NULL) {
318305b261ecSmrg	 if (which&XkbKeycodesNameMask)		length++;
318405b261ecSmrg	 if (which&XkbGeometryNameMask)		length++;
318505b261ecSmrg	 if (which&XkbSymbolsNameMask)		length++;
318605b261ecSmrg	 if (which&XkbPhysSymbolsNameMask)	length++;
318705b261ecSmrg	 if (which&XkbTypesNameMask)		length++;
318805b261ecSmrg	 if (which&XkbCompatNameMask)		length++;
318905b261ecSmrg    }
319005b261ecSmrg    else which&= ~XkbComponentNamesMask;
319105b261ecSmrg
319205b261ecSmrg    if (xkb->map!=NULL) {
319305b261ecSmrg	if (which&XkbKeyTypeNamesMask)
319405b261ecSmrg	    length+= xkb->map->num_types;
319505b261ecSmrg	rep->nTypes= xkb->map->num_types;
319605b261ecSmrg	if (which&XkbKTLevelNamesMask) {
319705b261ecSmrg	    XkbKeyTypePtr	pType = xkb->map->types;
319805b261ecSmrg	    int			nKTLevels = 0;
319905b261ecSmrg
320005b261ecSmrg	    length+= XkbPaddedSize(xkb->map->num_types)/4;
320105b261ecSmrg	    for (i=0;i<xkb->map->num_types;i++,pType++) {
320205b261ecSmrg		if (pType->level_names!=NULL)
320305b261ecSmrg		    nKTLevels+= pType->num_levels;
320405b261ecSmrg	    }
320505b261ecSmrg	    rep->nKTLevels= nKTLevels;
320605b261ecSmrg	    length+= nKTLevels;
320705b261ecSmrg	}
320805b261ecSmrg    }
320905b261ecSmrg    else {
321005b261ecSmrg	rep->nTypes=    0;
321105b261ecSmrg	rep->nKTLevels= 0;
321205b261ecSmrg	which&= ~(XkbKeyTypeNamesMask|XkbKTLevelNamesMask);
321305b261ecSmrg    }
321405b261ecSmrg
321505b261ecSmrg    rep->minKeyCode= xkb->min_key_code;
321605b261ecSmrg    rep->maxKeyCode= xkb->max_key_code;
321705b261ecSmrg    rep->indicators= 0;
321805b261ecSmrg    rep->virtualMods= 0;
321905b261ecSmrg    rep->groupNames= 0;
322005b261ecSmrg    if (xkb->names!=NULL) {
322105b261ecSmrg	if (which&XkbIndicatorNamesMask) {
322205b261ecSmrg	    int nLeds;
322305b261ecSmrg	    rep->indicators=
322405b261ecSmrg		_XkbCountAtoms(xkb->names->indicators,XkbNumIndicators,&nLeds);
322505b261ecSmrg	    length+= nLeds;
322605b261ecSmrg	    if (nLeds==0)
322705b261ecSmrg		which&= ~XkbIndicatorNamesMask;
322805b261ecSmrg	}
322905b261ecSmrg
323005b261ecSmrg	if (which&XkbVirtualModNamesMask) {
323105b261ecSmrg	    int nVMods;
323205b261ecSmrg	    rep->virtualMods=
323305b261ecSmrg		_XkbCountAtoms(xkb->names->vmods,XkbNumVirtualMods,&nVMods);
323405b261ecSmrg	    length+= nVMods;
323505b261ecSmrg	    if (nVMods==0)
323605b261ecSmrg		which&= ~XkbVirtualModNamesMask;
323705b261ecSmrg	}
323805b261ecSmrg
323905b261ecSmrg	if (which&XkbGroupNamesMask) {
324005b261ecSmrg	    int nGroups;
324105b261ecSmrg	    rep->groupNames=
324205b261ecSmrg		_XkbCountAtoms(xkb->names->groups,XkbNumKbdGroups,&nGroups);
324305b261ecSmrg	    length+= nGroups;
324405b261ecSmrg	    if (nGroups==0)
324505b261ecSmrg		which&= ~XkbGroupNamesMask;
324605b261ecSmrg	}
324705b261ecSmrg
324805b261ecSmrg	if ((which&XkbKeyNamesMask)&&(xkb->names->keys))
324905b261ecSmrg	     length+= rep->nKeys;
325005b261ecSmrg	else which&= ~XkbKeyNamesMask;
325105b261ecSmrg
325205b261ecSmrg	if ((which&XkbKeyAliasesMask)&&
325305b261ecSmrg	    (xkb->names->key_aliases)&&(xkb->names->num_key_aliases>0)) {
325405b261ecSmrg	    rep->nKeyAliases= xkb->names->num_key_aliases;
325505b261ecSmrg	    length+= rep->nKeyAliases*2;
325605b261ecSmrg	}
325705b261ecSmrg	else {
325805b261ecSmrg	    which&= ~XkbKeyAliasesMask;
325905b261ecSmrg	    rep->nKeyAliases= 0;
326005b261ecSmrg	}
326105b261ecSmrg
326205b261ecSmrg	if ((which&XkbRGNamesMask)&&(xkb->names->num_rg>0))
326305b261ecSmrg	     length+= xkb->names->num_rg;
326405b261ecSmrg	else which&= ~XkbRGNamesMask;
326505b261ecSmrg    }
326605b261ecSmrg    else {
326705b261ecSmrg	which&= ~(XkbIndicatorNamesMask|XkbVirtualModNamesMask);
326805b261ecSmrg	which&= ~(XkbGroupNamesMask|XkbKeyNamesMask|XkbKeyAliasesMask);
326905b261ecSmrg	which&= ~XkbRGNamesMask;
327005b261ecSmrg    }
327105b261ecSmrg
327205b261ecSmrg    rep->length= length;
327305b261ecSmrg    rep->which= which;
327405b261ecSmrg    return Success;
327505b261ecSmrg}
327605b261ecSmrg
327705b261ecSmrgstatic int
327805b261ecSmrgXkbSendNames(ClientPtr client,XkbDescPtr xkb,xkbGetNamesReply *rep)
327905b261ecSmrg{
328005b261ecSmrgregister unsigned 	i,length,which;
328105b261ecSmrgchar *			start;
328205b261ecSmrgchar *			desc;
328305b261ecSmrgregister int            n;
328405b261ecSmrg
328505b261ecSmrg    length= rep->length*4;
328605b261ecSmrg    which= rep->which;
328705b261ecSmrg    if (client->swapped) {
328805b261ecSmrg	swaps(&rep->sequenceNumber,n);
328905b261ecSmrg	swapl(&rep->length,n);
329005b261ecSmrg	swapl(&rep->which,n);
329105b261ecSmrg	swaps(&rep->virtualMods,n);
329205b261ecSmrg	swapl(&rep->indicators,n);
329305b261ecSmrg    }
329405b261ecSmrg
329505b261ecSmrg    start = desc = (char *)ALLOCATE_LOCAL(length);
329605b261ecSmrg    if ( !start )
329705b261ecSmrg	return BadAlloc;
329805b261ecSmrg    if (xkb->names) {
329905b261ecSmrg        if (which&XkbKeycodesNameMask) {
330005b261ecSmrg            *((CARD32 *)desc)= xkb->names->keycodes;
330105b261ecSmrg            if (client->swapped) {
330205b261ecSmrg                swapl(desc,n);
330305b261ecSmrg            }
330405b261ecSmrg            desc+= 4;
330505b261ecSmrg        }
330605b261ecSmrg        if (which&XkbGeometryNameMask)  {
330705b261ecSmrg            *((CARD32 *)desc)= xkb->names->geometry;
330805b261ecSmrg            if (client->swapped) {
330905b261ecSmrg                swapl(desc,n);
331005b261ecSmrg            }
331105b261ecSmrg            desc+= 4;
331205b261ecSmrg        }
331305b261ecSmrg        if (which&XkbSymbolsNameMask) {
331405b261ecSmrg            *((CARD32 *)desc)= xkb->names->symbols;
331505b261ecSmrg            if (client->swapped) {
331605b261ecSmrg                swapl(desc,n);
331705b261ecSmrg            }
331805b261ecSmrg            desc+= 4;
331905b261ecSmrg        }
332005b261ecSmrg        if (which&XkbPhysSymbolsNameMask) {
332105b261ecSmrg            register CARD32 *atm= (CARD32 *)desc;
332205b261ecSmrg            atm[0]= (CARD32)xkb->names->phys_symbols;
332305b261ecSmrg            if (client->swapped) {
332405b261ecSmrg                swapl(&atm[0],n);
332505b261ecSmrg            }
332605b261ecSmrg            desc+= 4;
332705b261ecSmrg        }
332805b261ecSmrg        if (which&XkbTypesNameMask) {
332905b261ecSmrg            *((CARD32 *)desc)= (CARD32)xkb->names->types;
333005b261ecSmrg            if (client->swapped) {
333105b261ecSmrg                swapl(desc,n);
333205b261ecSmrg            }
333305b261ecSmrg            desc+= 4;
333405b261ecSmrg        }
333505b261ecSmrg        if (which&XkbCompatNameMask) {
333605b261ecSmrg            *((CARD32 *)desc)= (CARD32)xkb->names->compat;
333705b261ecSmrg            if (client->swapped) {
333805b261ecSmrg                swapl(desc,n);
333905b261ecSmrg            }
334005b261ecSmrg            desc+= 4;
334105b261ecSmrg        }
334205b261ecSmrg        if (which&XkbKeyTypeNamesMask) {
334305b261ecSmrg            register CARD32 *atm= (CARD32 *)desc;
334405b261ecSmrg            register XkbKeyTypePtr type= xkb->map->types;
334505b261ecSmrg
334605b261ecSmrg            for (i=0;i<xkb->map->num_types;i++,atm++,type++) {
334705b261ecSmrg                *atm= (CARD32)type->name;
334805b261ecSmrg                if (client->swapped) {
334905b261ecSmrg                    swapl(atm,n);
335005b261ecSmrg                }
335105b261ecSmrg            }
335205b261ecSmrg            desc= (char *)atm;
335305b261ecSmrg        }
335405b261ecSmrg        if (which&XkbKTLevelNamesMask && xkb->map) {
335505b261ecSmrg            XkbKeyTypePtr type = xkb->map->types;
335605b261ecSmrg            register CARD32 *atm;
335705b261ecSmrg            for (i=0;i<rep->nTypes;i++,type++) {
335805b261ecSmrg                *desc++ = type->num_levels;
335905b261ecSmrg            }
336005b261ecSmrg            desc+= XkbPaddedSize(rep->nTypes)-rep->nTypes;
336105b261ecSmrg
336205b261ecSmrg            atm= (CARD32 *)desc;
336305b261ecSmrg            type = xkb->map->types;
336405b261ecSmrg            for (i=0;i<xkb->map->num_types;i++,type++) {
336505b261ecSmrg                register unsigned l;
336605b261ecSmrg                if (type->level_names) {
336705b261ecSmrg                    for (l=0;l<type->num_levels;l++,atm++) {
336805b261ecSmrg                        *atm= type->level_names[l];
336905b261ecSmrg                        if (client->swapped) {
337005b261ecSmrg                            swapl(atm,n);
337105b261ecSmrg                        }
337205b261ecSmrg                    }
337305b261ecSmrg                    desc+= type->num_levels*4;
337405b261ecSmrg                }
337505b261ecSmrg            }
337605b261ecSmrg        }
337705b261ecSmrg        if (which&XkbIndicatorNamesMask) {
337805b261ecSmrg            desc= _XkbWriteAtoms(desc,xkb->names->indicators,XkbNumIndicators,
337905b261ecSmrg                                 client->swapped);
338005b261ecSmrg        }
338105b261ecSmrg        if (which&XkbVirtualModNamesMask) {
338205b261ecSmrg            desc= _XkbWriteAtoms(desc,xkb->names->vmods,XkbNumVirtualMods,
338305b261ecSmrg                                 client->swapped);
338405b261ecSmrg        }
338505b261ecSmrg        if (which&XkbGroupNamesMask) {
338605b261ecSmrg            desc= _XkbWriteAtoms(desc,xkb->names->groups,XkbNumKbdGroups,
338705b261ecSmrg                                 client->swapped);
338805b261ecSmrg        }
338905b261ecSmrg        if (which&XkbKeyNamesMask) {
339005b261ecSmrg            for (i=0;i<rep->nKeys;i++,desc+= sizeof(XkbKeyNameRec)) {
339105b261ecSmrg                *((XkbKeyNamePtr)desc)= xkb->names->keys[i+rep->firstKey];
339205b261ecSmrg            }
339305b261ecSmrg        }
339405b261ecSmrg        if (which&XkbKeyAliasesMask) {
339505b261ecSmrg            XkbKeyAliasPtr	pAl;
339605b261ecSmrg            pAl= xkb->names->key_aliases;
339705b261ecSmrg            for (i=0;i<rep->nKeyAliases;i++,pAl++,desc+=2*XkbKeyNameLength) {
339805b261ecSmrg                *((XkbKeyAliasPtr)desc)= *pAl;
339905b261ecSmrg            }
340005b261ecSmrg        }
340105b261ecSmrg        if ((which&XkbRGNamesMask)&&(rep->nRadioGroups>0)) {
340205b261ecSmrg            register CARD32	*atm= (CARD32 *)desc;
340305b261ecSmrg            for (i=0;i<rep->nRadioGroups;i++,atm++) {
340405b261ecSmrg                *atm= (CARD32)xkb->names->radio_groups[i];
340505b261ecSmrg                if (client->swapped) {
340605b261ecSmrg                    swapl(atm,n);
340705b261ecSmrg                }
340805b261ecSmrg            }
340905b261ecSmrg            desc+= rep->nRadioGroups*4;
341005b261ecSmrg        }
341105b261ecSmrg    }
341205b261ecSmrg
341305b261ecSmrg    if ((desc-start)!=(length)) {
341405b261ecSmrg	ErrorF("BOGUS LENGTH in write names, expected %d, got %ld\n",
341505b261ecSmrg					length, (unsigned long)(desc-start));
341605b261ecSmrg    }
341705b261ecSmrg    WriteToClient(client, SIZEOF(xkbGetNamesReply), (char *)rep);
341805b261ecSmrg    WriteToClient(client, length, start);
341905b261ecSmrg    DEALLOCATE_LOCAL((char *)start);
342005b261ecSmrg    return client->noClientException;
342105b261ecSmrg}
342205b261ecSmrg
342305b261ecSmrgint
342405b261ecSmrgProcXkbGetNames(ClientPtr client)
342505b261ecSmrg{
342605b261ecSmrg    DeviceIntPtr	dev;
342705b261ecSmrg    XkbDescPtr		xkb;
342805b261ecSmrg    xkbGetNamesReply 	rep;
342905b261ecSmrg
343005b261ecSmrg    REQUEST(xkbGetNamesReq);
343105b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetNamesReq);
343205b261ecSmrg
343305b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
343405b261ecSmrg	return BadAccess;
343505b261ecSmrg
343605b261ecSmrg    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
343705b261ecSmrg    CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask);
343805b261ecSmrg
343905b261ecSmrg    xkb = dev->key->xkbInfo->desc;
344005b261ecSmrg    rep.type= X_Reply;
344105b261ecSmrg    rep.sequenceNumber= client->sequence;
344205b261ecSmrg    rep.length = 0;
344305b261ecSmrg    rep.deviceID = dev->id;
344405b261ecSmrg    rep.which = stuff->which;
344505b261ecSmrg    rep.nTypes = xkb->map->num_types;
344605b261ecSmrg    rep.firstKey = xkb->min_key_code;
344705b261ecSmrg    rep.nKeys = XkbNumKeys(xkb);
344805b261ecSmrg    if (xkb->names!=NULL) {
344905b261ecSmrg	rep.nKeyAliases= xkb->names->num_key_aliases;
345005b261ecSmrg	rep.nRadioGroups = xkb->names->num_rg;
345105b261ecSmrg    }
345205b261ecSmrg    else {
345305b261ecSmrg	rep.nKeyAliases= rep.nRadioGroups= 0;
345405b261ecSmrg    }
345505b261ecSmrg    XkbComputeGetNamesReplySize(xkb,&rep);
345605b261ecSmrg    return XkbSendNames(client,xkb,&rep);
345705b261ecSmrg}
345805b261ecSmrg
345905b261ecSmrg/***====================================================================***/
346005b261ecSmrg
346105b261ecSmrgstatic CARD32 *
346205b261ecSmrg_XkbCheckAtoms(CARD32 *wire,int nAtoms,int swapped,Atom *pError)
346305b261ecSmrg{
346405b261ecSmrgregister int i;
346505b261ecSmrg
346605b261ecSmrg    for (i=0;i<nAtoms;i++,wire++) {
346705b261ecSmrg	if (swapped) {
346805b261ecSmrg	    register int n;
346905b261ecSmrg	    swapl(wire,n);
347005b261ecSmrg	}
347105b261ecSmrg	if ((((Atom)*wire)!=None)&&(!ValidAtom((Atom)*wire))) {
347205b261ecSmrg	    *pError= ((Atom)*wire);
347305b261ecSmrg	    return NULL;
347405b261ecSmrg	}
347505b261ecSmrg    }
347605b261ecSmrg    return wire;
347705b261ecSmrg}
347805b261ecSmrg
347905b261ecSmrgstatic CARD32 *
348005b261ecSmrg_XkbCheckMaskedAtoms(CARD32 *wire,int nAtoms,CARD32 present,int swapped,
348105b261ecSmrg								Atom *pError)
348205b261ecSmrg{
348305b261ecSmrgregister unsigned i,bit;
348405b261ecSmrg
348505b261ecSmrg    for (i=0,bit=1;(i<nAtoms)&&(present);i++,bit<<=1) {
348605b261ecSmrg	if ((present&bit)==0)
348705b261ecSmrg	    continue;
348805b261ecSmrg	if (swapped) {
348905b261ecSmrg	    register int n;
349005b261ecSmrg	    swapl(wire,n);
349105b261ecSmrg	}
349205b261ecSmrg	if ((((Atom)*wire)!=None)&&(!ValidAtom(((Atom)*wire)))) {
349305b261ecSmrg	    *pError= (Atom)*wire;
349405b261ecSmrg	    return NULL;
349505b261ecSmrg	}
349605b261ecSmrg	wire++;
349705b261ecSmrg    }
349805b261ecSmrg    return wire;
349905b261ecSmrg}
350005b261ecSmrg
350105b261ecSmrgstatic Atom *
350205b261ecSmrg_XkbCopyMaskedAtoms(	Atom	*wire,
350305b261ecSmrg    			Atom	*dest,
350405b261ecSmrg			int   	 nAtoms,
350505b261ecSmrg			CARD32	 present)
350605b261ecSmrg{
350705b261ecSmrgregister int i,bit;
350805b261ecSmrg
350905b261ecSmrg    for (i=0,bit=1;(i<nAtoms)&&(present);i++,bit<<=1) {
351005b261ecSmrg	if ((present&bit)==0)
351105b261ecSmrg	    continue;
351205b261ecSmrg	dest[i]= *wire++;
351305b261ecSmrg    }
351405b261ecSmrg    return wire;
351505b261ecSmrg}
351605b261ecSmrg
351705b261ecSmrgstatic Bool
351805b261ecSmrg_XkbCheckTypeName(Atom name,int typeNdx)
351905b261ecSmrg{
352005b261ecSmrgchar *	str;
352105b261ecSmrg
352205b261ecSmrg    str= NameForAtom(name);
352305b261ecSmrg    if ((strcmp(str,"ONE_LEVEL")==0)||(strcmp(str,"TWO_LEVEL")==0)||
352405b261ecSmrg	(strcmp(str,"ALPHABETIC")==0)||(strcmp(str,"KEYPAD")==0))
352505b261ecSmrg	return False;
352605b261ecSmrg    return True;
352705b261ecSmrg}
352805b261ecSmrg
352905b261ecSmrg/* FIXME: Needs to set names on all core-sending devices. */
353005b261ecSmrgint
353105b261ecSmrgProcXkbSetNames(ClientPtr client)
353205b261ecSmrg{
353305b261ecSmrg    DeviceIntPtr	 dev;
353405b261ecSmrg    XkbDescRec		*xkb;
353505b261ecSmrg    XkbNamesRec		*names;
353605b261ecSmrg    xkbNamesNotify	 nn;
353705b261ecSmrg    CARD32		*tmp;
353805b261ecSmrg    Atom		 bad;
353905b261ecSmrg
354005b261ecSmrg    REQUEST(xkbSetNamesReq);
354105b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetNamesReq);
354205b261ecSmrg
354305b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
354405b261ecSmrg	return BadAccess;
354505b261ecSmrg
354605b261ecSmrg    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
354705b261ecSmrg    CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask);
354805b261ecSmrg
354905b261ecSmrg    xkb = dev->key->xkbInfo->desc;
355005b261ecSmrg    names = xkb->names;
355105b261ecSmrg    tmp = (CARD32 *)&stuff[1];
355205b261ecSmrg
355305b261ecSmrg    if (stuff->which&XkbKeycodesNameMask) {
355405b261ecSmrg	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
355505b261ecSmrg	if (!tmp) {
355605b261ecSmrg	    client->errorValue = bad;
355705b261ecSmrg	    return BadAtom;
355805b261ecSmrg	}
355905b261ecSmrg    }
356005b261ecSmrg    if (stuff->which&XkbGeometryNameMask) {
356105b261ecSmrg	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
356205b261ecSmrg	if (!tmp) {
356305b261ecSmrg	    client->errorValue = bad;
356405b261ecSmrg	    return BadAtom;
356505b261ecSmrg	}
356605b261ecSmrg    }
356705b261ecSmrg    if (stuff->which&XkbSymbolsNameMask) {
356805b261ecSmrg	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
356905b261ecSmrg	if (!tmp) {
357005b261ecSmrg	    client->errorValue = bad;
357105b261ecSmrg	    return BadAtom;
357205b261ecSmrg	}
357305b261ecSmrg    }
357405b261ecSmrg    if (stuff->which&XkbPhysSymbolsNameMask) {
357505b261ecSmrg	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
357605b261ecSmrg	if (!tmp) {
357705b261ecSmrg	    client->errorValue= bad;
357805b261ecSmrg	    return BadAtom;
357905b261ecSmrg	}
358005b261ecSmrg    }
358105b261ecSmrg    if (stuff->which&XkbTypesNameMask) {
358205b261ecSmrg	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
358305b261ecSmrg	if (!tmp) {
358405b261ecSmrg	    client->errorValue = bad;
358505b261ecSmrg	    return BadAtom;
358605b261ecSmrg	}
358705b261ecSmrg    }
358805b261ecSmrg    if (stuff->which&XkbCompatNameMask) {
358905b261ecSmrg	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
359005b261ecSmrg	if (!tmp) {
359105b261ecSmrg	    client->errorValue = bad;
359205b261ecSmrg	    return BadAtom;
359305b261ecSmrg	}
359405b261ecSmrg    }
359505b261ecSmrg    if (stuff->which&XkbKeyTypeNamesMask) {
359605b261ecSmrg	register int i;
359705b261ecSmrg	CARD32	*old;
359805b261ecSmrg	if ( stuff->nTypes<1 ) {
359905b261ecSmrg	    client->errorValue = _XkbErrCode2(0x02,stuff->nTypes);
360005b261ecSmrg	    return BadValue;
360105b261ecSmrg	}
360205b261ecSmrg	if ((unsigned)(stuff->firstType+stuff->nTypes-1)>=xkb->map->num_types) {
360305b261ecSmrg	    client->errorValue = _XkbErrCode4(0x03,stuff->firstType,
360405b261ecSmrg							stuff->nTypes,
360505b261ecSmrg							xkb->map->num_types);
360605b261ecSmrg	    return BadValue;
360705b261ecSmrg	}
360805b261ecSmrg	if (((unsigned)stuff->firstType)<=XkbLastRequiredType) {
360905b261ecSmrg	    client->errorValue = _XkbErrCode2(0x04,stuff->firstType);
361005b261ecSmrg	    return BadAccess;
361105b261ecSmrg	}
361205b261ecSmrg	old= tmp;
361305b261ecSmrg	tmp= _XkbCheckAtoms(tmp,stuff->nTypes,client->swapped,&bad);
361405b261ecSmrg	if (!tmp) {
361505b261ecSmrg	    client->errorValue= bad;
361605b261ecSmrg	    return BadAtom;
361705b261ecSmrg	}
361805b261ecSmrg	for (i=0;i<stuff->nTypes;i++,old++) {
361905b261ecSmrg	    if (!_XkbCheckTypeName((Atom)*old,stuff->firstType+i))
362005b261ecSmrg		client->errorValue= _XkbErrCode2(0x05,i);
362105b261ecSmrg	}
362205b261ecSmrg    }
362305b261ecSmrg    if (stuff->which&XkbKTLevelNamesMask) {
362405b261ecSmrg	register unsigned i;
362505b261ecSmrg	XkbKeyTypePtr	type;
362605b261ecSmrg	CARD8 *		width;
362705b261ecSmrg	if ( stuff->nKTLevels<1 ) {
362805b261ecSmrg	    client->errorValue = _XkbErrCode2(0x05,stuff->nKTLevels);
362905b261ecSmrg	    return BadValue;
363005b261ecSmrg	}
363105b261ecSmrg	if ((unsigned)(stuff->firstKTLevel+stuff->nKTLevels-1)>=
363205b261ecSmrg							xkb->map->num_types) {
363305b261ecSmrg	    client->errorValue = _XkbErrCode4(0x06,stuff->firstKTLevel,
363405b261ecSmrg				stuff->nKTLevels,xkb->map->num_types);
363505b261ecSmrg	    return BadValue;
363605b261ecSmrg	}
363705b261ecSmrg	width = (CARD8 *)tmp;
363805b261ecSmrg	tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels));
363905b261ecSmrg	type = &xkb->map->types[stuff->firstKTLevel];
364005b261ecSmrg	for (i=0;i<stuff->nKTLevels;i++,type++) {
364105b261ecSmrg	    if (width[i]==0)
364205b261ecSmrg		continue;
364305b261ecSmrg	    else if (width[i]!=type->num_levels) {
364405b261ecSmrg		client->errorValue= _XkbErrCode4(0x07,i+stuff->firstKTLevel,
364505b261ecSmrg						type->num_levels,width[i]);
364605b261ecSmrg		return BadMatch;
364705b261ecSmrg	    }
364805b261ecSmrg	    tmp= _XkbCheckAtoms(tmp,width[i],client->swapped,&bad);
364905b261ecSmrg	    if (!tmp) {
365005b261ecSmrg		client->errorValue= bad;
365105b261ecSmrg		return BadAtom;
365205b261ecSmrg	    }
365305b261ecSmrg	}
365405b261ecSmrg    }
365505b261ecSmrg    if (stuff->which&XkbIndicatorNamesMask) {
365605b261ecSmrg	if (stuff->indicators==0) {
365705b261ecSmrg	    client->errorValue= 0x08;
365805b261ecSmrg	    return BadMatch;
365905b261ecSmrg	}
366005b261ecSmrg	tmp= _XkbCheckMaskedAtoms(tmp,XkbNumIndicators,stuff->indicators,
366105b261ecSmrg							client->swapped,&bad);
366205b261ecSmrg	if (!tmp) {
366305b261ecSmrg	    client->errorValue= bad;
366405b261ecSmrg	    return BadAtom;
366505b261ecSmrg	}
366605b261ecSmrg    }
366705b261ecSmrg    if (stuff->which&XkbVirtualModNamesMask) {
366805b261ecSmrg	if (stuff->virtualMods==0) {
366905b261ecSmrg	    client->errorValue= 0x09;
367005b261ecSmrg	    return BadMatch;
367105b261ecSmrg	}
367205b261ecSmrg	tmp= _XkbCheckMaskedAtoms(tmp,XkbNumVirtualMods,
367305b261ecSmrg						(CARD32)stuff->virtualMods,
367405b261ecSmrg						client->swapped,&bad);
367505b261ecSmrg	if (!tmp) {
367605b261ecSmrg	    client->errorValue = bad;
367705b261ecSmrg	    return BadAtom;
367805b261ecSmrg	}
367905b261ecSmrg    }
368005b261ecSmrg    if (stuff->which&XkbGroupNamesMask) {
368105b261ecSmrg	if (stuff->groupNames==0) {
368205b261ecSmrg	    client->errorValue= 0x0a;
368305b261ecSmrg	    return BadMatch;
368405b261ecSmrg	}
368505b261ecSmrg	tmp= _XkbCheckMaskedAtoms(tmp,XkbNumKbdGroups,
368605b261ecSmrg						(CARD32)stuff->groupNames,
368705b261ecSmrg						client->swapped,&bad);
368805b261ecSmrg	if (!tmp) {
368905b261ecSmrg	    client->errorValue = bad;
369005b261ecSmrg	    return BadAtom;
369105b261ecSmrg	}
369205b261ecSmrg    }
369305b261ecSmrg    if (stuff->which&XkbKeyNamesMask) {
369405b261ecSmrg	if (stuff->firstKey<(unsigned)xkb->min_key_code) {
369505b261ecSmrg	    client->errorValue= _XkbErrCode3(0x0b,xkb->min_key_code,
369605b261ecSmrg							stuff->firstKey);
369705b261ecSmrg	    return BadValue;
369805b261ecSmrg	}
369905b261ecSmrg	if (((unsigned)(stuff->firstKey+stuff->nKeys-1)>xkb->max_key_code)||
370005b261ecSmrg							(stuff->nKeys<1)) {
370105b261ecSmrg	    client->errorValue= _XkbErrCode4(0x0c,xkb->max_key_code,
370205b261ecSmrg						stuff->firstKey,stuff->nKeys);
370305b261ecSmrg	    return BadValue;
370405b261ecSmrg	}
370505b261ecSmrg	tmp+= stuff->nKeys;
370605b261ecSmrg    }
370705b261ecSmrg    if ((stuff->which&XkbKeyAliasesMask)&&(stuff->nKeyAliases>0)) {
370805b261ecSmrg	tmp+= stuff->nKeyAliases*2;
370905b261ecSmrg    }
371005b261ecSmrg    if (stuff->which&XkbRGNamesMask) {
371105b261ecSmrg	if ( stuff->nRadioGroups<1 ) {
371205b261ecSmrg	    client->errorValue= _XkbErrCode2(0x0d,stuff->nRadioGroups);
371305b261ecSmrg	    return BadValue;
371405b261ecSmrg	}
371505b261ecSmrg	tmp= _XkbCheckAtoms(tmp,stuff->nRadioGroups,client->swapped,&bad);
371605b261ecSmrg	if (!tmp) {
371705b261ecSmrg	    client->errorValue= bad;
371805b261ecSmrg	    return BadAtom;
371905b261ecSmrg	}
372005b261ecSmrg    }
372105b261ecSmrg    if ((tmp-((CARD32 *)stuff))!=stuff->length) {
372205b261ecSmrg	client->errorValue = stuff->length;
372305b261ecSmrg	return BadLength;
372405b261ecSmrg    }
372505b261ecSmrg    if (XkbAllocNames(xkb,stuff->which,stuff->nRadioGroups,
372605b261ecSmrg					stuff->nKeyAliases)!=Success) {
372705b261ecSmrg	return BadAlloc;
372805b261ecSmrg    }
372905b261ecSmrg
373005b261ecSmrg    /* everything is okay -- update names */
373105b261ecSmrg    bzero(&nn,sizeof(xkbNamesNotify));
373205b261ecSmrg    nn.changed= stuff->which;
373305b261ecSmrg    tmp = (CARD32 *)&stuff[1];
373405b261ecSmrg    if (stuff->which&XkbKeycodesNameMask)
373505b261ecSmrg	names->keycodes= *tmp++;
373605b261ecSmrg    if (stuff->which&XkbGeometryNameMask)
373705b261ecSmrg	names->geometry= *tmp++;
373805b261ecSmrg    if (stuff->which&XkbSymbolsNameMask)
373905b261ecSmrg	names->symbols= *tmp++;
374005b261ecSmrg    if (stuff->which&XkbPhysSymbolsNameMask)
374105b261ecSmrg	names->phys_symbols= *tmp++;
374205b261ecSmrg    if (stuff->which&XkbTypesNameMask)
374305b261ecSmrg	names->types= *tmp++;
374405b261ecSmrg    if (stuff->which&XkbCompatNameMask)
374505b261ecSmrg	names->compat= *tmp++;
374605b261ecSmrg    if ((stuff->which&XkbKeyTypeNamesMask)&&(stuff->nTypes>0)) {
374705b261ecSmrg	register unsigned i;
374805b261ecSmrg	register XkbKeyTypePtr type;
374905b261ecSmrg
375005b261ecSmrg	type= &xkb->map->types[stuff->firstType];
375105b261ecSmrg	for (i=0;i<stuff->nTypes;i++,type++) {
375205b261ecSmrg	    type->name= *tmp++;
375305b261ecSmrg	}
375405b261ecSmrg	nn.firstType= stuff->firstType;
375505b261ecSmrg	nn.nTypes= stuff->nTypes;
375605b261ecSmrg    }
375705b261ecSmrg    if (stuff->which&XkbKTLevelNamesMask) {
375805b261ecSmrg	register XkbKeyTypePtr	type;
375905b261ecSmrg	register unsigned i;
376005b261ecSmrg	CARD8 *width;
376105b261ecSmrg
376205b261ecSmrg	width = (CARD8 *)tmp;
376305b261ecSmrg	tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels));
376405b261ecSmrg	type= &xkb->map->types[stuff->firstKTLevel];
376505b261ecSmrg	for (i=0;i<stuff->nKTLevels;i++,type++) {
376605b261ecSmrg	    if (width[i]>0) {
376705b261ecSmrg		if (type->level_names) {
376805b261ecSmrg		    register unsigned n;
376905b261ecSmrg		    for (n=0;n<width[i];n++) {
377005b261ecSmrg			type->level_names[n]= tmp[n];
377105b261ecSmrg		    }
377205b261ecSmrg		}
377305b261ecSmrg		tmp+= width[i];
377405b261ecSmrg	    }
377505b261ecSmrg	}
377605b261ecSmrg	nn.firstLevelName= 0;
377705b261ecSmrg	nn.nLevelNames= stuff->nTypes;
377805b261ecSmrg    }
377905b261ecSmrg    if (stuff->which&XkbIndicatorNamesMask) {
378005b261ecSmrg	tmp= _XkbCopyMaskedAtoms(tmp,names->indicators,XkbNumIndicators,
378105b261ecSmrg							stuff->indicators);
378205b261ecSmrg	nn.changedIndicators= stuff->indicators;
378305b261ecSmrg    }
378405b261ecSmrg    if (stuff->which&XkbVirtualModNamesMask) {
378505b261ecSmrg	tmp= _XkbCopyMaskedAtoms(tmp,names->vmods,XkbNumVirtualMods,
378605b261ecSmrg							stuff->virtualMods);
378705b261ecSmrg	nn.changedVirtualMods= stuff->virtualMods;
378805b261ecSmrg    }
378905b261ecSmrg    if (stuff->which&XkbGroupNamesMask) {
379005b261ecSmrg	tmp= _XkbCopyMaskedAtoms(tmp,names->groups,XkbNumKbdGroups,
379105b261ecSmrg							stuff->groupNames);
379205b261ecSmrg	nn.changedVirtualMods= stuff->groupNames;
379305b261ecSmrg    }
379405b261ecSmrg    if (stuff->which&XkbKeyNamesMask) {
379505b261ecSmrg	memcpy((char*)&names->keys[stuff->firstKey],(char *)tmp,
379605b261ecSmrg						stuff->nKeys*XkbKeyNameLength);
379705b261ecSmrg	tmp+= stuff->nKeys;
379805b261ecSmrg	nn.firstKey= stuff->firstKey;
379905b261ecSmrg	nn.nKeys= stuff->nKeys;
380005b261ecSmrg    }
380105b261ecSmrg    if (stuff->which&XkbKeyAliasesMask) {
380205b261ecSmrg	if (stuff->nKeyAliases>0) {
380305b261ecSmrg	    register int na= stuff->nKeyAliases;
380405b261ecSmrg	    if (XkbAllocNames(xkb,XkbKeyAliasesMask,0,na)!=Success)
380505b261ecSmrg		return BadAlloc;
380605b261ecSmrg	    memcpy((char *)names->key_aliases,(char *)tmp,
380705b261ecSmrg				stuff->nKeyAliases*sizeof(XkbKeyAliasRec));
380805b261ecSmrg	    tmp+= stuff->nKeyAliases*2;
380905b261ecSmrg	}
381005b261ecSmrg	else if (names->key_aliases!=NULL) {
381105b261ecSmrg	    _XkbFree(names->key_aliases);
381205b261ecSmrg	    names->key_aliases= NULL;
381305b261ecSmrg	    names->num_key_aliases= 0;
381405b261ecSmrg	}
381505b261ecSmrg	nn.nAliases= names->num_key_aliases;
381605b261ecSmrg    }
381705b261ecSmrg    if (stuff->which&XkbRGNamesMask) {
381805b261ecSmrg	if (stuff->nRadioGroups>0) {
381905b261ecSmrg	    register unsigned i,nrg;
382005b261ecSmrg	    nrg= stuff->nRadioGroups;
382105b261ecSmrg	    if (XkbAllocNames(xkb,XkbRGNamesMask,nrg,0)!=Success)
382205b261ecSmrg		return BadAlloc;
382305b261ecSmrg
382405b261ecSmrg	    for (i=0;i<stuff->nRadioGroups;i++) {
382505b261ecSmrg		names->radio_groups[i]= tmp[i];
382605b261ecSmrg	    }
382705b261ecSmrg	    tmp+= stuff->nRadioGroups;
382805b261ecSmrg	}
382905b261ecSmrg	else if (names->radio_groups) {
383005b261ecSmrg	    _XkbFree(names->radio_groups);
383105b261ecSmrg	    names->radio_groups= NULL;
383205b261ecSmrg	    names->num_rg= 0;
383305b261ecSmrg	}
383405b261ecSmrg	nn.nRadioGroups= names->num_rg;
383505b261ecSmrg    }
383605b261ecSmrg    if (nn.changed) {
383705b261ecSmrg	Bool needExtEvent;
383805b261ecSmrg	needExtEvent= (nn.changed&XkbIndicatorNamesMask)!=0;
383905b261ecSmrg	XkbSendNamesNotify(dev,&nn);
384005b261ecSmrg	if (needExtEvent) {
384105b261ecSmrg	    XkbSrvLedInfoPtr		sli;
384205b261ecSmrg	    xkbExtensionDeviceNotify	edev;
384305b261ecSmrg	    register int		i;
384405b261ecSmrg	    register unsigned		bit;
384505b261ecSmrg
384605b261ecSmrg	    sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,
384705b261ecSmrg							XkbXI_IndicatorsMask);
384805b261ecSmrg	    sli->namesPresent= 0;
384905b261ecSmrg	    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
385005b261ecSmrg		if (names->indicators[i]!=None)
385105b261ecSmrg		    sli->namesPresent|= bit;
385205b261ecSmrg	    }
385305b261ecSmrg	    bzero(&edev,sizeof(xkbExtensionDeviceNotify));
385405b261ecSmrg	    edev.reason=	XkbXI_IndicatorNamesMask;
385505b261ecSmrg	    edev.ledClass=	KbdFeedbackClass;
385605b261ecSmrg	    edev.ledID=		dev->kbdfeed->ctrl.id;
385705b261ecSmrg	    edev.ledsDefined= 	sli->namesPresent|sli->mapsPresent;
385805b261ecSmrg	    edev.ledState=	sli->effectiveState;
385905b261ecSmrg	    edev.firstBtn=	0;
386005b261ecSmrg	    edev.nBtns=		0;
386105b261ecSmrg	    edev.supported=	XkbXI_AllFeaturesMask;
386205b261ecSmrg	    edev.unsupported=	0;
386305b261ecSmrg	    XkbSendExtensionDeviceNotify(dev,client,&edev);
386405b261ecSmrg	}
386505b261ecSmrg    }
386605b261ecSmrg    return client->noClientException;
386705b261ecSmrg}
386805b261ecSmrg
386905b261ecSmrg/***====================================================================***/
387005b261ecSmrg
387105b261ecSmrg#include <X11/extensions/XKBgeom.h>
387205b261ecSmrg
387305b261ecSmrg#define	XkbSizeCountedString(s)  ((s)?((((2+strlen(s))+3)/4)*4):4)
387405b261ecSmrg
387505b261ecSmrgstatic char *
387605b261ecSmrgXkbWriteCountedString(char *wire,char *str,Bool swap)
387705b261ecSmrg{
387805b261ecSmrgCARD16	len,*pLen;
387905b261ecSmrg
388005b261ecSmrg    len= (str?strlen(str):0);
388105b261ecSmrg    pLen= (CARD16 *)wire;
388205b261ecSmrg    *pLen= len;
388305b261ecSmrg    if (swap) {
388405b261ecSmrg	register int n;
388505b261ecSmrg	swaps(pLen,n);
388605b261ecSmrg    }
388705b261ecSmrg    memcpy(&wire[2],str,len);
388805b261ecSmrg    wire+= ((2+len+3)/4)*4;
388905b261ecSmrg    return wire;
389005b261ecSmrg}
389105b261ecSmrg
389205b261ecSmrgstatic int
389305b261ecSmrgXkbSizeGeomProperties(XkbGeometryPtr geom)
389405b261ecSmrg{
389505b261ecSmrgregister int 	i,size;
389605b261ecSmrgXkbPropertyPtr	prop;
389705b261ecSmrg
389805b261ecSmrg    for (size=i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
389905b261ecSmrg	size+= XkbSizeCountedString(prop->name);
390005b261ecSmrg	size+= XkbSizeCountedString(prop->value);
390105b261ecSmrg    }
390205b261ecSmrg    return size;
390305b261ecSmrg}
390405b261ecSmrg
390505b261ecSmrgstatic char *
390605b261ecSmrgXkbWriteGeomProperties(char *wire,XkbGeometryPtr geom,Bool swap)
390705b261ecSmrg{
390805b261ecSmrgregister int 	i;
390905b261ecSmrgregister XkbPropertyPtr	prop;
391005b261ecSmrg
391105b261ecSmrg    for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
391205b261ecSmrg	wire= XkbWriteCountedString(wire,prop->name,swap);
391305b261ecSmrg	wire= XkbWriteCountedString(wire,prop->value,swap);
391405b261ecSmrg    }
391505b261ecSmrg    return wire;
391605b261ecSmrg}
391705b261ecSmrg
391805b261ecSmrgstatic int
391905b261ecSmrgXkbSizeGeomKeyAliases(XkbGeometryPtr geom)
392005b261ecSmrg{
392105b261ecSmrg    return geom->num_key_aliases*(2*XkbKeyNameLength);
392205b261ecSmrg}
392305b261ecSmrg
392405b261ecSmrgstatic char *
392505b261ecSmrgXkbWriteGeomKeyAliases(char *wire,XkbGeometryPtr geom,Bool swap)
392605b261ecSmrg{
392705b261ecSmrgregister int sz;
392805b261ecSmrg
392905b261ecSmrg    sz= geom->num_key_aliases*(XkbKeyNameLength*2);
393005b261ecSmrg    if (sz>0) {
393105b261ecSmrg	memcpy(wire,(char *)geom->key_aliases,sz);
393205b261ecSmrg	wire+= sz;
393305b261ecSmrg    }
393405b261ecSmrg    return wire;
393505b261ecSmrg}
393605b261ecSmrg
393705b261ecSmrgstatic int
393805b261ecSmrgXkbSizeGeomColors(XkbGeometryPtr geom)
393905b261ecSmrg{
394005b261ecSmrgregister int 		i,size;
394105b261ecSmrgregister XkbColorPtr	color;
394205b261ecSmrg
394305b261ecSmrg    for (i=size=0,color=geom->colors;i<geom->num_colors;i++,color++) {
394405b261ecSmrg	size+= XkbSizeCountedString(color->spec);
394505b261ecSmrg    }
394605b261ecSmrg    return size;
394705b261ecSmrg}
394805b261ecSmrg
394905b261ecSmrgstatic char *
395005b261ecSmrgXkbWriteGeomColors(char *wire,XkbGeometryPtr geom,Bool swap)
395105b261ecSmrg{
395205b261ecSmrgregister int		i;
395305b261ecSmrgregister XkbColorPtr	color;
395405b261ecSmrg
395505b261ecSmrg    for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) {
395605b261ecSmrg	wire= XkbWriteCountedString(wire,color->spec,swap);
395705b261ecSmrg    }
395805b261ecSmrg    return wire;
395905b261ecSmrg}
396005b261ecSmrg
396105b261ecSmrgstatic int
396205b261ecSmrgXkbSizeGeomShapes(XkbGeometryPtr geom)
396305b261ecSmrg{
396405b261ecSmrgregister int		i,size;
396505b261ecSmrgregister XkbShapePtr	shape;
396605b261ecSmrg
396705b261ecSmrg    for (i=size=0,shape=geom->shapes;i<geom->num_shapes;i++,shape++) {
396805b261ecSmrg	register int		n;
396905b261ecSmrg	register XkbOutlinePtr	ol;
397005b261ecSmrg	size+= SIZEOF(xkbShapeWireDesc);
397105b261ecSmrg	for (n=0,ol=shape->outlines;n<shape->num_outlines;n++,ol++) {
397205b261ecSmrg	    size+= SIZEOF(xkbOutlineWireDesc);
397305b261ecSmrg	    size+= ol->num_points*SIZEOF(xkbPointWireDesc);
397405b261ecSmrg	}
397505b261ecSmrg    }
397605b261ecSmrg    return size;
397705b261ecSmrg}
397805b261ecSmrg
397905b261ecSmrgstatic char *
398005b261ecSmrgXkbWriteGeomShapes(char *wire,XkbGeometryPtr geom,Bool swap)
398105b261ecSmrg{
398205b261ecSmrgint			i;
398305b261ecSmrgXkbShapePtr		shape;
398405b261ecSmrgxkbShapeWireDesc *	shapeWire;
398505b261ecSmrg
398605b261ecSmrg    for (i=0,shape=geom->shapes;i<geom->num_shapes;i++,shape++) {
398705b261ecSmrg	register int 		o;
398805b261ecSmrg	XkbOutlinePtr		ol;
398905b261ecSmrg	xkbOutlineWireDesc *	olWire;
399005b261ecSmrg	shapeWire= (xkbShapeWireDesc *)wire;
399105b261ecSmrg	shapeWire->name= shape->name;
399205b261ecSmrg	shapeWire->nOutlines= shape->num_outlines;
399305b261ecSmrg	if (shape->primary!=NULL)
399405b261ecSmrg	     shapeWire->primaryNdx= XkbOutlineIndex(shape,shape->primary);
399505b261ecSmrg	else shapeWire->primaryNdx= XkbNoShape;
399605b261ecSmrg	if (shape->approx!=NULL)
399705b261ecSmrg	     shapeWire->approxNdx= XkbOutlineIndex(shape,shape->approx);
399805b261ecSmrg	else shapeWire->approxNdx= XkbNoShape;
399905b261ecSmrg	if (swap) {
400005b261ecSmrg	    register int n;
400105b261ecSmrg	    swapl(&shapeWire->name,n);
400205b261ecSmrg	}
400305b261ecSmrg	wire= (char *)&shapeWire[1];
400405b261ecSmrg	for (o=0,ol=shape->outlines;o<shape->num_outlines;o++,ol++) {
400505b261ecSmrg	    register int	p;
400605b261ecSmrg	    XkbPointPtr		pt;
400705b261ecSmrg	    xkbPointWireDesc *	ptWire;
400805b261ecSmrg	    olWire= (xkbOutlineWireDesc *)wire;
400905b261ecSmrg	    olWire->nPoints= ol->num_points;
401005b261ecSmrg	    olWire->cornerRadius= ol->corner_radius;
401105b261ecSmrg	    wire= (char *)&olWire[1];
401205b261ecSmrg	    ptWire= (xkbPointWireDesc *)wire;
401305b261ecSmrg	    for (p=0,pt=ol->points;p<ol->num_points;p++,pt++) {
401405b261ecSmrg		ptWire[p].x= pt->x;
401505b261ecSmrg		ptWire[p].y= pt->y;
401605b261ecSmrg		if (swap) {
401705b261ecSmrg		    register int n;
401805b261ecSmrg		    swaps(&ptWire[p].x,n);
401905b261ecSmrg		    swaps(&ptWire[p].y,n);
402005b261ecSmrg		}
402105b261ecSmrg	    }
402205b261ecSmrg	    wire= (char *)&ptWire[ol->num_points];
402305b261ecSmrg	}
402405b261ecSmrg    }
402505b261ecSmrg    return wire;
402605b261ecSmrg}
402705b261ecSmrg
402805b261ecSmrgstatic int
402905b261ecSmrgXkbSizeGeomDoodads(int num_doodads,XkbDoodadPtr doodad)
403005b261ecSmrg{
403105b261ecSmrgregister int	i,size;
403205b261ecSmrg
403305b261ecSmrg    for (i=size=0;i<num_doodads;i++,doodad++) {
403405b261ecSmrg	size+= SIZEOF(xkbAnyDoodadWireDesc);
403505b261ecSmrg	if (doodad->any.type==XkbTextDoodad) {
403605b261ecSmrg	    size+= XkbSizeCountedString(doodad->text.text);
403705b261ecSmrg	    size+= XkbSizeCountedString(doodad->text.font);
403805b261ecSmrg	}
403905b261ecSmrg	else if (doodad->any.type==XkbLogoDoodad) {
404005b261ecSmrg	    size+= XkbSizeCountedString(doodad->logo.logo_name);
404105b261ecSmrg	}
404205b261ecSmrg    }
404305b261ecSmrg    return size;
404405b261ecSmrg}
404505b261ecSmrg
404605b261ecSmrgstatic char *
404705b261ecSmrgXkbWriteGeomDoodads(char *wire,int num_doodads,XkbDoodadPtr doodad,Bool swap)
404805b261ecSmrg{
404905b261ecSmrgregister int		i;
405005b261ecSmrgxkbDoodadWireDesc *	doodadWire;
405105b261ecSmrg
405205b261ecSmrg    for (i=0;i<num_doodads;i++,doodad++) {
405305b261ecSmrg	doodadWire= (xkbDoodadWireDesc *)wire;
405405b261ecSmrg	wire= (char *)&doodadWire[1];
405505b261ecSmrg	bzero(doodadWire,SIZEOF(xkbDoodadWireDesc));
405605b261ecSmrg	doodadWire->any.name= doodad->any.name;
405705b261ecSmrg	doodadWire->any.type= doodad->any.type;
405805b261ecSmrg	doodadWire->any.priority= doodad->any.priority;
405905b261ecSmrg	doodadWire->any.top= doodad->any.top;
406005b261ecSmrg	doodadWire->any.left= doodad->any.left;
406105b261ecSmrg	if (swap) {
406205b261ecSmrg	    register int n;
406305b261ecSmrg	    swapl(&doodadWire->any.name,n);
406405b261ecSmrg	    swaps(&doodadWire->any.top,n);
406505b261ecSmrg	    swaps(&doodadWire->any.left,n);
406605b261ecSmrg	}
406705b261ecSmrg	switch (doodad->any.type) {
406805b261ecSmrg	    case XkbOutlineDoodad:
406905b261ecSmrg	    case XkbSolidDoodad:
407005b261ecSmrg		doodadWire->shape.angle= doodad->shape.angle;
407105b261ecSmrg		doodadWire->shape.colorNdx= doodad->shape.color_ndx;
407205b261ecSmrg		doodadWire->shape.shapeNdx= doodad->shape.shape_ndx;
407305b261ecSmrg		if (swap) {
407405b261ecSmrg		    register int n;
407505b261ecSmrg		    swaps(&doodadWire->shape.angle,n);
407605b261ecSmrg		}
407705b261ecSmrg		break;
407805b261ecSmrg	    case XkbTextDoodad:
407905b261ecSmrg		doodadWire->text.angle= doodad->text.angle;
408005b261ecSmrg		doodadWire->text.width= doodad->text.width;
408105b261ecSmrg		doodadWire->text.height= doodad->text.height;
408205b261ecSmrg		doodadWire->text.colorNdx= doodad->text.color_ndx;
408305b261ecSmrg		if (swap) {
408405b261ecSmrg		    register int n;
408505b261ecSmrg		    swaps(&doodadWire->text.angle,n);
408605b261ecSmrg		    swaps(&doodadWire->text.width,n);
408705b261ecSmrg		    swaps(&doodadWire->text.height,n);
408805b261ecSmrg		}
408905b261ecSmrg		wire= XkbWriteCountedString(wire,doodad->text.text,swap);
409005b261ecSmrg		wire= XkbWriteCountedString(wire,doodad->text.font,swap);
409105b261ecSmrg		break;
409205b261ecSmrg	    case XkbIndicatorDoodad:
409305b261ecSmrg		doodadWire->indicator.shapeNdx= doodad->indicator.shape_ndx;
409405b261ecSmrg		doodadWire->indicator.onColorNdx=doodad->indicator.on_color_ndx;
409505b261ecSmrg		doodadWire->indicator.offColorNdx=
409605b261ecSmrg						doodad->indicator.off_color_ndx;
409705b261ecSmrg		break;
409805b261ecSmrg	    case XkbLogoDoodad:
409905b261ecSmrg		doodadWire->logo.angle= doodad->logo.angle;
410005b261ecSmrg		doodadWire->logo.colorNdx= doodad->logo.color_ndx;
410105b261ecSmrg		doodadWire->logo.shapeNdx= doodad->logo.shape_ndx;
410205b261ecSmrg		wire= XkbWriteCountedString(wire,doodad->logo.logo_name,swap);
410305b261ecSmrg		break;
410405b261ecSmrg	    default:
410505b261ecSmrg		ErrorF("Unknown doodad type %d in XkbWriteGeomDoodads\n",
410605b261ecSmrg			doodad->any.type);
410705b261ecSmrg		ErrorF("Ignored\n");
410805b261ecSmrg		break;
410905b261ecSmrg	}
411005b261ecSmrg    }
411105b261ecSmrg    return wire;
411205b261ecSmrg}
411305b261ecSmrg
411405b261ecSmrgstatic char *
411505b261ecSmrgXkbWriteGeomOverlay(char *wire,XkbOverlayPtr ol,Bool swap)
411605b261ecSmrg{
411705b261ecSmrgregister int		r;
411805b261ecSmrgXkbOverlayRowPtr	row;
411905b261ecSmrgxkbOverlayWireDesc *	olWire;
412005b261ecSmrg
412105b261ecSmrg   olWire= (xkbOverlayWireDesc *)wire;
412205b261ecSmrg   olWire->name= ol->name;
412305b261ecSmrg   olWire->nRows= ol->num_rows;
412405b261ecSmrg   if (swap) {
412505b261ecSmrg	register int n;
412605b261ecSmrg	swapl(&olWire->name,n);
412705b261ecSmrg   }
412805b261ecSmrg   wire= (char *)&olWire[1];
412905b261ecSmrg   for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
413005b261ecSmrg   	unsigned int		k;
413105b261ecSmrg	XkbOverlayKeyPtr	key;
413205b261ecSmrg	xkbOverlayRowWireDesc *	rowWire;
413305b261ecSmrg	rowWire= (xkbOverlayRowWireDesc *)wire;
413405b261ecSmrg	rowWire->rowUnder= row->row_under;
413505b261ecSmrg	rowWire->nKeys= row->num_keys;
413605b261ecSmrg	wire= (char *)&rowWire[1];
413705b261ecSmrg	for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
413805b261ecSmrg	    xkbOverlayKeyWireDesc *	keyWire;
413905b261ecSmrg	    keyWire= (xkbOverlayKeyWireDesc *)wire;
414005b261ecSmrg	    memcpy(keyWire->over,key->over.name,XkbKeyNameLength);
414105b261ecSmrg	    memcpy(keyWire->under,key->under.name,XkbKeyNameLength);
414205b261ecSmrg	    wire= (char *)&keyWire[1];
414305b261ecSmrg	}
414405b261ecSmrg   }
414505b261ecSmrg   return wire;
414605b261ecSmrg}
414705b261ecSmrg
414805b261ecSmrgstatic int
414905b261ecSmrgXkbSizeGeomSections(XkbGeometryPtr geom)
415005b261ecSmrg{
415105b261ecSmrgregister int 	i,size;
415205b261ecSmrgXkbSectionPtr	section;
415305b261ecSmrg
415405b261ecSmrg    for (i=size=0,section=geom->sections;i<geom->num_sections;i++,section++) {
415505b261ecSmrg	size+= SIZEOF(xkbSectionWireDesc);
415605b261ecSmrg	if (section->rows) {
415705b261ecSmrg	    int		r;
415805b261ecSmrg	    XkbRowPtr	row;
415905b261ecSmrg	    for (r=0,row=section->rows;r<section->num_rows;row++,r++) {
416005b261ecSmrg		size+= SIZEOF(xkbRowWireDesc);
416105b261ecSmrg		size+= row->num_keys*SIZEOF(xkbKeyWireDesc);
416205b261ecSmrg	    }
416305b261ecSmrg	}
416405b261ecSmrg	if (section->doodads)
416505b261ecSmrg	    size+= XkbSizeGeomDoodads(section->num_doodads,section->doodads);
416605b261ecSmrg	if (section->overlays) {
416705b261ecSmrg	    int			o;
416805b261ecSmrg	    XkbOverlayPtr	ol;
416905b261ecSmrg	    for (o=0,ol=section->overlays;o<section->num_overlays;o++,ol++) {
417005b261ecSmrg		int			r;
417105b261ecSmrg		XkbOverlayRowPtr	row;
417205b261ecSmrg		size+= SIZEOF(xkbOverlayWireDesc);
417305b261ecSmrg		for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
417405b261ecSmrg		   size+= SIZEOF(xkbOverlayRowWireDesc);
417505b261ecSmrg		   size+= row->num_keys*SIZEOF(xkbOverlayKeyWireDesc);
417605b261ecSmrg		}
417705b261ecSmrg	    }
417805b261ecSmrg	}
417905b261ecSmrg    }
418005b261ecSmrg    return size;
418105b261ecSmrg}
418205b261ecSmrg
418305b261ecSmrgstatic char *
418405b261ecSmrgXkbWriteGeomSections(char *wire,XkbGeometryPtr geom,Bool swap)
418505b261ecSmrg{
418605b261ecSmrgregister int		i;
418705b261ecSmrgXkbSectionPtr		section;
418805b261ecSmrgxkbSectionWireDesc *	sectionWire;
418905b261ecSmrg
419005b261ecSmrg    for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) {
419105b261ecSmrg	sectionWire= (xkbSectionWireDesc *)wire;
419205b261ecSmrg	sectionWire->name= section->name;
419305b261ecSmrg	sectionWire->top= section->top;
419405b261ecSmrg	sectionWire->left= section->left;
419505b261ecSmrg	sectionWire->width= section->width;
419605b261ecSmrg	sectionWire->height= section->height;
419705b261ecSmrg	sectionWire->angle= section->angle;
419805b261ecSmrg	sectionWire->priority= section->priority;
419905b261ecSmrg	sectionWire->nRows= section->num_rows;
420005b261ecSmrg	sectionWire->nDoodads= section->num_doodads;
420105b261ecSmrg	sectionWire->nOverlays= section->num_overlays;
420205b261ecSmrg	sectionWire->pad= 0;
420305b261ecSmrg	if (swap) {
420405b261ecSmrg	    register int n;
420505b261ecSmrg	    swapl(&sectionWire->name,n);
420605b261ecSmrg	    swaps(&sectionWire->top,n);
420705b261ecSmrg	    swaps(&sectionWire->left,n);
420805b261ecSmrg	    swaps(&sectionWire->width,n);
420905b261ecSmrg	    swaps(&sectionWire->height,n);
421005b261ecSmrg	    swaps(&sectionWire->angle,n);
421105b261ecSmrg	}
421205b261ecSmrg	wire= (char *)&sectionWire[1];
421305b261ecSmrg	if (section->rows) {
421405b261ecSmrg	    int			r;
421505b261ecSmrg	    XkbRowPtr		row;
421605b261ecSmrg	    xkbRowWireDesc *	rowWire;
421705b261ecSmrg	    for (r=0,row=section->rows;r<section->num_rows;r++,row++) {
421805b261ecSmrg		rowWire= (xkbRowWireDesc *)wire;
421905b261ecSmrg		rowWire->top= row->top;
422005b261ecSmrg		rowWire->left= row->left;
422105b261ecSmrg		rowWire->nKeys= row->num_keys;
422205b261ecSmrg		rowWire->vertical= row->vertical;
422305b261ecSmrg		rowWire->pad= 0;
422405b261ecSmrg		if (swap) {
422505b261ecSmrg		    register int n;
422605b261ecSmrg		    swaps(&rowWire->top,n);
422705b261ecSmrg		    swaps(&rowWire->left,n);
422805b261ecSmrg		}
422905b261ecSmrg		wire= (char *)&rowWire[1];
423005b261ecSmrg		if (row->keys) {
423105b261ecSmrg		    int			k;
423205b261ecSmrg		    XkbKeyPtr		key;
423305b261ecSmrg		    xkbKeyWireDesc *	keyWire;
423405b261ecSmrg		    keyWire= (xkbKeyWireDesc *)wire;
423505b261ecSmrg		    for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
423605b261ecSmrg			memcpy(keyWire[k].name,key->name.name,XkbKeyNameLength);
423705b261ecSmrg			keyWire[k].gap= key->gap;
423805b261ecSmrg			keyWire[k].shapeNdx= key->shape_ndx;
423905b261ecSmrg			keyWire[k].colorNdx= key->color_ndx;
424005b261ecSmrg			if (swap) {
424105b261ecSmrg			    register int n;
424205b261ecSmrg			    swaps(&keyWire[k].gap,n);
424305b261ecSmrg			}
424405b261ecSmrg		    }
424505b261ecSmrg		    wire= (char *)&keyWire[row->num_keys];
424605b261ecSmrg		}
424705b261ecSmrg	    }
424805b261ecSmrg	}
424905b261ecSmrg	if (section->doodads) {
425005b261ecSmrg	    wire= XkbWriteGeomDoodads(wire,
425105b261ecSmrg	    			      section->num_doodads,section->doodads,
425205b261ecSmrg				      swap);
425305b261ecSmrg	}
425405b261ecSmrg	if (section->overlays) {
425505b261ecSmrg	    register int o;
425605b261ecSmrg	    for (o=0;o<section->num_overlays;o++) {
425705b261ecSmrg		wire= XkbWriteGeomOverlay(wire,&section->overlays[o],swap);
425805b261ecSmrg	    }
425905b261ecSmrg	}
426005b261ecSmrg    }
426105b261ecSmrg    return wire;
426205b261ecSmrg}
426305b261ecSmrg
426405b261ecSmrgstatic Status
426505b261ecSmrgXkbComputeGetGeometryReplySize(	XkbGeometryPtr		geom,
426605b261ecSmrg				xkbGetGeometryReply *	rep,
426705b261ecSmrg				Atom			name)
426805b261ecSmrg{
426905b261ecSmrgint	len;
427005b261ecSmrg
427105b261ecSmrg    if (geom!=NULL) {
427205b261ecSmrg	len= XkbSizeCountedString(geom->label_font);
427305b261ecSmrg	len+= XkbSizeGeomProperties(geom);
427405b261ecSmrg	len+= XkbSizeGeomColors(geom);
427505b261ecSmrg	len+= XkbSizeGeomShapes(geom);
427605b261ecSmrg	len+= XkbSizeGeomSections(geom);
427705b261ecSmrg	len+= XkbSizeGeomDoodads(geom->num_doodads,geom->doodads);
427805b261ecSmrg	len+= XkbSizeGeomKeyAliases(geom);
427905b261ecSmrg	rep->length= len/4;
428005b261ecSmrg	rep->found= True;
428105b261ecSmrg	rep->name= geom->name;
428205b261ecSmrg	rep->widthMM= geom->width_mm;
428305b261ecSmrg	rep->heightMM= geom->height_mm;
428405b261ecSmrg	rep->nProperties= geom->num_properties;
428505b261ecSmrg	rep->nColors= geom->num_colors;
428605b261ecSmrg	rep->nShapes= geom->num_shapes;
428705b261ecSmrg	rep->nSections= geom->num_sections;
428805b261ecSmrg	rep->nDoodads= geom->num_doodads;
428905b261ecSmrg	rep->nKeyAliases= geom->num_key_aliases;
429005b261ecSmrg	rep->baseColorNdx= XkbGeomColorIndex(geom,geom->base_color);
429105b261ecSmrg	rep->labelColorNdx= XkbGeomColorIndex(geom,geom->label_color);
429205b261ecSmrg    }
429305b261ecSmrg    else {
429405b261ecSmrg	rep->length= 0;
429505b261ecSmrg	rep->found= False;
429605b261ecSmrg	rep->name= name;
429705b261ecSmrg	rep->widthMM= rep->heightMM= 0;
429805b261ecSmrg	rep->nProperties= rep->nColors= rep->nShapes= 0;
429905b261ecSmrg	rep->nSections= rep->nDoodads= 0;
430005b261ecSmrg	rep->nKeyAliases= 0;
430105b261ecSmrg	rep->labelColorNdx= rep->baseColorNdx= 0;
430205b261ecSmrg    }
430305b261ecSmrg    return Success;
430405b261ecSmrg}
430505b261ecSmrg
430605b261ecSmrgstatic int
430705b261ecSmrgXkbSendGeometry(	ClientPtr		client,
430805b261ecSmrg			XkbGeometryPtr		geom,
430905b261ecSmrg			xkbGetGeometryReply *	rep,
431005b261ecSmrg			Bool			freeGeom)
431105b261ecSmrg{
431205b261ecSmrg    char	*desc,*start;
431305b261ecSmrg    int		 len;
431405b261ecSmrg
431505b261ecSmrg    if (geom!=NULL) {
431605b261ecSmrg	len= rep->length*4;
431705b261ecSmrg	start= desc= (char *)ALLOCATE_LOCAL(len);
431805b261ecSmrg	if (!start)
431905b261ecSmrg	    return BadAlloc;
432005b261ecSmrg	desc=  XkbWriteCountedString(desc,geom->label_font,client->swapped);
432105b261ecSmrg	if ( rep->nProperties>0 )
432205b261ecSmrg	    desc = XkbWriteGeomProperties(desc,geom,client->swapped);
432305b261ecSmrg	if ( rep->nColors>0 )
432405b261ecSmrg	    desc = XkbWriteGeomColors(desc,geom,client->swapped);
432505b261ecSmrg	if ( rep->nShapes>0 )
432605b261ecSmrg	    desc = XkbWriteGeomShapes(desc,geom,client->swapped);
432705b261ecSmrg	if ( rep->nSections>0 )
432805b261ecSmrg	    desc = XkbWriteGeomSections(desc,geom,client->swapped);
432905b261ecSmrg	if ( rep->nDoodads>0 )
433005b261ecSmrg	    desc = XkbWriteGeomDoodads(desc,geom->num_doodads,geom->doodads,
433105b261ecSmrg							  client->swapped);
433205b261ecSmrg	if ( rep->nKeyAliases>0 )
433305b261ecSmrg	    desc = XkbWriteGeomKeyAliases(desc,geom,client->swapped);
433405b261ecSmrg	if ((desc-start)!=(len)) {
433505b261ecSmrg	    ErrorF("BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n",
433605b261ecSmrg			len, (unsigned long)(desc-start));
433705b261ecSmrg	}
433805b261ecSmrg    }
433905b261ecSmrg    else {
434005b261ecSmrg	len= 0;
434105b261ecSmrg	start= NULL;
434205b261ecSmrg    }
434305b261ecSmrg    if (client->swapped) {
434405b261ecSmrg	register int n;
434505b261ecSmrg	swaps(&rep->sequenceNumber,n);
434605b261ecSmrg	swapl(&rep->length,n);
434705b261ecSmrg	swapl(&rep->name,n);
434805b261ecSmrg	swaps(&rep->widthMM,n);
434905b261ecSmrg	swaps(&rep->heightMM,n);
435005b261ecSmrg	swaps(&rep->nProperties,n);
435105b261ecSmrg	swaps(&rep->nColors,n);
435205b261ecSmrg	swaps(&rep->nShapes,n);
435305b261ecSmrg	swaps(&rep->nSections,n);
435405b261ecSmrg	swaps(&rep->nDoodads,n);
435505b261ecSmrg	swaps(&rep->nKeyAliases,n);
435605b261ecSmrg    }
435705b261ecSmrg    WriteToClient(client, SIZEOF(xkbGetGeometryReply), (char *)rep);
435805b261ecSmrg    if (len>0)
435905b261ecSmrg	WriteToClient(client, len, start);
436005b261ecSmrg    if (start!=NULL)
436105b261ecSmrg	DEALLOCATE_LOCAL((char *)start);
436205b261ecSmrg    if (freeGeom)
436305b261ecSmrg	XkbFreeGeometry(geom,XkbGeomAllMask,True);
436405b261ecSmrg    return client->noClientException;
436505b261ecSmrg}
436605b261ecSmrg
436705b261ecSmrgint
436805b261ecSmrgProcXkbGetGeometry(ClientPtr client)
436905b261ecSmrg{
437005b261ecSmrg    DeviceIntPtr 	dev;
437105b261ecSmrg    xkbGetGeometryReply rep;
437205b261ecSmrg    XkbGeometryPtr	geom;
437305b261ecSmrg    Bool		shouldFree;
437405b261ecSmrg    Status		status;
437505b261ecSmrg
437605b261ecSmrg    REQUEST(xkbGetGeometryReq);
437705b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetGeometryReq);
437805b261ecSmrg
437905b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
438005b261ecSmrg	return BadAccess;
438105b261ecSmrg
438205b261ecSmrg    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
438305b261ecSmrg    CHK_ATOM_OR_NONE(stuff->name);
438405b261ecSmrg
438505b261ecSmrg    geom= XkbLookupNamedGeometry(dev,stuff->name,&shouldFree);
438605b261ecSmrg    rep.type= X_Reply;
438705b261ecSmrg    rep.deviceID= dev->id;
438805b261ecSmrg    rep.sequenceNumber= client->sequence;
438905b261ecSmrg    rep.length= 0;
439005b261ecSmrg    status= XkbComputeGetGeometryReplySize(geom,&rep,stuff->name);
439105b261ecSmrg    if (status!=Success)
439205b261ecSmrg	 return status;
439305b261ecSmrg    else return XkbSendGeometry(client,geom,&rep,shouldFree);
439405b261ecSmrg}
439505b261ecSmrg
439605b261ecSmrg/***====================================================================***/
439705b261ecSmrg
439805b261ecSmrgstatic char *
439905b261ecSmrg_GetCountedString(char **wire_inout,Bool swap)
440005b261ecSmrg{
440105b261ecSmrgchar *	wire,*str;
440205b261ecSmrgCARD16	len,*plen;
440305b261ecSmrg
440405b261ecSmrg    wire= *wire_inout;
440505b261ecSmrg    plen= (CARD16 *)wire;
440605b261ecSmrg    if (swap) {
440705b261ecSmrg	register int n;
440805b261ecSmrg	swaps(plen,n);
440905b261ecSmrg    }
441005b261ecSmrg    len= *plen;
441105b261ecSmrg    str= (char *)_XkbAlloc(len+1);
441205b261ecSmrg    if (str) {
441305b261ecSmrg	memcpy(str,&wire[2],len);
441405b261ecSmrg	str[len]= '\0';
441505b261ecSmrg    }
441605b261ecSmrg    wire+= XkbPaddedSize(len+2);
441705b261ecSmrg    *wire_inout= wire;
441805b261ecSmrg    return str;
441905b261ecSmrg}
442005b261ecSmrg
442105b261ecSmrgstatic Status
442205b261ecSmrg_CheckSetDoodad(	char **		wire_inout,
442305b261ecSmrg			XkbGeometryPtr	geom,
442405b261ecSmrg			XkbSectionPtr	section,
442505b261ecSmrg			ClientPtr	client)
442605b261ecSmrg{
442705b261ecSmrgchar *			wire;
442805b261ecSmrgxkbDoodadWireDesc *	dWire;
442905b261ecSmrgXkbDoodadPtr		doodad;
443005b261ecSmrg
443105b261ecSmrg    dWire= (xkbDoodadWireDesc *)(*wire_inout);
443205b261ecSmrg    wire= (char *)&dWire[1];
443305b261ecSmrg    if (client->swapped) {
443405b261ecSmrg	register int n;
443505b261ecSmrg	swapl(&dWire->any.name,n);
443605b261ecSmrg	swaps(&dWire->any.top,n);
443705b261ecSmrg	swaps(&dWire->any.left,n);
443805b261ecSmrg	swaps(&dWire->any.angle,n);
443905b261ecSmrg    }
444005b261ecSmrg    CHK_ATOM_ONLY(dWire->any.name);
444105b261ecSmrg    doodad= XkbAddGeomDoodad(geom,section,dWire->any.name);
444205b261ecSmrg    if (!doodad)
444305b261ecSmrg	return BadAlloc;
444405b261ecSmrg    doodad->any.type= dWire->any.type;
444505b261ecSmrg    doodad->any.priority= dWire->any.priority;
444605b261ecSmrg    doodad->any.top= dWire->any.top;
444705b261ecSmrg    doodad->any.left= dWire->any.left;
444805b261ecSmrg    doodad->any.angle= dWire->any.angle;
444905b261ecSmrg    switch (doodad->any.type) {
445005b261ecSmrg	case XkbOutlineDoodad:
445105b261ecSmrg	case XkbSolidDoodad:
445205b261ecSmrg	    if (dWire->shape.colorNdx>=geom->num_colors) {
445305b261ecSmrg		client->errorValue= _XkbErrCode3(0x40,geom->num_colors,
445405b261ecSmrg							dWire->shape.colorNdx);
445505b261ecSmrg		return BadMatch;
445605b261ecSmrg	    }
445705b261ecSmrg	    if (dWire->shape.shapeNdx>=geom->num_shapes) {
445805b261ecSmrg		client->errorValue= _XkbErrCode3(0x41,geom->num_shapes,
445905b261ecSmrg							dWire->shape.shapeNdx);
446005b261ecSmrg		return BadMatch;
446105b261ecSmrg	    }
446205b261ecSmrg	    doodad->shape.color_ndx= dWire->shape.colorNdx;
446305b261ecSmrg	    doodad->shape.shape_ndx= dWire->shape.shapeNdx;
446405b261ecSmrg	    break;
446505b261ecSmrg	case XkbTextDoodad:
446605b261ecSmrg	    if (dWire->text.colorNdx>=geom->num_colors) {
446705b261ecSmrg		client->errorValue= _XkbErrCode3(0x42,geom->num_colors,
446805b261ecSmrg							dWire->text.colorNdx);
446905b261ecSmrg		return BadMatch;
447005b261ecSmrg	    }
447105b261ecSmrg	    if (client->swapped) {
447205b261ecSmrg		register int n;
447305b261ecSmrg		swaps(&dWire->text.width,n);
447405b261ecSmrg		swaps(&dWire->text.height,n);
447505b261ecSmrg	    }
447605b261ecSmrg	    doodad->text.width= dWire->text.width;
447705b261ecSmrg	    doodad->text.height= dWire->text.height;
447805b261ecSmrg	    doodad->text.color_ndx= dWire->text.colorNdx;
447905b261ecSmrg	    doodad->text.text= _GetCountedString(&wire,client->swapped);
448005b261ecSmrg	    doodad->text.font= _GetCountedString(&wire,client->swapped);
448105b261ecSmrg	    break;
448205b261ecSmrg	case XkbIndicatorDoodad:
448305b261ecSmrg	    if (dWire->indicator.onColorNdx>=geom->num_colors) {
448405b261ecSmrg		client->errorValue= _XkbErrCode3(0x43,geom->num_colors,
448505b261ecSmrg						dWire->indicator.onColorNdx);
448605b261ecSmrg		return BadMatch;
448705b261ecSmrg	    }
448805b261ecSmrg	    if (dWire->indicator.offColorNdx>=geom->num_colors) {
448905b261ecSmrg		client->errorValue= _XkbErrCode3(0x44,geom->num_colors,
449005b261ecSmrg						dWire->indicator.offColorNdx);
449105b261ecSmrg		return BadMatch;
449205b261ecSmrg	    }
449305b261ecSmrg	    if (dWire->indicator.shapeNdx>=geom->num_shapes) {
449405b261ecSmrg		client->errorValue= _XkbErrCode3(0x45,geom->num_shapes,
449505b261ecSmrg						dWire->indicator.shapeNdx);
449605b261ecSmrg		return BadMatch;
449705b261ecSmrg	    }
449805b261ecSmrg	    doodad->indicator.shape_ndx= dWire->indicator.shapeNdx;
449905b261ecSmrg	    doodad->indicator.on_color_ndx= dWire->indicator.onColorNdx;
450005b261ecSmrg	    doodad->indicator.off_color_ndx= dWire->indicator.offColorNdx;
450105b261ecSmrg	    break;
450205b261ecSmrg	case XkbLogoDoodad:
450305b261ecSmrg	    if (dWire->logo.colorNdx>=geom->num_colors) {
450405b261ecSmrg		client->errorValue= _XkbErrCode3(0x46,geom->num_colors,
450505b261ecSmrg							dWire->logo.colorNdx);
450605b261ecSmrg		return BadMatch;
450705b261ecSmrg	    }
450805b261ecSmrg	    if (dWire->logo.shapeNdx>=geom->num_shapes) {
450905b261ecSmrg		client->errorValue= _XkbErrCode3(0x47,geom->num_shapes,
451005b261ecSmrg							dWire->logo.shapeNdx);
451105b261ecSmrg		return BadMatch;
451205b261ecSmrg	    }
451305b261ecSmrg	    doodad->logo.color_ndx= dWire->logo.colorNdx;
451405b261ecSmrg	    doodad->logo.shape_ndx= dWire->logo.shapeNdx;
451505b261ecSmrg	    doodad->logo.logo_name= _GetCountedString(&wire,client->swapped);
451605b261ecSmrg	    break;
451705b261ecSmrg	default:
451805b261ecSmrg	    client->errorValue= _XkbErrCode2(0x4F,dWire->any.type);
451905b261ecSmrg	    return BadValue;
452005b261ecSmrg    }
452105b261ecSmrg    *wire_inout= wire;
452205b261ecSmrg    return Success;
452305b261ecSmrg}
452405b261ecSmrg
452505b261ecSmrgstatic Status
452605b261ecSmrg_CheckSetOverlay(	char **		wire_inout,
452705b261ecSmrg			XkbGeometryPtr	geom,
452805b261ecSmrg			XkbSectionPtr	section,
452905b261ecSmrg			ClientPtr	client)
453005b261ecSmrg{
453105b261ecSmrgregister int		r;
453205b261ecSmrgchar *			wire;
453305b261ecSmrgXkbOverlayPtr		ol;
453405b261ecSmrgxkbOverlayWireDesc *	olWire;
453505b261ecSmrgxkbOverlayRowWireDesc *	rWire;
453605b261ecSmrg
453705b261ecSmrg    wire= *wire_inout;
453805b261ecSmrg    olWire= (xkbOverlayWireDesc *)wire;
453905b261ecSmrg    if (client->swapped) {
454005b261ecSmrg	register int n;
454105b261ecSmrg	swapl(&olWire->name,n);
454205b261ecSmrg    }
454305b261ecSmrg    CHK_ATOM_ONLY(olWire->name);
454405b261ecSmrg    ol= XkbAddGeomOverlay(section,olWire->name,olWire->nRows);
454505b261ecSmrg    rWire= (xkbOverlayRowWireDesc *)&olWire[1];
454605b261ecSmrg    for (r=0;r<olWire->nRows;r++) {
454705b261ecSmrg	register int		k;
454805b261ecSmrg	xkbOverlayKeyWireDesc *	kWire;
454905b261ecSmrg	XkbOverlayRowPtr	row;
455005b261ecSmrg
455105b261ecSmrg	if (rWire->rowUnder>section->num_rows) {
455205b261ecSmrg	    client->errorValue= _XkbErrCode4(0x20,r,section->num_rows,
455305b261ecSmrg							rWire->rowUnder);
455405b261ecSmrg	    return BadMatch;
455505b261ecSmrg	}
455605b261ecSmrg	row= XkbAddGeomOverlayRow(ol,rWire->rowUnder,rWire->nKeys);
455705b261ecSmrg	kWire= (xkbOverlayKeyWireDesc *)&rWire[1];
455805b261ecSmrg	for (k=0;k<rWire->nKeys;k++,kWire++) {
455905b261ecSmrg	    if (XkbAddGeomOverlayKey(ol,row,
456005b261ecSmrg	    		(char *)kWire->over,(char *)kWire->under)==NULL) {
456105b261ecSmrg		client->errorValue= _XkbErrCode3(0x21,r,k);
456205b261ecSmrg		return BadMatch;
456305b261ecSmrg	    }
456405b261ecSmrg	}
456505b261ecSmrg	rWire= (xkbOverlayRowWireDesc *)kWire;
456605b261ecSmrg    }
456705b261ecSmrg    olWire= (xkbOverlayWireDesc *)rWire;
456805b261ecSmrg    wire= (char *)olWire;
456905b261ecSmrg    *wire_inout= wire;
457005b261ecSmrg    return Success;
457105b261ecSmrg}
457205b261ecSmrg
457305b261ecSmrgstatic Status
457405b261ecSmrg_CheckSetSections( 	XkbGeometryPtr		geom,
457505b261ecSmrg			xkbSetGeometryReq *	req,
457605b261ecSmrg			char **			wire_inout,
457705b261ecSmrg			ClientPtr		client)
457805b261ecSmrg{
457905b261ecSmrgStatus			status;
458005b261ecSmrgregister int		s;
458105b261ecSmrgchar *			wire;
458205b261ecSmrgxkbSectionWireDesc *	sWire;
458305b261ecSmrgXkbSectionPtr		section;
458405b261ecSmrg
458505b261ecSmrg    wire= *wire_inout;
458605b261ecSmrg    if (req->nSections<1)
458705b261ecSmrg	return Success;
458805b261ecSmrg    sWire= (xkbSectionWireDesc *)wire;
458905b261ecSmrg    for (s=0;s<req->nSections;s++) {
459005b261ecSmrg	register int		r;
459105b261ecSmrg	xkbRowWireDesc *	rWire;
459205b261ecSmrg	if (client->swapped) {
459305b261ecSmrg	    register int n;
459405b261ecSmrg	    swapl(&sWire->name,n);
459505b261ecSmrg	    swaps(&sWire->top,n);
459605b261ecSmrg	    swaps(&sWire->left,n);
459705b261ecSmrg	    swaps(&sWire->width,n);
459805b261ecSmrg	    swaps(&sWire->height,n);
459905b261ecSmrg	    swaps(&sWire->angle,n);
460005b261ecSmrg	}
460105b261ecSmrg	CHK_ATOM_ONLY(sWire->name);
460205b261ecSmrg	section= XkbAddGeomSection(geom,sWire->name,sWire->nRows,
460305b261ecSmrg					sWire->nDoodads,sWire->nOverlays);
460405b261ecSmrg	if (!section)
460505b261ecSmrg	    return BadAlloc;
460605b261ecSmrg	section->priority=	sWire->priority;
460705b261ecSmrg	section->top=		sWire->top;
460805b261ecSmrg	section->left=		sWire->left;
460905b261ecSmrg	section->width=		sWire->width;
461005b261ecSmrg	section->height=	sWire->height;
461105b261ecSmrg	section->angle=		sWire->angle;
461205b261ecSmrg	rWire= (xkbRowWireDesc *)&sWire[1];
461305b261ecSmrg	for (r=0;r<sWire->nRows;r++) {
461405b261ecSmrg	    register int	k;
461505b261ecSmrg	    XkbRowPtr		row;
461605b261ecSmrg	    xkbKeyWireDesc *	kWire;
461705b261ecSmrg	    if (client->swapped) {
461805b261ecSmrg		register int n;
461905b261ecSmrg		swaps(&rWire->top,n);
462005b261ecSmrg		swaps(&rWire->left,n);
462105b261ecSmrg	    }
462205b261ecSmrg	    row= XkbAddGeomRow(section,rWire->nKeys);
462305b261ecSmrg	    if (!row)
462405b261ecSmrg		return BadAlloc;
462505b261ecSmrg	    row->top= rWire->top;
462605b261ecSmrg	    row->left= rWire->left;
462705b261ecSmrg	    row->vertical= rWire->vertical;
462805b261ecSmrg	    kWire= (xkbKeyWireDesc *)&rWire[1];
462905b261ecSmrg	    for (k=0;k<rWire->nKeys;k++) {
463005b261ecSmrg		XkbKeyPtr	key;
463105b261ecSmrg		key= XkbAddGeomKey(row);
463205b261ecSmrg		if (!key)
463305b261ecSmrg		    return BadAlloc;
463405b261ecSmrg		memcpy(key->name.name,kWire[k].name,XkbKeyNameLength);
463505b261ecSmrg		key->gap= kWire[k].gap;
463605b261ecSmrg		key->shape_ndx= kWire[k].shapeNdx;
463705b261ecSmrg		key->color_ndx= kWire[k].colorNdx;
463805b261ecSmrg		if (key->shape_ndx>=geom->num_shapes) {
463905b261ecSmrg		    client->errorValue= _XkbErrCode3(0x10,key->shape_ndx,
464005b261ecSmrg							  geom->num_shapes);
464105b261ecSmrg		    return BadMatch;
464205b261ecSmrg		}
464305b261ecSmrg		if (key->color_ndx>=geom->num_colors) {
464405b261ecSmrg		    client->errorValue= _XkbErrCode3(0x11,key->color_ndx,
464505b261ecSmrg							  geom->num_colors);
464605b261ecSmrg		    return BadMatch;
464705b261ecSmrg		}
464805b261ecSmrg	    }
464905b261ecSmrg	    rWire= (xkbRowWireDesc *)&kWire[rWire->nKeys];
465005b261ecSmrg	}
465105b261ecSmrg	wire= (char *)rWire;
465205b261ecSmrg	if (sWire->nDoodads>0) {
465305b261ecSmrg	    register int d;
465405b261ecSmrg	    for (d=0;d<sWire->nDoodads;d++) {
465505b261ecSmrg		status=_CheckSetDoodad(&wire,geom,section,client);
465605b261ecSmrg		if (status!=Success)
465705b261ecSmrg		    return status;
465805b261ecSmrg	    }
465905b261ecSmrg	}
466005b261ecSmrg	if (sWire->nOverlays>0) {
466105b261ecSmrg	    register int o;
466205b261ecSmrg	    for (o=0;o<sWire->nOverlays;o++) {
466305b261ecSmrg		status= _CheckSetOverlay(&wire,geom,section,client);
466405b261ecSmrg		if (status!=Success)
466505b261ecSmrg		    return status;
466605b261ecSmrg	    }
466705b261ecSmrg	}
466805b261ecSmrg	sWire= (xkbSectionWireDesc *)wire;
466905b261ecSmrg    }
467005b261ecSmrg    wire= (char *)sWire;
467105b261ecSmrg    *wire_inout= wire;
467205b261ecSmrg    return Success;
467305b261ecSmrg}
467405b261ecSmrg
467505b261ecSmrgstatic Status
467605b261ecSmrg_CheckSetShapes( 	XkbGeometryPtr		geom,
467705b261ecSmrg			xkbSetGeometryReq *	req,
467805b261ecSmrg			char **			wire_inout,
467905b261ecSmrg			ClientPtr		client)
468005b261ecSmrg{
468105b261ecSmrgregister int	i;
468205b261ecSmrgchar *		wire;
468305b261ecSmrg
468405b261ecSmrg    wire= *wire_inout;
468505b261ecSmrg    if (req->nShapes<1) {
468605b261ecSmrg	client->errorValue= _XkbErrCode2(0x06,req->nShapes);
468705b261ecSmrg	return BadValue;
468805b261ecSmrg    }
468905b261ecSmrg    else {
469005b261ecSmrg	xkbShapeWireDesc *	shapeWire;
469105b261ecSmrg	XkbShapePtr		shape;
469205b261ecSmrg	register int		o;
469305b261ecSmrg	shapeWire= (xkbShapeWireDesc *)wire;
469405b261ecSmrg	for (i=0;i<req->nShapes;i++) {
469505b261ecSmrg	    xkbOutlineWireDesc *	olWire;
469605b261ecSmrg	    XkbOutlinePtr		ol;
469705b261ecSmrg	    shape= XkbAddGeomShape(geom,shapeWire->name,shapeWire->nOutlines);
469805b261ecSmrg	    if (!shape)
469905b261ecSmrg		return BadAlloc;
470005b261ecSmrg	    olWire= (xkbOutlineWireDesc *)(&shapeWire[1]);
470105b261ecSmrg	    for (o=0;o<shapeWire->nOutlines;o++) {
470205b261ecSmrg		register int		p;
470305b261ecSmrg		XkbPointPtr		pt;
470405b261ecSmrg		xkbPointWireDesc *	ptWire;
470505b261ecSmrg
470605b261ecSmrg		ol= XkbAddGeomOutline(shape,olWire->nPoints);
470705b261ecSmrg		if (!ol)
470805b261ecSmrg		    return BadAlloc;
470905b261ecSmrg		ol->corner_radius=	olWire->cornerRadius;
471005b261ecSmrg		ptWire= (xkbPointWireDesc *)&olWire[1];
471105b261ecSmrg		for (p=0,pt=ol->points;p<olWire->nPoints;p++,pt++) {
471205b261ecSmrg		    pt->x= ptWire[p].x;
471305b261ecSmrg		    pt->y= ptWire[p].y;
471405b261ecSmrg		    if (client->swapped) {
471505b261ecSmrg			register int n;
471605b261ecSmrg			swaps(&pt->x,n);
471705b261ecSmrg			swaps(&pt->y,n);
471805b261ecSmrg		    }
471905b261ecSmrg		}
472005b261ecSmrg		ol->num_points= olWire->nPoints;
472105b261ecSmrg		olWire= (xkbOutlineWireDesc *)(&ptWire[olWire->nPoints]);
472205b261ecSmrg	    }
472305b261ecSmrg	    if (shapeWire->primaryNdx!=XkbNoShape)
472405b261ecSmrg		shape->primary= &shape->outlines[shapeWire->primaryNdx];
472505b261ecSmrg	    if (shapeWire->approxNdx!=XkbNoShape)
472605b261ecSmrg		shape->approx= &shape->outlines[shapeWire->approxNdx];
472705b261ecSmrg	    shapeWire= (xkbShapeWireDesc *)olWire;
472805b261ecSmrg	}
472905b261ecSmrg	wire= (char *)shapeWire;
473005b261ecSmrg    }
473105b261ecSmrg    if (geom->num_shapes!=req->nShapes) {
473205b261ecSmrg	client->errorValue= _XkbErrCode3(0x07,geom->num_shapes,req->nShapes);
473305b261ecSmrg	return BadMatch;
473405b261ecSmrg    }
473505b261ecSmrg
473605b261ecSmrg    *wire_inout= wire;
473705b261ecSmrg    return Success;
473805b261ecSmrg}
473905b261ecSmrg
474005b261ecSmrgstatic Status
474105b261ecSmrg_CheckSetGeom(	XkbGeometryPtr		geom,
474205b261ecSmrg		xkbSetGeometryReq *	req,
474305b261ecSmrg		ClientPtr 		client)
474405b261ecSmrg{
474505b261ecSmrgregister int	i;
474605b261ecSmrgStatus		status;
474705b261ecSmrgchar *		wire;
474805b261ecSmrg
474905b261ecSmrg    wire= (char *)&req[1];
475005b261ecSmrg    geom->label_font= _GetCountedString(&wire,client->swapped);
475105b261ecSmrg
475205b261ecSmrg    for (i=0;i<req->nProperties;i++) {
475305b261ecSmrg	char *name,*val;
475405b261ecSmrg	name= _GetCountedString(&wire,client->swapped);
475505b261ecSmrg        if (!name)
475605b261ecSmrg            return BadAlloc;
475705b261ecSmrg	val= _GetCountedString(&wire,client->swapped);
475805b261ecSmrg        if (!val) {
475905b261ecSmrg            xfree(name);
476005b261ecSmrg            return BadAlloc;
476105b261ecSmrg        }
476205b261ecSmrg	if (XkbAddGeomProperty(geom,name,val)==NULL) {
476305b261ecSmrg            xfree(name);
476405b261ecSmrg            xfree(val);
476505b261ecSmrg	    return BadAlloc;
476605b261ecSmrg        }
476705b261ecSmrg        xfree(name);
476805b261ecSmrg        xfree(val);
476905b261ecSmrg    }
477005b261ecSmrg
477105b261ecSmrg    if (req->nColors<2) {
477205b261ecSmrg	client->errorValue= _XkbErrCode3(0x01,2,req->nColors);
477305b261ecSmrg	return BadValue;
477405b261ecSmrg    }
477505b261ecSmrg    if (req->baseColorNdx>req->nColors) {
477605b261ecSmrg	client->errorValue=_XkbErrCode3(0x03,req->nColors,req->baseColorNdx);
477705b261ecSmrg	return BadMatch;
477805b261ecSmrg    }
477905b261ecSmrg    if (req->labelColorNdx>req->nColors) {
478005b261ecSmrg	client->errorValue= _XkbErrCode3(0x03,req->nColors,req->labelColorNdx);
478105b261ecSmrg	return BadMatch;
478205b261ecSmrg    }
478305b261ecSmrg    if (req->labelColorNdx==req->baseColorNdx) {
478405b261ecSmrg	client->errorValue= _XkbErrCode3(0x04,req->baseColorNdx,
478505b261ecSmrg                                         req->labelColorNdx);
478605b261ecSmrg	return BadMatch;
478705b261ecSmrg    }
478805b261ecSmrg
478905b261ecSmrg    for (i=0;i<req->nColors;i++) {
479005b261ecSmrg	char *name;
479105b261ecSmrg	name= _GetCountedString(&wire,client->swapped);
479205b261ecSmrg	if (!name)
479305b261ecSmrg            return BadAlloc;
479405b261ecSmrg        if (!XkbAddGeomColor(geom,name,geom->num_colors)) {
479505b261ecSmrg            xfree(name);
479605b261ecSmrg	    return BadAlloc;
479705b261ecSmrg        }
479805b261ecSmrg        xfree(name);
479905b261ecSmrg    }
480005b261ecSmrg    if (req->nColors!=geom->num_colors) {
480105b261ecSmrg	client->errorValue= _XkbErrCode3(0x05,req->nColors,geom->num_colors);
480205b261ecSmrg	return BadMatch;
480305b261ecSmrg    }
480405b261ecSmrg    geom->label_color= &geom->colors[req->labelColorNdx];
480505b261ecSmrg    geom->base_color= &geom->colors[req->baseColorNdx];
480605b261ecSmrg
480705b261ecSmrg    if ((status=_CheckSetShapes(geom,req,&wire,client))!=Success)
480805b261ecSmrg	return status;
480905b261ecSmrg
481005b261ecSmrg    if ((status=_CheckSetSections(geom,req,&wire,client))!=Success)
481105b261ecSmrg	return status;
481205b261ecSmrg
481305b261ecSmrg    for (i=0;i<req->nDoodads;i++) {
481405b261ecSmrg	status=_CheckSetDoodad(&wire,geom,NULL,client);
481505b261ecSmrg	if (status!=Success)
481605b261ecSmrg	    return status;
481705b261ecSmrg    }
481805b261ecSmrg
481905b261ecSmrg    for (i=0;i<req->nKeyAliases;i++) {
482005b261ecSmrg	if (XkbAddGeomKeyAlias(geom,&wire[XkbKeyNameLength],wire)==NULL)
482105b261ecSmrg	    return BadAlloc;
482205b261ecSmrg	wire+= 2*XkbKeyNameLength;
482305b261ecSmrg    }
482405b261ecSmrg    return Success;
482505b261ecSmrg}
482605b261ecSmrg
482705b261ecSmrg/* FIXME: Needs to set geom on all core-sending devices. */
482805b261ecSmrgint
482905b261ecSmrgProcXkbSetGeometry(ClientPtr client)
483005b261ecSmrg{
483105b261ecSmrg    DeviceIntPtr 	dev;
483205b261ecSmrg    XkbGeometryPtr	geom,old;
483305b261ecSmrg    XkbGeometrySizesRec	sizes;
483405b261ecSmrg    Status		status;
483505b261ecSmrg    XkbDescPtr		xkb;
483605b261ecSmrg    Bool		new_name;
483705b261ecSmrg    xkbNewKeyboardNotify	nkn;
483805b261ecSmrg
483905b261ecSmrg    REQUEST(xkbSetGeometryReq);
484005b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq);
484105b261ecSmrg
484205b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
484305b261ecSmrg	return BadAccess;
484405b261ecSmrg
484505b261ecSmrg    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
484605b261ecSmrg    CHK_ATOM_OR_NONE(stuff->name);
484705b261ecSmrg
484805b261ecSmrg    xkb= dev->key->xkbInfo->desc;
484905b261ecSmrg    old= xkb->geom;
485005b261ecSmrg    xkb->geom= NULL;
485105b261ecSmrg
485205b261ecSmrg    sizes.which= 		XkbGeomAllMask;
485305b261ecSmrg    sizes.num_properties=	stuff->nProperties;
485405b261ecSmrg    sizes.num_colors=	  	stuff->nColors;
485505b261ecSmrg    sizes.num_shapes=	  	stuff->nShapes;
485605b261ecSmrg    sizes.num_sections=	  	stuff->nSections;
485705b261ecSmrg    sizes.num_doodads=	  	stuff->nDoodads;
485805b261ecSmrg    sizes.num_key_aliases=	stuff->nKeyAliases;
485905b261ecSmrg    if ((status= XkbAllocGeometry(xkb,&sizes))!=Success) {
486005b261ecSmrg	xkb->geom= old;
486105b261ecSmrg	return status;
486205b261ecSmrg    }
486305b261ecSmrg    geom= xkb->geom;
486405b261ecSmrg    geom->name= stuff->name;
486505b261ecSmrg    geom->width_mm= stuff->widthMM;
486605b261ecSmrg    geom->height_mm= stuff->heightMM;
486705b261ecSmrg    if ((status= _CheckSetGeom(geom,stuff,client))!=Success) {
486805b261ecSmrg	XkbFreeGeometry(geom,XkbGeomAllMask,True);
486905b261ecSmrg	xkb->geom= old;
487005b261ecSmrg	return status;
487105b261ecSmrg    }
487205b261ecSmrg    new_name= (xkb->names->geometry!=geom->name);
487305b261ecSmrg    xkb->names->geometry= geom->name;
487405b261ecSmrg    if (old)
487505b261ecSmrg    	XkbFreeGeometry(old,XkbGeomAllMask,True);
487605b261ecSmrg    if (new_name) {
487705b261ecSmrg	xkbNamesNotify	nn;
487805b261ecSmrg	bzero(&nn,sizeof(xkbNamesNotify));
487905b261ecSmrg	nn.changed= XkbGeometryNameMask;
488005b261ecSmrg	XkbSendNamesNotify(dev,&nn);
488105b261ecSmrg    }
488205b261ecSmrg    nkn.deviceID= nkn.oldDeviceID= dev->id;
488305b261ecSmrg    nkn.minKeyCode= nkn.oldMinKeyCode= xkb->min_key_code;
488405b261ecSmrg    nkn.maxKeyCode= nkn.oldMaxKeyCode= xkb->max_key_code;
488505b261ecSmrg    nkn.requestMajor=	XkbReqCode;
488605b261ecSmrg    nkn.requestMinor=	X_kbSetGeometry;
488705b261ecSmrg    nkn.changed=	XkbNKN_GeometryMask;
488805b261ecSmrg    XkbSendNewKeyboardNotify(dev,&nkn);
488905b261ecSmrg    return Success;
489005b261ecSmrg}
489105b261ecSmrg
489205b261ecSmrg/***====================================================================***/
489305b261ecSmrg
489405b261ecSmrgint
489505b261ecSmrgProcXkbPerClientFlags(ClientPtr client)
489605b261ecSmrg{
489705b261ecSmrg    DeviceIntPtr 		dev;
489805b261ecSmrg    xkbPerClientFlagsReply 	rep;
489905b261ecSmrg    XkbInterestPtr		interest;
490005b261ecSmrg
490105b261ecSmrg    REQUEST(xkbPerClientFlagsReq);
490205b261ecSmrg    REQUEST_SIZE_MATCH(xkbPerClientFlagsReq);
490305b261ecSmrg
490405b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
490505b261ecSmrg	return BadAccess;
490605b261ecSmrg
490705b261ecSmrg    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
490805b261ecSmrg    CHK_MASK_LEGAL(0x01,stuff->change,XkbPCF_AllFlagsMask);
490905b261ecSmrg    CHK_MASK_MATCH(0x02,stuff->change,stuff->value);
491005b261ecSmrg
491105b261ecSmrg    interest = XkbFindClientResource((DevicePtr)dev,client);
491205b261ecSmrg    rep.type= X_Reply;
491305b261ecSmrg    rep.length = 0;
491405b261ecSmrg    rep.sequenceNumber = client->sequence;
491505b261ecSmrg    if (stuff->change) {
491605b261ecSmrg	client->xkbClientFlags&= ~stuff->change;
491705b261ecSmrg	client->xkbClientFlags|= stuff->value;
491805b261ecSmrg    }
491905b261ecSmrg    if (stuff->change&XkbPCF_AutoResetControlsMask) {
492005b261ecSmrg	Bool	want;
492105b261ecSmrg	want= stuff->value&XkbPCF_AutoResetControlsMask;
492205b261ecSmrg	if (interest && !want) {
492305b261ecSmrg	    interest->autoCtrls= interest->autoCtrlValues= 0;
492405b261ecSmrg	}
492505b261ecSmrg	else if (want && (!interest)) {
492605b261ecSmrg	    XID id = FakeClientID(client->index);
492705b261ecSmrg	    AddResource(id,RT_XKBCLIENT,dev);
492805b261ecSmrg	    interest= XkbAddClientResource((DevicePtr)dev,client,id);
492905b261ecSmrg	    if (!interest)
493005b261ecSmrg		return BadAlloc;
493105b261ecSmrg	}
493205b261ecSmrg	if (interest && want ) {
493305b261ecSmrg	    register unsigned affect;
493405b261ecSmrg	    affect= stuff->ctrlsToChange;
493505b261ecSmrg
493605b261ecSmrg	    CHK_MASK_LEGAL(0x03,affect,XkbAllBooleanCtrlsMask);
493705b261ecSmrg	    CHK_MASK_MATCH(0x04,affect,stuff->autoCtrls);
493805b261ecSmrg	    CHK_MASK_MATCH(0x05,stuff->autoCtrls,stuff->autoCtrlValues);
493905b261ecSmrg
494005b261ecSmrg	    interest->autoCtrls&= ~affect;
494105b261ecSmrg	    interest->autoCtrlValues&= ~affect;
494205b261ecSmrg	    interest->autoCtrls|= stuff->autoCtrls&affect;
494305b261ecSmrg	    interest->autoCtrlValues|= stuff->autoCtrlValues&affect;
494405b261ecSmrg	}
494505b261ecSmrg    }
494605b261ecSmrg    rep.supported = XkbPCF_AllFlagsMask;
494705b261ecSmrg    rep.value= client->xkbClientFlags&XkbPCF_AllFlagsMask;
494805b261ecSmrg    if (interest) {
494905b261ecSmrg	rep.autoCtrls= interest->autoCtrls;
495005b261ecSmrg	rep.autoCtrlValues= interest->autoCtrlValues;
495105b261ecSmrg    }
495205b261ecSmrg    else {
495305b261ecSmrg	rep.autoCtrls= rep.autoCtrlValues= 0;
495405b261ecSmrg    }
495505b261ecSmrg    if ( client->swapped ) {
495605b261ecSmrg	register int n;
495705b261ecSmrg	swaps(&rep.sequenceNumber, n);
495805b261ecSmrg	swapl(&rep.supported,n);
495905b261ecSmrg	swapl(&rep.value,n);
496005b261ecSmrg	swapl(&rep.autoCtrls,n);
496105b261ecSmrg	swapl(&rep.autoCtrlValues,n);
496205b261ecSmrg    }
496305b261ecSmrg    WriteToClient(client,SIZEOF(xkbPerClientFlagsReply), (char *)&rep);
496405b261ecSmrg    return client->noClientException;
496505b261ecSmrg}
496605b261ecSmrg
496705b261ecSmrg/***====================================================================***/
496805b261ecSmrg
496905b261ecSmrg/* all latin-1 alphanumerics, plus parens, minus, underscore, slash */
497005b261ecSmrg/* and wildcards */
497105b261ecSmrgstatic unsigned char componentSpecLegal[] = {
497205b261ecSmrg        0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x87,
497305b261ecSmrg        0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07,
497405b261ecSmrg        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
497505b261ecSmrg        0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
497605b261ecSmrg};
497705b261ecSmrg
497805b261ecSmrg/* same as above but accepts percent, plus and bar too */
497905b261ecSmrgstatic unsigned char componentExprLegal[] = {
498005b261ecSmrg        0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0xff, 0x87,
498105b261ecSmrg        0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x17,
498205b261ecSmrg        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
498305b261ecSmrg        0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
498405b261ecSmrg};
498505b261ecSmrg
498605b261ecSmrgstatic char *
498705b261ecSmrgGetComponentSpec(unsigned char **pWire,Bool allowExpr,int *errRtrn)
498805b261ecSmrg{
498905b261ecSmrgint		len;
499005b261ecSmrgregister int	i;
499105b261ecSmrgunsigned char	*wire,*str,*tmp,*legal;
499205b261ecSmrg
499305b261ecSmrg    if (allowExpr)	legal= &componentExprLegal[0];
499405b261ecSmrg    else		legal= &componentSpecLegal[0];
499505b261ecSmrg
499605b261ecSmrg    wire= *pWire;
499705b261ecSmrg    len= (*(unsigned char *)wire++);
499805b261ecSmrg    if (len>0) {
499905b261ecSmrg	str= (unsigned char *)_XkbCalloc(1, len+1);
500005b261ecSmrg	if (str) {
500105b261ecSmrg	    tmp= str;
500205b261ecSmrg	    for (i=0;i<len;i++) {
500305b261ecSmrg		if (legal[(*wire)/8]&(1<<((*wire)%8)))
500405b261ecSmrg		    *tmp++= *wire++;
500505b261ecSmrg		else wire++;
500605b261ecSmrg	    }
500705b261ecSmrg	    if (tmp!=str)
500805b261ecSmrg		*tmp++= '\0';
500905b261ecSmrg	    else {
501005b261ecSmrg		_XkbFree(str);
501105b261ecSmrg		str= NULL;
501205b261ecSmrg	    }
501305b261ecSmrg	}
501405b261ecSmrg	else {
501505b261ecSmrg	    *errRtrn= BadAlloc;
501605b261ecSmrg	}
501705b261ecSmrg    }
501805b261ecSmrg    else {
501905b261ecSmrg	str= NULL;
502005b261ecSmrg    }
502105b261ecSmrg    *pWire= wire;
502205b261ecSmrg    return (char *)str;
502305b261ecSmrg}
502405b261ecSmrg
502505b261ecSmrg/***====================================================================***/
502605b261ecSmrg
502705b261ecSmrgint
502805b261ecSmrgProcXkbListComponents(ClientPtr client)
502905b261ecSmrg{
503005b261ecSmrg    DeviceIntPtr 		dev;
503105b261ecSmrg    xkbListComponentsReply 	rep;
503205b261ecSmrg    unsigned			len;
503305b261ecSmrg    int				status;
503405b261ecSmrg    unsigned char *		str;
503505b261ecSmrg    XkbSrvListInfoRec		list;
503605b261ecSmrg
503705b261ecSmrg    REQUEST(xkbListComponentsReq);
503805b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbListComponentsReq);
503905b261ecSmrg
504005b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
504105b261ecSmrg	return BadAccess;
504205b261ecSmrg
504305b261ecSmrg    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
504405b261ecSmrg
504505b261ecSmrg    status= Success;
504605b261ecSmrg    str= (unsigned char *)&stuff[1];
504705b261ecSmrg    bzero(&list,sizeof(XkbSrvListInfoRec));
504805b261ecSmrg    list.maxRtrn= stuff->maxNames;
504905b261ecSmrg    list.pattern[_XkbListKeymaps]= GetComponentSpec(&str,False,&status);
505005b261ecSmrg    list.pattern[_XkbListKeycodes]= GetComponentSpec(&str,False,&status);
505105b261ecSmrg    list.pattern[_XkbListTypes]= GetComponentSpec(&str,False,&status);
505205b261ecSmrg    list.pattern[_XkbListCompat]= GetComponentSpec(&str,False,&status);
505305b261ecSmrg    list.pattern[_XkbListSymbols]= GetComponentSpec(&str,False,&status);
505405b261ecSmrg    list.pattern[_XkbListGeometry]= GetComponentSpec(&str,False,&status);
505505b261ecSmrg    if (status!=Success)
505605b261ecSmrg	return status;
505705b261ecSmrg    len= str-((unsigned char *)stuff);
505805b261ecSmrg    if ((XkbPaddedSize(len)/4)!=stuff->length)
505905b261ecSmrg	return BadLength;
506005b261ecSmrg    if ((status=XkbDDXList(dev,&list,client))!=Success) {
506105b261ecSmrg	if (list.pool) {
506205b261ecSmrg	    _XkbFree(list.pool);
506305b261ecSmrg	    list.pool= NULL;
506405b261ecSmrg	}
506505b261ecSmrg	return status;
506605b261ecSmrg    }
506705b261ecSmrg    bzero(&rep,sizeof(xkbListComponentsReply));
506805b261ecSmrg    rep.type= X_Reply;
506905b261ecSmrg    rep.deviceID = dev->id;
507005b261ecSmrg    rep.sequenceNumber = client->sequence;
507105b261ecSmrg    rep.length = XkbPaddedSize(list.nPool)/4;
507205b261ecSmrg    rep.nKeymaps = list.nFound[_XkbListKeymaps];
507305b261ecSmrg    rep.nKeycodes = list.nFound[_XkbListKeycodes];
507405b261ecSmrg    rep.nTypes = list.nFound[_XkbListTypes];
507505b261ecSmrg    rep.nCompatMaps = list.nFound[_XkbListCompat];
507605b261ecSmrg    rep.nSymbols = list.nFound[_XkbListSymbols];
507705b261ecSmrg    rep.nGeometries = list.nFound[_XkbListGeometry];
507805b261ecSmrg    rep.extra=	0;
507905b261ecSmrg    if (list.nTotal>list.maxRtrn)
508005b261ecSmrg	rep.extra = (list.nTotal-list.maxRtrn);
508105b261ecSmrg    if (client->swapped) {
508205b261ecSmrg	register int n;
508305b261ecSmrg	swaps(&rep.sequenceNumber,n);
508405b261ecSmrg	swapl(&rep.length,n);
508505b261ecSmrg	swaps(&rep.nKeymaps,n);
508605b261ecSmrg	swaps(&rep.nKeycodes,n);
508705b261ecSmrg	swaps(&rep.nTypes,n);
508805b261ecSmrg	swaps(&rep.nCompatMaps,n);
508905b261ecSmrg	swaps(&rep.nSymbols,n);
509005b261ecSmrg	swaps(&rep.nGeometries,n);
509105b261ecSmrg	swaps(&rep.extra,n);
509205b261ecSmrg    }
509305b261ecSmrg    WriteToClient(client,SIZEOF(xkbListComponentsReply),(char *)&rep);
509405b261ecSmrg    if (list.nPool && list.pool) {
509505b261ecSmrg	WriteToClient(client,XkbPaddedSize(list.nPool), (char *)list.pool);
509605b261ecSmrg	_XkbFree(list.pool);
509705b261ecSmrg	list.pool= NULL;
509805b261ecSmrg    }
509905b261ecSmrg    return client->noClientException;
510005b261ecSmrg}
510105b261ecSmrg
510205b261ecSmrg/***====================================================================***/
510305b261ecSmrg
510405b261ecSmrgint
510505b261ecSmrgProcXkbGetKbdByName(ClientPtr client)
510605b261ecSmrg{
510705b261ecSmrg    DeviceIntPtr 		dev;
510805b261ecSmrg    DeviceIntPtr                tmpd;
510905b261ecSmrg    XkbFileInfo			finfo;
511005b261ecSmrg    xkbGetKbdByNameReply 	rep;
511105b261ecSmrg    xkbGetMapReply		mrep;
511205b261ecSmrg    xkbGetCompatMapReply	crep;
511305b261ecSmrg    xkbGetIndicatorMapReply	irep;
511405b261ecSmrg    xkbGetNamesReply		nrep;
511505b261ecSmrg    xkbGetGeometryReply		grep;
511605b261ecSmrg    XkbComponentNamesRec	names;
511705b261ecSmrg    XkbDescPtr			xkb;
511805b261ecSmrg    unsigned char *		str;
511905b261ecSmrg    char 			mapFile[PATH_MAX];
512005b261ecSmrg    unsigned			len;
512105b261ecSmrg    unsigned			fwant,fneed,reported;
512205b261ecSmrg    int				status;
512305b261ecSmrg    Bool			geom_changed;
512405b261ecSmrg    XkbSrvLedInfoPtr            old_sli;
512505b261ecSmrg    XkbSrvLedInfoPtr            sli;
512605b261ecSmrg
512705b261ecSmrg    REQUEST(xkbGetKbdByNameReq);
512805b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq);
512905b261ecSmrg
513005b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
513105b261ecSmrg	return BadAccess;
513205b261ecSmrg
513305b261ecSmrg    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
513405b261ecSmrg
513505b261ecSmrg    xkb = dev->key->xkbInfo->desc;
513605b261ecSmrg    status= Success;
513705b261ecSmrg    str= (unsigned char *)&stuff[1];
513805b261ecSmrg    names.keymap= GetComponentSpec(&str,True,&status);
513905b261ecSmrg    names.keycodes= GetComponentSpec(&str,True,&status);
514005b261ecSmrg    names.types= GetComponentSpec(&str,True,&status);
514105b261ecSmrg    names.compat= GetComponentSpec(&str,True,&status);
514205b261ecSmrg    names.symbols= GetComponentSpec(&str,True,&status);
514305b261ecSmrg    names.geometry= GetComponentSpec(&str,True,&status);
514405b261ecSmrg    if (status!=Success)
514505b261ecSmrg	return status;
514605b261ecSmrg    len= str-((unsigned char *)stuff);
514705b261ecSmrg    if ((XkbPaddedSize(len)/4)!=stuff->length)
514805b261ecSmrg	return BadLength;
514905b261ecSmrg
515005b261ecSmrg    CHK_MASK_LEGAL(0x01,stuff->want,XkbGBN_AllComponentsMask);
515105b261ecSmrg    CHK_MASK_LEGAL(0x02,stuff->need,XkbGBN_AllComponentsMask);
515205b261ecSmrg
515305b261ecSmrg    if (stuff->load)
515405b261ecSmrg	 fwant= XkbGBN_AllComponentsMask;
515505b261ecSmrg    else fwant= stuff->want|stuff->need;
515605b261ecSmrg    if (!names.keymap) {
515705b261ecSmrg	if ((!names.compat)&&
515805b261ecSmrg    		(fwant&(XkbGBN_CompatMapMask|XkbGBN_IndicatorMapMask))) {
515905b261ecSmrg	    names.compat= _XkbDupString("%");
516005b261ecSmrg	}
516105b261ecSmrg	if ((!names.types)&&(fwant&(XkbGBN_TypesMask))) {
516205b261ecSmrg	    names.types= _XkbDupString("%");
516305b261ecSmrg	}
516405b261ecSmrg	if ((!names.symbols)&&(fwant&XkbGBN_SymbolsMask)) {
516505b261ecSmrg	    names.symbols= _XkbDupString("%");
516605b261ecSmrg	}
516705b261ecSmrg	geom_changed= ((names.geometry!=NULL)&&(strcmp(names.geometry,"%")!=0));
516805b261ecSmrg	if ((!names.geometry)&&(fwant&XkbGBN_GeometryMask)) {
516905b261ecSmrg	    names.geometry= _XkbDupString("%");
517005b261ecSmrg	    geom_changed= False;
517105b261ecSmrg	}
517205b261ecSmrg    }
517305b261ecSmrg    else {
517405b261ecSmrg	geom_changed= True;
517505b261ecSmrg    }
517605b261ecSmrg
517705b261ecSmrg    bzero(mapFile,PATH_MAX);
517805b261ecSmrg    rep.type= X_Reply;
517905b261ecSmrg    rep.deviceID = dev->id;
518005b261ecSmrg    rep.sequenceNumber = client->sequence;
518105b261ecSmrg    rep.length = 0;
518205b261ecSmrg    rep.minKeyCode = xkb->min_key_code;
518305b261ecSmrg    rep.maxKeyCode = xkb->max_key_code;
518405b261ecSmrg    rep.loaded=	False;
518505b261ecSmrg    fwant= XkbConvertGetByNameComponents(True,stuff->want)|XkmVirtualModsMask;
518605b261ecSmrg    fneed= XkbConvertGetByNameComponents(True,stuff->need);
518705b261ecSmrg    rep.reported= XkbConvertGetByNameComponents(False,fwant|fneed);
518805b261ecSmrg    if (stuff->load) {
518905b261ecSmrg	fneed|= XkmKeymapRequired;
519005b261ecSmrg	fwant|= XkmKeymapLegal;
519105b261ecSmrg    }
519205b261ecSmrg    if ((fwant|fneed)&XkmSymbolsMask) {
519305b261ecSmrg	fneed|= XkmKeyNamesIndex|XkmTypesIndex;
519405b261ecSmrg	fwant|= XkmIndicatorsIndex;
519505b261ecSmrg    }
519605b261ecSmrg
519705b261ecSmrg    /* We pass dev in here so we can get the old names out if needed. */
519805b261ecSmrg    rep.found = XkbDDXLoadKeymapByNames(dev,&names,fwant,fneed,&finfo,
519905b261ecSmrg                                        mapFile,PATH_MAX);
520005b261ecSmrg    rep.newKeyboard= False;
520105b261ecSmrg    rep.pad1= rep.pad2= rep.pad3= rep.pad4= 0;
520205b261ecSmrg
520305b261ecSmrg    stuff->want|= stuff->need;
520405b261ecSmrg    if (finfo.xkb==NULL)
520505b261ecSmrg	rep.reported= 0;
520605b261ecSmrg    else {
520705b261ecSmrg	if (stuff->load)
520805b261ecSmrg	    rep.loaded= True;
520905b261ecSmrg	if (stuff->load ||
521005b261ecSmrg		((rep.reported&XkbGBN_SymbolsMask) && (finfo.xkb->compat))) {
521105b261ecSmrg	    XkbChangesRec changes;
521205b261ecSmrg	    bzero(&changes,sizeof(changes));
521305b261ecSmrg	    XkbUpdateDescActions(finfo.xkb,
521405b261ecSmrg			finfo.xkb->min_key_code,XkbNumKeys(finfo.xkb),
521505b261ecSmrg			&changes);
521605b261ecSmrg	}
521705b261ecSmrg
521805b261ecSmrg	if (finfo.xkb->map==NULL)
521905b261ecSmrg	    rep.reported&= ~(XkbGBN_SymbolsMask|XkbGBN_TypesMask);
522005b261ecSmrg	else if (rep.reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask)) {
522105b261ecSmrg	    mrep.type= X_Reply;
522205b261ecSmrg	    mrep.deviceID = dev->id;
522305b261ecSmrg	    mrep.sequenceNumber= client->sequence;
522405b261ecSmrg	    mrep.length = ((SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2);
522505b261ecSmrg	    mrep.minKeyCode = finfo.xkb->min_key_code;
522605b261ecSmrg	    mrep.maxKeyCode = finfo.xkb->max_key_code;
522705b261ecSmrg	    mrep.present = 0;
522805b261ecSmrg	    mrep.totalSyms = mrep.totalActs =
522905b261ecSmrg		mrep.totalKeyBehaviors= mrep.totalKeyExplicit=
523005b261ecSmrg		mrep.totalModMapKeys= 0;
523105b261ecSmrg	    if (rep.reported&(XkbGBN_TypesMask|XkbGBN_ClientSymbolsMask)) {
523205b261ecSmrg		mrep.present|= XkbKeyTypesMask;
523305b261ecSmrg		mrep.firstType = 0;
523405b261ecSmrg		mrep.nTypes = mrep.totalTypes= finfo.xkb->map->num_types;
523505b261ecSmrg	    }
523605b261ecSmrg	    else {
523705b261ecSmrg		mrep.firstType = mrep.nTypes= 0;
523805b261ecSmrg		mrep.totalTypes= 0;
523905b261ecSmrg	    }
524005b261ecSmrg	    if (rep.reported&XkbGBN_ClientSymbolsMask) {
524105b261ecSmrg		mrep.present|= (XkbKeySymsMask|XkbModifierMapMask);
524205b261ecSmrg		mrep.firstKeySym = mrep.firstModMapKey= finfo.xkb->min_key_code;
524305b261ecSmrg		mrep.nKeySyms = mrep.nModMapKeys= XkbNumKeys(finfo.xkb);
524405b261ecSmrg	    }
524505b261ecSmrg	    else {
524605b261ecSmrg		mrep.firstKeySym= mrep.firstModMapKey= 0;
524705b261ecSmrg		mrep.nKeySyms= mrep.nModMapKeys= 0;
524805b261ecSmrg	    }
524905b261ecSmrg	    if (rep.reported&XkbGBN_ServerSymbolsMask) {
525005b261ecSmrg		mrep.present|= XkbAllServerInfoMask;
525105b261ecSmrg		mrep.virtualMods= ~0;
525205b261ecSmrg		mrep.firstKeyAct = mrep.firstKeyBehavior =
525305b261ecSmrg			mrep.firstKeyExplicit = finfo.xkb->min_key_code;
525405b261ecSmrg		mrep.nKeyActs = mrep.nKeyBehaviors =
525505b261ecSmrg			mrep.nKeyExplicit = XkbNumKeys(finfo.xkb);
525605b261ecSmrg	    }
525705b261ecSmrg	    else {
525805b261ecSmrg		mrep.virtualMods= 0;
525905b261ecSmrg		mrep.firstKeyAct= mrep.firstKeyBehavior=
526005b261ecSmrg			mrep.firstKeyExplicit = 0;
526105b261ecSmrg		mrep.nKeyActs= mrep.nKeyBehaviors= mrep.nKeyExplicit= 0;
526205b261ecSmrg	    }
526305b261ecSmrg	    XkbComputeGetMapReplySize(finfo.xkb,&mrep);
526405b261ecSmrg	    rep.length+= SIZEOF(xGenericReply)/4+mrep.length;
526505b261ecSmrg	}
526605b261ecSmrg	if (finfo.xkb->compat==NULL)
526705b261ecSmrg	    rep.reported&= ~XkbGBN_CompatMapMask;
526805b261ecSmrg	else if (rep.reported&XkbGBN_CompatMapMask) {
526905b261ecSmrg	    crep.type= X_Reply;
527005b261ecSmrg	    crep.deviceID= dev->id;
527105b261ecSmrg	    crep.sequenceNumber= client->sequence;
527205b261ecSmrg	    crep.length= 0;
527305b261ecSmrg	    crep.groups= XkbAllGroupsMask;
527405b261ecSmrg	    crep.firstSI= 0;
527505b261ecSmrg	    crep.nSI= crep.nTotalSI= finfo.xkb->compat->num_si;
527605b261ecSmrg	    XkbComputeGetCompatMapReplySize(finfo.xkb->compat,&crep);
527705b261ecSmrg	    rep.length+= SIZEOF(xGenericReply)/4+crep.length;
527805b261ecSmrg	}
527905b261ecSmrg	if (finfo.xkb->indicators==NULL)
528005b261ecSmrg	    rep.reported&= ~XkbGBN_IndicatorMapMask;
528105b261ecSmrg	else if (rep.reported&XkbGBN_IndicatorMapMask) {
528205b261ecSmrg	    irep.type= X_Reply;
528305b261ecSmrg	    irep.deviceID= dev->id;
528405b261ecSmrg	    irep.sequenceNumber= client->sequence;
528505b261ecSmrg	    irep.length= 0;
528605b261ecSmrg	    irep.which= XkbAllIndicatorsMask;
528705b261ecSmrg	    XkbComputeGetIndicatorMapReplySize(finfo.xkb->indicators,&irep);
528805b261ecSmrg	    rep.length+= SIZEOF(xGenericReply)/4+irep.length;
528905b261ecSmrg	}
529005b261ecSmrg	if (finfo.xkb->names==NULL)
529105b261ecSmrg	    rep.reported&= ~(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask);
529205b261ecSmrg	else if (rep.reported&(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask)) {
529305b261ecSmrg	    nrep.type= X_Reply;
529405b261ecSmrg	    nrep.deviceID= dev->id;
529505b261ecSmrg	    nrep.sequenceNumber= client->sequence;
529605b261ecSmrg	    nrep.length= 0;
529705b261ecSmrg	    nrep.minKeyCode= finfo.xkb->min_key_code;
529805b261ecSmrg	    nrep.maxKeyCode= finfo.xkb->max_key_code;
529905b261ecSmrg	    if (rep.reported&XkbGBN_OtherNamesMask) {
530005b261ecSmrg		nrep.which= XkbAllNamesMask;
530105b261ecSmrg		if (finfo.xkb->map!=NULL)
530205b261ecSmrg		     nrep.nTypes= finfo.xkb->map->num_types;
530305b261ecSmrg		else nrep.nTypes= 0;
530405b261ecSmrg		nrep.nKTLevels= 0;
530505b261ecSmrg		nrep.groupNames= XkbAllGroupsMask;
530605b261ecSmrg		nrep.virtualMods= XkbAllVirtualModsMask;
530705b261ecSmrg		nrep.indicators= XkbAllIndicatorsMask;
530805b261ecSmrg		nrep.nRadioGroups= finfo.xkb->names->num_rg;
530905b261ecSmrg	    }
531005b261ecSmrg	    else {
531105b261ecSmrg		nrep.which= 0;
531205b261ecSmrg		nrep.nTypes= 0;
531305b261ecSmrg		nrep.nKTLevels= 0;
531405b261ecSmrg		nrep.groupNames= 0;
531505b261ecSmrg		nrep.virtualMods= 0;
531605b261ecSmrg		nrep.indicators= 0;
531705b261ecSmrg		nrep.nRadioGroups= 0;
531805b261ecSmrg	    }
531905b261ecSmrg	    if (rep.reported&XkbGBN_KeyNamesMask) {
532005b261ecSmrg		nrep.which|= XkbKeyNamesMask;
532105b261ecSmrg		nrep.firstKey= finfo.xkb->min_key_code;
532205b261ecSmrg		nrep.nKeys= XkbNumKeys(finfo.xkb);
532305b261ecSmrg		nrep.nKeyAliases= finfo.xkb->names->num_key_aliases;
532405b261ecSmrg		if (nrep.nKeyAliases)
532505b261ecSmrg		    nrep.which|= XkbKeyAliasesMask;
532605b261ecSmrg	    }
532705b261ecSmrg	    else {
532805b261ecSmrg		nrep.which&= ~(XkbKeyNamesMask|XkbKeyAliasesMask);
532905b261ecSmrg		nrep.firstKey= nrep.nKeys= 0;
533005b261ecSmrg		nrep.nKeyAliases= 0;
533105b261ecSmrg	    }
533205b261ecSmrg	    XkbComputeGetNamesReplySize(finfo.xkb,&nrep);
533305b261ecSmrg	    rep.length+= SIZEOF(xGenericReply)/4+nrep.length;
533405b261ecSmrg	}
533505b261ecSmrg	if (finfo.xkb->geom==NULL)
533605b261ecSmrg	    rep.reported&= ~XkbGBN_GeometryMask;
533705b261ecSmrg	else if (rep.reported&XkbGBN_GeometryMask) {
533805b261ecSmrg	    grep.type= X_Reply;
533905b261ecSmrg	    grep.deviceID= dev->id;
534005b261ecSmrg	    grep.sequenceNumber= client->sequence;
534105b261ecSmrg	    grep.length= 0;
534205b261ecSmrg	    grep.found= True;
534305b261ecSmrg	    grep.pad= 0;
534405b261ecSmrg	    grep.widthMM= grep.heightMM= 0;
534505b261ecSmrg	    grep.nProperties= grep.nColors= grep.nShapes= 0;
534605b261ecSmrg	    grep.nSections= grep.nDoodads= 0;
534705b261ecSmrg	    grep.baseColorNdx= grep.labelColorNdx= 0;
534805b261ecSmrg	    XkbComputeGetGeometryReplySize(finfo.xkb->geom,&grep,None);
534905b261ecSmrg	    rep.length+= SIZEOF(xGenericReply)/4+grep.length;
535005b261ecSmrg	}
535105b261ecSmrg    }
535205b261ecSmrg
535305b261ecSmrg    reported= rep.reported;
535405b261ecSmrg    if ( client->swapped ) {
535505b261ecSmrg	register int n;
535605b261ecSmrg	swaps(&rep.sequenceNumber,n);
535705b261ecSmrg	swapl(&rep.length,n);
535805b261ecSmrg	swaps(&rep.found,n);
535905b261ecSmrg	swaps(&rep.reported,n);
536005b261ecSmrg    }
536105b261ecSmrg    WriteToClient(client,SIZEOF(xkbGetKbdByNameReply), (char *)&rep);
536205b261ecSmrg    if (reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask))
536305b261ecSmrg	XkbSendMap(client,finfo.xkb,&mrep);
536405b261ecSmrg    if (reported&XkbGBN_CompatMapMask)
536505b261ecSmrg	XkbSendCompatMap(client,finfo.xkb->compat,&crep);
536605b261ecSmrg    if (reported&XkbGBN_IndicatorMapMask)
536705b261ecSmrg	XkbSendIndicatorMap(client,finfo.xkb->indicators,&irep);
536805b261ecSmrg    if (reported&(XkbGBN_KeyNamesMask|XkbGBN_OtherNamesMask))
536905b261ecSmrg	XkbSendNames(client,finfo.xkb,&nrep);
537005b261ecSmrg    if (reported&XkbGBN_GeometryMask)
537105b261ecSmrg	XkbSendGeometry(client,finfo.xkb->geom,&grep,False);
537205b261ecSmrg    if (rep.loaded) {
537305b261ecSmrg	XkbDescPtr		old_xkb;
537405b261ecSmrg	xkbNewKeyboardNotify 	nkn;
537505b261ecSmrg	int 			i,nG,nTG;
537605b261ecSmrg	old_xkb= xkb;
537705b261ecSmrg	xkb= finfo.xkb;
537805b261ecSmrg	dev->key->xkbInfo->desc= xkb;
537905b261ecSmrg	finfo.xkb= old_xkb; /* so it'll get freed automatically */
538005b261ecSmrg
538105b261ecSmrg	*xkb->ctrls= *old_xkb->ctrls;
538205b261ecSmrg	for (nG=nTG=0,i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
538305b261ecSmrg	    nG= XkbKeyNumGroups(xkb,i);
538405b261ecSmrg	    if (nG>=XkbNumKbdGroups) {
538505b261ecSmrg		nTG= XkbNumKbdGroups;
538605b261ecSmrg		break;
538705b261ecSmrg	    }
538805b261ecSmrg	    if (nG>nTG) {
538905b261ecSmrg		nTG= nG;
539005b261ecSmrg	    }
539105b261ecSmrg	}
539205b261ecSmrg	xkb->ctrls->num_groups= nTG;
539305b261ecSmrg
539405b261ecSmrg        for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
539505b261ecSmrg            if (tmpd == dev ||
539605b261ecSmrg                (dev->id == inputInfo.keyboard->id && tmpd->key &&
539705b261ecSmrg                 tmpd->coreEvents)) {
539805b261ecSmrg
539905b261ecSmrg                memcpy(tmpd->key->modifierMap, xkb->map->modmap,
540005b261ecSmrg                       xkb->max_key_code + 1);
540105b261ecSmrg                if (tmpd != dev)
540205b261ecSmrg                    XkbCopyKeymap(dev->key->xkbInfo->desc,
540305b261ecSmrg                                  tmpd->key->xkbInfo->desc, True);
540405b261ecSmrg                XkbUpdateCoreDescription(tmpd, True);
540505b261ecSmrg
540605b261ecSmrg                if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) {
540705b261ecSmrg                    old_sli = tmpd->kbdfeed->xkb_sli;
540805b261ecSmrg                    tmpd->kbdfeed->xkb_sli = NULL;
540905b261ecSmrg                    sli = XkbAllocSrvLedInfo(tmpd, tmpd->kbdfeed, NULL, 0);
541005b261ecSmrg                    if (sli) {
541105b261ecSmrg                        sli->explicitState = old_sli->explicitState;
541205b261ecSmrg                        sli->effectiveState = old_sli->effectiveState;
541305b261ecSmrg                    }
541405b261ecSmrg                    tmpd->kbdfeed->xkb_sli = sli;
541505b261ecSmrg                    XkbFreeSrvLedInfo(old_sli);
541605b261ecSmrg                }
541705b261ecSmrg            }
541805b261ecSmrg        }
541905b261ecSmrg
542005b261ecSmrg        /* this should be either a MN or an NKN, depending on whether or not
542105b261ecSmrg         * the keycode range changed? */
542205b261ecSmrg	nkn.deviceID= nkn.oldDeviceID= dev->id;
542305b261ecSmrg	nkn.minKeyCode= finfo.xkb->min_key_code;
542405b261ecSmrg	nkn.maxKeyCode= finfo.xkb->max_key_code;
542505b261ecSmrg	nkn.oldMinKeyCode= xkb->min_key_code;
542605b261ecSmrg	nkn.oldMaxKeyCode= xkb->max_key_code;
542705b261ecSmrg	nkn.requestMajor= XkbReqCode;
542805b261ecSmrg	nkn.requestMinor= X_kbGetKbdByName;
542905b261ecSmrg	nkn.changed= XkbNKN_KeycodesMask;
543005b261ecSmrg	if (geom_changed)
543105b261ecSmrg	    nkn.changed|= XkbNKN_GeometryMask;
543205b261ecSmrg	XkbSendNewKeyboardNotify(dev,&nkn);
543305b261ecSmrg    }
543405b261ecSmrg    if ((finfo.xkb!=NULL)&&(finfo.xkb!=xkb)) {
543505b261ecSmrg	XkbFreeKeyboard(finfo.xkb,XkbAllComponentsMask,True);
543605b261ecSmrg	finfo.xkb= NULL;
543705b261ecSmrg    }
543805b261ecSmrg    if (names.keymap)	{ _XkbFree(names.keymap); names.keymap= NULL; }
543905b261ecSmrg    if (names.keycodes)	{ _XkbFree(names.keycodes); names.keycodes= NULL; }
544005b261ecSmrg    if (names.types)	{ _XkbFree(names.types); names.types= NULL; }
544105b261ecSmrg    if (names.compat)	{ _XkbFree(names.compat); names.compat= NULL; }
544205b261ecSmrg    if (names.symbols)	{ _XkbFree(names.symbols); names.symbols= NULL; }
544305b261ecSmrg    if (names.geometry)	{ _XkbFree(names.geometry); names.geometry= NULL; }
544405b261ecSmrg    return client->noClientException;
544505b261ecSmrg}
544605b261ecSmrg
544705b261ecSmrg/***====================================================================***/
544805b261ecSmrg
544905b261ecSmrgstatic int
545005b261ecSmrgComputeDeviceLedInfoSize(	DeviceIntPtr		dev,
545105b261ecSmrg				unsigned int		what,
545205b261ecSmrg				XkbSrvLedInfoPtr	sli)
545305b261ecSmrg{
545405b261ecSmrgint			nNames,nMaps;
545505b261ecSmrgregister unsigned 	n,bit;
545605b261ecSmrg
545705b261ecSmrg    if (sli==NULL)
545805b261ecSmrg	return 0;
545905b261ecSmrg    nNames= nMaps= 0;
546005b261ecSmrg    if ((what&XkbXI_IndicatorNamesMask)==0)
546105b261ecSmrg	sli->namesPresent= 0;
546205b261ecSmrg    if ((what&XkbXI_IndicatorMapsMask)==0)
546305b261ecSmrg	sli->mapsPresent= 0;
546405b261ecSmrg
546505b261ecSmrg    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
546605b261ecSmrg	if (sli->names && sli->names[n]!=None) {
546705b261ecSmrg	    sli->namesPresent|= bit;
546805b261ecSmrg	    nNames++;
546905b261ecSmrg	}
547005b261ecSmrg	if (sli->maps && XkbIM_InUse(&sli->maps[n])) {
547105b261ecSmrg	    sli->mapsPresent|= bit;
547205b261ecSmrg	    nMaps++;
547305b261ecSmrg	}
547405b261ecSmrg    }
547505b261ecSmrg    return (nNames*4)+(nMaps*SIZEOF(xkbIndicatorMapWireDesc));
547605b261ecSmrg}
547705b261ecSmrg
547805b261ecSmrgstatic int
547905b261ecSmrgCheckDeviceLedFBs(	DeviceIntPtr			dev,
548005b261ecSmrg			int				class,
548105b261ecSmrg			int				id,
548205b261ecSmrg			xkbGetDeviceInfoReply *		rep,
548305b261ecSmrg			ClientPtr			client)
548405b261ecSmrg{
548505b261ecSmrgint			nFBs= 0;
548605b261ecSmrgint			length= 0;
548705b261ecSmrgBool			classOk;
548805b261ecSmrg
548905b261ecSmrg    if (class==XkbDfltXIClass) {
549005b261ecSmrg	if (dev->kbdfeed)	class= KbdFeedbackClass;
549105b261ecSmrg	else if (dev->leds)	class= LedFeedbackClass;
549205b261ecSmrg	else {
549305b261ecSmrg	    client->errorValue= _XkbErrCode2(XkbErr_BadClass,class);
549405b261ecSmrg	    return XkbKeyboardErrorCode;
549505b261ecSmrg	}
549605b261ecSmrg    }
549705b261ecSmrg    classOk= False;
549805b261ecSmrg    if ((dev->kbdfeed)&&((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) {
549905b261ecSmrg	KbdFeedbackPtr kf;
550005b261ecSmrg	classOk= True;
550105b261ecSmrg	for (kf= dev->kbdfeed;(kf);kf=kf->next) {
550205b261ecSmrg	    if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=kf->ctrl.id))
550305b261ecSmrg		continue;
550405b261ecSmrg	    nFBs++;
550505b261ecSmrg	    length+= SIZEOF(xkbDeviceLedsWireDesc);
550605b261ecSmrg	    if (!kf->xkb_sli)
550705b261ecSmrg		kf->xkb_sli= XkbAllocSrvLedInfo(dev,kf,NULL,0);
550805b261ecSmrg	    length+= ComputeDeviceLedInfoSize(dev,rep->present,kf->xkb_sli);
550905b261ecSmrg	    if (id!=XkbAllXIIds)
551005b261ecSmrg		break;
551105b261ecSmrg	}
551205b261ecSmrg    }
551305b261ecSmrg    if ((dev->leds)&&((class==LedFeedbackClass)||(class==XkbAllXIClasses))) {
551405b261ecSmrg	LedFeedbackPtr lf;
551505b261ecSmrg	classOk= True;
551605b261ecSmrg	for (lf= dev->leds;(lf);lf=lf->next) {
551705b261ecSmrg	    if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=lf->ctrl.id))
551805b261ecSmrg		continue;
551905b261ecSmrg	    nFBs++;
552005b261ecSmrg	    length+= SIZEOF(xkbDeviceLedsWireDesc);
552105b261ecSmrg	    if (!lf->xkb_sli)
552205b261ecSmrg		lf->xkb_sli= XkbAllocSrvLedInfo(dev,NULL,lf,0);
552305b261ecSmrg	    length+= ComputeDeviceLedInfoSize(dev,rep->present,lf->xkb_sli);
552405b261ecSmrg	    if (id!=XkbAllXIIds)
552505b261ecSmrg		break;
552605b261ecSmrg	}
552705b261ecSmrg    }
552805b261ecSmrg    if (nFBs>0) {
552905b261ecSmrg	if (rep->supported&XkbXI_IndicatorsMask) {
553005b261ecSmrg	    rep->nDeviceLedFBs= nFBs;
553105b261ecSmrg	    rep->length+= (length/4);
553205b261ecSmrg	}
553305b261ecSmrg	return Success;
553405b261ecSmrg    }
553505b261ecSmrg    if (classOk) client->errorValue= _XkbErrCode2(XkbErr_BadId,id);
553605b261ecSmrg    else	 client->errorValue= _XkbErrCode2(XkbErr_BadClass,class);
553705b261ecSmrg    return XkbKeyboardErrorCode;
553805b261ecSmrg}
553905b261ecSmrg
554005b261ecSmrgstatic int
554105b261ecSmrgSendDeviceLedInfo(	XkbSrvLedInfoPtr	sli,
554205b261ecSmrg			ClientPtr		client)
554305b261ecSmrg{
554405b261ecSmrgxkbDeviceLedsWireDesc	wire;
554505b261ecSmrgint			length;
554605b261ecSmrg
554705b261ecSmrg    length= 0;
554805b261ecSmrg    wire.ledClass= 		sli->class;
554905b261ecSmrg    wire.ledID= 		sli->id;
555005b261ecSmrg    wire.namesPresent= 		sli->namesPresent;
555105b261ecSmrg    wire.mapsPresent=   	sli->mapsPresent;
555205b261ecSmrg    wire.physIndicators= 	sli->physIndicators;
555305b261ecSmrg    wire.state=			sli->effectiveState;
555405b261ecSmrg    if (client->swapped) {
555505b261ecSmrg	register int n;
555605b261ecSmrg	swaps(&wire.ledClass,n);
555705b261ecSmrg	swaps(&wire.ledID,n);
555805b261ecSmrg	swapl(&wire.namesPresent,n);
555905b261ecSmrg	swapl(&wire.mapsPresent,n);
556005b261ecSmrg	swapl(&wire.physIndicators,n);
556105b261ecSmrg	swapl(&wire.state,n);
556205b261ecSmrg    }
556305b261ecSmrg    WriteToClient(client,SIZEOF(xkbDeviceLedsWireDesc),(char *)&wire);
556405b261ecSmrg    length+= SIZEOF(xkbDeviceLedsWireDesc);
556505b261ecSmrg    if (sli->namesPresent|sli->mapsPresent) {
556605b261ecSmrg	register unsigned i,bit;
556705b261ecSmrg	if (sli->namesPresent) {
556805b261ecSmrg	    CARD32	awire;
556905b261ecSmrg	    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
557005b261ecSmrg		if (sli->namesPresent&bit) {
557105b261ecSmrg		    awire= (CARD32)sli->names[i];
557205b261ecSmrg		    if (client->swapped) {
557305b261ecSmrg			register int n;
557405b261ecSmrg			swapl(&awire,n);
557505b261ecSmrg		    }
557605b261ecSmrg		    WriteToClient(client,4,(char *)&awire);
557705b261ecSmrg		    length+= 4;
557805b261ecSmrg		}
557905b261ecSmrg	    }
558005b261ecSmrg	}
558105b261ecSmrg	if (sli->mapsPresent) {
558205b261ecSmrg	    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
558305b261ecSmrg		xkbIndicatorMapWireDesc	iwire;
558405b261ecSmrg		if (sli->mapsPresent&bit) {
558505b261ecSmrg		    iwire.flags= 	sli->maps[i].flags;
558605b261ecSmrg		    iwire.whichGroups=	sli->maps[i].which_groups;
558705b261ecSmrg		    iwire.groups=	sli->maps[i].groups;
558805b261ecSmrg		    iwire.whichMods=	sli->maps[i].which_mods;
558905b261ecSmrg		    iwire.mods=		sli->maps[i].mods.mask;
559005b261ecSmrg		    iwire.realMods=	sli->maps[i].mods.real_mods;
559105b261ecSmrg		    iwire.virtualMods=	sli->maps[i].mods.vmods;
559205b261ecSmrg		    iwire.ctrls= 	sli->maps[i].ctrls;
559305b261ecSmrg		    if (client->swapped) {
559405b261ecSmrg			register int n;
559505b261ecSmrg			swaps(&iwire.virtualMods,n);
559605b261ecSmrg			swapl(&iwire.ctrls,n);
559705b261ecSmrg		    }
559805b261ecSmrg		    WriteToClient(client,SIZEOF(xkbIndicatorMapWireDesc),
559905b261ecSmrg								(char *)&iwire);
560005b261ecSmrg		    length+= SIZEOF(xkbIndicatorMapWireDesc);
560105b261ecSmrg		}
560205b261ecSmrg	    }
560305b261ecSmrg	}
560405b261ecSmrg    }
560505b261ecSmrg    return length;
560605b261ecSmrg}
560705b261ecSmrg
560805b261ecSmrgstatic int
560905b261ecSmrgSendDeviceLedFBs(	DeviceIntPtr	dev,
561005b261ecSmrg			int		class,
561105b261ecSmrg			int		id,
561205b261ecSmrg			unsigned	wantLength,
561305b261ecSmrg			ClientPtr	client)
561405b261ecSmrg{
561505b261ecSmrgint			length= 0;
561605b261ecSmrg
561705b261ecSmrg    if (class==XkbDfltXIClass) {
561805b261ecSmrg	if (dev->kbdfeed)	class= KbdFeedbackClass;
561905b261ecSmrg	else if (dev->leds)	class= LedFeedbackClass;
562005b261ecSmrg    }
562105b261ecSmrg    if ((dev->kbdfeed)&&
562205b261ecSmrg	((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) {
562305b261ecSmrg	KbdFeedbackPtr kf;
562405b261ecSmrg	for (kf= dev->kbdfeed;(kf);kf=kf->next) {
562505b261ecSmrg	    if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==kf->ctrl.id)) {
562605b261ecSmrg		length+= SendDeviceLedInfo(kf->xkb_sli,client);
562705b261ecSmrg		if (id!=XkbAllXIIds)
562805b261ecSmrg		    break;
562905b261ecSmrg	    }
563005b261ecSmrg	}
563105b261ecSmrg    }
563205b261ecSmrg    if ((dev->leds)&&
563305b261ecSmrg	((class==LedFeedbackClass)||(class==XkbAllXIClasses))) {
563405b261ecSmrg	LedFeedbackPtr lf;
563505b261ecSmrg	for (lf= dev->leds;(lf);lf=lf->next) {
563605b261ecSmrg	    if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==lf->ctrl.id)) {
563705b261ecSmrg		length+= SendDeviceLedInfo(lf->xkb_sli,client);
563805b261ecSmrg		if (id!=XkbAllXIIds)
563905b261ecSmrg		    break;
564005b261ecSmrg	    }
564105b261ecSmrg	}
564205b261ecSmrg    }
564305b261ecSmrg    if (length==wantLength)
564405b261ecSmrg	 return Success;
564505b261ecSmrg    else return BadLength;
564605b261ecSmrg}
564705b261ecSmrg
564805b261ecSmrgint
564905b261ecSmrgProcXkbGetDeviceInfo(ClientPtr client)
565005b261ecSmrg{
565105b261ecSmrgDeviceIntPtr		dev;
565205b261ecSmrgxkbGetDeviceInfoReply	rep;
565305b261ecSmrgint			status,nDeviceLedFBs;
565405b261ecSmrgunsigned		length,nameLen;
565505b261ecSmrgCARD16			ledClass,ledID;
565605b261ecSmrgunsigned		wanted,supported;
565705b261ecSmrgchar *			str;
565805b261ecSmrg
565905b261ecSmrg    REQUEST(xkbGetDeviceInfoReq);
566005b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq);
566105b261ecSmrg
566205b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
566305b261ecSmrg	return BadAccess;
566405b261ecSmrg
566505b261ecSmrg    wanted= stuff->wanted;
566605b261ecSmrg
566705b261ecSmrg    CHK_ANY_DEVICE(dev,stuff->deviceSpec);
566805b261ecSmrg    CHK_MASK_LEGAL(0x01,wanted,XkbXI_AllDeviceFeaturesMask);
566905b261ecSmrg
567005b261ecSmrg    if ((!dev->button)||((stuff->nBtns<1)&&(!stuff->allBtns)))
567105b261ecSmrg	wanted&= ~XkbXI_ButtonActionsMask;
567205b261ecSmrg    if ((!dev->kbdfeed)&&(!dev->leds))
567305b261ecSmrg	wanted&= ~XkbXI_IndicatorsMask;
567405b261ecSmrg
567505b261ecSmrg    nameLen= XkbSizeCountedString(dev->name);
567605b261ecSmrg    bzero((char *)&rep,SIZEOF(xkbGetDeviceInfoReply));
567705b261ecSmrg    rep.type = X_Reply;
567805b261ecSmrg    rep.deviceID= dev->id;
567905b261ecSmrg    rep.sequenceNumber = client->sequence;
568005b261ecSmrg    rep.length = nameLen/4;
568105b261ecSmrg    rep.present = wanted;
568205b261ecSmrg    rep.supported = XkbXI_AllDeviceFeaturesMask;
568305b261ecSmrg    rep.unsupported = 0;
568405b261ecSmrg    rep.firstBtnWanted = rep.nBtnsWanted = 0;
568505b261ecSmrg    rep.firstBtnRtrn = rep.nBtnsRtrn = 0;
568605b261ecSmrg    if (dev->button)
568705b261ecSmrg	 rep.totalBtns= dev->button->numButtons;
568805b261ecSmrg    else rep.totalBtns= 0;
568905b261ecSmrg    rep.devType=	dev->type;
569005b261ecSmrg    rep.hasOwnState=	(dev->key && dev->key->xkbInfo);
569105b261ecSmrg    rep.nDeviceLedFBs = 0;
569205b261ecSmrg    if (dev->kbdfeed)	rep.dfltKbdFB= dev->kbdfeed->ctrl.id;
569305b261ecSmrg    else		rep.dfltKbdFB= XkbXINone;
569405b261ecSmrg    if (dev->leds)	rep.dfltLedFB= dev->leds->ctrl.id;
569505b261ecSmrg    else		rep.dfltLedFB= XkbXINone;
569605b261ecSmrg
569705b261ecSmrg    ledClass= stuff->ledClass;
569805b261ecSmrg    ledID= stuff->ledID;
569905b261ecSmrg
570005b261ecSmrg    rep.firstBtnWanted= rep.nBtnsWanted= 0;
570105b261ecSmrg    rep.firstBtnRtrn= rep.nBtnsRtrn= 0;
570205b261ecSmrg    if (wanted&XkbXI_ButtonActionsMask) {
570305b261ecSmrg	if (stuff->allBtns) {
570405b261ecSmrg	    stuff->firstBtn= 0;
570505b261ecSmrg	    stuff->nBtns= dev->button->numButtons;
570605b261ecSmrg	}
570705b261ecSmrg
570805b261ecSmrg	if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) {
570905b261ecSmrg	    client->errorValue = _XkbErrCode4(0x02,dev->button->numButtons,
571005b261ecSmrg							stuff->firstBtn,
571105b261ecSmrg							stuff->nBtns);
571205b261ecSmrg	    return BadValue;
571305b261ecSmrg	}
571405b261ecSmrg	else {
571505b261ecSmrg	    rep.firstBtnWanted= stuff->firstBtn;
571605b261ecSmrg	    rep.nBtnsWanted= stuff->nBtns;
571705b261ecSmrg	    if (dev->button->xkb_acts!=NULL) {
571805b261ecSmrg		XkbAction *act;
571905b261ecSmrg		register int i;
572005b261ecSmrg
572105b261ecSmrg		rep.firstBtnRtrn= stuff->firstBtn;
572205b261ecSmrg		rep.nBtnsRtrn= stuff->nBtns;
572305b261ecSmrg		act= &dev->button->xkb_acts[rep.firstBtnWanted];
572405b261ecSmrg		for (i=0;i<rep.nBtnsRtrn;i++,act++) {
572505b261ecSmrg		    if (act->type!=XkbSA_NoAction)
572605b261ecSmrg			break;
572705b261ecSmrg		}
572805b261ecSmrg		rep.firstBtnRtrn+=	i;
572905b261ecSmrg		rep.nBtnsRtrn-=		i;
573005b261ecSmrg		act= &dev->button->xkb_acts[rep.firstBtnRtrn+rep.nBtnsRtrn-1];
573105b261ecSmrg		for (i=0;i<rep.nBtnsRtrn;i++,act--) {
573205b261ecSmrg		    if (act->type!=XkbSA_NoAction)
573305b261ecSmrg			break;
573405b261ecSmrg		}
573505b261ecSmrg		rep.nBtnsRtrn-=		i;
573605b261ecSmrg	    }
573705b261ecSmrg	    rep.length+= (rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc))/4;
573805b261ecSmrg	}
573905b261ecSmrg    }
574005b261ecSmrg
574105b261ecSmrg    if (wanted&XkbXI_IndicatorsMask) {
574205b261ecSmrg	status= CheckDeviceLedFBs(dev,ledClass,ledID,&rep,client);
574305b261ecSmrg	if (status!=Success)
574405b261ecSmrg	    return status;
574505b261ecSmrg    }
574605b261ecSmrg    length= rep.length*4;
574705b261ecSmrg    supported= rep.supported;
574805b261ecSmrg    nDeviceLedFBs = rep.nDeviceLedFBs;
574905b261ecSmrg    if (client->swapped) {
575005b261ecSmrg	register int n;
575105b261ecSmrg	swaps(&rep.sequenceNumber,n);
575205b261ecSmrg	swapl(&rep.length,n);
575305b261ecSmrg	swaps(&rep.present,n);
575405b261ecSmrg	swaps(&rep.supported,n);
575505b261ecSmrg	swaps(&rep.unsupported,n);
575605b261ecSmrg	swaps(&rep.nDeviceLedFBs,n);
575705b261ecSmrg	swapl(&rep.type,n);
575805b261ecSmrg    }
575905b261ecSmrg    WriteToClient(client,SIZEOF(xkbGetDeviceInfoReply), (char *)&rep);
576005b261ecSmrg
576105b261ecSmrg    str= (char*) ALLOCATE_LOCAL(nameLen);
576205b261ecSmrg    if (!str)
576305b261ecSmrg	return BadAlloc;
576405b261ecSmrg    XkbWriteCountedString(str,dev->name,client->swapped);
576505b261ecSmrg    WriteToClient(client,nameLen,str);
576605b261ecSmrg    DEALLOCATE_LOCAL(str);
576705b261ecSmrg    length-= nameLen;
576805b261ecSmrg
576905b261ecSmrg    if (rep.nBtnsRtrn>0) {
577005b261ecSmrg	int			sz;
577105b261ecSmrg	xkbActionWireDesc *	awire;
577205b261ecSmrg	sz= rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc);
577305b261ecSmrg	awire= (xkbActionWireDesc *)&dev->button->xkb_acts[rep.firstBtnRtrn];
577405b261ecSmrg	WriteToClient(client,sz,(char *)awire);
577505b261ecSmrg	length-= sz;
577605b261ecSmrg    }
577705b261ecSmrg    if (nDeviceLedFBs>0) {
577805b261ecSmrg	status= SendDeviceLedFBs(dev,ledClass,ledID,length,client);
577905b261ecSmrg	if (status!=Success)
578005b261ecSmrg	    return status;
578105b261ecSmrg    }
578205b261ecSmrg    else if (length!=0)  {
578305b261ecSmrg#ifdef DEBUG
578405b261ecSmrg	ErrorF("Internal Error!  BadLength in ProcXkbGetDeviceInfo\n");
578505b261ecSmrg	ErrorF("                 Wrote %d fewer bytes than expected\n",length);
578605b261ecSmrg#endif
578705b261ecSmrg	return BadLength;
578805b261ecSmrg    }
578905b261ecSmrg    if (stuff->wanted&(~supported)) {
579005b261ecSmrg	xkbExtensionDeviceNotify ed;
579105b261ecSmrg	bzero((char *)&ed,SIZEOF(xkbExtensionDeviceNotify));
579205b261ecSmrg	ed.ledClass=		ledClass;
579305b261ecSmrg	ed.ledID=		ledID;
579405b261ecSmrg	ed.ledsDefined= 	0;
579505b261ecSmrg	ed.ledState=		0;
579605b261ecSmrg	ed.firstBtn= ed.nBtns=	0;
579705b261ecSmrg	ed.reason=		XkbXI_UnsupportedFeatureMask;
579805b261ecSmrg	ed.supported=		supported;
579905b261ecSmrg	ed.unsupported=		stuff->wanted&(~supported);
580005b261ecSmrg	XkbSendExtensionDeviceNotify(dev,client,&ed);
580105b261ecSmrg    }
580205b261ecSmrg    return client->noClientException;
580305b261ecSmrg}
580405b261ecSmrg
580505b261ecSmrgstatic char *
580605b261ecSmrgCheckSetDeviceIndicators(	char *		wire,
580705b261ecSmrg				DeviceIntPtr	dev,
580805b261ecSmrg				int		num,
580905b261ecSmrg				int *		status_rtrn,
581005b261ecSmrg				ClientPtr	client)
581105b261ecSmrg{
581205b261ecSmrgxkbDeviceLedsWireDesc *	ledWire;
581305b261ecSmrgint			i;
581405b261ecSmrgXkbSrvLedInfoPtr 	sli;
581505b261ecSmrg
581605b261ecSmrg    ledWire= (xkbDeviceLedsWireDesc *)wire;
581705b261ecSmrg    for (i=0;i<num;i++) {
581805b261ecSmrg	if (client->swapped) {
581905b261ecSmrg	   register int n;
582005b261ecSmrg	   swaps(&ledWire->ledClass,n);
582105b261ecSmrg	   swaps(&ledWire->ledID,n);
582205b261ecSmrg	   swapl(&ledWire->namesPresent,n);
582305b261ecSmrg	   swapl(&ledWire->mapsPresent,n);
582405b261ecSmrg	   swapl(&ledWire->physIndicators,n);
582505b261ecSmrg	}
582605b261ecSmrg
582705b261ecSmrg        sli= XkbFindSrvLedInfo(dev,ledWire->ledClass,ledWire->ledID,
582805b261ecSmrg							XkbXI_IndicatorsMask);
582905b261ecSmrg	if (sli!=NULL) {
583005b261ecSmrg	    register int n;
583105b261ecSmrg	    register unsigned bit;
583205b261ecSmrg	    int nMaps,nNames;
583305b261ecSmrg	    CARD32 *atomWire;
583405b261ecSmrg	    xkbIndicatorMapWireDesc *mapWire;
583505b261ecSmrg
583605b261ecSmrg	    nMaps= nNames= 0;
583705b261ecSmrg	    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
583805b261ecSmrg		if (ledWire->namesPresent&bit)
583905b261ecSmrg		    nNames++;
584005b261ecSmrg		if (ledWire->mapsPresent&bit)
584105b261ecSmrg		    nMaps++;
584205b261ecSmrg	    }
584305b261ecSmrg	    atomWire= (CARD32 *)&ledWire[1];
584405b261ecSmrg	    if (nNames>0) {
584505b261ecSmrg		for (n=0;n<nNames;n++) {
584605b261ecSmrg		    if (client->swapped) {
584705b261ecSmrg			register int t;
584805b261ecSmrg			swapl(atomWire,t);
584905b261ecSmrg		    }
585005b261ecSmrg		    CHK_ATOM_OR_NONE3(((Atom)(*atomWire)),client->errorValue,
585105b261ecSmrg							*status_rtrn,NULL);
585205b261ecSmrg		    atomWire++;
585305b261ecSmrg		}
585405b261ecSmrg	    }
585505b261ecSmrg	    mapWire= (xkbIndicatorMapWireDesc *)atomWire;
585605b261ecSmrg	    if (nMaps>0) {
585705b261ecSmrg		for (n=0;n<nMaps;n++) {
585805b261ecSmrg		    if (client->swapped) {
585905b261ecSmrg			register int t;
586005b261ecSmrg			swaps(&mapWire->virtualMods,t);
586105b261ecSmrg			swapl(&mapWire->ctrls,t);
586205b261ecSmrg		    }
586305b261ecSmrg		    CHK_MASK_LEGAL3(0x21,mapWire->whichGroups,
586405b261ecSmrg						XkbIM_UseAnyGroup,
586505b261ecSmrg						client->errorValue,
586605b261ecSmrg						*status_rtrn,NULL);
586705b261ecSmrg		    CHK_MASK_LEGAL3(0x22,mapWire->whichMods,XkbIM_UseAnyMods,
586805b261ecSmrg						client->errorValue,
586905b261ecSmrg						*status_rtrn,NULL);
587005b261ecSmrg		    mapWire++;
587105b261ecSmrg		}
587205b261ecSmrg	    }
587305b261ecSmrg	    ledWire= (xkbDeviceLedsWireDesc *)mapWire;
587405b261ecSmrg	}
587505b261ecSmrg	else {
587605b261ecSmrg	    /* SHOULD NEVER HAPPEN */
587705b261ecSmrg	    return (char *)ledWire;
587805b261ecSmrg	}
587905b261ecSmrg    }
588005b261ecSmrg    return (char *)ledWire;
588105b261ecSmrg}
588205b261ecSmrg
588305b261ecSmrgstatic char *
588405b261ecSmrgSetDeviceIndicators(	char *			wire,
588505b261ecSmrg			DeviceIntPtr		dev,
588605b261ecSmrg			unsigned		changed,
588705b261ecSmrg			int			num,
588805b261ecSmrg			int *			status_rtrn,
588905b261ecSmrg			ClientPtr		client,
589005b261ecSmrg			xkbExtensionDeviceNotify *ev)
589105b261ecSmrg{
589205b261ecSmrgxkbDeviceLedsWireDesc *		ledWire;
589305b261ecSmrgint				i;
589405b261ecSmrgXkbEventCauseRec		cause;
589505b261ecSmrgunsigned			namec,mapc,statec;
589605b261ecSmrgxkbExtensionDeviceNotify	ed;
589705b261ecSmrgXkbChangesRec			changes;
589805b261ecSmrgDeviceIntPtr			kbd;
589905b261ecSmrg
590005b261ecSmrg    bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify));
590105b261ecSmrg    bzero((char *)&changes,sizeof(XkbChangesRec));
590205b261ecSmrg    XkbSetCauseXkbReq(&cause,X_kbSetDeviceInfo,client);
590305b261ecSmrg    ledWire= (xkbDeviceLedsWireDesc *)wire;
590405b261ecSmrg    for (i=0;i<num;i++) {
590505b261ecSmrg	register int			n;
590605b261ecSmrg	register unsigned 		bit;
590705b261ecSmrg	CARD32 *			atomWire;
590805b261ecSmrg	xkbIndicatorMapWireDesc *	mapWire;
590905b261ecSmrg	XkbSrvLedInfoPtr		sli;
591005b261ecSmrg
591105b261ecSmrg	namec= mapc= statec= 0;
591205b261ecSmrg    	sli= XkbFindSrvLedInfo(dev,ledWire->ledClass,ledWire->ledID,
591305b261ecSmrg						XkbXI_IndicatorMapsMask);
591405b261ecSmrg	if (!sli) {
591505b261ecSmrg	    /* SHOULD NEVER HAPPEN!! */
591605b261ecSmrg	    return (char *)ledWire;
591705b261ecSmrg	}
591805b261ecSmrg
591905b261ecSmrg	atomWire= (CARD32 *)&ledWire[1];
592005b261ecSmrg	if (changed&XkbXI_IndicatorNamesMask) {
592105b261ecSmrg	    namec= sli->namesPresent|ledWire->namesPresent;
592205b261ecSmrg	    bzero((char *)sli->names,XkbNumIndicators*sizeof(Atom));
592305b261ecSmrg	}
592405b261ecSmrg	if (ledWire->namesPresent) {
592505b261ecSmrg	    sli->namesPresent= ledWire->namesPresent;
592605b261ecSmrg	    bzero((char *)sli->names,XkbNumIndicators*sizeof(Atom));
592705b261ecSmrg	    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
592805b261ecSmrg		if (ledWire->namesPresent&bit) {
592905b261ecSmrg		     sli->names[n]= (Atom)*atomWire;
593005b261ecSmrg		     if (sli->names[n]==None)
593105b261ecSmrg			ledWire->namesPresent&= ~bit;
593205b261ecSmrg		     atomWire++;
593305b261ecSmrg		}
593405b261ecSmrg	    }
593505b261ecSmrg	}
593605b261ecSmrg	mapWire= (xkbIndicatorMapWireDesc *)atomWire;
593705b261ecSmrg	if (changed&XkbXI_IndicatorMapsMask) {
593805b261ecSmrg	    mapc= sli->mapsPresent|ledWire->mapsPresent;
593905b261ecSmrg	    sli->mapsPresent= ledWire->mapsPresent;
594005b261ecSmrg	    bzero((char*)sli->maps,XkbNumIndicators*sizeof(XkbIndicatorMapRec));
594105b261ecSmrg	}
594205b261ecSmrg	if (ledWire->mapsPresent) {
594305b261ecSmrg	    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
594405b261ecSmrg		if (ledWire->mapsPresent&bit) {
594505b261ecSmrg		    sli->maps[n].flags=		mapWire->flags;
594605b261ecSmrg		    sli->maps[n].which_groups=	mapWire->whichGroups;
594705b261ecSmrg		    sli->maps[n].groups=	mapWire->groups;
594805b261ecSmrg		    sli->maps[n].which_mods=	mapWire->whichMods;
594905b261ecSmrg		    sli->maps[n].mods.mask=	mapWire->mods;
595005b261ecSmrg		    sli->maps[n].mods.real_mods=mapWire->realMods;
595105b261ecSmrg		    sli->maps[n].mods.vmods=	mapWire->virtualMods;
595205b261ecSmrg		    sli->maps[n].ctrls=		mapWire->ctrls;
595305b261ecSmrg		    mapWire++;
595405b261ecSmrg		}
595505b261ecSmrg	    }
595605b261ecSmrg	}
595705b261ecSmrg	if (changed&XkbXI_IndicatorStateMask) {
595805b261ecSmrg	    statec= sli->effectiveState^ledWire->state;
595905b261ecSmrg	    sli->explicitState&= ~statec;
596005b261ecSmrg	    sli->explicitState|= (ledWire->state&statec);
596105b261ecSmrg	}
596205b261ecSmrg	if (namec)
596305b261ecSmrg	    XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause);
596405b261ecSmrg	if (mapc)
596505b261ecSmrg	    XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause);
596605b261ecSmrg	if (statec)
596705b261ecSmrg	    XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause);
596805b261ecSmrg
596905b261ecSmrg	kbd= dev;
597005b261ecSmrg	if ((sli->flags&XkbSLI_HasOwnState)==0)
597105b261ecSmrg	    kbd= (DeviceIntPtr)LookupKeyboardDevice();
597205b261ecSmrg
597305b261ecSmrg	XkbFlushLedEvents(dev,kbd,sli,&ed,&changes,&cause);
597405b261ecSmrg	ledWire= (xkbDeviceLedsWireDesc *)mapWire;
597505b261ecSmrg    }
597605b261ecSmrg    return (char *)ledWire;
597705b261ecSmrg}
597805b261ecSmrg
597905b261ecSmrg/* FIXME: Needs to set info on all core-sending devices. */
598005b261ecSmrgint
598105b261ecSmrgProcXkbSetDeviceInfo(ClientPtr client)
598205b261ecSmrg{
598305b261ecSmrgDeviceIntPtr		dev;
598405b261ecSmrgunsigned		change;
598505b261ecSmrgchar *			wire;
598605b261ecSmrgxkbExtensionDeviceNotify ed;
598705b261ecSmrg
598805b261ecSmrg    REQUEST(xkbSetDeviceInfoReq);
598905b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq);
599005b261ecSmrg
599105b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
599205b261ecSmrg	return BadAccess;
599305b261ecSmrg
599405b261ecSmrg    change= stuff->change;
599505b261ecSmrg
599605b261ecSmrg    CHK_ANY_DEVICE(dev,stuff->deviceSpec);
599705b261ecSmrg    CHK_MASK_LEGAL(0x01,change,XkbXI_AllFeaturesMask);
599805b261ecSmrg
599905b261ecSmrg    wire= (char *)&stuff[1];
600005b261ecSmrg    if (change&XkbXI_ButtonActionsMask) {
600105b261ecSmrg	if (!dev->button) {
600205b261ecSmrg	    client->errorValue = _XkbErrCode2(XkbErr_BadClass,ButtonClass);
600305b261ecSmrg	    return XkbKeyboardErrorCode;
600405b261ecSmrg	}
600505b261ecSmrg	if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) {
600605b261ecSmrg	    client->errorValue= _XkbErrCode4(0x02,stuff->firstBtn,stuff->nBtns,
600705b261ecSmrg						dev->button->numButtons);
600805b261ecSmrg	    return BadMatch;
600905b261ecSmrg	}
601005b261ecSmrg	wire+= (stuff->nBtns*SIZEOF(xkbActionWireDesc));
601105b261ecSmrg    }
601205b261ecSmrg    if (stuff->change&XkbXI_IndicatorsMask) {
601305b261ecSmrg	int status= Success;
601405b261ecSmrg	wire= CheckSetDeviceIndicators(wire,dev,stuff->nDeviceLedFBs,
601505b261ecSmrg							&status,client);
601605b261ecSmrg	if (status!=Success)
601705b261ecSmrg	    return status;
601805b261ecSmrg    }
601905b261ecSmrg    if (((wire-((char *)stuff))/4)!=stuff->length)
602005b261ecSmrg	return BadLength;
602105b261ecSmrg
602205b261ecSmrg    bzero((char *)&ed,SIZEOF(xkbExtensionDeviceNotify));
602305b261ecSmrg    ed.deviceID=	dev->id;
602405b261ecSmrg    wire= (char *)&stuff[1];
602505b261ecSmrg    if (change&XkbXI_ButtonActionsMask) {
602605b261ecSmrg	int			nBtns,sz,i;
602705b261ecSmrg	XkbAction *		acts;
602805b261ecSmrg	DeviceIntPtr		kbd;
602905b261ecSmrg
603005b261ecSmrg	nBtns= dev->button->numButtons;
603105b261ecSmrg	acts= dev->button->xkb_acts;
603205b261ecSmrg	if (acts==NULL) {
603305b261ecSmrg	    acts= _XkbTypedCalloc(nBtns,XkbAction);
603405b261ecSmrg	    if (!acts)
603505b261ecSmrg		return BadAlloc;
603605b261ecSmrg	    dev->button->xkb_acts= acts;
603705b261ecSmrg	}
603805b261ecSmrg	sz= stuff->nBtns*SIZEOF(xkbActionWireDesc);
603905b261ecSmrg	memcpy((char *)&acts[stuff->firstBtn],(char *)wire,sz);
604005b261ecSmrg	wire+= sz;
604105b261ecSmrg	ed.reason|=	XkbXI_ButtonActionsMask;
604205b261ecSmrg	ed.firstBtn=	stuff->firstBtn;
604305b261ecSmrg	ed.nBtns=	stuff->nBtns;
604405b261ecSmrg
604505b261ecSmrg	if (dev->key)	kbd= dev;
604605b261ecSmrg	else		kbd= (DeviceIntPtr)LookupKeyboardDevice();
604705b261ecSmrg	acts= &dev->button->xkb_acts[stuff->firstBtn];
604805b261ecSmrg	for (i=0;i<stuff->nBtns;i++,acts++) {
604905b261ecSmrg	    if (acts->type!=XkbSA_NoAction)
605005b261ecSmrg		XkbSetActionKeyMods(kbd->key->xkbInfo->desc,acts,0);
605105b261ecSmrg	}
605205b261ecSmrg    }
605305b261ecSmrg    if (stuff->change&XkbXI_IndicatorsMask) {
605405b261ecSmrg	int status= Success;
605505b261ecSmrg	wire= SetDeviceIndicators(wire,dev,change,stuff->nDeviceLedFBs,
605605b261ecSmrg							&status,client,&ed);
605705b261ecSmrg	if (status!=Success)
605805b261ecSmrg	    return status;
605905b261ecSmrg    }
606005b261ecSmrg    if ((stuff->change)&&(ed.reason))
606105b261ecSmrg	XkbSendExtensionDeviceNotify(dev,client,&ed);
606205b261ecSmrg    return client->noClientException;
606305b261ecSmrg}
606405b261ecSmrg
606505b261ecSmrg/***====================================================================***/
606605b261ecSmrg
606705b261ecSmrgint
606805b261ecSmrgProcXkbSetDebuggingFlags(ClientPtr client)
606905b261ecSmrg{
607005b261ecSmrgCARD32 				newFlags,newCtrls,extraLength;
607105b261ecSmrgxkbSetDebuggingFlagsReply 	rep;
607205b261ecSmrg
607305b261ecSmrg    REQUEST(xkbSetDebuggingFlagsReq);
607405b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq);
607505b261ecSmrg
607605b261ecSmrg    newFlags=  xkbDebugFlags&(~stuff->affectFlags);
607705b261ecSmrg    newFlags|= (stuff->flags&stuff->affectFlags);
607805b261ecSmrg    newCtrls=  xkbDebugCtrls&(~stuff->affectCtrls);
607905b261ecSmrg    newCtrls|= (stuff->ctrls&stuff->affectCtrls);
608005b261ecSmrg    if (xkbDebugFlags || newFlags || stuff->msgLength) {
608105b261ecSmrg	ErrorF("XkbDebug: Setting debug flags to 0x%lx\n",(long)newFlags);
608205b261ecSmrg	if (newCtrls!=xkbDebugCtrls)
608305b261ecSmrg	    ErrorF("XkbDebug: Setting debug controls to 0x%lx\n",(long)newCtrls);
608405b261ecSmrg    }
608505b261ecSmrg    extraLength= (stuff->length<<2)-sz_xkbSetDebuggingFlagsReq;
608605b261ecSmrg    if (stuff->msgLength>0) {
608705b261ecSmrg	char *msg;
608805b261ecSmrg	if (extraLength<XkbPaddedSize(stuff->msgLength)) {
608905b261ecSmrg	    ErrorF("XkbDebug: msgLength= %d, length= %ld (should be %d)\n",
609005b261ecSmrg			stuff->msgLength,(long)extraLength,
609105b261ecSmrg			XkbPaddedSize(stuff->msgLength));
609205b261ecSmrg	    return BadLength;
609305b261ecSmrg	}
609405b261ecSmrg	msg= (char *)&stuff[1];
609505b261ecSmrg	if (msg[stuff->msgLength-1]!='\0') {
609605b261ecSmrg	    ErrorF("XkbDebug: message not null-terminated\n");
609705b261ecSmrg	    return BadValue;
609805b261ecSmrg	}
609905b261ecSmrg	ErrorF("XkbDebug: %s\n",msg);
610005b261ecSmrg    }
610105b261ecSmrg    xkbDebugFlags = newFlags;
610205b261ecSmrg    xkbDebugCtrls = newCtrls;
610305b261ecSmrg
610405b261ecSmrg    XkbDisableLockActions= (xkbDebugCtrls&XkbDF_DisableLocks);
610505b261ecSmrg
610605b261ecSmrg    rep.type= X_Reply;
610705b261ecSmrg    rep.length = 0;
610805b261ecSmrg    rep.sequenceNumber = client->sequence;
610905b261ecSmrg    rep.currentFlags = newFlags;
611005b261ecSmrg    rep.currentCtrls = newCtrls;
611105b261ecSmrg    rep.supportedFlags = ~0;
611205b261ecSmrg    rep.supportedCtrls = ~0;
611305b261ecSmrg    if ( client->swapped ) {
611405b261ecSmrg	register int n;
611505b261ecSmrg	swaps(&rep.sequenceNumber, n);
611605b261ecSmrg	swapl(&rep.currentFlags, n);
611705b261ecSmrg	swapl(&rep.currentCtrls, n);
611805b261ecSmrg	swapl(&rep.supportedFlags, n);
611905b261ecSmrg	swapl(&rep.supportedCtrls, n);
612005b261ecSmrg    }
612105b261ecSmrg    WriteToClient(client,SIZEOF(xkbSetDebuggingFlagsReply), (char *)&rep);
612205b261ecSmrg    return client->noClientException;
612305b261ecSmrg}
612405b261ecSmrg
612505b261ecSmrg/***====================================================================***/
612605b261ecSmrg
612705b261ecSmrgstatic int
612805b261ecSmrgProcXkbDispatch (ClientPtr client)
612905b261ecSmrg{
613005b261ecSmrg    REQUEST(xReq);
613105b261ecSmrg    switch (stuff->data)
613205b261ecSmrg    {
613305b261ecSmrg    case X_kbUseExtension:
613405b261ecSmrg	return ProcXkbUseExtension(client);
613505b261ecSmrg    case X_kbSelectEvents:
613605b261ecSmrg	return ProcXkbSelectEvents(client);
613705b261ecSmrg    case X_kbBell:
613805b261ecSmrg	return ProcXkbBell(client);
613905b261ecSmrg    case X_kbGetState:
614005b261ecSmrg	return ProcXkbGetState(client);
614105b261ecSmrg    case X_kbLatchLockState:
614205b261ecSmrg	return ProcXkbLatchLockState(client);
614305b261ecSmrg    case X_kbGetControls:
614405b261ecSmrg	return ProcXkbGetControls(client);
614505b261ecSmrg    case X_kbSetControls:
614605b261ecSmrg	return ProcXkbSetControls(client);
614705b261ecSmrg    case X_kbGetMap:
614805b261ecSmrg	return ProcXkbGetMap(client);
614905b261ecSmrg    case X_kbSetMap:
615005b261ecSmrg	return ProcXkbSetMap(client);
615105b261ecSmrg    case X_kbGetCompatMap:
615205b261ecSmrg	return ProcXkbGetCompatMap(client);
615305b261ecSmrg    case X_kbSetCompatMap:
615405b261ecSmrg	return ProcXkbSetCompatMap(client);
615505b261ecSmrg    case X_kbGetIndicatorState:
615605b261ecSmrg	return ProcXkbGetIndicatorState(client);
615705b261ecSmrg    case X_kbGetIndicatorMap:
615805b261ecSmrg	return ProcXkbGetIndicatorMap(client);
615905b261ecSmrg    case X_kbSetIndicatorMap:
616005b261ecSmrg	return ProcXkbSetIndicatorMap(client);
616105b261ecSmrg    case X_kbGetNamedIndicator:
616205b261ecSmrg	return ProcXkbGetNamedIndicator(client);
616305b261ecSmrg    case X_kbSetNamedIndicator:
616405b261ecSmrg	return ProcXkbSetNamedIndicator(client);
616505b261ecSmrg    case X_kbGetNames:
616605b261ecSmrg	return ProcXkbGetNames(client);
616705b261ecSmrg    case X_kbSetNames:
616805b261ecSmrg	return ProcXkbSetNames(client);
616905b261ecSmrg    case X_kbGetGeometry:
617005b261ecSmrg	return ProcXkbGetGeometry(client);
617105b261ecSmrg    case X_kbSetGeometry:
617205b261ecSmrg	return ProcXkbSetGeometry(client);
617305b261ecSmrg    case X_kbPerClientFlags:
617405b261ecSmrg	return ProcXkbPerClientFlags(client);
617505b261ecSmrg    case X_kbListComponents:
617605b261ecSmrg	return ProcXkbListComponents(client);
617705b261ecSmrg    case X_kbGetKbdByName:
617805b261ecSmrg	return ProcXkbGetKbdByName(client);
617905b261ecSmrg    case X_kbGetDeviceInfo:
618005b261ecSmrg	return ProcXkbGetDeviceInfo(client);
618105b261ecSmrg    case X_kbSetDeviceInfo:
618205b261ecSmrg	return ProcXkbSetDeviceInfo(client);
618305b261ecSmrg    case X_kbSetDebuggingFlags:
618405b261ecSmrg	return ProcXkbSetDebuggingFlags(client);
618505b261ecSmrg    default:
618605b261ecSmrg	return BadRequest;
618705b261ecSmrg    }
618805b261ecSmrg}
618905b261ecSmrg
619005b261ecSmrgstatic int
619105b261ecSmrgXkbClientGone(pointer data,XID id)
619205b261ecSmrg{
619305b261ecSmrg    DevicePtr	pXDev = (DevicePtr)data;
619405b261ecSmrg
619505b261ecSmrg    if (!XkbRemoveResourceClient(pXDev,id)) {
619605b261ecSmrg	ErrorF("Internal Error! bad RemoveResourceClient in XkbClientGone\n");
619705b261ecSmrg    }
619805b261ecSmrg    return 1;
619905b261ecSmrg}
620005b261ecSmrg
620105b261ecSmrg/*ARGSUSED*/
620205b261ecSmrgstatic void
620305b261ecSmrgXkbResetProc(ExtensionEntry *extEntry)
620405b261ecSmrg{
620505b261ecSmrg}
620605b261ecSmrg
620705b261ecSmrgvoid
620805b261ecSmrgXkbExtensionInit(void)
620905b261ecSmrg{
621005b261ecSmrg    ExtensionEntry *extEntry;
621105b261ecSmrg
621205b261ecSmrg    if ((extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors,
621305b261ecSmrg				 ProcXkbDispatch, SProcXkbDispatch,
621405b261ecSmrg				 XkbResetProc, StandardMinorOpcode))) {
621505b261ecSmrg	XkbReqCode = (unsigned char)extEntry->base;
621605b261ecSmrg	XkbEventBase = (unsigned char)extEntry->eventBase;
621705b261ecSmrg	XkbErrorBase = (unsigned char)extEntry->errorBase;
621805b261ecSmrg	XkbKeyboardErrorCode = XkbErrorBase+XkbKeyboard;
621905b261ecSmrg	RT_XKBCLIENT = CreateNewResourceType(XkbClientGone);
622005b261ecSmrg    }
622105b261ecSmrg    return;
622205b261ecSmrg}
622305b261ecSmrg
622405b261ecSmrg
6225