xkb.c revision 52397711
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"
414642e01fSmrg#include "xace.h"
4205b261ecSmrg#include "xkb.h"
4305b261ecSmrg
4405b261ecSmrg#include <X11/extensions/XI.h>
4505b261ecSmrg
4605b261ecSmrg	int	XkbEventBase;
4705b261ecSmrgstatic	int	XkbErrorBase;
4805b261ecSmrg	int	XkbReqCode;
494642e01fSmrg	int	XkbKeyboardErrorCode;
5005b261ecSmrgCARD32	xkbDebugFlags = 0;
5105b261ecSmrgstatic CARD32	xkbDebugCtrls = 0;
5205b261ecSmrg
5305b261ecSmrgstatic RESTYPE	RT_XKBCLIENT;
5405b261ecSmrg
5505b261ecSmrg/***====================================================================***/
5605b261ecSmrg
574642e01fSmrg#define	CHK_DEVICE(dev, id, client, access_mode, lf) {\
5805b261ecSmrg    int why;\
594642e01fSmrg    int rc = lf(&(dev), id, client, access_mode, &why);\
604642e01fSmrg    if (rc != Success) {\
614642e01fSmrg	client->errorValue = _XkbErrCode2(why, id);\
624642e01fSmrg	return rc;\
6305b261ecSmrg    }\
6405b261ecSmrg}
6505b261ecSmrg
664642e01fSmrg#define	CHK_KBD_DEVICE(dev, id, client, mode) \
674642e01fSmrg    CHK_DEVICE(dev, id, client, mode, _XkbLookupKeyboard)
684642e01fSmrg#define	CHK_LED_DEVICE(dev, id, client, mode) \
694642e01fSmrg    CHK_DEVICE(dev, id, client, mode, _XkbLookupLedDevice)
704642e01fSmrg#define	CHK_BELL_DEVICE(dev, id, client, mode) \
714642e01fSmrg    CHK_DEVICE(dev, id, client, mode, _XkbLookupBellDevice)
724642e01fSmrg#define	CHK_ANY_DEVICE(dev, id, client, mode) \
734642e01fSmrg    CHK_DEVICE(dev, id, client, mode, _XkbLookupAnyDevice)
7405b261ecSmrg
7505b261ecSmrg#define	CHK_ATOM_ONLY2(a,ev,er) {\
7605b261ecSmrg	if (((a)==None)||(!ValidAtom((a)))) {\
7705b261ecSmrg	    (ev)= (XID)(a);\
7805b261ecSmrg	    return er;\
7905b261ecSmrg	}\
8005b261ecSmrg}
8105b261ecSmrg#define	CHK_ATOM_ONLY(a) \
8205b261ecSmrg	CHK_ATOM_ONLY2(a,client->errorValue,BadAtom)
8305b261ecSmrg
8405b261ecSmrg#define	CHK_ATOM_OR_NONE3(a,ev,er,ret) {\
8505b261ecSmrg	if (((a)!=None)&&(!ValidAtom((a)))) {\
8605b261ecSmrg	    (ev)= (XID)(a);\
8705b261ecSmrg	    (er)= BadAtom;\
8805b261ecSmrg	    return ret;\
8905b261ecSmrg	}\
9005b261ecSmrg}
9105b261ecSmrg#define	CHK_ATOM_OR_NONE2(a,ev,er) {\
9205b261ecSmrg	if (((a)!=None)&&(!ValidAtom((a)))) {\
9305b261ecSmrg	    (ev)= (XID)(a);\
9405b261ecSmrg	    return er;\
9505b261ecSmrg	}\
9605b261ecSmrg}
9705b261ecSmrg#define	CHK_ATOM_OR_NONE(a) \
9805b261ecSmrg	CHK_ATOM_OR_NONE2(a,client->errorValue,BadAtom)
9905b261ecSmrg
10005b261ecSmrg#define	CHK_MASK_LEGAL3(err,mask,legal,ev,er,ret)	{\
10105b261ecSmrg	if ((mask)&(~(legal))) { \
10205b261ecSmrg	    (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\
10305b261ecSmrg	    (er)= BadValue;\
10405b261ecSmrg	    return ret;\
10505b261ecSmrg	}\
10605b261ecSmrg}
10705b261ecSmrg#define	CHK_MASK_LEGAL2(err,mask,legal,ev,er)	{\
10805b261ecSmrg	if ((mask)&(~(legal))) { \
10905b261ecSmrg	    (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\
11005b261ecSmrg	    return er;\
11105b261ecSmrg	}\
11205b261ecSmrg}
11305b261ecSmrg#define	CHK_MASK_LEGAL(err,mask,legal) \
11405b261ecSmrg	CHK_MASK_LEGAL2(err,mask,legal,client->errorValue,BadValue)
11505b261ecSmrg
11605b261ecSmrg#define	CHK_MASK_MATCH(err,affect,value) {\
11705b261ecSmrg	if ((value)&(~(affect))) { \
11805b261ecSmrg	    client->errorValue= _XkbErrCode2((err),((value)&(~(affect))));\
11905b261ecSmrg	    return BadMatch;\
12005b261ecSmrg	}\
12105b261ecSmrg}
12205b261ecSmrg#define	CHK_MASK_OVERLAP(err,m1,m2) {\
12305b261ecSmrg	if ((m1)&(m2)) { \
12405b261ecSmrg	    client->errorValue= _XkbErrCode2((err),((m1)&(m2)));\
12505b261ecSmrg	    return BadMatch;\
12605b261ecSmrg	}\
12705b261ecSmrg}
12805b261ecSmrg#define	CHK_KEY_RANGE2(err,first,num,x,ev,er) {\
12905b261ecSmrg	if (((unsigned)(first)+(num)-1)>(x)->max_key_code) {\
13005b261ecSmrg	    (ev)=_XkbErrCode4(err,(first),(num),(x)->max_key_code);\
13105b261ecSmrg	    return er;\
13205b261ecSmrg	}\
13305b261ecSmrg	else if ( (first)<(x)->min_key_code ) {\
13405b261ecSmrg	    (ev)=_XkbErrCode3(err+1,(first),xkb->min_key_code);\
13505b261ecSmrg	    return er;\
13605b261ecSmrg	}\
13705b261ecSmrg}
13805b261ecSmrg#define	CHK_KEY_RANGE(err,first,num,x)  \
13905b261ecSmrg	CHK_KEY_RANGE2(err,first,num,x,client->errorValue,BadValue)
14005b261ecSmrg
14105b261ecSmrg#define	CHK_REQ_KEY_RANGE2(err,first,num,r,ev,er) {\
14205b261ecSmrg	if (((unsigned)(first)+(num)-1)>(r)->maxKeyCode) {\
14305b261ecSmrg	    (ev)=_XkbErrCode4(err,(first),(num),(r)->maxKeyCode);\
14405b261ecSmrg	    return er;\
14505b261ecSmrg	}\
14605b261ecSmrg	else if ( (first)<(r)->minKeyCode ) {\
14705b261ecSmrg	    (ev)=_XkbErrCode3(err+1,(first),(r)->minKeyCode);\
14805b261ecSmrg	    return er;\
14905b261ecSmrg	}\
15005b261ecSmrg}
15105b261ecSmrg#define	CHK_REQ_KEY_RANGE(err,first,num,r)  \
15205b261ecSmrg	CHK_REQ_KEY_RANGE2(err,first,num,r,client->errorValue,BadValue)
15305b261ecSmrg
15405b261ecSmrg/***====================================================================***/
15505b261ecSmrg
15605b261ecSmrgint
15705b261ecSmrgProcXkbUseExtension(ClientPtr client)
15805b261ecSmrg{
15905b261ecSmrg    REQUEST(xkbUseExtensionReq);
16005b261ecSmrg    xkbUseExtensionReply	rep;
16105b261ecSmrg    register int n;
16205b261ecSmrg    int	supported;
16305b261ecSmrg
16405b261ecSmrg    REQUEST_SIZE_MATCH(xkbUseExtensionReq);
16505b261ecSmrg    if (stuff->wantedMajor != XkbMajorVersion) {
16605b261ecSmrg	/* pre-release version 0.65 is compatible with 1.00 */
16705b261ecSmrg	supported= ((XkbMajorVersion==1)&&
16805b261ecSmrg		    (stuff->wantedMajor==0)&&(stuff->wantedMinor==65));
16905b261ecSmrg    }
17005b261ecSmrg    else supported = 1;
17105b261ecSmrg
17205b261ecSmrg    if ((supported) && (!(client->xkbClientFlags&_XkbClientInitialized))) {
17305b261ecSmrg	client->xkbClientFlags= _XkbClientInitialized;
17405b261ecSmrg	client->vMajor= stuff->wantedMajor;
17505b261ecSmrg	client->vMinor= stuff->wantedMinor;
17605b261ecSmrg    }
17705b261ecSmrg    else if (xkbDebugFlags&0x1) {
1784642e01fSmrg	ErrorF("[xkb] Rejecting client %d (0x%lx) (wants %d.%02d, have %d.%02d)\n",
17905b261ecSmrg					client->index,
18005b261ecSmrg					(long)client->clientAsMask,
18105b261ecSmrg					stuff->wantedMajor,stuff->wantedMinor,
18205b261ecSmrg					XkbMajorVersion,XkbMinorVersion);
18305b261ecSmrg    }
18405b261ecSmrg    rep.type = X_Reply;
18505b261ecSmrg    rep.supported = supported;
18605b261ecSmrg    rep.length = 0;
18705b261ecSmrg    rep.sequenceNumber = client->sequence;
18805b261ecSmrg    rep.serverMajor = XkbMajorVersion;
18905b261ecSmrg    rep.serverMinor = XkbMinorVersion;
19005b261ecSmrg    if ( client->swapped ) {
19105b261ecSmrg	swaps(&rep.sequenceNumber, n);
19205b261ecSmrg	swaps(&rep.serverMajor, n);
19305b261ecSmrg	swaps(&rep.serverMinor, n);
19405b261ecSmrg    }
19505b261ecSmrg    WriteToClient(client,SIZEOF(xkbUseExtensionReply), (char *)&rep);
19605b261ecSmrg    return client->noClientException;
19705b261ecSmrg}
19805b261ecSmrg
19905b261ecSmrg/***====================================================================***/
20005b261ecSmrg
20105b261ecSmrgint
20205b261ecSmrgProcXkbSelectEvents(ClientPtr client)
20305b261ecSmrg{
20405b261ecSmrg    unsigned		legal;
20505b261ecSmrg    DeviceIntPtr 	dev;
20605b261ecSmrg    XkbInterestPtr	masks;
20705b261ecSmrg    REQUEST(xkbSelectEventsReq);
20805b261ecSmrg
20905b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSelectEventsReq);
21005b261ecSmrg
21105b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
21205b261ecSmrg	return BadAccess;
21305b261ecSmrg
2144642e01fSmrg    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixUseAccess);
21505b261ecSmrg
21605b261ecSmrg    if (((stuff->affectWhich&XkbMapNotifyMask)!=0)&&(stuff->affectMap)) {
21705b261ecSmrg	client->mapNotifyMask&= ~stuff->affectMap;
21805b261ecSmrg	client->mapNotifyMask|= (stuff->affectMap&stuff->map);
21905b261ecSmrg    }
22005b261ecSmrg    if ((stuff->affectWhich&(~XkbMapNotifyMask))==0)
22105b261ecSmrg	return client->noClientException;
22205b261ecSmrg
22305b261ecSmrg    masks = XkbFindClientResource((DevicePtr)dev,client);
22405b261ecSmrg    if (!masks){
22505b261ecSmrg	XID id = FakeClientID(client->index);
22605b261ecSmrg	AddResource(id,RT_XKBCLIENT,dev);
22705b261ecSmrg	masks= XkbAddClientResource((DevicePtr)dev,client,id);
22805b261ecSmrg    }
22905b261ecSmrg    if (masks) {
23005b261ecSmrg	union {
23105b261ecSmrg	    CARD8	*c8;
23205b261ecSmrg	    CARD16	*c16;
23305b261ecSmrg	    CARD32	*c32;
23405b261ecSmrg	} from,to;
23505b261ecSmrg	register unsigned bit,ndx,maskLeft,dataLeft,size;
23605b261ecSmrg
23705b261ecSmrg	from.c8= (CARD8 *)&stuff[1];
23805b261ecSmrg	dataLeft= (stuff->length*4)-SIZEOF(xkbSelectEventsReq);
23905b261ecSmrg	maskLeft= (stuff->affectWhich&(~XkbMapNotifyMask));
24005b261ecSmrg	for (ndx=0,bit=1; (maskLeft!=0); ndx++, bit<<=1) {
24105b261ecSmrg	    if ((bit&maskLeft)==0)
24205b261ecSmrg		continue;
24305b261ecSmrg	    maskLeft&= ~bit;
24405b261ecSmrg	    switch (ndx) {
24505b261ecSmrg		case XkbNewKeyboardNotify:
24605b261ecSmrg		    to.c16= &client->newKeyboardNotifyMask;
24705b261ecSmrg		    legal= XkbAllNewKeyboardEventsMask;
24805b261ecSmrg		    size= 2;
24905b261ecSmrg		    break;
25005b261ecSmrg		case XkbStateNotify:
25105b261ecSmrg		    to.c16= &masks->stateNotifyMask;
25205b261ecSmrg		    legal= XkbAllStateEventsMask;
25305b261ecSmrg		    size= 2;
25405b261ecSmrg		    break;
25505b261ecSmrg		case XkbControlsNotify:
25605b261ecSmrg		    to.c32= &masks->ctrlsNotifyMask;
25705b261ecSmrg		    legal= XkbAllControlEventsMask;
25805b261ecSmrg		    size= 4;
25905b261ecSmrg		    break;
26005b261ecSmrg		case XkbIndicatorStateNotify:
26105b261ecSmrg		    to.c32= &masks->iStateNotifyMask;
26205b261ecSmrg		    legal= XkbAllIndicatorEventsMask;
26305b261ecSmrg		    size= 4;
26405b261ecSmrg		    break;
26505b261ecSmrg		case XkbIndicatorMapNotify:
26605b261ecSmrg		    to.c32= &masks->iMapNotifyMask;
26705b261ecSmrg		    legal= XkbAllIndicatorEventsMask;
26805b261ecSmrg		    size= 4;
26905b261ecSmrg		    break;
27005b261ecSmrg		case XkbNamesNotify:
27105b261ecSmrg		    to.c16= &masks->namesNotifyMask;
27205b261ecSmrg		    legal= XkbAllNameEventsMask;
27305b261ecSmrg		    size= 2;
27405b261ecSmrg		    break;
27505b261ecSmrg		case XkbCompatMapNotify:
27605b261ecSmrg		    to.c8= &masks->compatNotifyMask;
27705b261ecSmrg		    legal= XkbAllCompatMapEventsMask;
27805b261ecSmrg		    size= 1;
27905b261ecSmrg		    break;
28005b261ecSmrg		case XkbBellNotify:
28105b261ecSmrg		    to.c8= &masks->bellNotifyMask;
28205b261ecSmrg		    legal= XkbAllBellEventsMask;
28305b261ecSmrg		    size= 1;
28405b261ecSmrg		    break;
28505b261ecSmrg		case XkbActionMessage:
28605b261ecSmrg		    to.c8= &masks->actionMessageMask;
28705b261ecSmrg		    legal= XkbAllActionMessagesMask;
28805b261ecSmrg		    size= 1;
28905b261ecSmrg		    break;
29005b261ecSmrg		case XkbAccessXNotify:
29105b261ecSmrg		    to.c16= &masks->accessXNotifyMask;
29205b261ecSmrg		    legal= XkbAllAccessXEventsMask;
29305b261ecSmrg		    size= 2;
29405b261ecSmrg		    break;
29505b261ecSmrg		case XkbExtensionDeviceNotify:
29605b261ecSmrg		    to.c16= &masks->extDevNotifyMask;
29705b261ecSmrg		    legal= XkbAllExtensionDeviceEventsMask;
29805b261ecSmrg		    size= 2;
29905b261ecSmrg		    break;
30005b261ecSmrg		default:
30105b261ecSmrg		    client->errorValue = _XkbErrCode2(33,bit);
30205b261ecSmrg		    return BadValue;
30305b261ecSmrg	    }
30405b261ecSmrg
30505b261ecSmrg	    if (stuff->clear&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 if (stuff->selectAll&bit) {
31105b261ecSmrg		if (size==2)		to.c16[0]= ~0;
31205b261ecSmrg		else if (size==4)	to.c32[0]= ~0;
31305b261ecSmrg		else			to.c8[0]=  ~0;
31405b261ecSmrg	    }
31505b261ecSmrg	    else {
31605b261ecSmrg		if (dataLeft<(size*2))
31705b261ecSmrg		    return BadLength;
31805b261ecSmrg		if (size==2) {
31905b261ecSmrg		    CHK_MASK_MATCH(ndx,from.c16[0],from.c16[1]);
32005b261ecSmrg		    CHK_MASK_LEGAL(ndx,from.c16[0],legal);
32105b261ecSmrg		    to.c16[0]&= ~from.c16[0];
32205b261ecSmrg		    to.c16[0]|= (from.c16[0]&from.c16[1]);
32305b261ecSmrg		}
32405b261ecSmrg		else if (size==4) {
32505b261ecSmrg		    CHK_MASK_MATCH(ndx,from.c32[0],from.c32[1]);
32605b261ecSmrg		    CHK_MASK_LEGAL(ndx,from.c32[0],legal);
32705b261ecSmrg		    to.c32[0]&= ~from.c32[0];
32805b261ecSmrg		    to.c32[0]|= (from.c32[0]&from.c32[1]);
32905b261ecSmrg		}
33005b261ecSmrg		else  {
33105b261ecSmrg		    CHK_MASK_MATCH(ndx,from.c8[0],from.c8[1]);
33205b261ecSmrg		    CHK_MASK_LEGAL(ndx,from.c8[0],legal);
33305b261ecSmrg		    to.c8[0]&= ~from.c8[0];
33405b261ecSmrg		    to.c8[0]|= (from.c8[0]&from.c8[1]);
33505b261ecSmrg		    size= 2;
33605b261ecSmrg		}
33705b261ecSmrg		from.c8+= (size*2);
33805b261ecSmrg		dataLeft-= (size*2);
33905b261ecSmrg	    }
34005b261ecSmrg	}
34105b261ecSmrg	if (dataLeft>2) {
3424642e01fSmrg	    ErrorF("[xkb] Extra data (%d bytes) after SelectEvents\n",dataLeft);
34305b261ecSmrg	    return BadLength;
34405b261ecSmrg	}
34505b261ecSmrg	return client->noClientException;
34605b261ecSmrg    }
34705b261ecSmrg    return BadAlloc;
34805b261ecSmrg}
34905b261ecSmrg
35005b261ecSmrg/***====================================================================***/
3514642e01fSmrg/**
3524642e01fSmrg * Ring a bell on the given device for the given client.
3534642e01fSmrg */
3544642e01fSmrgstatic int
3554642e01fSmrg_XkbBell(ClientPtr client, DeviceIntPtr dev, WindowPtr pWin,
3564642e01fSmrg         int bellClass, int bellID, int pitch, int duration,
3574642e01fSmrg         int percent, int forceSound, int eventOnly, Atom name)
3584642e01fSmrg{
3594642e01fSmrg    int         base;
3604642e01fSmrg    pointer     ctrl;
3614642e01fSmrg    int         oldPitch, oldDuration;
3624642e01fSmrg    int         newPercent;
3634642e01fSmrg
3644642e01fSmrg    if (bellClass == KbdFeedbackClass) {
3654642e01fSmrg        KbdFeedbackPtr	k;
3664642e01fSmrg        if (bellID==XkbDfltXIId)
3674642e01fSmrg            k= dev->kbdfeed;
3684642e01fSmrg        else {
3694642e01fSmrg            for (k=dev->kbdfeed; k; k=k->next) {
3704642e01fSmrg                if (k->ctrl.id == bellID)
3714642e01fSmrg                    break;
3724642e01fSmrg            }
3734642e01fSmrg        }
3744642e01fSmrg        if (!k) {
3754642e01fSmrg            client->errorValue = _XkbErrCode2(0x5,bellID);
3764642e01fSmrg            return BadValue;
3774642e01fSmrg        }
3784642e01fSmrg        base = k->ctrl.bell;
3794642e01fSmrg        ctrl = (pointer) &(k->ctrl);
3804642e01fSmrg        oldPitch= k->ctrl.bell_pitch;
3814642e01fSmrg        oldDuration= k->ctrl.bell_duration;
3824642e01fSmrg        if (pitch!=0) {
3834642e01fSmrg            if (pitch==-1)
3844642e01fSmrg                k->ctrl.bell_pitch= defaultKeyboardControl.bell_pitch;
3854642e01fSmrg            else k->ctrl.bell_pitch= pitch;
3864642e01fSmrg        }
3874642e01fSmrg        if (duration!=0) {
3884642e01fSmrg            if (duration==-1)
3894642e01fSmrg                k->ctrl.bell_duration= defaultKeyboardControl.bell_duration;
3904642e01fSmrg            else k->ctrl.bell_duration= duration;
3914642e01fSmrg        }
3924642e01fSmrg    }
3934642e01fSmrg    else if (bellClass == BellFeedbackClass) {
3944642e01fSmrg        BellFeedbackPtr	b;
3954642e01fSmrg        if (bellID==XkbDfltXIId)
3964642e01fSmrg            b= dev->bell;
3974642e01fSmrg        else {
3984642e01fSmrg            for (b=dev->bell; b; b=b->next) {
3994642e01fSmrg                if (b->ctrl.id == bellID)
4004642e01fSmrg                    break;
4014642e01fSmrg            }
4024642e01fSmrg        }
4034642e01fSmrg        if (!b) {
4044642e01fSmrg            client->errorValue = _XkbErrCode2(0x6,bellID);
4054642e01fSmrg            return BadValue;
4064642e01fSmrg        }
4074642e01fSmrg        base = b->ctrl.percent;
4084642e01fSmrg        ctrl = (pointer) &(b->ctrl);
4094642e01fSmrg        oldPitch= b->ctrl.pitch;
4104642e01fSmrg        oldDuration= b->ctrl.duration;
4114642e01fSmrg        if (pitch!=0) {
4124642e01fSmrg            if (pitch==-1)
4134642e01fSmrg                b->ctrl.pitch= defaultKeyboardControl.bell_pitch;
4144642e01fSmrg            else b->ctrl.pitch= pitch;
4154642e01fSmrg        }
4164642e01fSmrg        if (duration!=0) {
4174642e01fSmrg            if (duration==-1)
4184642e01fSmrg                b->ctrl.duration= defaultKeyboardControl.bell_duration;
4194642e01fSmrg            else b->ctrl.duration= duration;
4204642e01fSmrg        }
4214642e01fSmrg    }
4224642e01fSmrg    else {
4234642e01fSmrg        client->errorValue = _XkbErrCode2(0x7, bellClass);
4244642e01fSmrg        return BadValue;
4254642e01fSmrg    }
4264642e01fSmrg
4274642e01fSmrg    newPercent = (base * percent)/100;
4284642e01fSmrg    if (percent < 0)
4294642e01fSmrg         newPercent = base + newPercent;
4304642e01fSmrg    else newPercent = base - newPercent + percent;
4314642e01fSmrg
4324642e01fSmrg    XkbHandleBell(forceSound, eventOnly,
4334642e01fSmrg                  dev, newPercent, ctrl, bellClass,
4344642e01fSmrg                  name, pWin, client);
4354642e01fSmrg    if ((pitch!=0)||(duration!=0)) {
4364642e01fSmrg        if (bellClass == KbdFeedbackClass) {
4374642e01fSmrg            KbdFeedbackPtr      k;
4384642e01fSmrg            k= (KbdFeedbackPtr)ctrl;
4394642e01fSmrg            if (pitch!=0)
4404642e01fSmrg                k->ctrl.bell_pitch= oldPitch;
4414642e01fSmrg            if (duration!=0)
4424642e01fSmrg                k->ctrl.bell_duration= oldDuration;
4434642e01fSmrg        }
4444642e01fSmrg        else {
4454642e01fSmrg            BellFeedbackPtr     b;
4464642e01fSmrg            b= (BellFeedbackPtr)ctrl;
4474642e01fSmrg            if (pitch!=0)
4484642e01fSmrg                b->ctrl.pitch= oldPitch;
4494642e01fSmrg            if (duration!=0)
4504642e01fSmrg                b->ctrl.duration= oldDuration;
4514642e01fSmrg        }
4524642e01fSmrg    }
4534642e01fSmrg
4544642e01fSmrg    return Success;
4554642e01fSmrg}
45605b261ecSmrg
45705b261ecSmrgint
45805b261ecSmrgProcXkbBell(ClientPtr client)
45905b261ecSmrg{
46005b261ecSmrg    REQUEST(xkbBellReq);
46105b261ecSmrg    DeviceIntPtr dev;
46205b261ecSmrg    WindowPtr	 pWin;
4634642e01fSmrg    int rc;
46405b261ecSmrg
46505b261ecSmrg    REQUEST_SIZE_MATCH(xkbBellReq);
46605b261ecSmrg
46705b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
46805b261ecSmrg	return BadAccess;
46905b261ecSmrg
4704642e01fSmrg    CHK_BELL_DEVICE(dev, stuff->deviceSpec, client, DixBellAccess);
47105b261ecSmrg    CHK_ATOM_OR_NONE(stuff->name);
47205b261ecSmrg
4734642e01fSmrg    /* device-independent checks request for sane values */
47405b261ecSmrg    if ((stuff->forceSound)&&(stuff->eventOnly)) {
47505b261ecSmrg	client->errorValue=_XkbErrCode3(0x1,stuff->forceSound,stuff->eventOnly);
47605b261ecSmrg	return BadMatch;
47705b261ecSmrg    }
47805b261ecSmrg    if (stuff->percent < -100 || stuff->percent > 100) {
47905b261ecSmrg	client->errorValue = _XkbErrCode2(0x2,stuff->percent);
48005b261ecSmrg	return BadValue;
48105b261ecSmrg    }
48205b261ecSmrg    if (stuff->duration<-1) {
48305b261ecSmrg	client->errorValue = _XkbErrCode2(0x3,stuff->duration);
48405b261ecSmrg	return BadValue;
48505b261ecSmrg    }
48605b261ecSmrg    if (stuff->pitch<-1) {
48705b261ecSmrg	client->errorValue = _XkbErrCode2(0x4,stuff->pitch);
48805b261ecSmrg	return BadValue;
48905b261ecSmrg    }
49005b261ecSmrg
49105b261ecSmrg    if (stuff->bellClass == XkbDfltXIClass) {
49205b261ecSmrg	if (dev->kbdfeed!=NULL)
49305b261ecSmrg	     stuff->bellClass= KbdFeedbackClass;
49405b261ecSmrg	else stuff->bellClass= BellFeedbackClass;
49505b261ecSmrg    }
4964642e01fSmrg
49705b261ecSmrg    if (stuff->window!=None) {
4984642e01fSmrg	rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
4994642e01fSmrg	if (rc != Success) {
50005b261ecSmrg	    client->errorValue= stuff->window;
5014642e01fSmrg	    return rc;
50205b261ecSmrg	}
50305b261ecSmrg    }
50405b261ecSmrg    else pWin= NULL;
50505b261ecSmrg
5064642e01fSmrg    /* Client wants to ring a bell on the core keyboard?
5074642e01fSmrg       Ring the bell on the core keyboard (which does nothing, but if that
5084642e01fSmrg       fails the client is screwed anyway), and then on all extension devices.
5094642e01fSmrg       Fail if the core keyboard fails but not the extension devices.  this
5104642e01fSmrg       may cause some keyboards to ding and others to stay silent. Fix
5114642e01fSmrg       your client to use explicit keyboards to avoid this.
5124642e01fSmrg
5134642e01fSmrg       dev is the device the client requested.
5144642e01fSmrg     */
5154642e01fSmrg    rc = _XkbBell(client, dev, pWin, stuff->bellClass, stuff->bellID,
5164642e01fSmrg                  stuff->pitch, stuff->duration, stuff->percent,
5174642e01fSmrg                  stuff->forceSound, stuff->eventOnly, stuff->name);
5184642e01fSmrg
5194642e01fSmrg    if ((rc == Success) && ((stuff->deviceSpec == XkbUseCoreKbd) ||
5204642e01fSmrg                            (stuff->deviceSpec == XkbUseCorePtr)))
5214642e01fSmrg    {
5224642e01fSmrg        DeviceIntPtr other;
5234642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
5244642e01fSmrg        {
5254642e01fSmrg            if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
5264642e01fSmrg            {
5274642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixBellAccess);
5284642e01fSmrg                if (rc == Success)
5294642e01fSmrg                    _XkbBell(client, other, pWin, stuff->bellClass,
5304642e01fSmrg                             stuff->bellID, stuff->pitch, stuff->duration,
5314642e01fSmrg                             stuff->percent, stuff->forceSound,
5324642e01fSmrg                             stuff->eventOnly, stuff->name);
5334642e01fSmrg            }
5344642e01fSmrg        }
5354642e01fSmrg        rc = Success; /* reset to success, that's what we got for the VCK */
53605b261ecSmrg    }
5374642e01fSmrg
5384642e01fSmrg    return rc;
53905b261ecSmrg}
54005b261ecSmrg
54105b261ecSmrg/***====================================================================***/
54205b261ecSmrg
54305b261ecSmrgint
54405b261ecSmrgProcXkbGetState(ClientPtr client)
54505b261ecSmrg{
54605b261ecSmrg    REQUEST(xkbGetStateReq);
54705b261ecSmrg    DeviceIntPtr	dev;
54805b261ecSmrg    xkbGetStateReply	 rep;
54905b261ecSmrg    XkbStateRec		*xkb;
55005b261ecSmrg
55105b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetStateReq);
55205b261ecSmrg
55305b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
55405b261ecSmrg	return BadAccess;
55505b261ecSmrg
5564642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
55705b261ecSmrg
55805b261ecSmrg    xkb= &dev->key->xkbInfo->state;
55905b261ecSmrg    bzero(&rep,sizeof(xkbGetStateReply));
56005b261ecSmrg    rep.type= X_Reply;
56105b261ecSmrg    rep.sequenceNumber= client->sequence;
56205b261ecSmrg    rep.length = 0;
56305b261ecSmrg    rep.deviceID = dev->id;
56405b261ecSmrg    rep.mods = dev->key->state&0xff;
56505b261ecSmrg    rep.baseMods = xkb->base_mods;
56605b261ecSmrg    rep.lockedMods = xkb->locked_mods;
56705b261ecSmrg    rep.latchedMods = xkb->latched_mods;
56805b261ecSmrg    rep.group = xkb->group;
56905b261ecSmrg    rep.baseGroup = xkb->base_group;
57005b261ecSmrg    rep.latchedGroup = xkb->latched_group;
57105b261ecSmrg    rep.lockedGroup = xkb->locked_group;
57205b261ecSmrg    rep.compatState = xkb->compat_state;
57305b261ecSmrg    rep.ptrBtnState = xkb->ptr_buttons;
57405b261ecSmrg    if (client->swapped) {
57505b261ecSmrg	register int n;
57605b261ecSmrg	swaps(&rep.sequenceNumber,n);
57705b261ecSmrg	swaps(&rep.ptrBtnState,n);
57805b261ecSmrg    }
57905b261ecSmrg    WriteToClient(client, SIZEOF(xkbGetStateReply), (char *)&rep);
58005b261ecSmrg    return client->noClientException;
58105b261ecSmrg}
58205b261ecSmrg
58305b261ecSmrg/***====================================================================***/
58405b261ecSmrg
58505b261ecSmrgint
58605b261ecSmrgProcXkbLatchLockState(ClientPtr client)
58705b261ecSmrg{
58805b261ecSmrg    int status;
58905b261ecSmrg    DeviceIntPtr dev, tmpd;
59005b261ecSmrg    XkbStateRec	oldState,*newState;
59105b261ecSmrg    CARD16 changed;
59205b261ecSmrg    xkbStateNotify sn;
59305b261ecSmrg    XkbEventCauseRec cause;
59405b261ecSmrg
59505b261ecSmrg    REQUEST(xkbLatchLockStateReq);
59605b261ecSmrg    REQUEST_SIZE_MATCH(xkbLatchLockStateReq);
59705b261ecSmrg
59805b261ecSmrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
59905b261ecSmrg	return BadAccess;
60005b261ecSmrg
6014642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
60205b261ecSmrg    CHK_MASK_MATCH(0x01, stuff->affectModLocks, stuff->modLocks);
60305b261ecSmrg    CHK_MASK_MATCH(0x01, stuff->affectModLatches, stuff->modLatches);
60405b261ecSmrg
60505b261ecSmrg    status = Success;
60605b261ecSmrg
60705b261ecSmrg    for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
60805b261ecSmrg        if ((dev == inputInfo.keyboard && tmpd->key && tmpd->coreEvents) ||
60905b261ecSmrg            tmpd == dev) {
61005b261ecSmrg            if (!tmpd->key->xkbInfo)
61105b261ecSmrg                continue;
61205b261ecSmrg
61305b261ecSmrg            oldState = tmpd->key->xkbInfo->state;
61405b261ecSmrg            newState = &tmpd->key->xkbInfo->state;
61505b261ecSmrg            if (stuff->affectModLocks) {
61605b261ecSmrg                newState->locked_mods &= ~stuff->affectModLocks;
61705b261ecSmrg                newState->locked_mods |= (stuff->affectModLocks & stuff->modLocks);
61805b261ecSmrg            }
61905b261ecSmrg            if (status == Success && stuff->lockGroup)
62005b261ecSmrg                newState->locked_group = stuff->groupLock;
62105b261ecSmrg            if (status == Success && stuff->affectModLatches)
62205b261ecSmrg                status = XkbLatchModifiers(tmpd, stuff->affectModLatches,
62305b261ecSmrg                                           stuff->modLatches);
62405b261ecSmrg            if (status == Success && stuff->latchGroup)
62505b261ecSmrg                status = XkbLatchGroup(tmpd, stuff->groupLatch);
62605b261ecSmrg
62705b261ecSmrg            if (status != Success)
62805b261ecSmrg                return status;
62905b261ecSmrg
63005b261ecSmrg            XkbComputeDerivedState(tmpd->key->xkbInfo);
63105b261ecSmrg            tmpd->key->state = XkbStateFieldFromRec(newState);
63205b261ecSmrg
63305b261ecSmrg            changed = XkbStateChangedFlags(&oldState, newState);
63405b261ecSmrg            if (changed) {
63505b261ecSmrg                sn.keycode = 0;
63605b261ecSmrg                sn.eventType = 0;
63705b261ecSmrg                sn.requestMajor = XkbReqCode;
63805b261ecSmrg                sn.requestMinor = X_kbLatchLockState;
63905b261ecSmrg                sn.changed = changed;
64005b261ecSmrg                XkbSendStateNotify(tmpd, &sn);
64105b261ecSmrg                changed = XkbIndicatorsToUpdate(tmpd, changed, False);
64205b261ecSmrg                if (changed) {
64305b261ecSmrg                    XkbSetCauseXkbReq(&cause, X_kbLatchLockState, client);
64405b261ecSmrg                    XkbUpdateIndicators(tmpd, changed, True, NULL, &cause);
64505b261ecSmrg	        }
64605b261ecSmrg            }
64705b261ecSmrg        }
64805b261ecSmrg    }
64905b261ecSmrg
65005b261ecSmrg    return client->noClientException;
65105b261ecSmrg}
65205b261ecSmrg
65305b261ecSmrg/***====================================================================***/
65405b261ecSmrg
65505b261ecSmrgint
65605b261ecSmrgProcXkbGetControls(ClientPtr client)
65705b261ecSmrg{
65805b261ecSmrg    xkbGetControlsReply rep;
65905b261ecSmrg    XkbControlsPtr	xkb;
66005b261ecSmrg    DeviceIntPtr 	dev;
66105b261ecSmrg    register int 	n;
66205b261ecSmrg
66305b261ecSmrg    REQUEST(xkbGetControlsReq);
66405b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetControlsReq);
66505b261ecSmrg
66605b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
66705b261ecSmrg	return BadAccess;
66805b261ecSmrg
6694642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
67005b261ecSmrg
67105b261ecSmrg    xkb = dev->key->xkbInfo->desc->ctrls;
67205b261ecSmrg    rep.type = X_Reply;
67305b261ecSmrg    rep.length = (SIZEOF(xkbGetControlsReply)-
67405b261ecSmrg		  SIZEOF(xGenericReply)) >> 2;
67505b261ecSmrg    rep.sequenceNumber = client->sequence;
67605b261ecSmrg    rep.deviceID = ((DeviceIntPtr)dev)->id;
67705b261ecSmrg    rep.numGroups = xkb->num_groups;
67805b261ecSmrg    rep.groupsWrap = xkb->groups_wrap;
67905b261ecSmrg    rep.internalMods = xkb->internal.mask;
68005b261ecSmrg    rep.ignoreLockMods = xkb->ignore_lock.mask;
68105b261ecSmrg    rep.internalRealMods = xkb->internal.real_mods;
68205b261ecSmrg    rep.ignoreLockRealMods = xkb->ignore_lock.real_mods;
68305b261ecSmrg    rep.internalVMods = xkb->internal.vmods;
68405b261ecSmrg    rep.ignoreLockVMods = xkb->ignore_lock.vmods;
68505b261ecSmrg    rep.enabledCtrls = xkb->enabled_ctrls;
68605b261ecSmrg    rep.repeatDelay = xkb->repeat_delay;
68705b261ecSmrg    rep.repeatInterval = xkb->repeat_interval;
68805b261ecSmrg    rep.slowKeysDelay = xkb->slow_keys_delay;
68905b261ecSmrg    rep.debounceDelay = xkb->debounce_delay;
69005b261ecSmrg    rep.mkDelay = xkb->mk_delay;
69105b261ecSmrg    rep.mkInterval = xkb->mk_interval;
69205b261ecSmrg    rep.mkTimeToMax = xkb->mk_time_to_max;
69305b261ecSmrg    rep.mkMaxSpeed = xkb->mk_max_speed;
69405b261ecSmrg    rep.mkCurve = xkb->mk_curve;
69505b261ecSmrg    rep.mkDfltBtn = xkb->mk_dflt_btn;
69605b261ecSmrg    rep.axTimeout = xkb->ax_timeout;
69705b261ecSmrg    rep.axtCtrlsMask = xkb->axt_ctrls_mask;
69805b261ecSmrg    rep.axtCtrlsValues = xkb->axt_ctrls_values;
69905b261ecSmrg    rep.axtOptsMask = xkb->axt_opts_mask;
70005b261ecSmrg    rep.axtOptsValues = xkb->axt_opts_values;
70105b261ecSmrg    rep.axOptions = xkb->ax_options;
70205b261ecSmrg    memcpy(rep.perKeyRepeat,xkb->per_key_repeat,XkbPerKeyBitArraySize);
70305b261ecSmrg    if (client->swapped) {
70405b261ecSmrg    	swaps(&rep.sequenceNumber, n);
70505b261ecSmrg	swapl(&rep.length,n);
70605b261ecSmrg	swaps(&rep.internalVMods, n);
70705b261ecSmrg	swaps(&rep.ignoreLockVMods, n);
70805b261ecSmrg	swapl(&rep.enabledCtrls, n);
70905b261ecSmrg	swaps(&rep.repeatDelay, n);
71005b261ecSmrg	swaps(&rep.repeatInterval, n);
71105b261ecSmrg	swaps(&rep.slowKeysDelay, n);
71205b261ecSmrg	swaps(&rep.debounceDelay, n);
71305b261ecSmrg	swaps(&rep.mkDelay, n);
71405b261ecSmrg	swaps(&rep.mkInterval, n);
71505b261ecSmrg	swaps(&rep.mkTimeToMax, n);
71605b261ecSmrg	swaps(&rep.mkMaxSpeed, n);
71705b261ecSmrg	swaps(&rep.mkCurve, n);
71805b261ecSmrg	swaps(&rep.axTimeout, n);
71905b261ecSmrg	swapl(&rep.axtCtrlsMask, n);
72005b261ecSmrg	swapl(&rep.axtCtrlsValues, n);
72105b261ecSmrg	swaps(&rep.axtOptsMask, n);
72205b261ecSmrg	swaps(&rep.axtOptsValues, n);
72305b261ecSmrg	swaps(&rep.axOptions, n);
72405b261ecSmrg    }
72505b261ecSmrg    WriteToClient(client, SIZEOF(xkbGetControlsReply), (char *)&rep);
72605b261ecSmrg    return(client->noClientException);
72705b261ecSmrg}
72805b261ecSmrg
72905b261ecSmrgint
73005b261ecSmrgProcXkbSetControls(ClientPtr client)
73105b261ecSmrg{
73205b261ecSmrg    DeviceIntPtr 	dev, tmpd;
73305b261ecSmrg    XkbSrvInfoPtr	xkbi;
73405b261ecSmrg    XkbControlsPtr	ctrl;
73505b261ecSmrg    XkbControlsRec	new,old;
73605b261ecSmrg    xkbControlsNotify	cn;
73705b261ecSmrg    XkbEventCauseRec	cause;
73805b261ecSmrg    XkbSrvLedInfoPtr	sli;
73905b261ecSmrg
74005b261ecSmrg    REQUEST(xkbSetControlsReq);
74105b261ecSmrg    REQUEST_SIZE_MATCH(xkbSetControlsReq);
74205b261ecSmrg
74305b261ecSmrg    if (!(client->xkbClientFlags & _XkbClientInitialized))
74405b261ecSmrg	return BadAccess;
74505b261ecSmrg
7464642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
74705b261ecSmrg    CHK_MASK_LEGAL(0x01, stuff->changeCtrls, XkbAllControlsMask);
74805b261ecSmrg
74905b261ecSmrg    for (tmpd = inputInfo.keyboard; tmpd; tmpd = tmpd->next) {
75005b261ecSmrg        if ((dev == inputInfo.keyboard && tmpd->key && tmpd->coreEvents) ||
75105b261ecSmrg            tmpd == dev) {
75205b261ecSmrg
75305b261ecSmrg            xkbi = tmpd->key->xkbInfo;
75405b261ecSmrg            ctrl = xkbi->desc->ctrls;
75505b261ecSmrg            new = *ctrl;
75605b261ecSmrg            XkbSetCauseXkbReq(&cause, X_kbSetControls, client);
75705b261ecSmrg
75805b261ecSmrg            if (stuff->changeCtrls & XkbInternalModsMask) {
75905b261ecSmrg                CHK_MASK_MATCH(0x02, stuff->affectInternalMods,
76005b261ecSmrg                               stuff->internalMods);
76105b261ecSmrg                CHK_MASK_MATCH(0x03, stuff->affectInternalVMods,
76205b261ecSmrg                               stuff->internalVMods);
76305b261ecSmrg
76405b261ecSmrg                new.internal.real_mods &= ~(stuff->affectInternalMods);
76505b261ecSmrg                new.internal.real_mods |= (stuff->affectInternalMods &
76605b261ecSmrg                                           stuff->internalMods);
76705b261ecSmrg                new.internal.vmods &= ~(stuff->affectInternalVMods);
76805b261ecSmrg                new.internal.vmods |= (stuff->affectInternalVMods &
76905b261ecSmrg                                       stuff->internalVMods);
77005b261ecSmrg                new.internal.mask = new.internal.real_mods |
77105b261ecSmrg                                    XkbMaskForVMask(xkbi->desc,
77205b261ecSmrg                                                    new.internal.vmods);
77305b261ecSmrg            }
77405b261ecSmrg
77505b261ecSmrg            if (stuff->changeCtrls & XkbIgnoreLockModsMask) {
77605b261ecSmrg                CHK_MASK_MATCH(0x4, stuff->affectIgnoreLockMods,
77705b261ecSmrg                               stuff->ignoreLockMods);
77805b261ecSmrg                CHK_MASK_MATCH(0x5, stuff->affectIgnoreLockVMods,
77905b261ecSmrg                               stuff->ignoreLockVMods);
78005b261ecSmrg
78105b261ecSmrg                new.ignore_lock.real_mods &= ~(stuff->affectIgnoreLockMods);
78205b261ecSmrg                new.ignore_lock.real_mods |= (stuff->affectIgnoreLockMods &
78305b261ecSmrg                                              stuff->ignoreLockMods);
78405b261ecSmrg                new.ignore_lock.vmods &= ~(stuff->affectIgnoreLockVMods);
78505b261ecSmrg                new.ignore_lock.vmods |= (stuff->affectIgnoreLockVMods &
78605b261ecSmrg                                          stuff->ignoreLockVMods);
78705b261ecSmrg                new.ignore_lock.mask = new.ignore_lock.real_mods |
78805b261ecSmrg                                       XkbMaskForVMask(xkbi->desc,
78905b261ecSmrg                                                       new.ignore_lock.vmods);
79005b261ecSmrg            }
79105b261ecSmrg
79205b261ecSmrg            CHK_MASK_MATCH(0x06, stuff->affectEnabledCtrls,
79305b261ecSmrg                           stuff->enabledCtrls);
79405b261ecSmrg            if (stuff->affectEnabledCtrls) {
79505b261ecSmrg                CHK_MASK_LEGAL(0x07, stuff->affectEnabledCtrls,
79605b261ecSmrg                               XkbAllBooleanCtrlsMask);
79705b261ecSmrg
79805b261ecSmrg                new.enabled_ctrls &= ~(stuff->affectEnabledCtrls);
79905b261ecSmrg                new.enabled_ctrls |= (stuff->affectEnabledCtrls &
80005b261ecSmrg                                      stuff->enabledCtrls);
80105b261ecSmrg            }
80205b261ecSmrg
80305b261ecSmrg            if (stuff->changeCtrls & XkbRepeatKeysMask) {
80405b261ecSmrg                if (stuff->repeatDelay < 1 || stuff->repeatInterval < 1) {
80505b261ecSmrg                    client->errorValue = _XkbErrCode3(0x08, stuff->repeatDelay,
80605b261ecSmrg                                                      stuff->repeatInterval);
80705b261ecSmrg                    return BadValue;
80805b261ecSmrg                }
80905b261ecSmrg
81005b261ecSmrg                new.repeat_delay = stuff->repeatDelay;
81105b261ecSmrg                new.repeat_interval = stuff->repeatInterval;
81205b261ecSmrg            }
81305b261ecSmrg
81405b261ecSmrg            if (stuff->changeCtrls & XkbSlowKeysMask) {
81505b261ecSmrg                if (stuff->slowKeysDelay < 1) {
81605b261ecSmrg                    client->errorValue = _XkbErrCode2(0x09,
81705b261ecSmrg                                                      stuff->slowKeysDelay);
81805b261ecSmrg                    return BadValue;
81905b261ecSmrg                }
82005b261ecSmrg
82105b261ecSmrg                new.slow_keys_delay = stuff->slowKeysDelay;
82205b261ecSmrg            }
82305b261ecSmrg
82405b261ecSmrg            if (stuff->changeCtrls & XkbBounceKeysMask) {
82505b261ecSmrg                if (stuff->debounceDelay < 1) {
82605b261ecSmrg                    client->errorValue = _XkbErrCode2(0x0A,
82705b261ecSmrg                                                      stuff->debounceDelay);
82805b261ecSmrg                    return BadValue;
82905b261ecSmrg                }
83005b261ecSmrg
83105b261ecSmrg                new.debounce_delay = stuff->debounceDelay;
83205b261ecSmrg            }
83305b261ecSmrg
83405b261ecSmrg            if (stuff->changeCtrls & XkbMouseKeysMask) {
83505b261ecSmrg                if (stuff->mkDfltBtn > XkbMaxMouseKeysBtn) {
83605b261ecSmrg                    client->errorValue = _XkbErrCode2(0x0B, stuff->mkDfltBtn);
83705b261ecSmrg                    return BadValue;
83805b261ecSmrg                }
83905b261ecSmrg
84005b261ecSmrg                new.mk_dflt_btn = stuff->mkDfltBtn;
84105b261ecSmrg            }
84205b261ecSmrg
84305b261ecSmrg            if (stuff->changeCtrls & XkbMouseKeysAccelMask) {
84405b261ecSmrg                if (stuff->mkDelay < 1 || stuff->mkInterval < 1 ||
84505b261ecSmrg                    stuff->mkTimeToMax < 1 || stuff->mkMaxSpeed < 1 ||
84605b261ecSmrg                    stuff->mkCurve < -1000) {
84705b261ecSmrg                    client->errorValue = _XkbErrCode2(0x0C,0);
84805b261ecSmrg                    return BadValue;
84905b261ecSmrg                }
85005b261ecSmrg
85105b261ecSmrg                new.mk_delay = stuff->mkDelay;
85205b261ecSmrg                new.mk_interval = stuff->mkInterval;
85305b261ecSmrg                new.mk_time_to_max = stuff->mkTimeToMax;
85405b261ecSmrg                new.mk_max_speed = stuff->mkMaxSpeed;
85505b261ecSmrg                new.mk_curve = stuff->mkCurve;
85605b261ecSmrg                AccessXComputeCurveFactor(xkbi, &new);
85705b261ecSmrg            }
85805b261ecSmrg
85905b261ecSmrg            if (stuff->changeCtrls & XkbGroupsWrapMask) {
86005b261ecSmrg                unsigned act, num;
86105b261ecSmrg
86205b261ecSmrg                act = XkbOutOfRangeGroupAction(stuff->groupsWrap);
86305b261ecSmrg                switch (act) {
86405b261ecSmrg                case XkbRedirectIntoRange:
86505b261ecSmrg                    num = XkbOutOfRangeGroupNumber(stuff->groupsWrap);
86605b261ecSmrg                    if (num >= new.num_groups) {
86705b261ecSmrg                        client->errorValue = _XkbErrCode3(0x0D, new.num_groups,
86805b261ecSmrg                                                          num);
86905b261ecSmrg                        return BadValue;
87005b261ecSmrg                    }
87105b261ecSmrg                case XkbWrapIntoRange:
87205b261ecSmrg                case XkbClampIntoRange:
87305b261ecSmrg                    break;
87405b261ecSmrg                default:
87505b261ecSmrg                    client->errorValue = _XkbErrCode2(0x0E, act);
87605b261ecSmrg                    return BadValue;
87705b261ecSmrg                }
87805b261ecSmrg
87905b261ecSmrg                new.groups_wrap= stuff->groupsWrap;
88005b261ecSmrg            }
88105b261ecSmrg
88205b261ecSmrg            CHK_MASK_LEGAL(0x0F, stuff->axOptions, XkbAX_AllOptionsMask);
88305b261ecSmrg            if (stuff->changeCtrls & XkbAccessXKeysMask) {
88405b261ecSmrg                new.ax_options = stuff->axOptions & XkbAX_AllOptionsMask;
88505b261ecSmrg            }
88605b261ecSmrg            else {
88705b261ecSmrg                if (stuff->changeCtrls & XkbStickyKeysMask) {
88805b261ecSmrg                    new.ax_options &= ~(XkbAX_SKOptionsMask);
88905b261ecSmrg                    new.ax_options |= (stuff->axOptions & XkbAX_SKOptionsMask);
89005b261ecSmrg                }
89105b261ecSmrg
89205b261ecSmrg                if (stuff->changeCtrls & XkbAccessXFeedbackMask) {
89305b261ecSmrg                    new.ax_options &= ~(XkbAX_FBOptionsMask);
89405b261ecSmrg                    new.ax_options |= (stuff->axOptions & XkbAX_FBOptionsMask);
89505b261ecSmrg                }
89605b261ecSmrg            }
89705b261ecSmrg
89805b261ecSmrg            if (stuff->changeCtrls & XkbAccessXTimeoutMask) {
89905b261ecSmrg                if (stuff->axTimeout < 1) {
90005b261ecSmrg                    client->errorValue = _XkbErrCode2(0x10, stuff->axTimeout);
90105b261ecSmrg                    return BadValue;
90205b261ecSmrg                }
90305b261ecSmrg                CHK_MASK_MATCH(0x11, stuff->axtCtrlsMask,
90405b261ecSmrg                               stuff->axtCtrlsValues);
90505b261ecSmrg                CHK_MASK_LEGAL(0x12, stuff->axtCtrlsMask,
90605b261ecSmrg                               XkbAllBooleanCtrlsMask);
90705b261ecSmrg                CHK_MASK_MATCH(0x13, stuff->axtOptsMask, stuff->axtOptsValues);
90805b261ecSmrg                CHK_MASK_LEGAL(0x14, stuff->axtOptsMask, XkbAX_AllOptionsMask);
90905b261ecSmrg                new.ax_timeout = stuff->axTimeout;
91005b261ecSmrg                new.axt_ctrls_mask = stuff->axtCtrlsMask;
91105b261ecSmrg                new.axt_ctrls_values = (stuff->axtCtrlsValues &
91205b261ecSmrg                                        stuff->axtCtrlsMask);
91305b261ecSmrg                new.axt_opts_mask = stuff->axtOptsMask;
91405b261ecSmrg                new.axt_opts_values = (stuff->axtOptsValues &
91505b261ecSmrg                                       stuff->axtOptsMask);
91605b261ecSmrg            }
91705b261ecSmrg
91805b261ecSmrg            if (stuff->changeCtrls & XkbPerKeyRepeatMask)
91905b261ecSmrg                memcpy(new.per_key_repeat, stuff->perKeyRepeat,
92005b261ecSmrg                       XkbPerKeyBitArraySize);
92105b261ecSmrg
92205b261ecSmrg            old= *ctrl;
92305b261ecSmrg            *ctrl= new;
92405b261ecSmrg            XkbDDXChangeControls(tmpd, &old, ctrl);
92505b261ecSmrg
92605b261ecSmrg            if (XkbComputeControlsNotify(tmpd, &old, ctrl, &cn, False)) {
92705b261ecSmrg                cn.keycode = 0;
92805b261ecSmrg                cn.eventType = 0;
92905b261ecSmrg                cn.requestMajor = XkbReqCode;
93005b261ecSmrg                cn.requestMinor = X_kbSetControls;
93105b261ecSmrg                XkbSendControlsNotify(tmpd, &cn);
93205b261ecSmrg            }
93305b261ecSmrg
93405b261ecSmrg            sli = XkbFindSrvLedInfo(tmpd, XkbDfltXIClass, XkbDfltXIId, 0);
93505b261ecSmrg            if (sli)
93605b261ecSmrg                XkbUpdateIndicators(tmpd, sli->usesControls, True, NULL,
93705b261ecSmrg                                    &cause);
93805b261ecSmrg
93905b261ecSmrg            /* If sticky keys were disabled, clear all locks and latches */
94005b261ecSmrg            if ((old.enabled_ctrls & XkbStickyKeysMask) &&
94105b261ecSmrg                !(ctrl->enabled_ctrls & XkbStickyKeysMask))
94205b261ecSmrg                XkbClearAllLatchesAndLocks(tmpd, xkbi, True, &cause);
94305b261ecSmrg        }
94405b261ecSmrg    }
94505b261ecSmrg
94605b261ecSmrg    return client->noClientException;
94705b261ecSmrg}
94805b261ecSmrg
94905b261ecSmrg/***====================================================================***/
95005b261ecSmrg
95105b261ecSmrgstatic int
95205b261ecSmrgXkbSizeKeyTypes(XkbDescPtr xkb,xkbGetMapReply *rep)
95305b261ecSmrg{
95405b261ecSmrg    XkbKeyTypeRec 	*type;
95505b261ecSmrg    unsigned		i,len;
95605b261ecSmrg
95705b261ecSmrg    len= 0;
95805b261ecSmrg    if (((rep->present&XkbKeyTypesMask)==0)||(rep->nTypes<1)||
95905b261ecSmrg	(!xkb)||(!xkb->map)||(!xkb->map->types)) {
96005b261ecSmrg	rep->present&= ~XkbKeyTypesMask;
96105b261ecSmrg	rep->firstType= rep->nTypes= 0;
96205b261ecSmrg	return 0;
96305b261ecSmrg    }
96405b261ecSmrg    type= &xkb->map->types[rep->firstType];
96505b261ecSmrg    for (i=0;i<rep->nTypes;i++,type++){
96605b261ecSmrg	len+= SIZEOF(xkbKeyTypeWireDesc);
96705b261ecSmrg	if (type->map_count>0) {
96805b261ecSmrg	    len+= (type->map_count*SIZEOF(xkbKTMapEntryWireDesc));
96905b261ecSmrg	    if (type->preserve)
97005b261ecSmrg		len+= (type->map_count*SIZEOF(xkbModsWireDesc));
97105b261ecSmrg	}
97205b261ecSmrg    }
97305b261ecSmrg    return len;
97405b261ecSmrg}
97505b261ecSmrg
97605b261ecSmrgstatic char *
97705b261ecSmrgXkbWriteKeyTypes(	XkbDescPtr		xkb,
97805b261ecSmrg			xkbGetMapReply *	rep,
97905b261ecSmrg			char *			buf,
98005b261ecSmrg			ClientPtr 		client)
98105b261ecSmrg{
98205b261ecSmrg    XkbKeyTypePtr	type;
98305b261ecSmrg    unsigned		i;
98405b261ecSmrg    xkbKeyTypeWireDesc *wire;
98505b261ecSmrg
98605b261ecSmrg    type= &xkb->map->types[rep->firstType];
98705b261ecSmrg    for (i=0;i<rep->nTypes;i++,type++) {
98805b261ecSmrg	register unsigned n;
98905b261ecSmrg	wire= (xkbKeyTypeWireDesc *)buf;
99005b261ecSmrg	wire->mask = type->mods.mask;
99105b261ecSmrg	wire->realMods = type->mods.real_mods;
99205b261ecSmrg	wire->virtualMods = type->mods.vmods;
99305b261ecSmrg	wire->numLevels = type->num_levels;
99405b261ecSmrg	wire->nMapEntries = type->map_count;
99505b261ecSmrg	wire->preserve = (type->preserve!=NULL);
99605b261ecSmrg	if (client->swapped) {
99705b261ecSmrg	    register int n;
99805b261ecSmrg	    swaps(&wire->virtualMods,n);
99905b261ecSmrg	}
100005b261ecSmrg
100105b261ecSmrg	buf= (char *)&wire[1];
100205b261ecSmrg	if (wire->nMapEntries>0) {
100305b261ecSmrg	    xkbKTMapEntryWireDesc *	wire;
100405b261ecSmrg	    XkbKTMapEntryPtr		entry;
100505b261ecSmrg	    wire= (xkbKTMapEntryWireDesc *)buf;
100605b261ecSmrg	    entry= type->map;
100705b261ecSmrg	    for (n=0;n<type->map_count;n++,wire++,entry++) {
100805b261ecSmrg		wire->active= entry->active;
100905b261ecSmrg		wire->mask= entry->mods.mask;
101005b261ecSmrg		wire->level= entry->level;
101105b261ecSmrg		wire->realMods= entry->mods.real_mods;
101205b261ecSmrg		wire->virtualMods= entry->mods.vmods;
101305b261ecSmrg		if (client->swapped) {
101405b261ecSmrg		    register int n;
101505b261ecSmrg		    swaps(&wire->virtualMods,n);
101605b261ecSmrg		}
101705b261ecSmrg	    }
101805b261ecSmrg	    buf= (char *)wire;
101905b261ecSmrg	    if (type->preserve!=NULL) {
102005b261ecSmrg		xkbModsWireDesc *	pwire;
102105b261ecSmrg		XkbModsPtr		preserve;
102205b261ecSmrg		pwire= (xkbModsWireDesc *)buf;
102305b261ecSmrg		preserve= type->preserve;
102405b261ecSmrg		for (n=0;n<type->map_count;n++,pwire++,preserve++) {
102505b261ecSmrg		    pwire->mask= preserve->mask;
102605b261ecSmrg		    pwire->realMods= preserve->real_mods;
102705b261ecSmrg		    pwire->virtualMods= preserve->vmods;
102805b261ecSmrg		    if (client->swapped) {
102905b261ecSmrg			register int n;
103005b261ecSmrg			swaps(&pwire->virtualMods,n);
103105b261ecSmrg		    }
103205b261ecSmrg		}
103305b261ecSmrg		buf= (char *)pwire;
103405b261ecSmrg	    }
103505b261ecSmrg	}
103605b261ecSmrg    }
103705b261ecSmrg    return buf;
103805b261ecSmrg}
103905b261ecSmrg
104005b261ecSmrgstatic int
104105b261ecSmrgXkbSizeKeySyms(XkbDescPtr xkb,xkbGetMapReply *rep)
104205b261ecSmrg{
104305b261ecSmrg    XkbSymMapPtr	symMap;
104405b261ecSmrg    unsigned		i,len;
104505b261ecSmrg    unsigned		nSyms,nSymsThisKey;
104605b261ecSmrg
104705b261ecSmrg    if (((rep->present&XkbKeySymsMask)==0)||(rep->nKeySyms<1)||
104805b261ecSmrg	(!xkb)||(!xkb->map)||(!xkb->map->key_sym_map)) {
104905b261ecSmrg	rep->present&= ~XkbKeySymsMask;
105005b261ecSmrg	rep->firstKeySym= rep->nKeySyms= 0;
105105b261ecSmrg	rep->totalSyms= 0;
105205b261ecSmrg	return 0;
105305b261ecSmrg    }
105405b261ecSmrg    len= rep->nKeySyms*SIZEOF(xkbSymMapWireDesc);
105505b261ecSmrg    symMap = &xkb->map->key_sym_map[rep->firstKeySym];
105605b261ecSmrg    for (i=nSyms=0;i<rep->nKeySyms;i++,symMap++) {
105705b261ecSmrg	if (symMap->offset!=0) {
105805b261ecSmrg	    nSymsThisKey= XkbNumGroups(symMap->group_info)*symMap->width;
105905b261ecSmrg	    nSyms+= nSymsThisKey;
106005b261ecSmrg	}
106105b261ecSmrg    }
106205b261ecSmrg    len+= nSyms*4;
106305b261ecSmrg    rep->totalSyms= nSyms;
106405b261ecSmrg    return len;
106505b261ecSmrg}
106605b261ecSmrg
106705b261ecSmrgstatic int
106805b261ecSmrgXkbSizeVirtualMods(XkbDescPtr xkb,xkbGetMapReply *rep)
106905b261ecSmrg{
107005b261ecSmrgregister unsigned i,nMods,bit;
107105b261ecSmrg
107205b261ecSmrg    if (((rep->present&XkbVirtualModsMask)==0)||(rep->virtualMods==0)||
107305b261ecSmrg	(!xkb)||(!xkb->server)) {
107405b261ecSmrg	rep->present&= ~XkbVirtualModsMask;
107505b261ecSmrg	rep->virtualMods= 0;
107605b261ecSmrg	return 0;
107705b261ecSmrg    }
107805b261ecSmrg    for (i=nMods=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
107905b261ecSmrg        if (rep->virtualMods&bit)
108005b261ecSmrg	    nMods++;
108105b261ecSmrg    }
108205b261ecSmrg    return XkbPaddedSize(nMods);
108305b261ecSmrg}
108405b261ecSmrg
108505b261ecSmrgstatic char *
108605b261ecSmrgXkbWriteKeySyms(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,ClientPtr client)
108705b261ecSmrg{
108805b261ecSmrgregister KeySym *	pSym;
108905b261ecSmrgXkbSymMapPtr		symMap;
109005b261ecSmrgxkbSymMapWireDesc *	outMap;
109105b261ecSmrgregister unsigned	i;
109205b261ecSmrg
109305b261ecSmrg    symMap = &xkb->map->key_sym_map[rep->firstKeySym];
109405b261ecSmrg    for (i=0;i<rep->nKeySyms;i++,symMap++) {
109505b261ecSmrg	outMap = (xkbSymMapWireDesc *)buf;
109605b261ecSmrg	outMap->ktIndex[0] = symMap->kt_index[0];
109705b261ecSmrg	outMap->ktIndex[1] = symMap->kt_index[1];
109805b261ecSmrg	outMap->ktIndex[2] = symMap->kt_index[2];
109905b261ecSmrg	outMap->ktIndex[3] = symMap->kt_index[3];
110005b261ecSmrg	outMap->groupInfo = symMap->group_info;
110105b261ecSmrg	outMap->width= symMap->width;
110205b261ecSmrg	outMap->nSyms = symMap->width*XkbNumGroups(symMap->group_info);
110305b261ecSmrg	buf= (char *)&outMap[1];
110405b261ecSmrg	if (outMap->nSyms==0)
110505b261ecSmrg	    continue;
110605b261ecSmrg
110705b261ecSmrg	pSym = &xkb->map->syms[symMap->offset];
110805b261ecSmrg	memcpy((char *)buf,(char *)pSym,outMap->nSyms*4);
110905b261ecSmrg	if (client->swapped) {
111005b261ecSmrg	    register int n,nSyms= outMap->nSyms;
111105b261ecSmrg	    swaps(&outMap->nSyms,n);
111205b261ecSmrg	    while (nSyms-->0) {
111305b261ecSmrg		swapl(buf,n);
111405b261ecSmrg		buf+= 4;
111505b261ecSmrg	    }
111605b261ecSmrg	}
111705b261ecSmrg	else buf+= outMap->nSyms*4;
111805b261ecSmrg    }
111905b261ecSmrg    return buf;
112005b261ecSmrg}
112105b261ecSmrg
112205b261ecSmrgstatic int
112305b261ecSmrgXkbSizeKeyActions(XkbDescPtr xkb,xkbGetMapReply *rep)
112405b261ecSmrg{
112505b261ecSmrg    unsigned		i,len,nActs;
112605b261ecSmrg    register KeyCode	firstKey;
112705b261ecSmrg
112805b261ecSmrg    if (((rep->present&XkbKeyActionsMask)==0)||(rep->nKeyActs<1)||
112905b261ecSmrg	(!xkb)||(!xkb->server)||(!xkb->server->key_acts)) {
113005b261ecSmrg	rep->present&= ~XkbKeyActionsMask;
113105b261ecSmrg	rep->firstKeyAct= rep->nKeyActs= 0;
113205b261ecSmrg	rep->totalActs= 0;
113305b261ecSmrg	return 0;
113405b261ecSmrg    }
113505b261ecSmrg    firstKey= rep->firstKeyAct;
113605b261ecSmrg    for (nActs=i=0;i<rep->nKeyActs;i++) {
113705b261ecSmrg	if (xkb->server->key_acts[i+firstKey]!=0)
113805b261ecSmrg	    nActs+= XkbKeyNumActions(xkb,i+firstKey);
113905b261ecSmrg    }
114005b261ecSmrg    len= XkbPaddedSize(rep->nKeyActs)+(nActs*SIZEOF(xkbActionWireDesc));
114105b261ecSmrg    rep->totalActs= nActs;
114205b261ecSmrg    return len;
114305b261ecSmrg}
114405b261ecSmrg
114505b261ecSmrgstatic char *
114605b261ecSmrgXkbWriteKeyActions(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
114705b261ecSmrg							ClientPtr client)
114805b261ecSmrg{
114905b261ecSmrg    unsigned		i;
115005b261ecSmrg    CARD8 *		numDesc;
115105b261ecSmrg    XkbAnyAction *	actDesc;
115205b261ecSmrg
115305b261ecSmrg    numDesc = (CARD8 *)buf;
115405b261ecSmrg    for (i=0;i<rep->nKeyActs;i++) {
115505b261ecSmrg	if (xkb->server->key_acts[i+rep->firstKeyAct]==0)
115605b261ecSmrg	     numDesc[i] = 0;
115705b261ecSmrg	else numDesc[i] = XkbKeyNumActions(xkb,(i+rep->firstKeyAct));
115805b261ecSmrg    }
115905b261ecSmrg    buf+= XkbPaddedSize(rep->nKeyActs);
116005b261ecSmrg
116105b261ecSmrg    actDesc = (XkbAnyAction *)buf;
116205b261ecSmrg    for (i=0;i<rep->nKeyActs;i++) {
116305b261ecSmrg	if (xkb->server->key_acts[i+rep->firstKeyAct]!=0) {
116405b261ecSmrg	    unsigned int num;
116505b261ecSmrg	    num = XkbKeyNumActions(xkb,(i+rep->firstKeyAct));
116605b261ecSmrg	    memcpy((char *)actDesc,
116705b261ecSmrg		   (char*)XkbKeyActionsPtr(xkb,(i+rep->firstKeyAct)),
116805b261ecSmrg		   num*SIZEOF(xkbActionWireDesc));
116905b261ecSmrg	    actDesc+= num;
117005b261ecSmrg	}
117105b261ecSmrg    }
117205b261ecSmrg    buf = (char *)actDesc;
117305b261ecSmrg    return buf;
117405b261ecSmrg}
117505b261ecSmrg
117605b261ecSmrgstatic int
117705b261ecSmrgXkbSizeKeyBehaviors(XkbDescPtr xkb,xkbGetMapReply *rep)
117805b261ecSmrg{
117905b261ecSmrg    unsigned		i,len,nBhvr;
118005b261ecSmrg    XkbBehavior *	bhv;
118105b261ecSmrg
118205b261ecSmrg    if (((rep->present&XkbKeyBehaviorsMask)==0)||(rep->nKeyBehaviors<1)||
118305b261ecSmrg	(!xkb)||(!xkb->server)||(!xkb->server->behaviors)) {
118405b261ecSmrg	rep->present&= ~XkbKeyBehaviorsMask;
118505b261ecSmrg	rep->firstKeyBehavior= rep->nKeyBehaviors= 0;
118605b261ecSmrg	rep->totalKeyBehaviors= 0;
118705b261ecSmrg	return 0;
118805b261ecSmrg    }
118905b261ecSmrg    bhv= &xkb->server->behaviors[rep->firstKeyBehavior];
119005b261ecSmrg    for (nBhvr=i=0;i<rep->nKeyBehaviors;i++,bhv++) {
119105b261ecSmrg	if (bhv->type!=XkbKB_Default)
119205b261ecSmrg	    nBhvr++;
119305b261ecSmrg    }
119405b261ecSmrg    len= nBhvr*SIZEOF(xkbBehaviorWireDesc);
119505b261ecSmrg    rep->totalKeyBehaviors= nBhvr;
119605b261ecSmrg    return len;
119705b261ecSmrg}
119805b261ecSmrg
119905b261ecSmrgstatic char *
120005b261ecSmrgXkbWriteKeyBehaviors(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
120105b261ecSmrg							ClientPtr client)
120205b261ecSmrg{
120305b261ecSmrg    unsigned		i;
120405b261ecSmrg    xkbBehaviorWireDesc	*wire;
120505b261ecSmrg    XkbBehavior		*pBhvr;
120605b261ecSmrg
120705b261ecSmrg    wire = (xkbBehaviorWireDesc *)buf;
120805b261ecSmrg    pBhvr= &xkb->server->behaviors[rep->firstKeyBehavior];
120905b261ecSmrg    for (i=0;i<rep->nKeyBehaviors;i++,pBhvr++) {
121005b261ecSmrg	if (pBhvr->type!=XkbKB_Default) {
121105b261ecSmrg	    wire->key=  i+rep->firstKeyBehavior;
121205b261ecSmrg	    wire->type= pBhvr->type;
121305b261ecSmrg	    wire->data= pBhvr->data;
121405b261ecSmrg	    wire++;
121505b261ecSmrg	}
121605b261ecSmrg    }
121705b261ecSmrg    buf = (char *)wire;
121805b261ecSmrg    return buf;
121905b261ecSmrg}
122005b261ecSmrg
122105b261ecSmrgstatic int
122205b261ecSmrgXkbSizeExplicit(XkbDescPtr xkb,xkbGetMapReply *rep)
122305b261ecSmrg{
122405b261ecSmrg    unsigned	i,len,nRtrn;
122505b261ecSmrg
122605b261ecSmrg    if (((rep->present&XkbExplicitComponentsMask)==0)||(rep->nKeyExplicit<1)||
122705b261ecSmrg	(!xkb)||(!xkb->server)||(!xkb->server->explicit)) {
122805b261ecSmrg	rep->present&= ~XkbExplicitComponentsMask;
122905b261ecSmrg	rep->firstKeyExplicit= rep->nKeyExplicit= 0;
123005b261ecSmrg	rep->totalKeyExplicit= 0;
123105b261ecSmrg	return 0;
123205b261ecSmrg    }
123305b261ecSmrg    for (nRtrn=i=0;i<rep->nKeyExplicit;i++) {
123405b261ecSmrg	if (xkb->server->explicit[i+rep->firstKeyExplicit]!=0)
123505b261ecSmrg	    nRtrn++;
123605b261ecSmrg    }
123705b261ecSmrg    rep->totalKeyExplicit= nRtrn;
123805b261ecSmrg    len= XkbPaddedSize(nRtrn*2); /* two bytes per non-zero explicit component */
123905b261ecSmrg    return len;
124005b261ecSmrg}
124105b261ecSmrg
124205b261ecSmrgstatic char *
124305b261ecSmrgXkbWriteExplicit(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,ClientPtr client)
124405b261ecSmrg{
124505b261ecSmrgunsigned	i;
124605b261ecSmrgchar *		start;
124705b261ecSmrgunsigned char *	pExp;
124805b261ecSmrg
124905b261ecSmrg    start= buf;
125005b261ecSmrg    pExp= &xkb->server->explicit[rep->firstKeyExplicit];
125105b261ecSmrg    for (i=0;i<rep->nKeyExplicit;i++,pExp++) {
125205b261ecSmrg	if (*pExp!=0) {
125305b261ecSmrg	    *buf++= i+rep->firstKeyExplicit;
125405b261ecSmrg	    *buf++= *pExp;
125505b261ecSmrg	}
125605b261ecSmrg    }
125705b261ecSmrg    i= XkbPaddedSize(buf-start)-(buf-start); /* pad to word boundary */
125805b261ecSmrg    return buf+i;
125905b261ecSmrg}
126005b261ecSmrg
126105b261ecSmrgstatic int
126205b261ecSmrgXkbSizeModifierMap(XkbDescPtr xkb,xkbGetMapReply *rep)
126305b261ecSmrg{
126405b261ecSmrg    unsigned	i,len,nRtrn;
126505b261ecSmrg
126605b261ecSmrg    if (((rep->present&XkbModifierMapMask)==0)||(rep->nModMapKeys<1)||
126705b261ecSmrg	(!xkb)||(!xkb->map)||(!xkb->map->modmap)) {
126805b261ecSmrg	rep->present&= ~XkbModifierMapMask;
126905b261ecSmrg	rep->firstModMapKey= rep->nModMapKeys= 0;
127005b261ecSmrg	rep->totalModMapKeys= 0;
127105b261ecSmrg	return 0;
127205b261ecSmrg    }
127305b261ecSmrg    for (nRtrn=i=0;i<rep->nModMapKeys;i++) {
127405b261ecSmrg	if (xkb->map->modmap[i+rep->firstModMapKey]!=0)
127505b261ecSmrg	    nRtrn++;
127605b261ecSmrg    }
127705b261ecSmrg    rep->totalModMapKeys= nRtrn;
127805b261ecSmrg    len= XkbPaddedSize(nRtrn*2); /* two bytes per non-zero modmap component */
127905b261ecSmrg    return len;
128005b261ecSmrg}
128105b261ecSmrg
128205b261ecSmrgstatic char *
128305b261ecSmrgXkbWriteModifierMap(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
128405b261ecSmrg							ClientPtr client)
128505b261ecSmrg{
128605b261ecSmrgunsigned	i;
128705b261ecSmrgchar *		start;
128805b261ecSmrgunsigned char *	pMap;
128905b261ecSmrg
129005b261ecSmrg    start= buf;
129105b261ecSmrg    pMap= &xkb->map->modmap[rep->firstModMapKey];
129205b261ecSmrg    for (i=0;i<rep->nModMapKeys;i++,pMap++) {
129305b261ecSmrg	if (*pMap!=0) {
129405b261ecSmrg	    *buf++= i+rep->firstModMapKey;
129505b261ecSmrg	    *buf++= *pMap;
129605b261ecSmrg	}
129705b261ecSmrg    }
129805b261ecSmrg    i= XkbPaddedSize(buf-start)-(buf-start); /* pad to word boundary */
129905b261ecSmrg    return buf+i;
130005b261ecSmrg}
130105b261ecSmrg
130205b261ecSmrgstatic int
130305b261ecSmrgXkbSizeVirtualModMap(XkbDescPtr xkb,xkbGetMapReply *rep)
130405b261ecSmrg{
130505b261ecSmrg    unsigned	i,len,nRtrn;
130605b261ecSmrg
130705b261ecSmrg    if (((rep->present&XkbVirtualModMapMask)==0)||(rep->nVModMapKeys<1)||
130805b261ecSmrg	(!xkb)||(!xkb->server)||(!xkb->server->vmodmap)) {
130905b261ecSmrg	rep->present&= ~XkbVirtualModMapMask;
131005b261ecSmrg	rep->firstVModMapKey= rep->nVModMapKeys= 0;
131105b261ecSmrg	rep->totalVModMapKeys= 0;
131205b261ecSmrg	return 0;
131305b261ecSmrg    }
131452397711Smrg    for (nRtrn=i=0;i<rep->nVModMapKeys;i++) {
131505b261ecSmrg	if (xkb->server->vmodmap[i+rep->firstVModMapKey]!=0)
131605b261ecSmrg	    nRtrn++;
131705b261ecSmrg    }
131805b261ecSmrg    rep->totalVModMapKeys= nRtrn;
131905b261ecSmrg    len= nRtrn*SIZEOF(xkbVModMapWireDesc);
132005b261ecSmrg    return len;
132105b261ecSmrg}
132205b261ecSmrg
132305b261ecSmrgstatic char *
132405b261ecSmrgXkbWriteVirtualModMap(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
132505b261ecSmrg							ClientPtr client)
132605b261ecSmrg{
132705b261ecSmrgunsigned		i;
132805b261ecSmrgxkbVModMapWireDesc *	wire;
132905b261ecSmrgunsigned short *	pMap;
133005b261ecSmrg
133105b261ecSmrg    wire= (xkbVModMapWireDesc *)buf;
133205b261ecSmrg    pMap= &xkb->server->vmodmap[rep->firstVModMapKey];
133352397711Smrg    for (i=0;i<rep->nVModMapKeys;i++,pMap++) {
133405b261ecSmrg	if (*pMap!=0) {
133505b261ecSmrg	    wire->key= i+rep->firstVModMapKey;
133605b261ecSmrg	    wire->vmods= *pMap;
133705b261ecSmrg	    wire++;
133805b261ecSmrg	}
133905b261ecSmrg    }
134005b261ecSmrg    return (char *)wire;
134105b261ecSmrg}
134205b261ecSmrg
134305b261ecSmrgstatic Status
134405b261ecSmrgXkbComputeGetMapReplySize(XkbDescPtr xkb,xkbGetMapReply *rep)
134505b261ecSmrg{
134605b261ecSmrgint	len;
134705b261ecSmrg
134805b261ecSmrg    rep->minKeyCode= xkb->min_key_code;
134905b261ecSmrg    rep->maxKeyCode= xkb->max_key_code;
135005b261ecSmrg    len= XkbSizeKeyTypes(xkb,rep);
135105b261ecSmrg    len+= XkbSizeKeySyms(xkb,rep);
135205b261ecSmrg    len+= XkbSizeKeyActions(xkb,rep);
135305b261ecSmrg    len+= XkbSizeKeyBehaviors(xkb,rep);
135405b261ecSmrg    len+= XkbSizeVirtualMods(xkb,rep);
135505b261ecSmrg    len+= XkbSizeExplicit(xkb,rep);
135605b261ecSmrg    len+= XkbSizeModifierMap(xkb,rep);
135705b261ecSmrg    len+= XkbSizeVirtualModMap(xkb,rep);
135805b261ecSmrg    rep->length+= (len/4);
135905b261ecSmrg    return Success;
136005b261ecSmrg}
136105b261ecSmrg
136205b261ecSmrgstatic int
136305b261ecSmrgXkbSendMap(ClientPtr client,XkbDescPtr xkb,xkbGetMapReply *rep)
136405b261ecSmrg{
136505b261ecSmrgunsigned	i,len;
136605b261ecSmrgchar		*desc,*start;
136705b261ecSmrg
136805b261ecSmrg    len= (rep->length*4)-(SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply));
13694642e01fSmrg    start= desc= (char *)xalloc(len);
137005b261ecSmrg    if (!start)
137105b261ecSmrg	return BadAlloc;
137205b261ecSmrg    if ( rep->nTypes>0 )
137305b261ecSmrg	desc = XkbWriteKeyTypes(xkb,rep,desc,client);
137405b261ecSmrg    if ( rep->nKeySyms>0 )
137505b261ecSmrg	desc = XkbWriteKeySyms(xkb,rep,desc,client);
137605b261ecSmrg    if ( rep->nKeyActs>0 )
137705b261ecSmrg	desc = XkbWriteKeyActions(xkb,rep,desc,client);
137805b261ecSmrg    if ( rep->totalKeyBehaviors>0 )
137905b261ecSmrg	desc = XkbWriteKeyBehaviors(xkb,rep,desc,client);
138005b261ecSmrg    if ( rep->virtualMods ) {
138105b261ecSmrg	register int sz,bit;
138205b261ecSmrg	for (i=sz=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
138305b261ecSmrg	    if (rep->virtualMods&bit) {
138405b261ecSmrg		desc[sz++]= xkb->server->vmods[i];
138505b261ecSmrg	    }
138605b261ecSmrg	}
138705b261ecSmrg	desc+= XkbPaddedSize(sz);
138805b261ecSmrg    }
138905b261ecSmrg    if ( rep->totalKeyExplicit>0 )
139005b261ecSmrg	desc= XkbWriteExplicit(xkb,rep,desc,client);
139105b261ecSmrg    if ( rep->totalModMapKeys>0 )
139205b261ecSmrg	desc= XkbWriteModifierMap(xkb,rep,desc,client);
139305b261ecSmrg    if ( rep->totalVModMapKeys>0 )
139405b261ecSmrg	desc= XkbWriteVirtualModMap(xkb,rep,desc,client);
139505b261ecSmrg    if ((desc-start)!=(len)) {
13964642e01fSmrg	ErrorF("[xkb] BOGUS LENGTH in write keyboard desc, expected %d, got %ld\n",
139705b261ecSmrg					len, (unsigned long)(desc-start));
139805b261ecSmrg    }
139905b261ecSmrg    if (client->swapped) {
140005b261ecSmrg	register int n;
140105b261ecSmrg	swaps(&rep->sequenceNumber,n);
140205b261ecSmrg	swapl(&rep->length,n);
140305b261ecSmrg	swaps(&rep->present,n);
140405b261ecSmrg	swaps(&rep->totalSyms,n);
140505b261ecSmrg	swaps(&rep->totalActs,n);
140605b261ecSmrg    }
140705b261ecSmrg    WriteToClient(client, (i=SIZEOF(xkbGetMapReply)), (char *)rep);
140805b261ecSmrg    WriteToClient(client, len, start);
14094642e01fSmrg    xfree((char *)start);
141005b261ecSmrg    return client->noClientException;
141105b261ecSmrg}
141205b261ecSmrg
141305b261ecSmrgint
141405b261ecSmrgProcXkbGetMap(ClientPtr client)
141505b261ecSmrg{
141605b261ecSmrg    DeviceIntPtr	 dev;
141705b261ecSmrg    xkbGetMapReply	 rep;
141805b261ecSmrg    XkbDescRec		*xkb;
141905b261ecSmrg    int			 n,status;
142005b261ecSmrg
142105b261ecSmrg    REQUEST(xkbGetMapReq);
142205b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetMapReq);
142305b261ecSmrg
142405b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
142505b261ecSmrg	return BadAccess;
142605b261ecSmrg
14274642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
142805b261ecSmrg    CHK_MASK_OVERLAP(0x01,stuff->full,stuff->partial);
142905b261ecSmrg    CHK_MASK_LEGAL(0x02,stuff->full,XkbAllMapComponentsMask);
143005b261ecSmrg    CHK_MASK_LEGAL(0x03,stuff->partial,XkbAllMapComponentsMask);
143105b261ecSmrg
143205b261ecSmrg    xkb= dev->key->xkbInfo->desc;
143305b261ecSmrg    bzero(&rep,sizeof(xkbGetMapReply));
143405b261ecSmrg    rep.type= X_Reply;
143505b261ecSmrg    rep.sequenceNumber= client->sequence;
143605b261ecSmrg    rep.length = (SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2;
143705b261ecSmrg    rep.deviceID = dev->id;
143805b261ecSmrg    rep.present = stuff->partial|stuff->full;
143905b261ecSmrg    rep.minKeyCode = xkb->min_key_code;
144005b261ecSmrg    rep.maxKeyCode = xkb->max_key_code;
144105b261ecSmrg    if ( stuff->full&XkbKeyTypesMask ) {
144205b261ecSmrg	rep.firstType = 0;
144305b261ecSmrg	rep.nTypes = xkb->map->num_types;
144405b261ecSmrg    }
144505b261ecSmrg    else if (stuff->partial&XkbKeyTypesMask) {
144605b261ecSmrg	if (((unsigned)stuff->firstType+stuff->nTypes)>xkb->map->num_types) {
144705b261ecSmrg	    client->errorValue = _XkbErrCode4(0x04,xkb->map->num_types,
144805b261ecSmrg					stuff->firstType,stuff->nTypes);
144905b261ecSmrg	    return BadValue;
145005b261ecSmrg	}
145105b261ecSmrg	rep.firstType = stuff->firstType;
145205b261ecSmrg	rep.nTypes = stuff->nTypes;
145305b261ecSmrg    }
145405b261ecSmrg    else rep.nTypes = 0;
145505b261ecSmrg    rep.totalTypes = xkb->map->num_types;
145605b261ecSmrg
145705b261ecSmrg    n= XkbNumKeys(xkb);
145805b261ecSmrg    if ( stuff->full&XkbKeySymsMask ) {
145905b261ecSmrg	rep.firstKeySym = xkb->min_key_code;
146005b261ecSmrg	rep.nKeySyms = n;
146105b261ecSmrg    }
146205b261ecSmrg    else if (stuff->partial&XkbKeySymsMask) {
146305b261ecSmrg	CHK_KEY_RANGE(0x05,stuff->firstKeySym,stuff->nKeySyms,xkb);
146405b261ecSmrg	rep.firstKeySym = stuff->firstKeySym;
146505b261ecSmrg	rep.nKeySyms = stuff->nKeySyms;
146605b261ecSmrg    }
146705b261ecSmrg    else rep.nKeySyms = 0;
146805b261ecSmrg    rep.totalSyms= 0;
146905b261ecSmrg
147005b261ecSmrg    if ( stuff->full&XkbKeyActionsMask ) {
147105b261ecSmrg	rep.firstKeyAct= xkb->min_key_code;
147205b261ecSmrg	rep.nKeyActs= n;
147305b261ecSmrg    }
147405b261ecSmrg    else if (stuff->partial&XkbKeyActionsMask) {
147505b261ecSmrg	CHK_KEY_RANGE(0x07,stuff->firstKeyAct,stuff->nKeyActs,xkb);
147605b261ecSmrg	rep.firstKeyAct= stuff->firstKeyAct;
147705b261ecSmrg	rep.nKeyActs= stuff->nKeyActs;
147805b261ecSmrg    }
147905b261ecSmrg    else rep.nKeyActs= 0;
148005b261ecSmrg    rep.totalActs= 0;
148105b261ecSmrg
148205b261ecSmrg    if ( stuff->full&XkbKeyBehaviorsMask ) {
148305b261ecSmrg	rep.firstKeyBehavior = xkb->min_key_code;
148405b261ecSmrg	rep.nKeyBehaviors = n;
148505b261ecSmrg    }
148605b261ecSmrg    else if (stuff->partial&XkbKeyBehaviorsMask) {
148705b261ecSmrg	CHK_KEY_RANGE(0x09,stuff->firstKeyBehavior,stuff->nKeyBehaviors,xkb);
148805b261ecSmrg	rep.firstKeyBehavior= stuff->firstKeyBehavior;
148905b261ecSmrg	rep.nKeyBehaviors= stuff->nKeyBehaviors;
149005b261ecSmrg    }
149105b261ecSmrg    else rep.nKeyBehaviors = 0;
149205b261ecSmrg    rep.totalKeyBehaviors= 0;
149305b261ecSmrg
149405b261ecSmrg    if (stuff->full&XkbVirtualModsMask)
149505b261ecSmrg	rep.virtualMods= ~0;
149605b261ecSmrg    else if (stuff->partial&XkbVirtualModsMask)
149705b261ecSmrg	rep.virtualMods= stuff->virtualMods;
149805b261ecSmrg
149905b261ecSmrg    if (stuff->full&XkbExplicitComponentsMask) {
150005b261ecSmrg	rep.firstKeyExplicit= xkb->min_key_code;
150105b261ecSmrg	rep.nKeyExplicit= n;
150205b261ecSmrg    }
150305b261ecSmrg    else if (stuff->partial&XkbExplicitComponentsMask) {
150405b261ecSmrg	CHK_KEY_RANGE(0x0B,stuff->firstKeyExplicit,stuff->nKeyExplicit,xkb);
150505b261ecSmrg	rep.firstKeyExplicit= stuff->firstKeyExplicit;
150605b261ecSmrg	rep.nKeyExplicit= stuff->nKeyExplicit;
150705b261ecSmrg    }
150805b261ecSmrg    else rep.nKeyExplicit = 0;
150905b261ecSmrg    rep.totalKeyExplicit=  0;
151005b261ecSmrg
151105b261ecSmrg    if (stuff->full&XkbModifierMapMask) {
151205b261ecSmrg	rep.firstModMapKey= xkb->min_key_code;
151305b261ecSmrg	rep.nModMapKeys= n;
151405b261ecSmrg    }
151505b261ecSmrg    else if (stuff->partial&XkbModifierMapMask) {
151605b261ecSmrg	CHK_KEY_RANGE(0x0D,stuff->firstModMapKey,stuff->nModMapKeys,xkb);
151705b261ecSmrg	rep.firstModMapKey= stuff->firstModMapKey;
151805b261ecSmrg	rep.nModMapKeys= stuff->nModMapKeys;
151905b261ecSmrg    }
152005b261ecSmrg    else rep.nModMapKeys = 0;
152105b261ecSmrg    rep.totalModMapKeys= 0;
152205b261ecSmrg
152305b261ecSmrg    if (stuff->full&XkbVirtualModMapMask) {
152405b261ecSmrg	rep.firstVModMapKey= xkb->min_key_code;
152505b261ecSmrg	rep.nVModMapKeys= n;
152605b261ecSmrg    }
152705b261ecSmrg    else if (stuff->partial&XkbVirtualModMapMask) {
152805b261ecSmrg	CHK_KEY_RANGE(0x0F,stuff->firstVModMapKey,stuff->nVModMapKeys,xkb);
152905b261ecSmrg	rep.firstVModMapKey= stuff->firstVModMapKey;
153005b261ecSmrg	rep.nVModMapKeys= stuff->nVModMapKeys;
153105b261ecSmrg    }
153205b261ecSmrg    else rep.nVModMapKeys = 0;
153305b261ecSmrg    rep.totalVModMapKeys= 0;
153405b261ecSmrg
153505b261ecSmrg    if ((status=XkbComputeGetMapReplySize(xkb,&rep))!=Success)
153605b261ecSmrg	return status;
153705b261ecSmrg    return XkbSendMap(client,xkb,&rep);
153805b261ecSmrg}
153905b261ecSmrg
154005b261ecSmrg/***====================================================================***/
154105b261ecSmrg
154205b261ecSmrgstatic int
154305b261ecSmrgCheckKeyTypes(	ClientPtr	client,
154405b261ecSmrg		XkbDescPtr	xkb,
154505b261ecSmrg		xkbSetMapReq *	req,
154605b261ecSmrg		xkbKeyTypeWireDesc **wireRtrn,
154705b261ecSmrg		int	 *	nMapsRtrn,
154805b261ecSmrg		CARD8 *		mapWidthRtrn)
154905b261ecSmrg{
155005b261ecSmrgunsigned		nMaps;
155105b261ecSmrgregister unsigned	i,n;
155205b261ecSmrgregister CARD8 *	map;
155305b261ecSmrgregister xkbKeyTypeWireDesc	*wire = *wireRtrn;
155405b261ecSmrg
155505b261ecSmrg    if (req->firstType>((unsigned)xkb->map->num_types)) {
155605b261ecSmrg	*nMapsRtrn = _XkbErrCode3(0x01,req->firstType,xkb->map->num_types);
155705b261ecSmrg	return 0;
155805b261ecSmrg    }
155905b261ecSmrg    if (req->flags&XkbSetMapResizeTypes) {
156005b261ecSmrg	nMaps = req->firstType+req->nTypes;
156105b261ecSmrg	if (nMaps<XkbNumRequiredTypes) {  /* canonical types must be there */
156205b261ecSmrg	    *nMapsRtrn= _XkbErrCode4(0x02,req->firstType,req->nTypes,4);
156305b261ecSmrg	    return 0;
156405b261ecSmrg	}
156505b261ecSmrg    }
156605b261ecSmrg    else if (req->present&XkbKeyTypesMask) {
156705b261ecSmrg	nMaps = xkb->map->num_types;
156805b261ecSmrg	if ((req->firstType+req->nTypes)>nMaps) {
156905b261ecSmrg	    *nMapsRtrn = req->firstType+req->nTypes;
157005b261ecSmrg	    return 0;
157105b261ecSmrg	}
157205b261ecSmrg    }
157305b261ecSmrg    else {
157405b261ecSmrg	*nMapsRtrn = xkb->map->num_types;
157505b261ecSmrg	for (i=0;i<xkb->map->num_types;i++) {
157605b261ecSmrg	    mapWidthRtrn[i] = xkb->map->types[i].num_levels;
157705b261ecSmrg	}
157805b261ecSmrg	return 1;
157905b261ecSmrg    }
158005b261ecSmrg
158105b261ecSmrg    for (i=0;i<req->firstType;i++) {
158205b261ecSmrg	mapWidthRtrn[i] = xkb->map->types[i].num_levels;
158305b261ecSmrg    }
158405b261ecSmrg    for (i=0;i<req->nTypes;i++) {
158505b261ecSmrg	unsigned	width;
158605b261ecSmrg	if (client->swapped) {
158705b261ecSmrg	    register int s;
158805b261ecSmrg	    swaps(&wire->virtualMods,s);
158905b261ecSmrg	}
159005b261ecSmrg	n= i+req->firstType;
159105b261ecSmrg	width= wire->numLevels;
159205b261ecSmrg	if (width<1) {
159305b261ecSmrg	    *nMapsRtrn= _XkbErrCode3(0x04,n,width);
159405b261ecSmrg	    return 0;
159505b261ecSmrg	}
159605b261ecSmrg	else if ((n==XkbOneLevelIndex)&&(width!=1)) { /* must be width 1 */
159705b261ecSmrg	    *nMapsRtrn= _XkbErrCode3(0x05,n,width);
159805b261ecSmrg	    return 0;
159905b261ecSmrg	}
160005b261ecSmrg	else if ((width!=2)&&
160105b261ecSmrg		 ((n==XkbTwoLevelIndex)||(n==XkbKeypadIndex)||
160205b261ecSmrg		  (n==XkbAlphabeticIndex))) {
160305b261ecSmrg	    /* TWO_LEVEL, ALPHABETIC and KEYPAD must be width 2 */
160405b261ecSmrg	    *nMapsRtrn= _XkbErrCode3(0x05,n,width);
160505b261ecSmrg	    return 0;
160605b261ecSmrg	}
160705b261ecSmrg	if (wire->nMapEntries>0) {
160805b261ecSmrg	    xkbKTSetMapEntryWireDesc *	mapWire;
160905b261ecSmrg	    xkbModsWireDesc *		preWire;
161005b261ecSmrg	    mapWire= (xkbKTSetMapEntryWireDesc *)&wire[1];
161105b261ecSmrg	    preWire= (xkbModsWireDesc *)&mapWire[wire->nMapEntries];
161205b261ecSmrg	    for (n=0;n<wire->nMapEntries;n++) {
161305b261ecSmrg		if (client->swapped) {
161405b261ecSmrg		    register int s;
161505b261ecSmrg		    swaps(&mapWire[n].virtualMods,s);
161605b261ecSmrg		}
161705b261ecSmrg		if (mapWire[n].realMods&(~wire->realMods)) {
161805b261ecSmrg		    *nMapsRtrn= _XkbErrCode4(0x06,n,mapWire[n].realMods,
161905b261ecSmrg						 wire->realMods);
162005b261ecSmrg		    return 0;
162105b261ecSmrg		}
162205b261ecSmrg		if (mapWire[n].virtualMods&(~wire->virtualMods)) {
162305b261ecSmrg		    *nMapsRtrn= _XkbErrCode3(0x07,n,mapWire[n].virtualMods);
162405b261ecSmrg		    return 0;
162505b261ecSmrg		}
162605b261ecSmrg		if (mapWire[n].level>=wire->numLevels) {
162705b261ecSmrg		    *nMapsRtrn= _XkbErrCode4(0x08,n,wire->numLevels,
162805b261ecSmrg						 mapWire[n].level);
162905b261ecSmrg		    return 0;
163005b261ecSmrg		}
163105b261ecSmrg		if (wire->preserve) {
163205b261ecSmrg		    if (client->swapped) {
163305b261ecSmrg			register int s;
163405b261ecSmrg			swaps(&preWire[n].virtualMods,s);
163505b261ecSmrg		    }
163605b261ecSmrg		    if (preWire[n].realMods&(~mapWire[n].realMods)) {
163705b261ecSmrg			*nMapsRtrn= _XkbErrCode4(0x09,n,preWire[n].realMods,
163805b261ecSmrg							mapWire[n].realMods);
163905b261ecSmrg			return 0;
164005b261ecSmrg		    }
164105b261ecSmrg		    if (preWire[n].virtualMods&(~mapWire[n].virtualMods)) {
164205b261ecSmrg			*nMapsRtrn=_XkbErrCode3(0x0a,n,preWire[n].virtualMods);
164305b261ecSmrg			return 0;
164405b261ecSmrg		    }
164505b261ecSmrg		}
164605b261ecSmrg	    }
164705b261ecSmrg	    if (wire->preserve)
164805b261ecSmrg		 map= (CARD8 *)&preWire[wire->nMapEntries];
164905b261ecSmrg	    else map= (CARD8 *)&mapWire[wire->nMapEntries];
165005b261ecSmrg	}
165105b261ecSmrg	else map= (CARD8 *)&wire[1];
165205b261ecSmrg	mapWidthRtrn[i+req->firstType] = wire->numLevels;
165305b261ecSmrg	wire= (xkbKeyTypeWireDesc *)map;
165405b261ecSmrg    }
165505b261ecSmrg    for (i=req->firstType+req->nTypes;i<nMaps;i++) {
165605b261ecSmrg	mapWidthRtrn[i] = xkb->map->types[i].num_levels;
165705b261ecSmrg    }
165805b261ecSmrg    *nMapsRtrn = nMaps;
165905b261ecSmrg    *wireRtrn = wire;
166005b261ecSmrg    return 1;
166105b261ecSmrg}
166205b261ecSmrg
166305b261ecSmrgstatic int
166405b261ecSmrgCheckKeySyms(	ClientPtr		client,
166505b261ecSmrg		XkbDescPtr		xkb,
166605b261ecSmrg		xkbSetMapReq *		req,
166705b261ecSmrg		int			nTypes,
166805b261ecSmrg		CARD8 *	 		mapWidths,
166905b261ecSmrg		CARD16 *	 	symsPerKey,
167005b261ecSmrg		xkbSymMapWireDesc **	wireRtrn,
167105b261ecSmrg		int *			errorRtrn)
167205b261ecSmrg{
167305b261ecSmrgregister unsigned	i;
167405b261ecSmrgXkbSymMapPtr		map;
167505b261ecSmrgxkbSymMapWireDesc*	wire = *wireRtrn;
167605b261ecSmrg
167705b261ecSmrg    if (!(XkbKeySymsMask&req->present))
167805b261ecSmrg	return 1;
167905b261ecSmrg    CHK_REQ_KEY_RANGE2(0x11,req->firstKeySym,req->nKeySyms,req,(*errorRtrn),0);
168005b261ecSmrg    map = &xkb->map->key_sym_map[xkb->min_key_code];
168105b261ecSmrg    for (i=xkb->min_key_code;i<(unsigned)req->firstKeySym;i++,map++) {
168205b261ecSmrg	register int g,ng,w;
168305b261ecSmrg	ng= XkbNumGroups(map->group_info);
168405b261ecSmrg	for (w=g=0;g<ng;g++) {
168505b261ecSmrg	    if (map->kt_index[g]>=(unsigned)nTypes) {
168605b261ecSmrg		*errorRtrn = _XkbErrCode4(0x13,i,g,map->kt_index[g]);
168705b261ecSmrg		return 0;
168805b261ecSmrg	    }
168905b261ecSmrg	    if (mapWidths[map->kt_index[g]]>w)
169005b261ecSmrg		w= mapWidths[map->kt_index[g]];
169105b261ecSmrg	}
169205b261ecSmrg	symsPerKey[i] = w*ng;
169305b261ecSmrg    }
169405b261ecSmrg    for (i=0;i<req->nKeySyms;i++) {
169505b261ecSmrg	KeySym *pSyms;
169605b261ecSmrg	register unsigned nG;
169705b261ecSmrg	if (client->swapped) {
169805b261ecSmrg	    swaps(&wire->nSyms,nG);
169905b261ecSmrg	}
170005b261ecSmrg	nG = XkbNumGroups(wire->groupInfo);
170105b261ecSmrg	if (nG>XkbNumKbdGroups) {
170205b261ecSmrg	    *errorRtrn = _XkbErrCode3(0x14,i+req->firstKeySym,nG);
170305b261ecSmrg	    return 0;
170405b261ecSmrg	}
170505b261ecSmrg	if (nG>0) {
170605b261ecSmrg	    register int g,w;
170705b261ecSmrg	    for (g=w=0;g<nG;g++) {
170805b261ecSmrg		if (wire->ktIndex[g]>=(unsigned)nTypes) {
170905b261ecSmrg		    *errorRtrn= _XkbErrCode4(0x15,i+req->firstKeySym,g,
171005b261ecSmrg		    					   wire->ktIndex[g]);
171105b261ecSmrg		    return 0;
171205b261ecSmrg		}
171305b261ecSmrg		if (mapWidths[wire->ktIndex[g]]>w)
171405b261ecSmrg		    w= mapWidths[wire->ktIndex[g]];
171505b261ecSmrg	    }
171605b261ecSmrg	    if (wire->width!=w) {
171705b261ecSmrg		*errorRtrn= _XkbErrCode3(0x16,i+req->firstKeySym,wire->width);
171805b261ecSmrg		return 0;
171905b261ecSmrg	    }
172005b261ecSmrg	    w*= nG;
172105b261ecSmrg	    symsPerKey[i+req->firstKeySym] = w;
172205b261ecSmrg	    if (w!=wire->nSyms) {
172305b261ecSmrg		*errorRtrn=_XkbErrCode4(0x16,i+req->firstKeySym,wire->nSyms,w);
172405b261ecSmrg		return 0;
172505b261ecSmrg	    }
172605b261ecSmrg	}
172705b261ecSmrg	else if (wire->nSyms!=0) {
172805b261ecSmrg	    *errorRtrn = _XkbErrCode3(0x17,i+req->firstKeySym,wire->nSyms);
172905b261ecSmrg	    return 0;
173005b261ecSmrg	}
173105b261ecSmrg	pSyms = (KeySym *)&wire[1];
173205b261ecSmrg	wire = (xkbSymMapWireDesc *)&pSyms[wire->nSyms];
173305b261ecSmrg    }
173405b261ecSmrg
173505b261ecSmrg    map = &xkb->map->key_sym_map[i];
173605b261ecSmrg    for (;i<=(unsigned)xkb->max_key_code;i++,map++) {
173705b261ecSmrg	register int g,nG,w;
173805b261ecSmrg	nG= XkbKeyNumGroups(xkb,i);
173905b261ecSmrg	for (w=g=0;g<nG;g++)  {
174005b261ecSmrg	    if (map->kt_index[g]>=(unsigned)nTypes) {
174105b261ecSmrg		*errorRtrn = _XkbErrCode4(0x18,i,g,map->kt_index[g]);
174205b261ecSmrg		return 0;
174305b261ecSmrg	    }
174405b261ecSmrg	    if (mapWidths[map->kt_index[g]]>w)
174505b261ecSmrg		    w= mapWidths[map->kt_index[g]];
174605b261ecSmrg	}
174705b261ecSmrg	symsPerKey[i] = w*nG;
174805b261ecSmrg    }
174905b261ecSmrg    *wireRtrn = wire;
175005b261ecSmrg    return 1;
175105b261ecSmrg}
175205b261ecSmrg
175305b261ecSmrgstatic int
175405b261ecSmrgCheckKeyActions(	XkbDescPtr	xkb,
175505b261ecSmrg			xkbSetMapReq *	req,
175605b261ecSmrg			int		nTypes,
175705b261ecSmrg			CARD8 *		mapWidths,
175805b261ecSmrg			CARD16 *	symsPerKey,
175905b261ecSmrg			CARD8 **	wireRtrn,
176005b261ecSmrg			int *		nActsRtrn)
176105b261ecSmrg{
176205b261ecSmrgint			 nActs;
176305b261ecSmrgCARD8 *			 wire = *wireRtrn;
176405b261ecSmrgregister unsigned	 i;
176505b261ecSmrg
176605b261ecSmrg    if (!(XkbKeyActionsMask&req->present))
176705b261ecSmrg	return 1;
176805b261ecSmrg    CHK_REQ_KEY_RANGE2(0x21,req->firstKeyAct,req->nKeyActs,req,(*nActsRtrn),0);
176905b261ecSmrg    for (nActs=i=0;i<req->nKeyActs;i++) {
177005b261ecSmrg	if (wire[0]!=0) {
177105b261ecSmrg	    if (wire[0]==symsPerKey[i+req->firstKeyAct])
177205b261ecSmrg		nActs+= wire[0];
177305b261ecSmrg	    else {
177405b261ecSmrg		*nActsRtrn= _XkbErrCode3(0x23,i+req->firstKeyAct,wire[0]);
177505b261ecSmrg		return 0;
177605b261ecSmrg	    }
177705b261ecSmrg	}
177805b261ecSmrg	wire++;
177905b261ecSmrg    }
178005b261ecSmrg    if (req->nKeyActs%4)
178105b261ecSmrg	wire+= 4-(req->nKeyActs%4);
178205b261ecSmrg    *wireRtrn = (CARD8 *)(((XkbAnyAction *)wire)+nActs);
178305b261ecSmrg    *nActsRtrn = nActs;
178405b261ecSmrg    return 1;
178505b261ecSmrg}
178605b261ecSmrg
178705b261ecSmrgstatic int
178805b261ecSmrgCheckKeyBehaviors(	XkbDescPtr 		xkb,
178905b261ecSmrg			xkbSetMapReq *		req,
179005b261ecSmrg			xkbBehaviorWireDesc **	wireRtrn,
179105b261ecSmrg			int *			errorRtrn)
179205b261ecSmrg{
179305b261ecSmrgregister xkbBehaviorWireDesc *	wire = *wireRtrn;
179405b261ecSmrgregister XkbServerMapPtr	server = xkb->server;
179505b261ecSmrgregister unsigned	 	i;
179605b261ecSmrgunsigned			first,last;
179705b261ecSmrg
179805b261ecSmrg    if (((req->present&XkbKeyBehaviorsMask)==0)||(req->nKeyBehaviors<1)) {
179905b261ecSmrg	req->present&= ~XkbKeyBehaviorsMask;
180005b261ecSmrg	req->nKeyBehaviors= 0;
180105b261ecSmrg	return 1;
180205b261ecSmrg    }
180305b261ecSmrg    first= req->firstKeyBehavior;
180405b261ecSmrg    last=  req->firstKeyBehavior+req->nKeyBehaviors-1;
180505b261ecSmrg    if (first<req->minKeyCode) {
180605b261ecSmrg	*errorRtrn = _XkbErrCode3(0x31,first,req->minKeyCode);
180705b261ecSmrg	return 0;
180805b261ecSmrg    }
180905b261ecSmrg    if (last>req->maxKeyCode) {
181005b261ecSmrg	*errorRtrn = _XkbErrCode3(0x32,last,req->maxKeyCode);
181105b261ecSmrg	return 0;
181205b261ecSmrg    }
181305b261ecSmrg
181405b261ecSmrg    for (i=0;i<req->totalKeyBehaviors;i++,wire++) {
181505b261ecSmrg	if ((wire->key<first)||(wire->key>last)) {
181605b261ecSmrg	    *errorRtrn = _XkbErrCode4(0x33,first,last,wire->key);
181705b261ecSmrg	    return 0;
181805b261ecSmrg	}
181905b261ecSmrg	if ((wire->type&XkbKB_Permanent)&&
182005b261ecSmrg	    ((server->behaviors[wire->key].type!=wire->type)||
182105b261ecSmrg	     (server->behaviors[wire->key].data!=wire->data))) {
182205b261ecSmrg	    *errorRtrn = _XkbErrCode3(0x33,wire->key,wire->type);
182305b261ecSmrg	    return 0;
182405b261ecSmrg	}
182505b261ecSmrg	if ((wire->type==XkbKB_RadioGroup)&&
182605b261ecSmrg		((wire->data&(~XkbKB_RGAllowNone))>XkbMaxRadioGroups)) {
182705b261ecSmrg	    *errorRtrn= _XkbErrCode4(0x34,wire->key,wire->data,
182805b261ecSmrg							XkbMaxRadioGroups);
182905b261ecSmrg	    return 0;
183005b261ecSmrg	}
183105b261ecSmrg	if ((wire->type==XkbKB_Overlay1)||(wire->type==XkbKB_Overlay2)) {
183205b261ecSmrg	    CHK_KEY_RANGE2(0x35,wire->key,1,xkb,*errorRtrn,0);
183305b261ecSmrg	}
183405b261ecSmrg    }
183505b261ecSmrg    *wireRtrn = wire;
183605b261ecSmrg    return 1;
183705b261ecSmrg}
183805b261ecSmrg
183905b261ecSmrgstatic int
184005b261ecSmrgCheckVirtualMods(	XkbDescRec *	xkb,
184105b261ecSmrg			xkbSetMapReq *	req,
184205b261ecSmrg			CARD8 **	wireRtrn,
184305b261ecSmrg			int *		errorRtrn)
184405b261ecSmrg{
184505b261ecSmrgregister CARD8		*wire = *wireRtrn;
184605b261ecSmrgregister unsigned 	 i,nMods,bit;
184705b261ecSmrg
184805b261ecSmrg    if (((req->present&XkbVirtualModsMask)==0)||(req->virtualMods==0))
184905b261ecSmrg	return 1;
185005b261ecSmrg    for (i=nMods=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
185105b261ecSmrg	if (req->virtualMods&bit)
185205b261ecSmrg	    nMods++;
185305b261ecSmrg    }
185405b261ecSmrg    *wireRtrn= (wire+XkbPaddedSize(nMods));
185505b261ecSmrg    return 1;
185605b261ecSmrg}
185705b261ecSmrg
185805b261ecSmrgstatic int
185905b261ecSmrgCheckKeyExplicit(	XkbDescPtr	xkb,
186005b261ecSmrg			xkbSetMapReq *	req,
186105b261ecSmrg			CARD8 **	wireRtrn,
186205b261ecSmrg			int	*	errorRtrn)
186305b261ecSmrg{
186405b261ecSmrgregister CARD8 *	wire = *wireRtrn;
186505b261ecSmrgCARD8	*		start;
186605b261ecSmrgregister unsigned 	i;
186705b261ecSmrgint			first,last;
186805b261ecSmrg
186905b261ecSmrg    if (((req->present&XkbExplicitComponentsMask)==0)||(req->nKeyExplicit<1)) {
187005b261ecSmrg	req->present&= ~XkbExplicitComponentsMask;
187105b261ecSmrg	req->nKeyExplicit= 0;
187205b261ecSmrg	return 1;
187305b261ecSmrg    }
187405b261ecSmrg    first= req->firstKeyExplicit;
187505b261ecSmrg    last=  first+req->nKeyExplicit-1;
187605b261ecSmrg    if (first<req->minKeyCode) {
187705b261ecSmrg	*errorRtrn = _XkbErrCode3(0x51,first,req->minKeyCode);
187805b261ecSmrg	return 0;
187905b261ecSmrg    }
188005b261ecSmrg    if (last>req->maxKeyCode) {
188105b261ecSmrg	*errorRtrn = _XkbErrCode3(0x52,last,req->maxKeyCode);
188205b261ecSmrg	return 0;
188305b261ecSmrg    }
188405b261ecSmrg    start= wire;
188505b261ecSmrg    for (i=0;i<req->totalKeyExplicit;i++,wire+=2) {
188605b261ecSmrg	if ((wire[0]<first)||(wire[0]>last)) {
188705b261ecSmrg	    *errorRtrn = _XkbErrCode4(0x53,first,last,wire[0]);
188805b261ecSmrg	    return 0;
188905b261ecSmrg	}
189005b261ecSmrg	if (wire[1]&(~XkbAllExplicitMask)) {
189105b261ecSmrg	     *errorRtrn= _XkbErrCode3(0x52,~XkbAllExplicitMask,wire[1]);
189205b261ecSmrg	     return 0;
189305b261ecSmrg	}
189405b261ecSmrg    }
189505b261ecSmrg    wire+= XkbPaddedSize(wire-start)-(wire-start);
189605b261ecSmrg    *wireRtrn= wire;
189705b261ecSmrg    return 1;
189805b261ecSmrg}
189905b261ecSmrg
190005b261ecSmrgstatic int
190105b261ecSmrgCheckModifierMap(XkbDescPtr xkb,xkbSetMapReq *req,CARD8 **wireRtrn,int *errRtrn)
190205b261ecSmrg{
190305b261ecSmrgregister CARD8 *	wire = *wireRtrn;
190405b261ecSmrgCARD8	*		start;
190505b261ecSmrgregister unsigned 	i;
190605b261ecSmrgint			first,last;
190705b261ecSmrg
190805b261ecSmrg    if (((req->present&XkbModifierMapMask)==0)||(req->nModMapKeys<1)) {
190905b261ecSmrg	req->present&= ~XkbModifierMapMask;
191005b261ecSmrg	req->nModMapKeys= 0;
191105b261ecSmrg	return 1;
191205b261ecSmrg    }
191305b261ecSmrg    first= req->firstModMapKey;
191405b261ecSmrg    last=  first+req->nModMapKeys-1;
191505b261ecSmrg    if (first<req->minKeyCode) {
191605b261ecSmrg	*errRtrn = _XkbErrCode3(0x61,first,req->minKeyCode);
191705b261ecSmrg	return 0;
191805b261ecSmrg    }
191905b261ecSmrg    if (last>req->maxKeyCode) {
192005b261ecSmrg	*errRtrn = _XkbErrCode3(0x62,last,req->maxKeyCode);
192105b261ecSmrg	return 0;
192205b261ecSmrg    }
192305b261ecSmrg    start= wire;
192405b261ecSmrg    for (i=0;i<req->totalModMapKeys;i++,wire+=2) {
192505b261ecSmrg	if ((wire[0]<first)||(wire[0]>last)) {
192605b261ecSmrg	    *errRtrn = _XkbErrCode4(0x63,first,last,wire[0]);
192705b261ecSmrg	    return 0;
192805b261ecSmrg	}
192905b261ecSmrg    }
193005b261ecSmrg    wire+= XkbPaddedSize(wire-start)-(wire-start);
193105b261ecSmrg    *wireRtrn= wire;
193205b261ecSmrg    return 1;
193305b261ecSmrg}
193405b261ecSmrg
193505b261ecSmrgstatic int
193605b261ecSmrgCheckVirtualModMap(	XkbDescPtr xkb,
193705b261ecSmrg			xkbSetMapReq *req,
193805b261ecSmrg			xkbVModMapWireDesc **wireRtrn,
193905b261ecSmrg			int *errRtrn)
194005b261ecSmrg{
194105b261ecSmrgregister xkbVModMapWireDesc *	wire = *wireRtrn;
194205b261ecSmrgregister unsigned 		i;
194305b261ecSmrgint				first,last;
194405b261ecSmrg
194505b261ecSmrg    if (((req->present&XkbVirtualModMapMask)==0)||(req->nVModMapKeys<1)) {
194605b261ecSmrg	req->present&= ~XkbVirtualModMapMask;
194705b261ecSmrg	req->nVModMapKeys= 0;
194805b261ecSmrg	return 1;
194905b261ecSmrg    }
195005b261ecSmrg    first= req->firstVModMapKey;
195105b261ecSmrg    last=  first+req->nVModMapKeys-1;
195205b261ecSmrg    if (first<req->minKeyCode) {
195305b261ecSmrg	*errRtrn = _XkbErrCode3(0x71,first,req->minKeyCode);
195405b261ecSmrg	return 0;
195505b261ecSmrg    }
195605b261ecSmrg    if (last>req->maxKeyCode) {
195705b261ecSmrg	*errRtrn = _XkbErrCode3(0x72,last,req->maxKeyCode);
195805b261ecSmrg	return 0;
195905b261ecSmrg    }
196005b261ecSmrg    for (i=0;i<req->totalVModMapKeys;i++,wire++) {
196105b261ecSmrg	if ((wire->key<first)||(wire->key>last)) {
196205b261ecSmrg	    *errRtrn = _XkbErrCode4(0x73,first,last,wire->key);
196305b261ecSmrg	    return 0;
196405b261ecSmrg	}
196505b261ecSmrg    }
196605b261ecSmrg    *wireRtrn= wire;
196705b261ecSmrg    return 1;
196805b261ecSmrg}
196905b261ecSmrg
197005b261ecSmrgstatic char *
197105b261ecSmrgSetKeyTypes(	XkbDescPtr		xkb,
197205b261ecSmrg		xkbSetMapReq *		req,
197305b261ecSmrg		xkbKeyTypeWireDesc *	wire,
197405b261ecSmrg		XkbChangesPtr		changes)
197505b261ecSmrg{
197605b261ecSmrgregister unsigned	i;
197705b261ecSmrgunsigned		first,last;
197805b261ecSmrgCARD8			*map;
197905b261ecSmrg
198005b261ecSmrg    if ((unsigned)(req->firstType+req->nTypes)>xkb->map->size_types) {
198105b261ecSmrg	i= req->firstType+req->nTypes;
198205b261ecSmrg	if (XkbAllocClientMap(xkb,XkbKeyTypesMask,i)!=Success) {
198305b261ecSmrg	    return NULL;
198405b261ecSmrg	}
198505b261ecSmrg    }
198605b261ecSmrg    if ((unsigned)(req->firstType+req->nTypes)>xkb->map->num_types)
198705b261ecSmrg	xkb->map->num_types= req->firstType+req->nTypes;
198805b261ecSmrg
198905b261ecSmrg    for (i=0;i<req->nTypes;i++) {
199005b261ecSmrg	XkbKeyTypePtr		pOld;
199105b261ecSmrg	register unsigned 	n;
199205b261ecSmrg
199305b261ecSmrg	if (XkbResizeKeyType(xkb,i+req->firstType,wire->nMapEntries,
199405b261ecSmrg				wire->preserve,wire->numLevels)!=Success) {
199505b261ecSmrg	    return NULL;
199605b261ecSmrg	}
199705b261ecSmrg	pOld = &xkb->map->types[i+req->firstType];
199805b261ecSmrg	map = (CARD8 *)&wire[1];
199905b261ecSmrg
200005b261ecSmrg	pOld->mods.real_mods = wire->realMods;
200105b261ecSmrg	pOld->mods.vmods= wire->virtualMods;
200205b261ecSmrg	pOld->num_levels = wire->numLevels;
200305b261ecSmrg	pOld->map_count= wire->nMapEntries;
200405b261ecSmrg
200505b261ecSmrg	pOld->mods.mask= pOld->mods.real_mods|
200605b261ecSmrg					XkbMaskForVMask(xkb,pOld->mods.vmods);
200705b261ecSmrg
200805b261ecSmrg	if (wire->nMapEntries) {
200905b261ecSmrg	    xkbKTSetMapEntryWireDesc *mapWire;
201005b261ecSmrg	    xkbModsWireDesc *preWire;
201105b261ecSmrg	    unsigned tmp;
201205b261ecSmrg	    mapWire= (xkbKTSetMapEntryWireDesc *)map;
201305b261ecSmrg	    preWire= (xkbModsWireDesc *)&mapWire[wire->nMapEntries];
201405b261ecSmrg	    for (n=0;n<wire->nMapEntries;n++) {
201505b261ecSmrg		pOld->map[n].active= 1;
201605b261ecSmrg		pOld->map[n].mods.mask= mapWire[n].realMods;
201705b261ecSmrg		pOld->map[n].mods.real_mods= mapWire[n].realMods;
201805b261ecSmrg		pOld->map[n].mods.vmods= mapWire[n].virtualMods;
201905b261ecSmrg		pOld->map[n].level= mapWire[n].level;
202005b261ecSmrg		if (mapWire[n].virtualMods!=0) {
202105b261ecSmrg		    tmp= XkbMaskForVMask(xkb,mapWire[n].virtualMods);
202205b261ecSmrg		    pOld->map[n].active= (tmp!=0);
202305b261ecSmrg		    pOld->map[n].mods.mask|= tmp;
202405b261ecSmrg		}
202505b261ecSmrg		if (wire->preserve) {
202605b261ecSmrg		    pOld->preserve[n].real_mods= preWire[n].realMods;
202705b261ecSmrg		    pOld->preserve[n].vmods= preWire[n].virtualMods;
202805b261ecSmrg		    tmp= XkbMaskForVMask(xkb,preWire[n].virtualMods);
202905b261ecSmrg		    pOld->preserve[n].mask= preWire[n].realMods|tmp;
203005b261ecSmrg		}
203105b261ecSmrg	    }
203205b261ecSmrg	    if (wire->preserve)
203305b261ecSmrg		 map= (CARD8 *)&preWire[wire->nMapEntries];
203405b261ecSmrg	    else map= (CARD8 *)&mapWire[wire->nMapEntries];
203505b261ecSmrg	}
203605b261ecSmrg	else map= (CARD8 *)&wire[1];
203705b261ecSmrg	wire = (xkbKeyTypeWireDesc *)map;
203805b261ecSmrg    }
203905b261ecSmrg    first= req->firstType;
204005b261ecSmrg    last= first+req->nTypes-1; /* last changed type */
204105b261ecSmrg    if (changes->map.changed&XkbKeyTypesMask) {
204205b261ecSmrg	int oldLast;
204305b261ecSmrg	oldLast= changes->map.first_type+changes->map.num_types-1;
204405b261ecSmrg	if (changes->map.first_type<first)
204505b261ecSmrg	    first= changes->map.first_type;
204605b261ecSmrg	if (oldLast>last)
204705b261ecSmrg	    last= oldLast;
204805b261ecSmrg    }
204905b261ecSmrg    changes->map.changed|= XkbKeyTypesMask;
205005b261ecSmrg    changes->map.first_type = first;
205105b261ecSmrg    changes->map.num_types = (last-first)+1;
205205b261ecSmrg    return (char *)wire;
205305b261ecSmrg}
205405b261ecSmrg
205505b261ecSmrgstatic char *
205605b261ecSmrgSetKeySyms(	ClientPtr		client,
205705b261ecSmrg		XkbDescPtr		xkb,
205805b261ecSmrg		xkbSetMapReq *		req,
205905b261ecSmrg		xkbSymMapWireDesc *	wire,
206005b261ecSmrg		XkbChangesPtr 		changes,
206105b261ecSmrg		DeviceIntPtr		dev)
206205b261ecSmrg{
206305b261ecSmrgregister unsigned 	i,s;
206405b261ecSmrgXkbSymMapPtr		oldMap;
206505b261ecSmrgKeySym *		newSyms;
206605b261ecSmrgKeySym *		pSyms;
206705b261ecSmrgunsigned		first,last;
206805b261ecSmrg
206905b261ecSmrg    oldMap = &xkb->map->key_sym_map[req->firstKeySym];
207005b261ecSmrg    for (i=0;i<req->nKeySyms;i++,oldMap++) {
207105b261ecSmrg	pSyms = (KeySym *)&wire[1];
207205b261ecSmrg	if (wire->nSyms>0) {
207305b261ecSmrg	    newSyms = XkbResizeKeySyms(xkb,i+req->firstKeySym,wire->nSyms);
207405b261ecSmrg	    for (s=0;s<wire->nSyms;s++) {
207505b261ecSmrg		newSyms[s]= pSyms[s];
207605b261ecSmrg	    }
207705b261ecSmrg	    if (client->swapped) {
207805b261ecSmrg		int n;
207905b261ecSmrg		for (s=0;s<wire->nSyms;s++) {
208005b261ecSmrg		    swapl(&newSyms[s],n);
208105b261ecSmrg		}
208205b261ecSmrg	    }
208305b261ecSmrg	}
208405b261ecSmrg	oldMap->kt_index[0] = wire->ktIndex[0];
208505b261ecSmrg	oldMap->kt_index[1] = wire->ktIndex[1];
208605b261ecSmrg	oldMap->kt_index[2] = wire->ktIndex[2];
208705b261ecSmrg	oldMap->kt_index[3] = wire->ktIndex[3];
208805b261ecSmrg	oldMap->group_info = wire->groupInfo;
208905b261ecSmrg	oldMap->width = wire->width;
209005b261ecSmrg	wire= (xkbSymMapWireDesc *)&pSyms[wire->nSyms];
209105b261ecSmrg    }
209205b261ecSmrg    first= req->firstKeySym;
209305b261ecSmrg    last= first+req->nKeySyms-1;
209405b261ecSmrg    if (changes->map.changed&XkbKeySymsMask) {
209505b261ecSmrg	int oldLast= (changes->map.first_key_sym+changes->map.num_key_syms-1);
209605b261ecSmrg	if (changes->map.first_key_sym<first)
209705b261ecSmrg	    first= changes->map.first_key_sym;
209805b261ecSmrg	if (oldLast>last)
209905b261ecSmrg	    last= oldLast;
210005b261ecSmrg    }
210105b261ecSmrg    changes->map.changed|= XkbKeySymsMask;
210205b261ecSmrg    changes->map.first_key_sym = first;
210305b261ecSmrg    changes->map.num_key_syms = (last-first+1);
210405b261ecSmrg
210505b261ecSmrg    s= 0;
210605b261ecSmrg    for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
210705b261ecSmrg	if (XkbKeyNumGroups(xkb,i)>s)
210805b261ecSmrg	    s= XkbKeyNumGroups(xkb,i);
210905b261ecSmrg    }
211005b261ecSmrg    if (s!=xkb->ctrls->num_groups) {
211105b261ecSmrg	xkbControlsNotify	cn;
211205b261ecSmrg	XkbControlsRec		old;
211305b261ecSmrg	cn.keycode= 0;
211405b261ecSmrg	cn.eventType= 0;
211505b261ecSmrg	cn.requestMajor= XkbReqCode;
211605b261ecSmrg	cn.requestMinor= X_kbSetMap;
211705b261ecSmrg	old= *xkb->ctrls;
211805b261ecSmrg	xkb->ctrls->num_groups= s;
211905b261ecSmrg	if (XkbComputeControlsNotify(dev,&old,xkb->ctrls,&cn,False))
212005b261ecSmrg	    XkbSendControlsNotify(dev,&cn);
212105b261ecSmrg    }
212205b261ecSmrg    return (char *)wire;
212305b261ecSmrg}
212405b261ecSmrg
212505b261ecSmrgstatic char *
212605b261ecSmrgSetKeyActions(	XkbDescPtr	xkb,
212705b261ecSmrg		xkbSetMapReq *	req,
212805b261ecSmrg		CARD8 *		wire,
212905b261ecSmrg		XkbChangesPtr	changes)
213005b261ecSmrg{
213105b261ecSmrgregister unsigned	i,first,last;
213205b261ecSmrgCARD8 *			nActs = wire;
213305b261ecSmrgXkbAction *		newActs;
213405b261ecSmrg
213505b261ecSmrg    wire+= XkbPaddedSize(req->nKeyActs);
213605b261ecSmrg    for (i=0;i<req->nKeyActs;i++) {
213705b261ecSmrg	if (nActs[i]==0)
213805b261ecSmrg	    xkb->server->key_acts[i+req->firstKeyAct]= 0;
213905b261ecSmrg	else {
214005b261ecSmrg	    newActs= XkbResizeKeyActions(xkb,i+req->firstKeyAct,nActs[i]);
214105b261ecSmrg	    memcpy((char *)newActs,(char *)wire,
214205b261ecSmrg					nActs[i]*SIZEOF(xkbActionWireDesc));
214305b261ecSmrg	    wire+= nActs[i]*SIZEOF(xkbActionWireDesc);
214405b261ecSmrg	}
214505b261ecSmrg    }
214605b261ecSmrg    first= req->firstKeyAct;
214705b261ecSmrg    last= (first+req->nKeyActs-1);
214805b261ecSmrg    if (changes->map.changed&XkbKeyActionsMask) {
214905b261ecSmrg	int oldLast;
215005b261ecSmrg	oldLast= changes->map.first_key_act+changes->map.num_key_acts-1;
215105b261ecSmrg	if (changes->map.first_key_act<first)
215205b261ecSmrg	    first= changes->map.first_key_act;
215305b261ecSmrg	if (oldLast>last)
215405b261ecSmrg	    last= oldLast;
215505b261ecSmrg    }
215605b261ecSmrg    changes->map.changed|= XkbKeyActionsMask;
215705b261ecSmrg    changes->map.first_key_act= first;
215805b261ecSmrg    changes->map.num_key_acts= (last-first+1);
215905b261ecSmrg    return (char *)wire;
216005b261ecSmrg}
216105b261ecSmrg
216205b261ecSmrgstatic char *
216305b261ecSmrgSetKeyBehaviors(	XkbSrvInfoPtr	 xkbi,
216405b261ecSmrg    			xkbSetMapReq	*req,
216505b261ecSmrg    			xkbBehaviorWireDesc	*wire,
216605b261ecSmrg    			XkbChangesPtr	 changes)
216705b261ecSmrg{
216805b261ecSmrgregister unsigned i;
216905b261ecSmrgint maxRG = -1;
217005b261ecSmrgXkbDescPtr       xkb = xkbi->desc;
217105b261ecSmrgXkbServerMapPtr	 server = xkb->server;
217205b261ecSmrgunsigned	 first,last;
217305b261ecSmrg
217405b261ecSmrg    first= req->firstKeyBehavior;
217505b261ecSmrg    last= req->firstKeyBehavior+req->nKeyBehaviors-1;
217605b261ecSmrg    bzero(&server->behaviors[first],req->nKeyBehaviors*sizeof(XkbBehavior));
217705b261ecSmrg    for (i=0;i<req->totalKeyBehaviors;i++) {
217805b261ecSmrg	if ((server->behaviors[wire->key].type&XkbKB_Permanent)==0) {
217905b261ecSmrg	    server->behaviors[wire->key].type= wire->type;
218005b261ecSmrg	    server->behaviors[wire->key].data= wire->data;
218105b261ecSmrg	    if ((wire->type==XkbKB_RadioGroup)&&(((int)wire->data)>maxRG))
218205b261ecSmrg		maxRG= wire->data + 1;
218305b261ecSmrg	}
218405b261ecSmrg	wire++;
218505b261ecSmrg    }
218605b261ecSmrg
218705b261ecSmrg    if (maxRG>(int)xkbi->nRadioGroups) {
218805b261ecSmrg        int sz = maxRG*sizeof(XkbRadioGroupRec);
218905b261ecSmrg        if (xkbi->radioGroups)
219005b261ecSmrg             xkbi->radioGroups=(XkbRadioGroupPtr)_XkbRealloc(xkbi->radioGroups,sz);
219105b261ecSmrg        else xkbi->radioGroups= (XkbRadioGroupPtr)_XkbCalloc(1, sz);
219205b261ecSmrg        if (xkbi->radioGroups) {
219305b261ecSmrg             if (xkbi->nRadioGroups)
219405b261ecSmrg                bzero(&xkbi->radioGroups[xkbi->nRadioGroups],
219505b261ecSmrg                        (maxRG-xkbi->nRadioGroups)*sizeof(XkbRadioGroupRec));
219605b261ecSmrg             xkbi->nRadioGroups= maxRG;
219705b261ecSmrg        }
219805b261ecSmrg        else xkbi->nRadioGroups= 0;
219905b261ecSmrg        /* should compute members here */
220005b261ecSmrg    }
220105b261ecSmrg    if (changes->map.changed&XkbKeyBehaviorsMask) {
220205b261ecSmrg	unsigned oldLast;
220305b261ecSmrg	oldLast= changes->map.first_key_behavior+
220405b261ecSmrg					changes->map.num_key_behaviors-1;
220505b261ecSmrg        if (changes->map.first_key_behavior<req->firstKeyBehavior)
220605b261ecSmrg             first= changes->map.first_key_behavior;
220705b261ecSmrg        if (oldLast>last)
220805b261ecSmrg            last= oldLast;
220905b261ecSmrg    }
221005b261ecSmrg    changes->map.changed|= XkbKeyBehaviorsMask;
221105b261ecSmrg    changes->map.first_key_behavior = first;
221205b261ecSmrg    changes->map.num_key_behaviors = (last-first+1);
221305b261ecSmrg    return (char *)wire;
221405b261ecSmrg}
221505b261ecSmrg
221605b261ecSmrgstatic char *
221705b261ecSmrgSetVirtualMods(XkbSrvInfoPtr xkbi,xkbSetMapReq *req,CARD8 *wire,
221805b261ecSmrg						XkbChangesPtr changes)
221905b261ecSmrg{
222005b261ecSmrgregister int 		i,bit,nMods;
222105b261ecSmrgXkbServerMapPtr		srv = xkbi->desc->server;
222205b261ecSmrg
222305b261ecSmrg    if (((req->present&XkbVirtualModsMask)==0)||(req->virtualMods==0))
222405b261ecSmrg	return (char *)wire;
222505b261ecSmrg    for (i=nMods=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
222605b261ecSmrg	if (req->virtualMods&bit) {
222705b261ecSmrg	    if (srv->vmods[i]!=wire[nMods]) {
222805b261ecSmrg		changes->map.changed|= XkbVirtualModsMask;
222905b261ecSmrg		changes->map.vmods|= bit;
223005b261ecSmrg		srv->vmods[i]= wire[nMods];
223105b261ecSmrg	    }
223205b261ecSmrg	    nMods++;
223305b261ecSmrg	}
223405b261ecSmrg    }
223505b261ecSmrg    return (char *)(wire+XkbPaddedSize(nMods));
223605b261ecSmrg}
223705b261ecSmrg
223805b261ecSmrgstatic char *
223905b261ecSmrgSetKeyExplicit(XkbSrvInfoPtr xkbi,xkbSetMapReq *req,CARD8 *wire,
224005b261ecSmrg							XkbChangesPtr changes)
224105b261ecSmrg{
224205b261ecSmrgregister unsigned	i,first,last;
224305b261ecSmrgXkbServerMapPtr		xkb = xkbi->desc->server;
224405b261ecSmrgCARD8 *			start;
224505b261ecSmrg
224605b261ecSmrg    start= wire;
224705b261ecSmrg    first= req->firstKeyExplicit;
224805b261ecSmrg    last=  req->firstKeyExplicit+req->nKeyExplicit-1;
224905b261ecSmrg    bzero(&xkb->explicit[first],req->nKeyExplicit);
225005b261ecSmrg    for (i=0;i<req->totalKeyExplicit;i++,wire+= 2) {
225105b261ecSmrg	xkb->explicit[wire[0]]= wire[1];
225205b261ecSmrg    }
225305b261ecSmrg    if (first>0) {
225405b261ecSmrg	if (changes->map.changed&XkbExplicitComponentsMask) {
225505b261ecSmrg	    int oldLast;
225605b261ecSmrg	    oldLast= changes->map.first_key_explicit+
225705b261ecSmrg					changes->map.num_key_explicit-1;
225805b261ecSmrg	    if (changes->map.first_key_explicit<first)
225905b261ecSmrg		first= changes->map.first_key_explicit;
226005b261ecSmrg	    if (oldLast>last)
226105b261ecSmrg		last= oldLast;
226205b261ecSmrg	}
226305b261ecSmrg	changes->map.first_key_explicit= first;
226405b261ecSmrg	changes->map.num_key_explicit= (last-first)+1;
226505b261ecSmrg    }
226605b261ecSmrg    wire+= XkbPaddedSize(wire-start)-(wire-start);
226705b261ecSmrg    return (char *)wire;
226805b261ecSmrg}
226905b261ecSmrg
227005b261ecSmrgstatic char *
227105b261ecSmrgSetModifierMap(	XkbSrvInfoPtr	xkbi,
227205b261ecSmrg		xkbSetMapReq *	req,
227305b261ecSmrg		CARD8 *		wire,
227405b261ecSmrg		XkbChangesPtr	changes)
227505b261ecSmrg{
227605b261ecSmrgregister unsigned	i,first,last;
227705b261ecSmrgXkbClientMapPtr		xkb = xkbi->desc->map;
227805b261ecSmrgCARD8 *			start;
227905b261ecSmrg
228005b261ecSmrg    start= wire;
228105b261ecSmrg    first= req->firstModMapKey;
228205b261ecSmrg    last=  req->firstModMapKey+req->nModMapKeys-1;
228305b261ecSmrg    bzero(&xkb->modmap[first],req->nModMapKeys);
228405b261ecSmrg    for (i=0;i<req->totalModMapKeys;i++,wire+= 2) {
228505b261ecSmrg	xkb->modmap[wire[0]]= wire[1];
228605b261ecSmrg    }
228705b261ecSmrg    if (first>0) {
228805b261ecSmrg	if (changes->map.changed&XkbModifierMapMask) {
228905b261ecSmrg	    int oldLast;
229005b261ecSmrg	    oldLast= changes->map.first_modmap_key+
229105b261ecSmrg						changes->map.num_modmap_keys-1;
229205b261ecSmrg	    if (changes->map.first_modmap_key<first)
229305b261ecSmrg		first= changes->map.first_modmap_key;
229405b261ecSmrg	    if (oldLast>last)
229505b261ecSmrg		last= oldLast;
229605b261ecSmrg	}
229705b261ecSmrg	changes->map.first_modmap_key= first;
229805b261ecSmrg	changes->map.num_modmap_keys= (last-first)+1;
229905b261ecSmrg    }
230005b261ecSmrg    wire+= XkbPaddedSize(wire-start)-(wire-start);
230105b261ecSmrg    return (char *)wire;
230205b261ecSmrg}
230305b261ecSmrg
230405b261ecSmrgstatic char *
230505b261ecSmrgSetVirtualModMap(	XkbSrvInfoPtr		xkbi,
230605b261ecSmrg			xkbSetMapReq *		req,
230705b261ecSmrg			xkbVModMapWireDesc *	wire,
230805b261ecSmrg			XkbChangesPtr 		changes)
230905b261ecSmrg{
231005b261ecSmrgregister unsigned	i,first,last;
231105b261ecSmrgXkbServerMapPtr		srv = xkbi->desc->server;
231205b261ecSmrg
231305b261ecSmrg    first= req->firstVModMapKey;
231405b261ecSmrg    last=  req->firstVModMapKey+req->nVModMapKeys-1;
231505b261ecSmrg    bzero(&srv->vmodmap[first],req->nVModMapKeys*sizeof(unsigned short));
231605b261ecSmrg    for (i=0;i<req->totalVModMapKeys;i++,wire++) {
231705b261ecSmrg	srv->vmodmap[wire->key]= wire->vmods;
231805b261ecSmrg    }
231905b261ecSmrg    if (first>0) {
232005b261ecSmrg	if (changes->map.changed&XkbVirtualModMapMask) {
232105b261ecSmrg	    int oldLast;
232205b261ecSmrg	    oldLast= changes->map.first_vmodmap_key+
232305b261ecSmrg					changes->map.num_vmodmap_keys-1;
232405b261ecSmrg	    if (changes->map.first_vmodmap_key<first)
232505b261ecSmrg		first= changes->map.first_vmodmap_key;
232605b261ecSmrg	    if (oldLast>last)
232705b261ecSmrg		last= oldLast;
232805b261ecSmrg	}
232905b261ecSmrg	changes->map.first_vmodmap_key= first;
233005b261ecSmrg	changes->map.num_vmodmap_keys= (last-first)+1;
233105b261ecSmrg    }
233205b261ecSmrg    return (char *)wire;
233305b261ecSmrg}
233405b261ecSmrg
23354642e01fSmrg/**
23364642e01fSmrg * Check if the given request can be applied to the given device but don't
23374642e01fSmrg * actually do anything..
23384642e01fSmrg */
23394642e01fSmrgstatic int
23404642e01fSmrg_XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq *req, char* values)
234105b261ecSmrg{
23424642e01fSmrg    XkbSrvInfoPtr       xkbi;
23434642e01fSmrg    XkbDescPtr          xkb;
23444642e01fSmrg    int                 error;
23454642e01fSmrg    int                 nTypes = 0, nActions;
23464642e01fSmrg    CARD8               mapWidths[XkbMaxLegalKeyCode + 1];
23474642e01fSmrg    CARD16              symsPerKey[XkbMaxLegalKeyCode + 1];
234805b261ecSmrg
234905b261ecSmrg    xkbi= dev->key->xkbInfo;
235005b261ecSmrg    xkb = xkbi->desc;
235105b261ecSmrg
23524642e01fSmrg    if ((xkb->min_key_code != req->minKeyCode)||
23534642e01fSmrg        (xkb->max_key_code != req->maxKeyCode)) {
235405b261ecSmrg	if (client->vMajor!=1) { /* pre 1.0 versions of Xlib have a bug */
23554642e01fSmrg	    req->minKeyCode= xkb->min_key_code;
23564642e01fSmrg	    req->maxKeyCode= xkb->max_key_code;
235705b261ecSmrg	}
235805b261ecSmrg	else {
23594642e01fSmrg	    if (!XkbIsLegalKeycode(req->minKeyCode)) {
23604642e01fSmrg		client->errorValue = _XkbErrCode3(2, req->minKeyCode, req->maxKeyCode);
236105b261ecSmrg		return BadValue;
236205b261ecSmrg	    }
23634642e01fSmrg	    if (req->minKeyCode > req->maxKeyCode) {
23644642e01fSmrg		client->errorValue = _XkbErrCode3(3, req->minKeyCode, req->maxKeyCode);
236505b261ecSmrg		return BadMatch;
236605b261ecSmrg	    }
236705b261ecSmrg	}
236805b261ecSmrg    }
236905b261ecSmrg
23704642e01fSmrg    if ((req->present & XkbKeyTypesMask) &&
23714642e01fSmrg	(!CheckKeyTypes(client,xkb,req,(xkbKeyTypeWireDesc **)&values,
237205b261ecSmrg						&nTypes,mapWidths))) {
237305b261ecSmrg	client->errorValue = nTypes;
237405b261ecSmrg	return BadValue;
237505b261ecSmrg    }
23764642e01fSmrg    if ((req->present & XkbKeySymsMask) &&
23774642e01fSmrg	(!CheckKeySyms(client,xkb,req,nTypes,mapWidths,symsPerKey,
23784642e01fSmrg					(xkbSymMapWireDesc **)&values,&error))) {
237905b261ecSmrg	client->errorValue = error;
238005b261ecSmrg	return BadValue;
238105b261ecSmrg    }
238205b261ecSmrg
23834642e01fSmrg    if ((req->present & XkbKeyActionsMask) &&
23844642e01fSmrg	(!CheckKeyActions(xkb,req,nTypes,mapWidths,symsPerKey,
23854642e01fSmrg						(CARD8 **)&values,&nActions))) {
238605b261ecSmrg	client->errorValue = nActions;
238705b261ecSmrg	return BadValue;
238805b261ecSmrg    }
238905b261ecSmrg
23904642e01fSmrg    if ((req->present & XkbKeyBehaviorsMask) &&
23914642e01fSmrg	(!CheckKeyBehaviors(xkb,req,(xkbBehaviorWireDesc**)&values,&error))) {
239205b261ecSmrg	client->errorValue = error;
239305b261ecSmrg	return BadValue;
239405b261ecSmrg    }
239505b261ecSmrg
23964642e01fSmrg    if ((req->present & XkbVirtualModsMask) &&
23974642e01fSmrg	(!CheckVirtualMods(xkb,req,(CARD8 **)&values,&error))) {
239805b261ecSmrg	client->errorValue= error;
239905b261ecSmrg	return BadValue;
240005b261ecSmrg    }
24014642e01fSmrg    if ((req->present&XkbExplicitComponentsMask) &&
24024642e01fSmrg	(!CheckKeyExplicit(xkb,req,(CARD8 **)&values,&error))) {
240305b261ecSmrg	client->errorValue= error;
240405b261ecSmrg	return BadValue;
240505b261ecSmrg    }
24064642e01fSmrg    if ((req->present&XkbModifierMapMask) &&
24074642e01fSmrg	(!CheckModifierMap(xkb,req,(CARD8 **)&values,&error))) {
240805b261ecSmrg	client->errorValue= error;
240905b261ecSmrg	return BadValue;
241005b261ecSmrg    }
24114642e01fSmrg    if ((req->present&XkbVirtualModMapMask) &&
24124642e01fSmrg	(!CheckVirtualModMap(xkb,req,(xkbVModMapWireDesc **)&values,&error))) {
241305b261ecSmrg	client->errorValue= error;
241405b261ecSmrg	return BadValue;
241505b261ecSmrg    }
24164642e01fSmrg
24174642e01fSmrg    if (((values-((char *)req))/4)!= req->length) {
24184642e01fSmrg	ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after check)\n");
24194642e01fSmrg	client->errorValue = values-((char *)&req[1]);
242005b261ecSmrg	return BadLength;
242105b261ecSmrg    }
24224642e01fSmrg
24234642e01fSmrg    return Success;
24244642e01fSmrg}
24254642e01fSmrg
24264642e01fSmrg/**
24274642e01fSmrg * Apply the given request on the given device.
24284642e01fSmrg */
24294642e01fSmrgstatic int
24304642e01fSmrg_XkbSetMap(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq *req, char *values)
24314642e01fSmrg{
24324642e01fSmrg    XkbEventCauseRec	cause;
24334642e01fSmrg    XkbChangesRec	change;
24344642e01fSmrg    Bool		sentNKN;
24354642e01fSmrg    XkbSrvInfoPtr       xkbi;
24364642e01fSmrg    XkbDescPtr          xkb;
24374642e01fSmrg
24384642e01fSmrg    xkbi= dev->key->xkbInfo;
24394642e01fSmrg    xkb = xkbi->desc;
24404642e01fSmrg
24414642e01fSmrg    XkbSetCauseXkbReq(&cause,X_kbSetMap,client);
24424642e01fSmrg    bzero(&change, sizeof(change));
24434642e01fSmrg    sentNKN = False;
24444642e01fSmrg    if ((xkb->min_key_code!=req->minKeyCode)||
24454642e01fSmrg        (xkb->max_key_code!=req->maxKeyCode)) {
244605b261ecSmrg	Status			status;
244705b261ecSmrg	xkbNewKeyboardNotify	nkn;
24484642e01fSmrg	nkn.deviceID = nkn.oldDeviceID = dev->id;
24494642e01fSmrg	nkn.oldMinKeyCode = xkb->min_key_code;
24504642e01fSmrg	nkn.oldMaxKeyCode = xkb->max_key_code;
24514642e01fSmrg	status= XkbChangeKeycodeRange(xkb, req->minKeyCode,
24524642e01fSmrg                                      req->maxKeyCode, &change);
24534642e01fSmrg	if (status != Success)
24544642e01fSmrg	    return status; /* oh-oh. what about the other keyboards? */
24554642e01fSmrg	nkn.minKeyCode = xkb->min_key_code;
24564642e01fSmrg	nkn.maxKeyCode = xkb->max_key_code;
24574642e01fSmrg	nkn.requestMajor = XkbReqCode;
24584642e01fSmrg	nkn.requestMinor = X_kbSetMap;
24594642e01fSmrg	nkn.changed = XkbNKN_KeycodesMask;
246005b261ecSmrg	XkbSendNewKeyboardNotify(dev,&nkn);
24614642e01fSmrg	sentNKN = True;
24624642e01fSmrg    }
24634642e01fSmrg
24644642e01fSmrg    if (req->present&XkbKeyTypesMask) {
24654642e01fSmrg	values = SetKeyTypes(xkb,req,(xkbKeyTypeWireDesc *)values,&change);
24664642e01fSmrg	if (!values)	goto allocFailure;
24674642e01fSmrg    }
24684642e01fSmrg    if (req->present&XkbKeySymsMask) {
24694642e01fSmrg	values = SetKeySyms(client,xkb,req,(xkbSymMapWireDesc *)values,&change,dev);
24704642e01fSmrg	if (!values)	goto allocFailure;
24714642e01fSmrg    }
24724642e01fSmrg    if (req->present&XkbKeyActionsMask) {
24734642e01fSmrg	values = SetKeyActions(xkb,req,(CARD8 *)values,&change);
24744642e01fSmrg	if (!values)	goto allocFailure;
24754642e01fSmrg    }
24764642e01fSmrg    if (req->present&XkbKeyBehaviorsMask) {
24774642e01fSmrg	values= SetKeyBehaviors(xkbi,req,(xkbBehaviorWireDesc *)values,&change);
24784642e01fSmrg	if (!values)	goto allocFailure;
24794642e01fSmrg    }
24804642e01fSmrg    if (req->present&XkbVirtualModsMask)
24814642e01fSmrg	values= SetVirtualMods(xkbi,req,(CARD8 *)values,&change);
24824642e01fSmrg    if (req->present&XkbExplicitComponentsMask)
24834642e01fSmrg	values= SetKeyExplicit(xkbi,req,(CARD8 *)values,&change);
24844642e01fSmrg    if (req->present&XkbModifierMapMask)
24854642e01fSmrg	values= SetModifierMap(xkbi,req,(CARD8 *)values,&change);
24864642e01fSmrg    if (req->present&XkbVirtualModMapMask)
24874642e01fSmrg	values= SetVirtualModMap(xkbi,req,(xkbVModMapWireDesc *)values,&change);
24884642e01fSmrg    if (((values-((char *)req))/4)!=req->length) {
24894642e01fSmrg	ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after set)\n");
24904642e01fSmrg	client->errorValue = values-((char *)&req[1]);
249105b261ecSmrg	return BadLength;
249205b261ecSmrg    }
24934642e01fSmrg    if (req->flags&XkbSetMapRecomputeActions) {
249405b261ecSmrg	KeyCode		first,last,firstMM,lastMM;
249505b261ecSmrg	if (change.map.num_key_syms>0) {
249605b261ecSmrg	    first= change.map.first_key_sym;
249705b261ecSmrg	    last= first+change.map.num_key_syms-1;
249805b261ecSmrg	}
249905b261ecSmrg	else first= last= 0;
250005b261ecSmrg	if (change.map.num_modmap_keys>0) {
250105b261ecSmrg	    firstMM= change.map.first_modmap_key;
250205b261ecSmrg	    lastMM= first+change.map.num_modmap_keys-1;
250305b261ecSmrg	}
250405b261ecSmrg	else firstMM= lastMM= 0;
250505b261ecSmrg	if ((last>0) && (lastMM>0)) {
250605b261ecSmrg	    if (firstMM<first)
250705b261ecSmrg		first= firstMM;
250805b261ecSmrg	    if (lastMM>last)
250905b261ecSmrg		last= lastMM;
251005b261ecSmrg	}
251105b261ecSmrg	else if (lastMM>0) {
251205b261ecSmrg	    first= firstMM;
251305b261ecSmrg	    last= lastMM;
251405b261ecSmrg	}
251505b261ecSmrg	if (last>0) {
251605b261ecSmrg	    unsigned check= 0;
251705b261ecSmrg	    XkbUpdateActions(dev,first,(last-first+1),&change,&check,&cause);
251805b261ecSmrg	    if (check)
251905b261ecSmrg		XkbCheckSecondaryEffects(xkbi,check,&change,&cause);
252005b261ecSmrg	}
252105b261ecSmrg    }
252205b261ecSmrg    if (!sentNKN)
252305b261ecSmrg	XkbSendNotification(dev,&change,&cause);
252405b261ecSmrg
252505b261ecSmrg    XkbUpdateCoreDescription(dev,False);
25264642e01fSmrg    return Success;
252705b261ecSmrgallocFailure:
252805b261ecSmrg    return BadAlloc;
252905b261ecSmrg}
253005b261ecSmrg
25314642e01fSmrg
25324642e01fSmrgint
25334642e01fSmrgProcXkbSetMap(ClientPtr client)
25344642e01fSmrg{
25354642e01fSmrg    DeviceIntPtr	dev;
25364642e01fSmrg    char *		tmp;
25374642e01fSmrg    int                 rc;
25384642e01fSmrg
25394642e01fSmrg    REQUEST(xkbSetMapReq);
25404642e01fSmrg    REQUEST_AT_LEAST_SIZE(xkbSetMapReq);
25414642e01fSmrg
25424642e01fSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
25434642e01fSmrg	return BadAccess;
25444642e01fSmrg
25454642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
25464642e01fSmrg    CHK_MASK_LEGAL(0x01,stuff->present,XkbAllMapComponentsMask);
25474642e01fSmrg
25484642e01fSmrg    tmp = (char *)&stuff[1];
25494642e01fSmrg
25504642e01fSmrg    /* Check if we can to the SetMap on the requested device. If this
25514642e01fSmrg       succeeds, do the same thing for all extension devices (if needed).
25524642e01fSmrg       If any of them fails, fail.  */
25534642e01fSmrg    rc = _XkbSetMapChecks(client, dev, stuff, tmp);
25544642e01fSmrg
25554642e01fSmrg    if (rc != Success)
25564642e01fSmrg        return rc;
25574642e01fSmrg
25584642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd)
25594642e01fSmrg    {
25604642e01fSmrg        DeviceIntPtr other;
25614642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
25624642e01fSmrg        {
25634642e01fSmrg            if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
25644642e01fSmrg            {
25654642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
25664642e01fSmrg                if (rc == Success)
25674642e01fSmrg                {
25684642e01fSmrg                    rc = _XkbSetMapChecks(client, other, stuff, tmp);
25694642e01fSmrg                    if (rc != Success)
25704642e01fSmrg                        return rc;
25714642e01fSmrg                }
25724642e01fSmrg            }
25734642e01fSmrg        }
25744642e01fSmrg    }
25754642e01fSmrg
25764642e01fSmrg    /* We know now that we will succed with the SetMap. In theory anyway. */
25774642e01fSmrg    rc = _XkbSetMap(client, dev, stuff, tmp);
25784642e01fSmrg    if (rc != Success)
25794642e01fSmrg        return rc;
25804642e01fSmrg
25814642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd)
25824642e01fSmrg    {
25834642e01fSmrg        DeviceIntPtr other;
25844642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
25854642e01fSmrg        {
25864642e01fSmrg            if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
25874642e01fSmrg            {
25884642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
25894642e01fSmrg                if (rc == Success)
25904642e01fSmrg                    _XkbSetMap(client, other, stuff, tmp);
25914642e01fSmrg                /* ignore rc. if the SetMap failed although the check above
25924642e01fSmrg                   reported true there isn't much we can do. we still need to
25934642e01fSmrg                   set all other devices, hoping that at least they stay in
25944642e01fSmrg                   sync. */
25954642e01fSmrg            }
25964642e01fSmrg        }
25974642e01fSmrg    }
25984642e01fSmrg
25994642e01fSmrg    return client->noClientException;
26004642e01fSmrg}
26014642e01fSmrg
260205b261ecSmrg/***====================================================================***/
260305b261ecSmrg
260405b261ecSmrgstatic Status
260505b261ecSmrgXkbComputeGetCompatMapReplySize(	XkbCompatMapPtr 	compat,
260605b261ecSmrg					xkbGetCompatMapReply *	rep)
260705b261ecSmrg{
260805b261ecSmrgunsigned	 size,nGroups;
260905b261ecSmrg
261005b261ecSmrg    nGroups= 0;
261105b261ecSmrg    if (rep->groups!=0) {
261205b261ecSmrg	register int i,bit;
261305b261ecSmrg	for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
261405b261ecSmrg	    if (rep->groups&bit)
261505b261ecSmrg		nGroups++;
261605b261ecSmrg	}
261705b261ecSmrg    }
261805b261ecSmrg    size= nGroups*SIZEOF(xkbModsWireDesc);
261905b261ecSmrg    size+= (rep->nSI*SIZEOF(xkbSymInterpretWireDesc));
262005b261ecSmrg    rep->length= size/4;
262105b261ecSmrg    return Success;
262205b261ecSmrg}
262305b261ecSmrg
262405b261ecSmrgstatic int
262505b261ecSmrgXkbSendCompatMap(	ClientPtr 		client,
262605b261ecSmrg			XkbCompatMapPtr 	compat,
262705b261ecSmrg			xkbGetCompatMapReply *	rep)
262805b261ecSmrg{
262905b261ecSmrgchar	*	data;
263005b261ecSmrgint		size;
263105b261ecSmrg
263205b261ecSmrg    size= rep->length*4;
263305b261ecSmrg    if (size>0) {
26344642e01fSmrg	data = (char *)xalloc(size);
263505b261ecSmrg	if (data) {
263605b261ecSmrg	    register unsigned i,bit;
263705b261ecSmrg	    xkbModsWireDesc *	grp;
263805b261ecSmrg	    XkbSymInterpretPtr	sym= &compat->sym_interpret[rep->firstSI];
263905b261ecSmrg	    xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data;
264005b261ecSmrg	    for (i=0;i<rep->nSI;i++,sym++,wire++) {
264105b261ecSmrg		wire->sym= sym->sym;
264205b261ecSmrg		wire->mods= sym->mods;
264305b261ecSmrg		wire->match= sym->match;
264405b261ecSmrg		wire->virtualMod= sym->virtual_mod;
264505b261ecSmrg		wire->flags= sym->flags;
264605b261ecSmrg		memcpy((char*)&wire->act,(char*)&sym->act,sz_xkbActionWireDesc);
264705b261ecSmrg		if (client->swapped) {
264805b261ecSmrg		    register int n;
264905b261ecSmrg		    swapl(&wire->sym,n);
265005b261ecSmrg		}
265105b261ecSmrg	    }
265205b261ecSmrg	    if (rep->groups) {
265305b261ecSmrg		grp = (xkbModsWireDesc *)wire;
265405b261ecSmrg		for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
265505b261ecSmrg		    if (rep->groups&bit) {
265605b261ecSmrg			grp->mask= compat->groups[i].mask;
265705b261ecSmrg			grp->realMods= compat->groups[i].real_mods;
265805b261ecSmrg			grp->virtualMods= compat->groups[i].vmods;
265905b261ecSmrg			if (client->swapped) {
266005b261ecSmrg			    register int n;
266105b261ecSmrg			    swaps(&grp->virtualMods,n);
266205b261ecSmrg			}
266305b261ecSmrg			grp++;
266405b261ecSmrg		    }
266505b261ecSmrg		}
266605b261ecSmrg		wire= (xkbSymInterpretWireDesc*)grp;
266705b261ecSmrg	    }
266805b261ecSmrg	}
266905b261ecSmrg	else return BadAlloc;
267005b261ecSmrg    }
267105b261ecSmrg    else data= NULL;
267205b261ecSmrg
267305b261ecSmrg    if (client->swapped) {
267405b261ecSmrg	register int n;
267505b261ecSmrg	swaps(&rep->sequenceNumber,n);
267605b261ecSmrg	swapl(&rep->length,n);
267705b261ecSmrg	swaps(&rep->firstSI,n);
267805b261ecSmrg	swaps(&rep->nSI,n);
267905b261ecSmrg	swaps(&rep->nTotalSI,n);
268005b261ecSmrg    }
268105b261ecSmrg
268205b261ecSmrg    WriteToClient(client, SIZEOF(xkbGetCompatMapReply), (char *)rep);
268305b261ecSmrg    if (data) {
268405b261ecSmrg	WriteToClient(client, size, data);
26854642e01fSmrg	xfree((char *)data);
268605b261ecSmrg    }
268705b261ecSmrg    return client->noClientException;
268805b261ecSmrg}
268905b261ecSmrg
269005b261ecSmrgint
269105b261ecSmrgProcXkbGetCompatMap(ClientPtr client)
269205b261ecSmrg{
269305b261ecSmrg    xkbGetCompatMapReply 	rep;
269405b261ecSmrg    DeviceIntPtr 		dev;
269505b261ecSmrg    XkbDescPtr			xkb;
269605b261ecSmrg    XkbCompatMapPtr		compat;
269705b261ecSmrg
269805b261ecSmrg    REQUEST(xkbGetCompatMapReq);
269905b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetCompatMapReq);
270005b261ecSmrg
270105b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
270205b261ecSmrg	return BadAccess;
270305b261ecSmrg
27044642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
270505b261ecSmrg
270605b261ecSmrg    xkb = dev->key->xkbInfo->desc;
270705b261ecSmrg    compat= xkb->compat;
270805b261ecSmrg
270905b261ecSmrg    rep.type = X_Reply;
271005b261ecSmrg    rep.deviceID = dev->id;
271105b261ecSmrg    rep.sequenceNumber = client->sequence;
271205b261ecSmrg    rep.length = 0;
271305b261ecSmrg    rep.firstSI = stuff->firstSI;
271405b261ecSmrg    rep.nSI = stuff->nSI;
271505b261ecSmrg    if (stuff->getAllSI) {
271605b261ecSmrg	rep.firstSI = 0;
271705b261ecSmrg	rep.nSI = compat->num_si;
271805b261ecSmrg    }
271905b261ecSmrg    else if ((((unsigned)stuff->nSI)>0)&&
272005b261ecSmrg		((unsigned)(stuff->firstSI+stuff->nSI-1)>=compat->num_si)) {
272105b261ecSmrg	client->errorValue = _XkbErrCode2(0x05,compat->num_si);
272205b261ecSmrg	return BadValue;
272305b261ecSmrg    }
272405b261ecSmrg    rep.nTotalSI = compat->num_si;
272505b261ecSmrg    rep.groups= stuff->groups;
272605b261ecSmrg    XkbComputeGetCompatMapReplySize(compat,&rep);
272705b261ecSmrg    return XkbSendCompatMap(client,compat,&rep);
272805b261ecSmrg}
272905b261ecSmrg
27304642e01fSmrg/**
27314642e01fSmrg * Apply the given request on the given device.
27324642e01fSmrg * If dryRun is True, then value checks are performed, but the device isn't
27334642e01fSmrg * modified.
27344642e01fSmrg */
27354642e01fSmrgstatic int
27364642e01fSmrg_XkbSetCompatMap(ClientPtr client, DeviceIntPtr dev,
27374642e01fSmrg                 xkbSetCompatMapReq *req, char* data, BOOL dryRun)
273805b261ecSmrg{
27394642e01fSmrg    XkbSrvInfoPtr       xkbi;
27404642e01fSmrg    XkbDescPtr          xkb;
27414642e01fSmrg    XkbCompatMapPtr     compat;
27424642e01fSmrg    int                 nGroups;
27434642e01fSmrg    unsigned            i,bit;
274405b261ecSmrg
274505b261ecSmrg    xkbi = dev->key->xkbInfo;
27464642e01fSmrg    xkb = xkbi->desc;
27474642e01fSmrg    compat = xkb->compat;
27484642e01fSmrg
27494642e01fSmrg    if ((req->nSI>0)||(req->truncateSI)) {
275005b261ecSmrg	xkbSymInterpretWireDesc *wire;
27514642e01fSmrg	if (req->firstSI>compat->num_si) {
275205b261ecSmrg	    client->errorValue = _XkbErrCode2(0x02,compat->num_si);
275305b261ecSmrg	    return BadValue;
275405b261ecSmrg	}
275505b261ecSmrg	wire= (xkbSymInterpretWireDesc *)data;
27564642e01fSmrg	wire+= req->nSI;
275705b261ecSmrg	data = (char *)wire;
275805b261ecSmrg    }
27594642e01fSmrg
276005b261ecSmrg    nGroups= 0;
27614642e01fSmrg    if (req->groups!=0) {
276205b261ecSmrg	for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
27634642e01fSmrg	    if ( req->groups&bit )
276405b261ecSmrg		nGroups++;
276505b261ecSmrg	}
276605b261ecSmrg    }
276705b261ecSmrg    data+= nGroups*SIZEOF(xkbModsWireDesc);
27684642e01fSmrg    if (((data-((char *)req))/4)!=req->length) {
276905b261ecSmrg	return BadLength;
277005b261ecSmrg    }
27714642e01fSmrg
27724642e01fSmrg    /* Done all the checks we can do */
27734642e01fSmrg    if (dryRun)
27744642e01fSmrg        return Success;
27754642e01fSmrg
27764642e01fSmrg    data = (char *)&req[1];
27774642e01fSmrg    if (req->nSI>0) {
277805b261ecSmrg	xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data;
277905b261ecSmrg	XkbSymInterpretPtr	sym;
27804642e01fSmrg	if ((unsigned)(req->firstSI+req->nSI)>compat->num_si) {
27814642e01fSmrg	    compat->num_si= req->firstSI+req->nSI;
278205b261ecSmrg	    compat->sym_interpret= _XkbTypedRealloc(compat->sym_interpret,
278305b261ecSmrg						   compat->num_si,
278405b261ecSmrg						   XkbSymInterpretRec);
278505b261ecSmrg	    if (!compat->sym_interpret) {
278605b261ecSmrg		compat->num_si= 0;
278705b261ecSmrg		return BadAlloc;
278805b261ecSmrg	    }
278905b261ecSmrg	}
27904642e01fSmrg	else if (req->truncateSI) {
27914642e01fSmrg	    compat->num_si = req->firstSI+req->nSI;
279205b261ecSmrg	}
27934642e01fSmrg	sym = &compat->sym_interpret[req->firstSI];
27944642e01fSmrg	for (i=0;i<req->nSI;i++,wire++,sym++) {
279505b261ecSmrg	    if (client->swapped) {
27964642e01fSmrg		int n;
279705b261ecSmrg		swapl(&wire->sym,n);
279805b261ecSmrg	    }
279905b261ecSmrg	    sym->sym= wire->sym;
280005b261ecSmrg	    sym->mods= wire->mods;
280105b261ecSmrg	    sym->match= wire->match;
280205b261ecSmrg	    sym->flags= wire->flags;
280305b261ecSmrg	    sym->virtual_mod= wire->virtualMod;
280405b261ecSmrg	    memcpy((char *)&sym->act,(char *)&wire->act,
28054642e01fSmrg                   SIZEOF(xkbActionWireDesc));
280605b261ecSmrg	}
280705b261ecSmrg	data = (char *)wire;
280805b261ecSmrg    }
28094642e01fSmrg    else if (req->truncateSI) {
28104642e01fSmrg	compat->num_si = req->firstSI;
281105b261ecSmrg    }
281205b261ecSmrg
28134642e01fSmrg    if (req->groups!=0) {
28144642e01fSmrg	unsigned i, bit;
281505b261ecSmrg	xkbModsWireDesc *wire = (xkbModsWireDesc *)data;
28164642e01fSmrg	for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
28174642e01fSmrg	    if (req->groups & bit) {
281805b261ecSmrg		if (client->swapped) {
28194642e01fSmrg		    int n;
282005b261ecSmrg		    swaps(&wire->virtualMods,n);
282105b261ecSmrg		}
282205b261ecSmrg		compat->groups[i].mask= wire->realMods;
282305b261ecSmrg		compat->groups[i].real_mods= wire->realMods;
282405b261ecSmrg		compat->groups[i].vmods= wire->virtualMods;
282505b261ecSmrg		if (wire->virtualMods!=0) {
282605b261ecSmrg		    unsigned tmp;
282705b261ecSmrg		    tmp= XkbMaskForVMask(xkb,wire->virtualMods);
282805b261ecSmrg		    compat->groups[i].mask|= tmp;
282905b261ecSmrg		}
283005b261ecSmrg		data+= SIZEOF(xkbModsWireDesc);
283105b261ecSmrg		wire= (xkbModsWireDesc *)data;
283205b261ecSmrg	    }
283305b261ecSmrg	}
283405b261ecSmrg    }
28354642e01fSmrg    i= XkbPaddedSize((data-((char *)req)));
28364642e01fSmrg    if ((i/4)!=req->length) {
28374642e01fSmrg	ErrorF("[xkb] Internal length error on read in _XkbSetCompatMap\n");
283805b261ecSmrg	return BadLength;
283905b261ecSmrg    }
28404642e01fSmrg
284105b261ecSmrg    if (dev->xkb_interest) {
284205b261ecSmrg	xkbCompatMapNotify ev;
284305b261ecSmrg	ev.deviceID = dev->id;
28444642e01fSmrg	ev.changedGroups = req->groups;
28454642e01fSmrg	ev.firstSI = req->firstSI;
28464642e01fSmrg	ev.nSI = req->nSI;
284705b261ecSmrg	ev.nTotalSI = compat->num_si;
284805b261ecSmrg	XkbSendCompatMapNotify(dev,&ev);
284905b261ecSmrg    }
285005b261ecSmrg
28514642e01fSmrg    if (req->recomputeActions) {
285205b261ecSmrg	XkbChangesRec		change;
285305b261ecSmrg	unsigned		check;
285405b261ecSmrg	XkbEventCauseRec	cause;
285505b261ecSmrg
285605b261ecSmrg	XkbSetCauseXkbReq(&cause,X_kbSetCompatMap,client);
285705b261ecSmrg	bzero(&change,sizeof(XkbChangesRec));
285805b261ecSmrg	XkbUpdateActions(dev,xkb->min_key_code,XkbNumKeys(xkb),&change,&check,
285905b261ecSmrg									&cause);
286005b261ecSmrg	if (check)
286105b261ecSmrg	    XkbCheckSecondaryEffects(xkbi,check,&change,&cause);
286205b261ecSmrg	XkbUpdateCoreDescription(dev,False);
286305b261ecSmrg	XkbSendNotification(dev,&change,&cause);
286405b261ecSmrg    }
28654642e01fSmrg    return Success;
28664642e01fSmrg}
28674642e01fSmrg
28684642e01fSmrgint
28694642e01fSmrgProcXkbSetCompatMap(ClientPtr client)
28704642e01fSmrg{
28714642e01fSmrg    DeviceIntPtr        dev;
28724642e01fSmrg    char                *data;
28734642e01fSmrg    int                 rc;
28744642e01fSmrg
28754642e01fSmrg    REQUEST(xkbSetCompatMapReq);
28764642e01fSmrg    REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq);
28774642e01fSmrg
28784642e01fSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
28794642e01fSmrg	return BadAccess;
28804642e01fSmrg
28814642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
28824642e01fSmrg
28834642e01fSmrg    data = (char *)&stuff[1];
28844642e01fSmrg
28854642e01fSmrg    /* check first using a dry-run */
28864642e01fSmrg    rc = _XkbSetCompatMap(client, dev, stuff, data, TRUE);
28874642e01fSmrg    if (rc != Success)
28884642e01fSmrg        return rc;
28894642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd)
28904642e01fSmrg    {
28914642e01fSmrg        DeviceIntPtr other;
28924642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
28934642e01fSmrg        {
28944642e01fSmrg            if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
28954642e01fSmrg            {
28964642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
28974642e01fSmrg                if (rc == Success)
28984642e01fSmrg                {
28994642e01fSmrg                    /* dry-run */
29004642e01fSmrg                    rc = _XkbSetCompatMap(client, other, stuff, data, TRUE);
29014642e01fSmrg                    if (rc != Success)
29024642e01fSmrg                        return rc;
29034642e01fSmrg                }
29044642e01fSmrg            }
29054642e01fSmrg        }
29064642e01fSmrg    }
29074642e01fSmrg
29084642e01fSmrg    /* Yay, the dry-runs succeed. Let's apply */
29094642e01fSmrg    rc = _XkbSetCompatMap(client, dev, stuff, data, FALSE);
29104642e01fSmrg    if (rc != Success)
29114642e01fSmrg        return rc;
29124642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd)
29134642e01fSmrg    {
29144642e01fSmrg        DeviceIntPtr other;
29154642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
29164642e01fSmrg        {
29174642e01fSmrg            if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
29184642e01fSmrg            {
29194642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
29204642e01fSmrg                if (rc == Success)
29214642e01fSmrg                {
29224642e01fSmrg                    rc = _XkbSetCompatMap(client, other, stuff, data, FALSE);
29234642e01fSmrg                    if (rc != Success)
29244642e01fSmrg                        return rc;
29254642e01fSmrg                }
29264642e01fSmrg            }
29274642e01fSmrg        }
29284642e01fSmrg    }
29294642e01fSmrg
293005b261ecSmrg    return client->noClientException;
293105b261ecSmrg}
293205b261ecSmrg
293305b261ecSmrg/***====================================================================***/
293405b261ecSmrg
293505b261ecSmrgint
293605b261ecSmrgProcXkbGetIndicatorState(ClientPtr client)
293705b261ecSmrg{
293805b261ecSmrg    xkbGetIndicatorStateReply 	rep;
293905b261ecSmrg    XkbSrvLedInfoPtr		sli;
294005b261ecSmrg    DeviceIntPtr 		dev;
294105b261ecSmrg    register int 		i;
294205b261ecSmrg
294305b261ecSmrg    REQUEST(xkbGetIndicatorStateReq);
294405b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq);
294505b261ecSmrg
294605b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
294705b261ecSmrg	return BadAccess;
294805b261ecSmrg
29494642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
295005b261ecSmrg
295105b261ecSmrg    sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,
295205b261ecSmrg						XkbXI_IndicatorStateMask);
295305b261ecSmrg    if (!sli)
295405b261ecSmrg	return BadAlloc;
295505b261ecSmrg
295605b261ecSmrg    rep.type = X_Reply;
295705b261ecSmrg    rep.sequenceNumber = client->sequence;
295805b261ecSmrg    rep.length = 0;
295905b261ecSmrg    rep.deviceID = dev->id;
296005b261ecSmrg    rep.state = sli->effectiveState;
296105b261ecSmrg
296205b261ecSmrg    if (client->swapped) {
296305b261ecSmrg	swaps(&rep.sequenceNumber,i);
296405b261ecSmrg	swapl(&rep.state,i);
296505b261ecSmrg    }
296605b261ecSmrg    WriteToClient(client, SIZEOF(xkbGetIndicatorStateReply), (char *)&rep);
296705b261ecSmrg    return client->noClientException;
296805b261ecSmrg}
296905b261ecSmrg
297005b261ecSmrg/***====================================================================***/
297105b261ecSmrg
297205b261ecSmrgstatic Status
297305b261ecSmrgXkbComputeGetIndicatorMapReplySize(
297405b261ecSmrg    XkbIndicatorPtr		indicators,
297505b261ecSmrg    xkbGetIndicatorMapReply	*rep)
297605b261ecSmrg{
297705b261ecSmrgregister int 	i,bit;
297805b261ecSmrgint		nIndicators;
297905b261ecSmrg
298005b261ecSmrg    rep->realIndicators = indicators->phys_indicators;
298105b261ecSmrg    for (i=nIndicators=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
298205b261ecSmrg	if (rep->which&bit)
298305b261ecSmrg	    nIndicators++;
298405b261ecSmrg    }
298505b261ecSmrg    rep->length = (nIndicators*SIZEOF(xkbIndicatorMapWireDesc))/4;
298605b261ecSmrg    return Success;
298705b261ecSmrg}
298805b261ecSmrg
298905b261ecSmrgstatic int
299005b261ecSmrgXkbSendIndicatorMap(	ClientPtr			client,
299105b261ecSmrg			XkbIndicatorPtr			indicators,
299205b261ecSmrg			xkbGetIndicatorMapReply *	rep)
299305b261ecSmrg{
299405b261ecSmrgint 			length;
299505b261ecSmrgCARD8 *			map;
299605b261ecSmrgregister int		i;
299705b261ecSmrgregister unsigned	bit;
299805b261ecSmrg
299905b261ecSmrg    length = rep->length*4;
300005b261ecSmrg    if (length>0) {
300105b261ecSmrg	CARD8 *to;
30024642e01fSmrg	to= map= (CARD8 *)xalloc(length);
300305b261ecSmrg	if (map) {
300405b261ecSmrg	    xkbIndicatorMapWireDesc  *wire = (xkbIndicatorMapWireDesc *)to;
300505b261ecSmrg	    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
300605b261ecSmrg		if (rep->which&bit) {
300705b261ecSmrg		    wire->flags= indicators->maps[i].flags;
300805b261ecSmrg		    wire->whichGroups= indicators->maps[i].which_groups;
300905b261ecSmrg		    wire->groups= indicators->maps[i].groups;
301005b261ecSmrg		    wire->whichMods= indicators->maps[i].which_mods;
301105b261ecSmrg		    wire->mods= indicators->maps[i].mods.mask;
301205b261ecSmrg		    wire->realMods= indicators->maps[i].mods.real_mods;
301305b261ecSmrg		    wire->virtualMods= indicators->maps[i].mods.vmods;
301405b261ecSmrg		    wire->ctrls= indicators->maps[i].ctrls;
301505b261ecSmrg		    if (client->swapped) {
301605b261ecSmrg			register int n;
301705b261ecSmrg			swaps(&wire->virtualMods,n);
301805b261ecSmrg			swapl(&wire->ctrls,n);
301905b261ecSmrg		    }
302005b261ecSmrg		    wire++;
302105b261ecSmrg		}
302205b261ecSmrg	    }
302305b261ecSmrg	    to = (CARD8 *)wire;
302405b261ecSmrg	    if ((to-map)!=length) {
302505b261ecSmrg		client->errorValue = _XkbErrCode2(0xff,length);
302605b261ecSmrg		return BadLength;
302705b261ecSmrg	    }
302805b261ecSmrg	}
302905b261ecSmrg	else return BadAlloc;
303005b261ecSmrg    }
303105b261ecSmrg    else map = NULL;
303205b261ecSmrg    if (client->swapped) {
303305b261ecSmrg	swaps(&rep->sequenceNumber,i);
303405b261ecSmrg	swapl(&rep->length,i);
303505b261ecSmrg	swapl(&rep->which,i);
303605b261ecSmrg	swapl(&rep->realIndicators,i);
303705b261ecSmrg    }
303805b261ecSmrg    WriteToClient(client, SIZEOF(xkbGetIndicatorMapReply), (char *)rep);
303905b261ecSmrg    if (map) {
304005b261ecSmrg	WriteToClient(client, length, (char *)map);
30414642e01fSmrg	xfree((char *)map);
304205b261ecSmrg    }
304305b261ecSmrg    return client->noClientException;
304405b261ecSmrg}
304505b261ecSmrg
304605b261ecSmrgint
304705b261ecSmrgProcXkbGetIndicatorMap(ClientPtr client)
304805b261ecSmrg{
304905b261ecSmrgxkbGetIndicatorMapReply rep;
305005b261ecSmrgDeviceIntPtr		dev;
305105b261ecSmrgXkbDescPtr		xkb;
305205b261ecSmrgXkbIndicatorPtr		leds;
305305b261ecSmrg
305405b261ecSmrg    REQUEST(xkbGetIndicatorMapReq);
305505b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq);
305605b261ecSmrg
305705b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
305805b261ecSmrg	return BadAccess;
305905b261ecSmrg
30604642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
306105b261ecSmrg
306205b261ecSmrg    xkb= dev->key->xkbInfo->desc;
306305b261ecSmrg    leds= xkb->indicators;
306405b261ecSmrg
306505b261ecSmrg    rep.type = X_Reply;
306605b261ecSmrg    rep.sequenceNumber = client->sequence;
306705b261ecSmrg    rep.length = 0;
306805b261ecSmrg    rep.deviceID = dev->id;
306905b261ecSmrg    rep.which = stuff->which;
307005b261ecSmrg    XkbComputeGetIndicatorMapReplySize(leds,&rep);
307105b261ecSmrg    return XkbSendIndicatorMap(client,leds,&rep);
307205b261ecSmrg}
307305b261ecSmrg
30744642e01fSmrg/**
30754642e01fSmrg * Apply the given map to the given device. Which specifies which components
30764642e01fSmrg * to apply.
30774642e01fSmrg */
30784642e01fSmrgstatic int
30794642e01fSmrg_XkbSetIndicatorMap(ClientPtr client, DeviceIntPtr dev,
30804642e01fSmrg                    int which, xkbIndicatorMapWireDesc *desc)
30814642e01fSmrg{
30824642e01fSmrg    XkbSrvInfoPtr       xkbi;
30834642e01fSmrg    XkbSrvLedInfoPtr    sli;
30844642e01fSmrg    XkbEventCauseRec    cause;
30854642e01fSmrg    int                 i, bit;
30864642e01fSmrg
30874642e01fSmrg    xkbi = dev->key->xkbInfo;
30884642e01fSmrg
30894642e01fSmrg    sli= XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
30904642e01fSmrg						XkbXI_IndicatorMapsMask);
30914642e01fSmrg    if (!sli)
30924642e01fSmrg	return BadAlloc;
30934642e01fSmrg
30944642e01fSmrg    for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
30954642e01fSmrg	if (which & bit) {
30964642e01fSmrg	    sli->maps[i].flags = desc->flags;
30974642e01fSmrg	    sli->maps[i].which_groups = desc->whichGroups;
30984642e01fSmrg	    sli->maps[i].groups = desc->groups;
30994642e01fSmrg	    sli->maps[i].which_mods = desc->whichMods;
31004642e01fSmrg	    sli->maps[i].mods.mask = desc->mods;
31014642e01fSmrg	    sli->maps[i].mods.real_mods = desc->mods;
31024642e01fSmrg	    sli->maps[i].mods.vmods= desc->virtualMods;
31034642e01fSmrg	    sli->maps[i].ctrls = desc->ctrls;
31044642e01fSmrg	    if (desc->virtualMods!=0) {
31054642e01fSmrg		unsigned tmp;
31064642e01fSmrg		tmp= XkbMaskForVMask(xkbi->desc,desc->virtualMods);
31074642e01fSmrg		sli->maps[i].mods.mask= desc->mods|tmp;
31084642e01fSmrg	    }
31094642e01fSmrg	    desc++;
31104642e01fSmrg	}
31114642e01fSmrg    }
31124642e01fSmrg
31134642e01fSmrg    XkbSetCauseXkbReq(&cause,X_kbSetIndicatorMap,client);
31144642e01fSmrg    XkbApplyLedMapChanges(dev,sli,which,NULL,NULL,&cause);
31154642e01fSmrg
31164642e01fSmrg    return Success;
31174642e01fSmrg}
31184642e01fSmrg
311905b261ecSmrgint
312005b261ecSmrgProcXkbSetIndicatorMap(ClientPtr client)
312105b261ecSmrg{
31224642e01fSmrg    int                 i, bit;
31234642e01fSmrg    int                 nIndicators;
31244642e01fSmrg    DeviceIntPtr        dev;
31254642e01fSmrg    xkbIndicatorMapWireDesc     *from;
31264642e01fSmrg    int                 rc;
312705b261ecSmrg
312805b261ecSmrg    REQUEST(xkbSetIndicatorMapReq);
312905b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq);
313005b261ecSmrg
313105b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
313205b261ecSmrg	return BadAccess;
313305b261ecSmrg
31344642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
313505b261ecSmrg
313605b261ecSmrg    if (stuff->which==0)
313705b261ecSmrg	return client->noClientException;
313805b261ecSmrg
313905b261ecSmrg    for (nIndicators=i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
314005b261ecSmrg	if (stuff->which&bit)
314105b261ecSmrg	    nIndicators++;
314205b261ecSmrg    }
314305b261ecSmrg    if (stuff->length!=((SIZEOF(xkbSetIndicatorMapReq)+
314405b261ecSmrg			(nIndicators*SIZEOF(xkbIndicatorMapWireDesc)))/4)) {
314505b261ecSmrg	return BadLength;
314605b261ecSmrg    }
314705b261ecSmrg
314805b261ecSmrg    from = (xkbIndicatorMapWireDesc *)&stuff[1];
314905b261ecSmrg    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
315005b261ecSmrg	if (stuff->which&bit) {
315105b261ecSmrg	    if (client->swapped) {
31524642e01fSmrg		int n;
315305b261ecSmrg		swaps(&from->virtualMods,n);
315405b261ecSmrg		swapl(&from->ctrls,n);
315505b261ecSmrg	    }
315605b261ecSmrg	    CHK_MASK_LEGAL(i,from->whichGroups,XkbIM_UseAnyGroup);
315705b261ecSmrg	    CHK_MASK_LEGAL(i,from->whichMods,XkbIM_UseAnyMods);
315805b261ecSmrg	    from++;
315905b261ecSmrg	}
316005b261ecSmrg    }
316105b261ecSmrg
316205b261ecSmrg    from = (xkbIndicatorMapWireDesc *)&stuff[1];
31634642e01fSmrg    rc = _XkbSetIndicatorMap(client, dev, stuff->which, from);
31644642e01fSmrg    if (rc != Success)
31654642e01fSmrg        return rc;
31664642e01fSmrg
31674642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd)
31684642e01fSmrg    {
31694642e01fSmrg        DeviceIntPtr other;
31704642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
31714642e01fSmrg        {
31724642e01fSmrg            if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
31734642e01fSmrg            {
31744642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess);
31754642e01fSmrg                if (rc == Success)
31764642e01fSmrg                    _XkbSetIndicatorMap(client, other, stuff->which, from);
31774642e01fSmrg            }
31784642e01fSmrg        }
317905b261ecSmrg    }
318005b261ecSmrg
31814642e01fSmrg    return Success;
318205b261ecSmrg}
318305b261ecSmrg
318405b261ecSmrg/***====================================================================***/
318505b261ecSmrg
318605b261ecSmrgint
318705b261ecSmrgProcXkbGetNamedIndicator(ClientPtr client)
318805b261ecSmrg{
318905b261ecSmrg    DeviceIntPtr 		dev;
319005b261ecSmrg    xkbGetNamedIndicatorReply 	rep;
319105b261ecSmrg    register int		i = 0;
319205b261ecSmrg    XkbSrvLedInfoPtr		sli;
319305b261ecSmrg    XkbIndicatorMapPtr		map = NULL;
319405b261ecSmrg
319505b261ecSmrg    REQUEST(xkbGetNamedIndicatorReq);
319605b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq);
319705b261ecSmrg
319805b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
319905b261ecSmrg	return BadAccess;
320005b261ecSmrg
32014642e01fSmrg    CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
320205b261ecSmrg    CHK_ATOM_ONLY(stuff->indicator);
320305b261ecSmrg
320405b261ecSmrg    sli= XkbFindSrvLedInfo(dev,stuff->ledClass,stuff->ledID,0);
320505b261ecSmrg    if (!sli)
320605b261ecSmrg	return BadAlloc;
320705b261ecSmrg
320805b261ecSmrg    i= 0;
320905b261ecSmrg    map= NULL;
321005b261ecSmrg    if ((sli->names)&&(sli->maps)) {
321105b261ecSmrg        for (i=0;i<XkbNumIndicators;i++) {
321205b261ecSmrg            if (stuff->indicator==sli->names[i]) {
321305b261ecSmrg                map= &sli->maps[i];
321405b261ecSmrg                break;
321505b261ecSmrg            }
321605b261ecSmrg        }
321705b261ecSmrg    }
321805b261ecSmrg
321905b261ecSmrg    rep.type= X_Reply;
322005b261ecSmrg    rep.length = 0;
322105b261ecSmrg    rep.sequenceNumber = client->sequence;
322205b261ecSmrg    rep.deviceID = dev->id;
322305b261ecSmrg    rep.indicator= stuff->indicator;
322405b261ecSmrg    if (map!=NULL) {
322505b261ecSmrg	rep.found= 		True;
322605b261ecSmrg	rep.on=			((sli->effectiveState&(1<<i))!=0);
322705b261ecSmrg	rep.realIndicator=	((sli->physIndicators&(1<<i))!=0);
322805b261ecSmrg	rep.ndx= 		i;
322905b261ecSmrg	rep.flags= 		map->flags;
323005b261ecSmrg	rep.whichGroups= 	map->which_groups;
323105b261ecSmrg	rep.groups= 		map->groups;
323205b261ecSmrg	rep.whichMods= 		map->which_mods;
323305b261ecSmrg	rep.mods= 		map->mods.mask;
323405b261ecSmrg	rep.realMods= 		map->mods.real_mods;
323505b261ecSmrg	rep.virtualMods= 	map->mods.vmods;
323605b261ecSmrg	rep.ctrls= 		map->ctrls;
323705b261ecSmrg	rep.supported= 		True;
323805b261ecSmrg    }
323905b261ecSmrg    else  {
324005b261ecSmrg	rep.found= 		False;
324105b261ecSmrg	rep.on= 		False;
324205b261ecSmrg	rep.realIndicator= 	False;
324305b261ecSmrg	rep.ndx= 		XkbNoIndicator;
324405b261ecSmrg	rep.flags= 		0;
324505b261ecSmrg	rep.whichGroups= 	0;
324605b261ecSmrg	rep.groups= 		0;
324705b261ecSmrg	rep.whichMods= 		0;
324805b261ecSmrg	rep.mods=		0;
324905b261ecSmrg	rep.realMods= 		0;
325005b261ecSmrg	rep.virtualMods= 	0;
325105b261ecSmrg	rep.ctrls= 		0;
325205b261ecSmrg	rep.supported= 		True;
325305b261ecSmrg    }
325405b261ecSmrg    if ( client->swapped ) {
325505b261ecSmrg	register int n;
325605b261ecSmrg	swapl(&rep.length,n);
325705b261ecSmrg	swaps(&rep.sequenceNumber,n);
325805b261ecSmrg	swapl(&rep.indicator,n);
325905b261ecSmrg	swaps(&rep.virtualMods,n);
326005b261ecSmrg	swapl(&rep.ctrls,n);
326105b261ecSmrg    }
326205b261ecSmrg
326305b261ecSmrg    WriteToClient(client,SIZEOF(xkbGetNamedIndicatorReply), (char *)&rep);
326405b261ecSmrg    return client->noClientException;
326505b261ecSmrg}
326605b261ecSmrg
326705b261ecSmrg
32684642e01fSmrg/**
32694642e01fSmrg * Find the IM on the device.
32704642e01fSmrg * Returns the map, or NULL if the map doesn't exist.
32714642e01fSmrg * If the return value is NULL, led_return is undefined. Otherwise, led_return
32724642e01fSmrg * is set to the led index of the map.
32734642e01fSmrg */
32744642e01fSmrgstatic XkbIndicatorMapPtr
32754642e01fSmrg_XkbFindNamedIndicatorMap(XkbSrvLedInfoPtr sli, Atom indicator,
32764642e01fSmrg                          int *led_return)
32774642e01fSmrg{
32784642e01fSmrg    XkbIndicatorMapPtr  map;
32794642e01fSmrg    int                 led;
328005b261ecSmrg
32814642e01fSmrg    /* search for the right indicator */
32824642e01fSmrg    map = NULL;
328305b261ecSmrg    if (sli->names && sli->maps) {
32844642e01fSmrg	for (led = 0; (led < XkbNumIndicators) && (map == NULL); led++) {
32854642e01fSmrg	    if (sli->names[led] == indicator) {
328605b261ecSmrg		map= &sli->maps[led];
328705b261ecSmrg		break;
328805b261ecSmrg	    }
328905b261ecSmrg	}
329005b261ecSmrg    }
329105b261ecSmrg
32924642e01fSmrg    *led_return = led;
32934642e01fSmrg    return map;
32944642e01fSmrg}
32954642e01fSmrg
32964642e01fSmrg/**
32974642e01fSmrg * Creates an indicator map on the device. If dryRun is True, it only checks
32984642e01fSmrg * if creation is possible, but doesn't actually create it.
32994642e01fSmrg */
33004642e01fSmrgstatic int
33014642e01fSmrg_XkbCreateIndicatorMap(DeviceIntPtr dev, Atom indicator,
33024642e01fSmrg                       int ledClass, int ledID,
33034642e01fSmrg                       XkbIndicatorMapPtr *map_return, int *led_return,
33044642e01fSmrg                       Bool dryRun)
33054642e01fSmrg{
33064642e01fSmrg    XkbSrvLedInfoPtr    sli;
33074642e01fSmrg    XkbIndicatorMapPtr  map;
33084642e01fSmrg    int                 led;
33094642e01fSmrg
33104642e01fSmrg    sli = XkbFindSrvLedInfo(dev, ledClass, ledID, XkbXI_IndicatorsMask);
33114642e01fSmrg    if (!sli)
33124642e01fSmrg        return BadAlloc;
33134642e01fSmrg
33144642e01fSmrg    map = _XkbFindNamedIndicatorMap(sli, indicator, &led);
33154642e01fSmrg
33164642e01fSmrg    if (!map)
33174642e01fSmrg    {
33184642e01fSmrg        /* find first unused indicator maps and assign the name to it */
33194642e01fSmrg        for (led = 0, map = NULL; (led < XkbNumIndicators) && (map == NULL); led++) {
33204642e01fSmrg            if ((sli->names) && (sli->maps) && (sli->names[led] == None) &&
33214642e01fSmrg                    (!XkbIM_InUse(&sli->maps[led])))
33224642e01fSmrg            {
33234642e01fSmrg                map = &sli->maps[led];
33244642e01fSmrg                if (!dryRun)
33254642e01fSmrg                    sli->names[led] = indicator;
33264642e01fSmrg                break;
33274642e01fSmrg            }
33284642e01fSmrg        }
33294642e01fSmrg    }
33304642e01fSmrg
33314642e01fSmrg    if (!map)
33324642e01fSmrg        return BadAlloc;
33334642e01fSmrg
33344642e01fSmrg    *led_return = led;
33354642e01fSmrg    *map_return = map;
33364642e01fSmrg    return Success;
33374642e01fSmrg}
33384642e01fSmrg
33394642e01fSmrgstatic int
33404642e01fSmrg_XkbSetNamedIndicator(ClientPtr client, DeviceIntPtr dev,
33414642e01fSmrg                      xkbSetNamedIndicatorReq *stuff)
33424642e01fSmrg{
33434642e01fSmrg    unsigned int                extDevReason;
33444642e01fSmrg    unsigned int                statec, namec, mapc;
33454642e01fSmrg    XkbSrvLedInfoPtr            sli;
33464642e01fSmrg    int                         led = 0;
33474642e01fSmrg    XkbIndicatorMapPtr          map;
33484642e01fSmrg    DeviceIntPtr                kbd;
33494642e01fSmrg    XkbEventCauseRec            cause;
33504642e01fSmrg    xkbExtensionDeviceNotify    ed;
33514642e01fSmrg    XkbChangesRec               changes;
33524642e01fSmrg    int                         rc;
33534642e01fSmrg
33544642e01fSmrg    rc = _XkbCreateIndicatorMap(dev, stuff->indicator, stuff->ledClass,
33554642e01fSmrg                                stuff->ledID, &map, &led, FALSE);
33564642e01fSmrg    if (rc != Success || !map) /* oh-oh */
33574642e01fSmrg        return rc;
33584642e01fSmrg
33594642e01fSmrg    sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID,
33604642e01fSmrg                            XkbXI_IndicatorsMask);
33614642e01fSmrg    if (!sli)
33624642e01fSmrg        return BadAlloc;
33634642e01fSmrg
33644642e01fSmrg    namec = mapc = statec = 0;
33654642e01fSmrg    extDevReason = 0;
33664642e01fSmrg
33674642e01fSmrg    namec |= (1<<led);
33684642e01fSmrg    sli->namesPresent |= ((stuff->indicator != None) ? (1 << led) : 0);
33694642e01fSmrg    extDevReason |= XkbXI_IndicatorNamesMask;
33704642e01fSmrg
33714642e01fSmrg    if (stuff->setMap) {
33724642e01fSmrg        map->flags = stuff->flags;
33734642e01fSmrg        map->which_groups = stuff->whichGroups;
33744642e01fSmrg        map->groups = stuff->groups;
33754642e01fSmrg        map->which_mods = stuff->whichMods;
33764642e01fSmrg        map->mods.mask = stuff->realMods;
33774642e01fSmrg        map->mods.real_mods = stuff->realMods;
33784642e01fSmrg        map->mods.vmods= stuff->virtualMods;
33794642e01fSmrg        map->ctrls = stuff->ctrls;
33804642e01fSmrg        mapc|= (1<<led);
33814642e01fSmrg    }
33824642e01fSmrg
33834642e01fSmrg    if ((stuff->setState) && ((map->flags & XkbIM_NoExplicit) == 0))
33844642e01fSmrg    {
33854642e01fSmrg        if (stuff->on)	sli->explicitState |=  (1<<led);
33864642e01fSmrg        else		sli->explicitState &= ~(1<<led);
33874642e01fSmrg        statec |= ((sli->effectiveState ^ sli->explicitState) & (1 << led));
338805b261ecSmrg    }
33894642e01fSmrg
339005b261ecSmrg    bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify));
339105b261ecSmrg    bzero((char *)&changes,sizeof(XkbChangesRec));
339205b261ecSmrg    XkbSetCauseXkbReq(&cause,X_kbSetNamedIndicator,client);
339305b261ecSmrg    if (namec)
33944642e01fSmrg        XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause);
339505b261ecSmrg    if (mapc)
33964642e01fSmrg        XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause);
339705b261ecSmrg    if (statec)
33984642e01fSmrg        XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause);
339905b261ecSmrg
34004642e01fSmrg    kbd = dev;
340105b261ecSmrg    if ((sli->flags&XkbSLI_HasOwnState)==0)
34024642e01fSmrg        kbd = inputInfo.keyboard;
34034642e01fSmrg    XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause);
34044642e01fSmrg
34054642e01fSmrg    return Success;
34064642e01fSmrg}
34074642e01fSmrg
34084642e01fSmrgint
34094642e01fSmrgProcXkbSetNamedIndicator(ClientPtr client)
34104642e01fSmrg{
34114642e01fSmrg    int                         rc;
34124642e01fSmrg    DeviceIntPtr                dev;
34134642e01fSmrg    int                         led = 0;
34144642e01fSmrg    XkbIndicatorMapPtr          map;
34154642e01fSmrg
34164642e01fSmrg    REQUEST(xkbSetNamedIndicatorReq);
34174642e01fSmrg    REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq);
34184642e01fSmrg
34194642e01fSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
34204642e01fSmrg	return BadAccess;
34214642e01fSmrg
34224642e01fSmrg    CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
34234642e01fSmrg    CHK_ATOM_ONLY(stuff->indicator);
34244642e01fSmrg    CHK_MASK_LEGAL(0x10,stuff->whichGroups,XkbIM_UseAnyGroup);
34254642e01fSmrg    CHK_MASK_LEGAL(0x11,stuff->whichMods,XkbIM_UseAnyMods);
34264642e01fSmrg
34274642e01fSmrg    /* Dry-run for checks */
34284642e01fSmrg    rc = _XkbCreateIndicatorMap(dev, stuff->indicator,
34294642e01fSmrg                                stuff->ledClass, stuff->ledID,
34304642e01fSmrg                                &map, &led, TRUE);
34314642e01fSmrg    if (rc != Success || !map) /* couldn't be created or didn't exist */
34324642e01fSmrg        return rc;
34334642e01fSmrg
34344642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd ||
34354642e01fSmrg        stuff->deviceSpec == XkbUseCorePtr)
34364642e01fSmrg    {
34374642e01fSmrg        DeviceIntPtr other;
34384642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
34394642e01fSmrg        {
34404642e01fSmrg            if ((other != dev) && !other->isMaster && (other->u.master == dev) &&
344152397711Smrg                (other->kbdfeed || other->leds) &&
34424642e01fSmrg                (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) == Success))
34434642e01fSmrg            {
34444642e01fSmrg                rc = _XkbCreateIndicatorMap(other, stuff->indicator,
34454642e01fSmrg                                            stuff->ledClass, stuff->ledID,
34464642e01fSmrg                                            &map, &led, TRUE);
34474642e01fSmrg                if (rc != Success || !map)
34484642e01fSmrg                    return rc;
34494642e01fSmrg            }
34504642e01fSmrg        }
34514642e01fSmrg    }
34524642e01fSmrg
34534642e01fSmrg    /* All checks passed, let's do it */
34544642e01fSmrg    rc = _XkbSetNamedIndicator(client, dev, stuff);
34554642e01fSmrg    if (rc != Success)
34564642e01fSmrg        return rc;
34574642e01fSmrg
34584642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd ||
34594642e01fSmrg        stuff->deviceSpec == XkbUseCorePtr)
34604642e01fSmrg    {
34614642e01fSmrg        DeviceIntPtr other;
34624642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
34634642e01fSmrg        {
34644642e01fSmrg            if ((other != dev) && !other->isMaster && (other->u.master == dev) &&
346552397711Smrg                (other->kbdfeed || other->leds) &&
34664642e01fSmrg                (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) == Success))
34674642e01fSmrg            {
34684642e01fSmrg                _XkbSetNamedIndicator(client, other, stuff);
34694642e01fSmrg            }
34704642e01fSmrg        }
34714642e01fSmrg    }
34724642e01fSmrg
347305b261ecSmrg    return client->noClientException;
347405b261ecSmrg}
347505b261ecSmrg
347605b261ecSmrg/***====================================================================***/
347705b261ecSmrg
347805b261ecSmrgstatic CARD32
347905b261ecSmrg_XkbCountAtoms(Atom *atoms,int maxAtoms,int *count)
348005b261ecSmrg{
348105b261ecSmrgregister unsigned int i,bit,nAtoms;
348205b261ecSmrgregister CARD32 atomsPresent;
348305b261ecSmrg
348405b261ecSmrg    for (i=nAtoms=atomsPresent=0,bit=1;i<maxAtoms;i++,bit<<=1) {
348505b261ecSmrg	if (atoms[i]!=None) {
348605b261ecSmrg	    atomsPresent|= bit;
348705b261ecSmrg	    nAtoms++;
348805b261ecSmrg	}
348905b261ecSmrg    }
349005b261ecSmrg    if (count)
349105b261ecSmrg	*count= nAtoms;
349205b261ecSmrg    return atomsPresent;
349305b261ecSmrg}
349405b261ecSmrg
349505b261ecSmrgstatic char *
349605b261ecSmrg_XkbWriteAtoms(char *wire,Atom *atoms,int maxAtoms,int swap)
349705b261ecSmrg{
349805b261ecSmrgregister unsigned int i;
349905b261ecSmrgAtom *atm;
350005b261ecSmrg
350105b261ecSmrg    atm = (Atom *)wire;
350205b261ecSmrg    for (i=0;i<maxAtoms;i++) {
350305b261ecSmrg	if (atoms[i]!=None) {
350405b261ecSmrg	    *atm= atoms[i];
350505b261ecSmrg	    if (swap) {
350605b261ecSmrg		register int n;
350705b261ecSmrg		swapl(atm,n);
350805b261ecSmrg	    }
350905b261ecSmrg	    atm++;
351005b261ecSmrg	}
351105b261ecSmrg    }
351205b261ecSmrg    return (char *)atm;
351305b261ecSmrg}
351405b261ecSmrg
351505b261ecSmrgstatic Status
351605b261ecSmrgXkbComputeGetNamesReplySize(XkbDescPtr xkb,xkbGetNamesReply *rep)
351705b261ecSmrg{
351805b261ecSmrgregister unsigned	which,length;
351905b261ecSmrgregister int		i;
352005b261ecSmrg
352105b261ecSmrg    rep->minKeyCode= xkb->min_key_code;
352205b261ecSmrg    rep->maxKeyCode= xkb->max_key_code;
352305b261ecSmrg    which= rep->which;
352405b261ecSmrg    length= 0;
352505b261ecSmrg    if (xkb->names!=NULL) {
352605b261ecSmrg	 if (which&XkbKeycodesNameMask)		length++;
352705b261ecSmrg	 if (which&XkbGeometryNameMask)		length++;
352805b261ecSmrg	 if (which&XkbSymbolsNameMask)		length++;
352905b261ecSmrg	 if (which&XkbPhysSymbolsNameMask)	length++;
353005b261ecSmrg	 if (which&XkbTypesNameMask)		length++;
353105b261ecSmrg	 if (which&XkbCompatNameMask)		length++;
353205b261ecSmrg    }
353305b261ecSmrg    else which&= ~XkbComponentNamesMask;
353405b261ecSmrg
353505b261ecSmrg    if (xkb->map!=NULL) {
353605b261ecSmrg	if (which&XkbKeyTypeNamesMask)
353705b261ecSmrg	    length+= xkb->map->num_types;
353805b261ecSmrg	rep->nTypes= xkb->map->num_types;
353905b261ecSmrg	if (which&XkbKTLevelNamesMask) {
354005b261ecSmrg	    XkbKeyTypePtr	pType = xkb->map->types;
354105b261ecSmrg	    int			nKTLevels = 0;
354205b261ecSmrg
354305b261ecSmrg	    length+= XkbPaddedSize(xkb->map->num_types)/4;
354405b261ecSmrg	    for (i=0;i<xkb->map->num_types;i++,pType++) {
354505b261ecSmrg		if (pType->level_names!=NULL)
354605b261ecSmrg		    nKTLevels+= pType->num_levels;
354705b261ecSmrg	    }
354805b261ecSmrg	    rep->nKTLevels= nKTLevels;
354905b261ecSmrg	    length+= nKTLevels;
355005b261ecSmrg	}
355105b261ecSmrg    }
355205b261ecSmrg    else {
355305b261ecSmrg	rep->nTypes=    0;
355405b261ecSmrg	rep->nKTLevels= 0;
355505b261ecSmrg	which&= ~(XkbKeyTypeNamesMask|XkbKTLevelNamesMask);
355605b261ecSmrg    }
355705b261ecSmrg
355805b261ecSmrg    rep->minKeyCode= xkb->min_key_code;
355905b261ecSmrg    rep->maxKeyCode= xkb->max_key_code;
356005b261ecSmrg    rep->indicators= 0;
356105b261ecSmrg    rep->virtualMods= 0;
356205b261ecSmrg    rep->groupNames= 0;
356305b261ecSmrg    if (xkb->names!=NULL) {
356405b261ecSmrg	if (which&XkbIndicatorNamesMask) {
356505b261ecSmrg	    int nLeds;
356605b261ecSmrg	    rep->indicators=
356705b261ecSmrg		_XkbCountAtoms(xkb->names->indicators,XkbNumIndicators,&nLeds);
356805b261ecSmrg	    length+= nLeds;
356905b261ecSmrg	    if (nLeds==0)
357005b261ecSmrg		which&= ~XkbIndicatorNamesMask;
357105b261ecSmrg	}
357205b261ecSmrg
357305b261ecSmrg	if (which&XkbVirtualModNamesMask) {
357405b261ecSmrg	    int nVMods;
357505b261ecSmrg	    rep->virtualMods=
357605b261ecSmrg		_XkbCountAtoms(xkb->names->vmods,XkbNumVirtualMods,&nVMods);
357705b261ecSmrg	    length+= nVMods;
357805b261ecSmrg	    if (nVMods==0)
357905b261ecSmrg		which&= ~XkbVirtualModNamesMask;
358005b261ecSmrg	}
358105b261ecSmrg
358205b261ecSmrg	if (which&XkbGroupNamesMask) {
358305b261ecSmrg	    int nGroups;
358405b261ecSmrg	    rep->groupNames=
358505b261ecSmrg		_XkbCountAtoms(xkb->names->groups,XkbNumKbdGroups,&nGroups);
358605b261ecSmrg	    length+= nGroups;
358705b261ecSmrg	    if (nGroups==0)
358805b261ecSmrg		which&= ~XkbGroupNamesMask;
358905b261ecSmrg	}
359005b261ecSmrg
359105b261ecSmrg	if ((which&XkbKeyNamesMask)&&(xkb->names->keys))
359205b261ecSmrg	     length+= rep->nKeys;
359305b261ecSmrg	else which&= ~XkbKeyNamesMask;
359405b261ecSmrg
359505b261ecSmrg	if ((which&XkbKeyAliasesMask)&&
359605b261ecSmrg	    (xkb->names->key_aliases)&&(xkb->names->num_key_aliases>0)) {
359705b261ecSmrg	    rep->nKeyAliases= xkb->names->num_key_aliases;
359805b261ecSmrg	    length+= rep->nKeyAliases*2;
359905b261ecSmrg	}
360005b261ecSmrg	else {
360105b261ecSmrg	    which&= ~XkbKeyAliasesMask;
360205b261ecSmrg	    rep->nKeyAliases= 0;
360305b261ecSmrg	}
360405b261ecSmrg
360505b261ecSmrg	if ((which&XkbRGNamesMask)&&(xkb->names->num_rg>0))
360605b261ecSmrg	     length+= xkb->names->num_rg;
360705b261ecSmrg	else which&= ~XkbRGNamesMask;
360805b261ecSmrg    }
360905b261ecSmrg    else {
361005b261ecSmrg	which&= ~(XkbIndicatorNamesMask|XkbVirtualModNamesMask);
361105b261ecSmrg	which&= ~(XkbGroupNamesMask|XkbKeyNamesMask|XkbKeyAliasesMask);
361205b261ecSmrg	which&= ~XkbRGNamesMask;
361305b261ecSmrg    }
361405b261ecSmrg
361505b261ecSmrg    rep->length= length;
361605b261ecSmrg    rep->which= which;
361705b261ecSmrg    return Success;
361805b261ecSmrg}
361905b261ecSmrg
362005b261ecSmrgstatic int
362105b261ecSmrgXkbSendNames(ClientPtr client,XkbDescPtr xkb,xkbGetNamesReply *rep)
362205b261ecSmrg{
362305b261ecSmrgregister unsigned 	i,length,which;
362405b261ecSmrgchar *			start;
362505b261ecSmrgchar *			desc;
362605b261ecSmrgregister int            n;
362705b261ecSmrg
362805b261ecSmrg    length= rep->length*4;
362905b261ecSmrg    which= rep->which;
363005b261ecSmrg    if (client->swapped) {
363105b261ecSmrg	swaps(&rep->sequenceNumber,n);
363205b261ecSmrg	swapl(&rep->length,n);
363305b261ecSmrg	swapl(&rep->which,n);
363405b261ecSmrg	swaps(&rep->virtualMods,n);
363505b261ecSmrg	swapl(&rep->indicators,n);
363605b261ecSmrg    }
363705b261ecSmrg
36384642e01fSmrg    start = desc = (char *)xalloc(length);
363905b261ecSmrg    if ( !start )
364005b261ecSmrg	return BadAlloc;
364105b261ecSmrg    if (xkb->names) {
364205b261ecSmrg        if (which&XkbKeycodesNameMask) {
364305b261ecSmrg            *((CARD32 *)desc)= xkb->names->keycodes;
364405b261ecSmrg            if (client->swapped) {
364505b261ecSmrg                swapl(desc,n);
364605b261ecSmrg            }
364705b261ecSmrg            desc+= 4;
364805b261ecSmrg        }
364905b261ecSmrg        if (which&XkbGeometryNameMask)  {
365005b261ecSmrg            *((CARD32 *)desc)= xkb->names->geometry;
365105b261ecSmrg            if (client->swapped) {
365205b261ecSmrg                swapl(desc,n);
365305b261ecSmrg            }
365405b261ecSmrg            desc+= 4;
365505b261ecSmrg        }
365605b261ecSmrg        if (which&XkbSymbolsNameMask) {
365705b261ecSmrg            *((CARD32 *)desc)= xkb->names->symbols;
365805b261ecSmrg            if (client->swapped) {
365905b261ecSmrg                swapl(desc,n);
366005b261ecSmrg            }
366105b261ecSmrg            desc+= 4;
366205b261ecSmrg        }
366305b261ecSmrg        if (which&XkbPhysSymbolsNameMask) {
366405b261ecSmrg            register CARD32 *atm= (CARD32 *)desc;
366505b261ecSmrg            atm[0]= (CARD32)xkb->names->phys_symbols;
366605b261ecSmrg            if (client->swapped) {
366705b261ecSmrg                swapl(&atm[0],n);
366805b261ecSmrg            }
366905b261ecSmrg            desc+= 4;
367005b261ecSmrg        }
367105b261ecSmrg        if (which&XkbTypesNameMask) {
367205b261ecSmrg            *((CARD32 *)desc)= (CARD32)xkb->names->types;
367305b261ecSmrg            if (client->swapped) {
367405b261ecSmrg                swapl(desc,n);
367505b261ecSmrg            }
367605b261ecSmrg            desc+= 4;
367705b261ecSmrg        }
367805b261ecSmrg        if (which&XkbCompatNameMask) {
367905b261ecSmrg            *((CARD32 *)desc)= (CARD32)xkb->names->compat;
368005b261ecSmrg            if (client->swapped) {
368105b261ecSmrg                swapl(desc,n);
368205b261ecSmrg            }
368305b261ecSmrg            desc+= 4;
368405b261ecSmrg        }
368505b261ecSmrg        if (which&XkbKeyTypeNamesMask) {
368605b261ecSmrg            register CARD32 *atm= (CARD32 *)desc;
368705b261ecSmrg            register XkbKeyTypePtr type= xkb->map->types;
368805b261ecSmrg
368905b261ecSmrg            for (i=0;i<xkb->map->num_types;i++,atm++,type++) {
369005b261ecSmrg                *atm= (CARD32)type->name;
369105b261ecSmrg                if (client->swapped) {
369205b261ecSmrg                    swapl(atm,n);
369305b261ecSmrg                }
369405b261ecSmrg            }
369505b261ecSmrg            desc= (char *)atm;
369605b261ecSmrg        }
369705b261ecSmrg        if (which&XkbKTLevelNamesMask && xkb->map) {
369805b261ecSmrg            XkbKeyTypePtr type = xkb->map->types;
369905b261ecSmrg            register CARD32 *atm;
370005b261ecSmrg            for (i=0;i<rep->nTypes;i++,type++) {
370105b261ecSmrg                *desc++ = type->num_levels;
370205b261ecSmrg            }
370305b261ecSmrg            desc+= XkbPaddedSize(rep->nTypes)-rep->nTypes;
370405b261ecSmrg
370505b261ecSmrg            atm= (CARD32 *)desc;
370605b261ecSmrg            type = xkb->map->types;
370705b261ecSmrg            for (i=0;i<xkb->map->num_types;i++,type++) {
370805b261ecSmrg                register unsigned l;
370905b261ecSmrg                if (type->level_names) {
371005b261ecSmrg                    for (l=0;l<type->num_levels;l++,atm++) {
371105b261ecSmrg                        *atm= type->level_names[l];
371205b261ecSmrg                        if (client->swapped) {
371305b261ecSmrg                            swapl(atm,n);
371405b261ecSmrg                        }
371505b261ecSmrg                    }
371605b261ecSmrg                    desc+= type->num_levels*4;
371705b261ecSmrg                }
371805b261ecSmrg            }
371905b261ecSmrg        }
372005b261ecSmrg        if (which&XkbIndicatorNamesMask) {
372105b261ecSmrg            desc= _XkbWriteAtoms(desc,xkb->names->indicators,XkbNumIndicators,
372205b261ecSmrg                                 client->swapped);
372305b261ecSmrg        }
372405b261ecSmrg        if (which&XkbVirtualModNamesMask) {
372505b261ecSmrg            desc= _XkbWriteAtoms(desc,xkb->names->vmods,XkbNumVirtualMods,
372605b261ecSmrg                                 client->swapped);
372705b261ecSmrg        }
372805b261ecSmrg        if (which&XkbGroupNamesMask) {
372905b261ecSmrg            desc= _XkbWriteAtoms(desc,xkb->names->groups,XkbNumKbdGroups,
373005b261ecSmrg                                 client->swapped);
373105b261ecSmrg        }
373205b261ecSmrg        if (which&XkbKeyNamesMask) {
373305b261ecSmrg            for (i=0;i<rep->nKeys;i++,desc+= sizeof(XkbKeyNameRec)) {
373405b261ecSmrg                *((XkbKeyNamePtr)desc)= xkb->names->keys[i+rep->firstKey];
373505b261ecSmrg            }
373605b261ecSmrg        }
373705b261ecSmrg        if (which&XkbKeyAliasesMask) {
373805b261ecSmrg            XkbKeyAliasPtr	pAl;
373905b261ecSmrg            pAl= xkb->names->key_aliases;
374005b261ecSmrg            for (i=0;i<rep->nKeyAliases;i++,pAl++,desc+=2*XkbKeyNameLength) {
374105b261ecSmrg                *((XkbKeyAliasPtr)desc)= *pAl;
374205b261ecSmrg            }
374305b261ecSmrg        }
374405b261ecSmrg        if ((which&XkbRGNamesMask)&&(rep->nRadioGroups>0)) {
374505b261ecSmrg            register CARD32	*atm= (CARD32 *)desc;
374605b261ecSmrg            for (i=0;i<rep->nRadioGroups;i++,atm++) {
374705b261ecSmrg                *atm= (CARD32)xkb->names->radio_groups[i];
374805b261ecSmrg                if (client->swapped) {
374905b261ecSmrg                    swapl(atm,n);
375005b261ecSmrg                }
375105b261ecSmrg            }
375205b261ecSmrg            desc+= rep->nRadioGroups*4;
375305b261ecSmrg        }
375405b261ecSmrg    }
375505b261ecSmrg
375605b261ecSmrg    if ((desc-start)!=(length)) {
37574642e01fSmrg	ErrorF("[xkb] BOGUS LENGTH in write names, expected %d, got %ld\n",
375805b261ecSmrg					length, (unsigned long)(desc-start));
375905b261ecSmrg    }
376005b261ecSmrg    WriteToClient(client, SIZEOF(xkbGetNamesReply), (char *)rep);
376105b261ecSmrg    WriteToClient(client, length, start);
37624642e01fSmrg    xfree((char *)start);
376305b261ecSmrg    return client->noClientException;
376405b261ecSmrg}
376505b261ecSmrg
376605b261ecSmrgint
376705b261ecSmrgProcXkbGetNames(ClientPtr client)
376805b261ecSmrg{
376905b261ecSmrg    DeviceIntPtr	dev;
377005b261ecSmrg    XkbDescPtr		xkb;
377105b261ecSmrg    xkbGetNamesReply 	rep;
377205b261ecSmrg
377305b261ecSmrg    REQUEST(xkbGetNamesReq);
377405b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetNamesReq);
377505b261ecSmrg
377605b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
377705b261ecSmrg	return BadAccess;
377805b261ecSmrg
37794642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
378005b261ecSmrg    CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask);
378105b261ecSmrg
378205b261ecSmrg    xkb = dev->key->xkbInfo->desc;
378305b261ecSmrg    rep.type= X_Reply;
378405b261ecSmrg    rep.sequenceNumber= client->sequence;
378505b261ecSmrg    rep.length = 0;
378605b261ecSmrg    rep.deviceID = dev->id;
378705b261ecSmrg    rep.which = stuff->which;
378805b261ecSmrg    rep.nTypes = xkb->map->num_types;
378905b261ecSmrg    rep.firstKey = xkb->min_key_code;
379005b261ecSmrg    rep.nKeys = XkbNumKeys(xkb);
379105b261ecSmrg    if (xkb->names!=NULL) {
379205b261ecSmrg	rep.nKeyAliases= xkb->names->num_key_aliases;
379305b261ecSmrg	rep.nRadioGroups = xkb->names->num_rg;
379405b261ecSmrg    }
379505b261ecSmrg    else {
379605b261ecSmrg	rep.nKeyAliases= rep.nRadioGroups= 0;
379705b261ecSmrg    }
379805b261ecSmrg    XkbComputeGetNamesReplySize(xkb,&rep);
379905b261ecSmrg    return XkbSendNames(client,xkb,&rep);
380005b261ecSmrg}
380105b261ecSmrg
380205b261ecSmrg/***====================================================================***/
380305b261ecSmrg
380405b261ecSmrgstatic CARD32 *
380505b261ecSmrg_XkbCheckAtoms(CARD32 *wire,int nAtoms,int swapped,Atom *pError)
380605b261ecSmrg{
380705b261ecSmrgregister int i;
380805b261ecSmrg
380905b261ecSmrg    for (i=0;i<nAtoms;i++,wire++) {
381005b261ecSmrg	if (swapped) {
381105b261ecSmrg	    register int n;
381205b261ecSmrg	    swapl(wire,n);
381305b261ecSmrg	}
381405b261ecSmrg	if ((((Atom)*wire)!=None)&&(!ValidAtom((Atom)*wire))) {
381505b261ecSmrg	    *pError= ((Atom)*wire);
381605b261ecSmrg	    return NULL;
381705b261ecSmrg	}
381805b261ecSmrg    }
381905b261ecSmrg    return wire;
382005b261ecSmrg}
382105b261ecSmrg
382205b261ecSmrgstatic CARD32 *
382305b261ecSmrg_XkbCheckMaskedAtoms(CARD32 *wire,int nAtoms,CARD32 present,int swapped,
382405b261ecSmrg								Atom *pError)
382505b261ecSmrg{
382605b261ecSmrgregister unsigned i,bit;
382705b261ecSmrg
382805b261ecSmrg    for (i=0,bit=1;(i<nAtoms)&&(present);i++,bit<<=1) {
382905b261ecSmrg	if ((present&bit)==0)
383005b261ecSmrg	    continue;
383105b261ecSmrg	if (swapped) {
383205b261ecSmrg	    register int n;
383305b261ecSmrg	    swapl(wire,n);
383405b261ecSmrg	}
383505b261ecSmrg	if ((((Atom)*wire)!=None)&&(!ValidAtom(((Atom)*wire)))) {
383605b261ecSmrg	    *pError= (Atom)*wire;
383705b261ecSmrg	    return NULL;
383805b261ecSmrg	}
383905b261ecSmrg	wire++;
384005b261ecSmrg    }
384105b261ecSmrg    return wire;
384205b261ecSmrg}
384305b261ecSmrg
384405b261ecSmrgstatic Atom *
384505b261ecSmrg_XkbCopyMaskedAtoms(	Atom	*wire,
384605b261ecSmrg    			Atom	*dest,
384705b261ecSmrg			int   	 nAtoms,
384805b261ecSmrg			CARD32	 present)
384905b261ecSmrg{
385005b261ecSmrgregister int i,bit;
385105b261ecSmrg
385205b261ecSmrg    for (i=0,bit=1;(i<nAtoms)&&(present);i++,bit<<=1) {
385305b261ecSmrg	if ((present&bit)==0)
385405b261ecSmrg	    continue;
385505b261ecSmrg	dest[i]= *wire++;
385605b261ecSmrg    }
385705b261ecSmrg    return wire;
385805b261ecSmrg}
385905b261ecSmrg
386005b261ecSmrgstatic Bool
386105b261ecSmrg_XkbCheckTypeName(Atom name,int typeNdx)
386205b261ecSmrg{
386305b261ecSmrgchar *	str;
386405b261ecSmrg
386505b261ecSmrg    str= NameForAtom(name);
386605b261ecSmrg    if ((strcmp(str,"ONE_LEVEL")==0)||(strcmp(str,"TWO_LEVEL")==0)||
386705b261ecSmrg	(strcmp(str,"ALPHABETIC")==0)||(strcmp(str,"KEYPAD")==0))
386805b261ecSmrg	return False;
386905b261ecSmrg    return True;
387005b261ecSmrg}
387105b261ecSmrg
38724642e01fSmrg/**
38734642e01fSmrg * Check the device-dependent data in the request against the device. Returns
38744642e01fSmrg * Success, or the appropriate error code.
38754642e01fSmrg */
38764642e01fSmrgstatic int
38774642e01fSmrg_XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
38784642e01fSmrg                  xkbSetNamesReq *stuff, CARD32 *data)
387905b261ecSmrg{
388005b261ecSmrg    XkbDescRec		*xkb;
388105b261ecSmrg    XkbNamesRec		*names;
388205b261ecSmrg    CARD32		*tmp;
388305b261ecSmrg    Atom		 bad;
388405b261ecSmrg
38854642e01fSmrg    tmp = data;
38864642e01fSmrg    xkb = dev->key->xkbInfo->desc;
38874642e01fSmrg    names = xkb->names;
38884642e01fSmrg
38894642e01fSmrg
38904642e01fSmrg    if (stuff->which & XkbKeyTypeNamesMask) {
38914642e01fSmrg        int i;
38924642e01fSmrg        CARD32	*old;
38934642e01fSmrg        if ( stuff->nTypes<1 ) {
38944642e01fSmrg            client->errorValue = _XkbErrCode2(0x02,stuff->nTypes);
38954642e01fSmrg            return BadValue;
38964642e01fSmrg        }
38974642e01fSmrg        if ((unsigned)(stuff->firstType+stuff->nTypes-1)>=xkb->map->num_types) {
38984642e01fSmrg            client->errorValue = _XkbErrCode4(0x03,stuff->firstType,
38994642e01fSmrg                    stuff->nTypes,
39004642e01fSmrg                    xkb->map->num_types);
39014642e01fSmrg            return BadValue;
39024642e01fSmrg        }
39034642e01fSmrg        if (((unsigned)stuff->firstType)<=XkbLastRequiredType) {
39044642e01fSmrg            client->errorValue = _XkbErrCode2(0x04,stuff->firstType);
39054642e01fSmrg            return BadAccess;
39064642e01fSmrg        }
39074642e01fSmrg        old= tmp;
39084642e01fSmrg        tmp= _XkbCheckAtoms(tmp,stuff->nTypes,client->swapped,&bad);
39094642e01fSmrg        if (!tmp) {
39104642e01fSmrg            client->errorValue= bad;
39114642e01fSmrg            return BadAtom;
39124642e01fSmrg        }
39134642e01fSmrg        for (i=0;i<stuff->nTypes;i++,old++) {
39144642e01fSmrg            if (!_XkbCheckTypeName((Atom)*old,stuff->firstType+i))
39154642e01fSmrg                client->errorValue= _XkbErrCode2(0x05,i);
39164642e01fSmrg        }
39174642e01fSmrg    }
39184642e01fSmrg    if (stuff->which&XkbKTLevelNamesMask) {
39194642e01fSmrg        unsigned i;
39204642e01fSmrg        XkbKeyTypePtr	type;
39214642e01fSmrg        CARD8 *		width;
39224642e01fSmrg        if ( stuff->nKTLevels<1 ) {
39234642e01fSmrg            client->errorValue = _XkbErrCode2(0x05,stuff->nKTLevels);
39244642e01fSmrg            return BadValue;
39254642e01fSmrg        }
39264642e01fSmrg        if ((unsigned)(stuff->firstKTLevel+stuff->nKTLevels-1)>=
39274642e01fSmrg                xkb->map->num_types) {
39284642e01fSmrg            client->errorValue = _XkbErrCode4(0x06,stuff->firstKTLevel,
39294642e01fSmrg                    stuff->nKTLevels,xkb->map->num_types);
39304642e01fSmrg            return BadValue;
39314642e01fSmrg        }
39324642e01fSmrg        width = (CARD8 *)tmp;
39334642e01fSmrg        tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels));
39344642e01fSmrg        type = &xkb->map->types[stuff->firstKTLevel];
39354642e01fSmrg        for (i=0;i<stuff->nKTLevels;i++,type++) {
39364642e01fSmrg            if (width[i]==0)
39374642e01fSmrg                continue;
39384642e01fSmrg            else if (width[i]!=type->num_levels) {
39394642e01fSmrg                client->errorValue= _XkbErrCode4(0x07,i+stuff->firstKTLevel,
39404642e01fSmrg                        type->num_levels,width[i]);
39414642e01fSmrg                return BadMatch;
39424642e01fSmrg            }
39434642e01fSmrg            tmp= _XkbCheckAtoms(tmp,width[i],client->swapped,&bad);
39444642e01fSmrg            if (!tmp) {
39454642e01fSmrg                client->errorValue= bad;
39464642e01fSmrg                return BadAtom;
39474642e01fSmrg            }
39484642e01fSmrg        }
39494642e01fSmrg    }
39504642e01fSmrg    if (stuff->which&XkbIndicatorNamesMask) {
39514642e01fSmrg        if (stuff->indicators==0) {
39524642e01fSmrg            client->errorValue= 0x08;
39534642e01fSmrg            return BadMatch;
39544642e01fSmrg        }
39554642e01fSmrg        tmp= _XkbCheckMaskedAtoms(tmp,XkbNumIndicators,stuff->indicators,
39564642e01fSmrg                client->swapped,&bad);
39574642e01fSmrg        if (!tmp) {
39584642e01fSmrg            client->errorValue= bad;
39594642e01fSmrg            return BadAtom;
39604642e01fSmrg        }
39614642e01fSmrg    }
39624642e01fSmrg    if (stuff->which&XkbVirtualModNamesMask) {
39634642e01fSmrg        if (stuff->virtualMods==0) {
39644642e01fSmrg            client->errorValue= 0x09;
39654642e01fSmrg            return BadMatch;
39664642e01fSmrg        }
39674642e01fSmrg        tmp= _XkbCheckMaskedAtoms(tmp,XkbNumVirtualMods,
39684642e01fSmrg                (CARD32)stuff->virtualMods,
39694642e01fSmrg                client->swapped,&bad);
39704642e01fSmrg        if (!tmp) {
39714642e01fSmrg            client->errorValue = bad;
39724642e01fSmrg            return BadAtom;
39734642e01fSmrg        }
39744642e01fSmrg    }
39754642e01fSmrg    if (stuff->which&XkbGroupNamesMask) {
39764642e01fSmrg        if (stuff->groupNames==0) {
39774642e01fSmrg            client->errorValue= 0x0a;
39784642e01fSmrg            return BadMatch;
39794642e01fSmrg        }
39804642e01fSmrg        tmp= _XkbCheckMaskedAtoms(tmp,XkbNumKbdGroups,
39814642e01fSmrg                (CARD32)stuff->groupNames,
39824642e01fSmrg                client->swapped,&bad);
39834642e01fSmrg        if (!tmp) {
39844642e01fSmrg            client->errorValue = bad;
39854642e01fSmrg            return BadAtom;
39864642e01fSmrg        }
39874642e01fSmrg    }
39884642e01fSmrg    if (stuff->which&XkbKeyNamesMask) {
39894642e01fSmrg        if (stuff->firstKey<(unsigned)xkb->min_key_code) {
39904642e01fSmrg            client->errorValue= _XkbErrCode3(0x0b,xkb->min_key_code,
39914642e01fSmrg                    stuff->firstKey);
39924642e01fSmrg            return BadValue;
39934642e01fSmrg        }
39944642e01fSmrg        if (((unsigned)(stuff->firstKey+stuff->nKeys-1)>xkb->max_key_code)||
39954642e01fSmrg                (stuff->nKeys<1)) {
39964642e01fSmrg            client->errorValue= _XkbErrCode4(0x0c,xkb->max_key_code,
39974642e01fSmrg                    stuff->firstKey,stuff->nKeys);
39984642e01fSmrg            return BadValue;
39994642e01fSmrg        }
40004642e01fSmrg        tmp+= stuff->nKeys;
40014642e01fSmrg    }
40024642e01fSmrg    if ((stuff->which&XkbKeyAliasesMask)&&(stuff->nKeyAliases>0)) {
40034642e01fSmrg        tmp+= stuff->nKeyAliases*2;
40044642e01fSmrg    }
40054642e01fSmrg    if (stuff->which&XkbRGNamesMask) {
40064642e01fSmrg        if ( stuff->nRadioGroups<1 ) {
40074642e01fSmrg            client->errorValue= _XkbErrCode2(0x0d,stuff->nRadioGroups);
40084642e01fSmrg            return BadValue;
40094642e01fSmrg        }
40104642e01fSmrg        tmp= _XkbCheckAtoms(tmp,stuff->nRadioGroups,client->swapped,&bad);
40114642e01fSmrg        if (!tmp) {
40124642e01fSmrg            client->errorValue= bad;
40134642e01fSmrg            return BadAtom;
40144642e01fSmrg        }
40154642e01fSmrg    }
40164642e01fSmrg    if ((tmp-((CARD32 *)stuff))!=stuff->length) {
40174642e01fSmrg        client->errorValue = stuff->length;
40184642e01fSmrg        return BadLength;
40194642e01fSmrg    }
40204642e01fSmrg
40214642e01fSmrg
40224642e01fSmrg
40234642e01fSmrg    return Success;
40244642e01fSmrg}
40254642e01fSmrg
40264642e01fSmrgstatic int
40274642e01fSmrg_XkbSetNames(ClientPtr client, DeviceIntPtr dev, xkbSetNamesReq *stuff)
40284642e01fSmrg{
40294642e01fSmrg    XkbDescRec		*xkb;
40304642e01fSmrg    XkbNamesRec		*names;
40314642e01fSmrg    CARD32		*tmp;
40324642e01fSmrg    xkbNamesNotify	 nn;
40334642e01fSmrg
40344642e01fSmrg    tmp = (CARD32 *)&stuff[1];
40354642e01fSmrg    xkb = dev->key->xkbInfo->desc;
40364642e01fSmrg    names = xkb->names;
40374642e01fSmrg
40384642e01fSmrg    if (XkbAllocNames(xkb,stuff->which,stuff->nRadioGroups,
40394642e01fSmrg                stuff->nKeyAliases)!=Success) {
40404642e01fSmrg        return BadAlloc;
40414642e01fSmrg    }
40424642e01fSmrg
40434642e01fSmrg    bzero(&nn,sizeof(xkbNamesNotify));
40444642e01fSmrg    nn.changed= stuff->which;
40454642e01fSmrg    tmp = (CARD32 *)&stuff[1];
40464642e01fSmrg    if (stuff->which&XkbKeycodesNameMask)
40474642e01fSmrg        names->keycodes= *tmp++;
40484642e01fSmrg    if (stuff->which&XkbGeometryNameMask)
40494642e01fSmrg        names->geometry= *tmp++;
40504642e01fSmrg    if (stuff->which&XkbSymbolsNameMask)
40514642e01fSmrg        names->symbols= *tmp++;
40524642e01fSmrg    if (stuff->which&XkbPhysSymbolsNameMask)
40534642e01fSmrg        names->phys_symbols= *tmp++;
40544642e01fSmrg    if (stuff->which&XkbTypesNameMask)
40554642e01fSmrg        names->types= *tmp++;
40564642e01fSmrg    if (stuff->which&XkbCompatNameMask)
40574642e01fSmrg        names->compat= *tmp++;
40584642e01fSmrg    if ((stuff->which&XkbKeyTypeNamesMask)&&(stuff->nTypes>0)) {
40594642e01fSmrg        register unsigned i;
40604642e01fSmrg        register XkbKeyTypePtr type;
40614642e01fSmrg
40624642e01fSmrg        type= &xkb->map->types[stuff->firstType];
40634642e01fSmrg        for (i=0;i<stuff->nTypes;i++,type++) {
40644642e01fSmrg            type->name= *tmp++;
40654642e01fSmrg        }
40664642e01fSmrg        nn.firstType= stuff->firstType;
40674642e01fSmrg        nn.nTypes= stuff->nTypes;
40684642e01fSmrg    }
40694642e01fSmrg    if (stuff->which&XkbKTLevelNamesMask) {
40704642e01fSmrg        register XkbKeyTypePtr	type;
40714642e01fSmrg        register unsigned i;
40724642e01fSmrg        CARD8 *width;
40734642e01fSmrg
40744642e01fSmrg        width = (CARD8 *)tmp;
40754642e01fSmrg        tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels));
40764642e01fSmrg        type= &xkb->map->types[stuff->firstKTLevel];
40774642e01fSmrg        for (i=0;i<stuff->nKTLevels;i++,type++) {
40784642e01fSmrg            if (width[i]>0) {
40794642e01fSmrg                if (type->level_names) {
40804642e01fSmrg                    register unsigned n;
40814642e01fSmrg                    for (n=0;n<width[i];n++) {
40824642e01fSmrg                        type->level_names[n]= tmp[n];
40834642e01fSmrg                    }
40844642e01fSmrg                }
40854642e01fSmrg                tmp+= width[i];
40864642e01fSmrg            }
40874642e01fSmrg        }
40884642e01fSmrg        nn.firstLevelName= 0;
40894642e01fSmrg        nn.nLevelNames= stuff->nTypes;
40904642e01fSmrg    }
40914642e01fSmrg    if (stuff->which&XkbIndicatorNamesMask) {
40924642e01fSmrg        tmp= _XkbCopyMaskedAtoms(tmp,names->indicators,XkbNumIndicators,
40934642e01fSmrg                stuff->indicators);
40944642e01fSmrg        nn.changedIndicators= stuff->indicators;
40954642e01fSmrg    }
40964642e01fSmrg    if (stuff->which&XkbVirtualModNamesMask) {
40974642e01fSmrg        tmp= _XkbCopyMaskedAtoms(tmp,names->vmods,XkbNumVirtualMods,
40984642e01fSmrg                stuff->virtualMods);
40994642e01fSmrg        nn.changedVirtualMods= stuff->virtualMods;
41004642e01fSmrg    }
41014642e01fSmrg    if (stuff->which&XkbGroupNamesMask) {
41024642e01fSmrg        tmp= _XkbCopyMaskedAtoms(tmp,names->groups,XkbNumKbdGroups,
41034642e01fSmrg                stuff->groupNames);
41044642e01fSmrg        nn.changedVirtualMods= stuff->groupNames;
41054642e01fSmrg    }
41064642e01fSmrg    if (stuff->which&XkbKeyNamesMask) {
41074642e01fSmrg        memcpy((char*)&names->keys[stuff->firstKey],(char *)tmp,
41084642e01fSmrg                stuff->nKeys*XkbKeyNameLength);
41094642e01fSmrg        tmp+= stuff->nKeys;
41104642e01fSmrg        nn.firstKey= stuff->firstKey;
41114642e01fSmrg        nn.nKeys= stuff->nKeys;
41124642e01fSmrg    }
41134642e01fSmrg    if (stuff->which&XkbKeyAliasesMask) {
41144642e01fSmrg        if (stuff->nKeyAliases>0) {
41154642e01fSmrg            register int na= stuff->nKeyAliases;
41164642e01fSmrg            if (XkbAllocNames(xkb,XkbKeyAliasesMask,0,na)!=Success)
41174642e01fSmrg                return BadAlloc;
41184642e01fSmrg            memcpy((char *)names->key_aliases,(char *)tmp,
41194642e01fSmrg                    stuff->nKeyAliases*sizeof(XkbKeyAliasRec));
41204642e01fSmrg            tmp+= stuff->nKeyAliases*2;
41214642e01fSmrg        }
41224642e01fSmrg        else if (names->key_aliases!=NULL) {
41234642e01fSmrg            _XkbFree(names->key_aliases);
41244642e01fSmrg            names->key_aliases= NULL;
41254642e01fSmrg            names->num_key_aliases= 0;
41264642e01fSmrg        }
41274642e01fSmrg        nn.nAliases= names->num_key_aliases;
41284642e01fSmrg    }
41294642e01fSmrg    if (stuff->which&XkbRGNamesMask) {
41304642e01fSmrg        if (stuff->nRadioGroups>0) {
41314642e01fSmrg            register unsigned i,nrg;
41324642e01fSmrg            nrg= stuff->nRadioGroups;
41334642e01fSmrg            if (XkbAllocNames(xkb,XkbRGNamesMask,nrg,0)!=Success)
41344642e01fSmrg                return BadAlloc;
41354642e01fSmrg
41364642e01fSmrg            for (i=0;i<stuff->nRadioGroups;i++) {
41374642e01fSmrg                names->radio_groups[i]= tmp[i];
41384642e01fSmrg            }
41394642e01fSmrg            tmp+= stuff->nRadioGroups;
41404642e01fSmrg        }
41414642e01fSmrg        else if (names->radio_groups) {
41424642e01fSmrg            _XkbFree(names->radio_groups);
41434642e01fSmrg            names->radio_groups= NULL;
41444642e01fSmrg            names->num_rg= 0;
41454642e01fSmrg        }
41464642e01fSmrg        nn.nRadioGroups= names->num_rg;
41474642e01fSmrg    }
41484642e01fSmrg    if (nn.changed) {
41494642e01fSmrg        Bool needExtEvent;
41504642e01fSmrg        needExtEvent= (nn.changed&XkbIndicatorNamesMask)!=0;
41514642e01fSmrg        XkbSendNamesNotify(dev,&nn);
41524642e01fSmrg        if (needExtEvent) {
41534642e01fSmrg            XkbSrvLedInfoPtr		sli;
41544642e01fSmrg            xkbExtensionDeviceNotify	edev;
41554642e01fSmrg            register int		i;
41564642e01fSmrg            register unsigned		bit;
41574642e01fSmrg
41584642e01fSmrg            sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,
41594642e01fSmrg                    XkbXI_IndicatorsMask);
41604642e01fSmrg            sli->namesPresent= 0;
41614642e01fSmrg            for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
41624642e01fSmrg                if (names->indicators[i]!=None)
41634642e01fSmrg                    sli->namesPresent|= bit;
41644642e01fSmrg            }
41654642e01fSmrg            bzero(&edev,sizeof(xkbExtensionDeviceNotify));
41664642e01fSmrg            edev.reason=	XkbXI_IndicatorNamesMask;
41674642e01fSmrg            edev.ledClass=	KbdFeedbackClass;
41684642e01fSmrg            edev.ledID=		dev->kbdfeed->ctrl.id;
41694642e01fSmrg            edev.ledsDefined= 	sli->namesPresent|sli->mapsPresent;
41704642e01fSmrg            edev.ledState=	sli->effectiveState;
41714642e01fSmrg            edev.firstBtn=	0;
41724642e01fSmrg            edev.nBtns=		0;
41734642e01fSmrg            edev.supported=	XkbXI_AllFeaturesMask;
41744642e01fSmrg            edev.unsupported=	0;
41754642e01fSmrg            XkbSendExtensionDeviceNotify(dev,client,&edev);
41764642e01fSmrg        }
41774642e01fSmrg    }
41784642e01fSmrg    return Success;
41794642e01fSmrg}
41804642e01fSmrg
41814642e01fSmrgint
41824642e01fSmrgProcXkbSetNames(ClientPtr client)
41834642e01fSmrg{
41844642e01fSmrg    DeviceIntPtr	 dev;
41854642e01fSmrg    CARD32		*tmp;
41864642e01fSmrg    Atom                 bad;
41874642e01fSmrg    int                  rc;
41884642e01fSmrg
418905b261ecSmrg    REQUEST(xkbSetNamesReq);
419005b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetNamesReq);
419105b261ecSmrg
419205b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
419305b261ecSmrg	return BadAccess;
419405b261ecSmrg
41954642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
419605b261ecSmrg    CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask);
419705b261ecSmrg
41984642e01fSmrg    /* check device-independent stuff */
419905b261ecSmrg    tmp = (CARD32 *)&stuff[1];
420005b261ecSmrg
420105b261ecSmrg    if (stuff->which&XkbKeycodesNameMask) {
420205b261ecSmrg	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
420305b261ecSmrg	if (!tmp) {
420405b261ecSmrg	    client->errorValue = bad;
420505b261ecSmrg	    return BadAtom;
420605b261ecSmrg	}
420705b261ecSmrg    }
420805b261ecSmrg    if (stuff->which&XkbGeometryNameMask) {
420905b261ecSmrg	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
421005b261ecSmrg	if (!tmp) {
421105b261ecSmrg	    client->errorValue = bad;
421205b261ecSmrg	    return BadAtom;
421305b261ecSmrg	}
421405b261ecSmrg    }
421505b261ecSmrg    if (stuff->which&XkbSymbolsNameMask) {
421605b261ecSmrg	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
421705b261ecSmrg	if (!tmp) {
421805b261ecSmrg	    client->errorValue = bad;
421905b261ecSmrg	    return BadAtom;
422005b261ecSmrg	}
422105b261ecSmrg    }
422205b261ecSmrg    if (stuff->which&XkbPhysSymbolsNameMask) {
422305b261ecSmrg	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
422405b261ecSmrg	if (!tmp) {
422505b261ecSmrg	    client->errorValue= bad;
422605b261ecSmrg	    return BadAtom;
422705b261ecSmrg	}
422805b261ecSmrg    }
422905b261ecSmrg    if (stuff->which&XkbTypesNameMask) {
423005b261ecSmrg	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
423105b261ecSmrg	if (!tmp) {
423205b261ecSmrg	    client->errorValue = bad;
423305b261ecSmrg	    return BadAtom;
423405b261ecSmrg	}
423505b261ecSmrg    }
423605b261ecSmrg    if (stuff->which&XkbCompatNameMask) {
423705b261ecSmrg	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
423805b261ecSmrg	if (!tmp) {
423905b261ecSmrg	    client->errorValue = bad;
424005b261ecSmrg	    return BadAtom;
424105b261ecSmrg	}
424205b261ecSmrg    }
42434642e01fSmrg
42444642e01fSmrg    /* start of device-dependent tests */
42454642e01fSmrg    rc = _XkbSetNamesCheck(client, dev, stuff, tmp);
42464642e01fSmrg    if (rc != Success)
42474642e01fSmrg        return rc;
42484642e01fSmrg
42494642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd)
42504642e01fSmrg    {
42514642e01fSmrg        DeviceIntPtr other;
42524642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
42534642e01fSmrg        {
42544642e01fSmrg            if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
42554642e01fSmrg            {
42564642e01fSmrg
42574642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
42584642e01fSmrg                if (rc == Success)
42594642e01fSmrg                {
42604642e01fSmrg                    rc = _XkbSetNamesCheck(client, other, stuff, tmp);
42614642e01fSmrg                    if (rc != Success)
42624642e01fSmrg                        return rc;
42634642e01fSmrg                }
42644642e01fSmrg            }
42654642e01fSmrg        }
426605b261ecSmrg    }
426705b261ecSmrg
426805b261ecSmrg    /* everything is okay -- update names */
426905b261ecSmrg
42704642e01fSmrg    rc = _XkbSetNames(client, dev, stuff);
42714642e01fSmrg    if (rc != Success)
42724642e01fSmrg        return rc;
427305b261ecSmrg
42744642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd)
42754642e01fSmrg    {
42764642e01fSmrg        DeviceIntPtr other;
42774642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
42784642e01fSmrg        {
42794642e01fSmrg            if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
42804642e01fSmrg            {
42814642e01fSmrg
42824642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
42834642e01fSmrg                if (rc == Success)
42844642e01fSmrg                    _XkbSetNames(client, other, stuff);
42854642e01fSmrg            }
42864642e01fSmrg        }
428705b261ecSmrg    }
42884642e01fSmrg
42894642e01fSmrg    /* everything is okay -- update names */
42904642e01fSmrg
429105b261ecSmrg    return client->noClientException;
429205b261ecSmrg}
429305b261ecSmrg
429405b261ecSmrg/***====================================================================***/
429505b261ecSmrg
42964642e01fSmrg#include "xkbgeom.h"
429705b261ecSmrg
429805b261ecSmrg#define	XkbSizeCountedString(s)  ((s)?((((2+strlen(s))+3)/4)*4):4)
429905b261ecSmrg
430005b261ecSmrgstatic char *
430105b261ecSmrgXkbWriteCountedString(char *wire,char *str,Bool swap)
430205b261ecSmrg{
430305b261ecSmrgCARD16	len,*pLen;
430405b261ecSmrg
430505b261ecSmrg    len= (str?strlen(str):0);
430605b261ecSmrg    pLen= (CARD16 *)wire;
430705b261ecSmrg    *pLen= len;
430805b261ecSmrg    if (swap) {
430905b261ecSmrg	register int n;
431005b261ecSmrg	swaps(pLen,n);
431105b261ecSmrg    }
431205b261ecSmrg    memcpy(&wire[2],str,len);
431305b261ecSmrg    wire+= ((2+len+3)/4)*4;
431405b261ecSmrg    return wire;
431505b261ecSmrg}
431605b261ecSmrg
431705b261ecSmrgstatic int
431805b261ecSmrgXkbSizeGeomProperties(XkbGeometryPtr geom)
431905b261ecSmrg{
432005b261ecSmrgregister int 	i,size;
432105b261ecSmrgXkbPropertyPtr	prop;
432205b261ecSmrg
432305b261ecSmrg    for (size=i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
432405b261ecSmrg	size+= XkbSizeCountedString(prop->name);
432505b261ecSmrg	size+= XkbSizeCountedString(prop->value);
432605b261ecSmrg    }
432705b261ecSmrg    return size;
432805b261ecSmrg}
432905b261ecSmrg
433005b261ecSmrgstatic char *
433105b261ecSmrgXkbWriteGeomProperties(char *wire,XkbGeometryPtr geom,Bool swap)
433205b261ecSmrg{
433305b261ecSmrgregister int 	i;
433405b261ecSmrgregister XkbPropertyPtr	prop;
433505b261ecSmrg
433605b261ecSmrg    for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
433705b261ecSmrg	wire= XkbWriteCountedString(wire,prop->name,swap);
433805b261ecSmrg	wire= XkbWriteCountedString(wire,prop->value,swap);
433905b261ecSmrg    }
434005b261ecSmrg    return wire;
434105b261ecSmrg}
434205b261ecSmrg
434305b261ecSmrgstatic int
434405b261ecSmrgXkbSizeGeomKeyAliases(XkbGeometryPtr geom)
434505b261ecSmrg{
434605b261ecSmrg    return geom->num_key_aliases*(2*XkbKeyNameLength);
434705b261ecSmrg}
434805b261ecSmrg
434905b261ecSmrgstatic char *
435005b261ecSmrgXkbWriteGeomKeyAliases(char *wire,XkbGeometryPtr geom,Bool swap)
435105b261ecSmrg{
435205b261ecSmrgregister int sz;
435305b261ecSmrg
435405b261ecSmrg    sz= geom->num_key_aliases*(XkbKeyNameLength*2);
435505b261ecSmrg    if (sz>0) {
435605b261ecSmrg	memcpy(wire,(char *)geom->key_aliases,sz);
435705b261ecSmrg	wire+= sz;
435805b261ecSmrg    }
435905b261ecSmrg    return wire;
436005b261ecSmrg}
436105b261ecSmrg
436205b261ecSmrgstatic int
436305b261ecSmrgXkbSizeGeomColors(XkbGeometryPtr geom)
436405b261ecSmrg{
436505b261ecSmrgregister int 		i,size;
436605b261ecSmrgregister XkbColorPtr	color;
436705b261ecSmrg
436805b261ecSmrg    for (i=size=0,color=geom->colors;i<geom->num_colors;i++,color++) {
436905b261ecSmrg	size+= XkbSizeCountedString(color->spec);
437005b261ecSmrg    }
437105b261ecSmrg    return size;
437205b261ecSmrg}
437305b261ecSmrg
437405b261ecSmrgstatic char *
437505b261ecSmrgXkbWriteGeomColors(char *wire,XkbGeometryPtr geom,Bool swap)
437605b261ecSmrg{
437705b261ecSmrgregister int		i;
437805b261ecSmrgregister XkbColorPtr	color;
437905b261ecSmrg
438005b261ecSmrg    for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) {
438105b261ecSmrg	wire= XkbWriteCountedString(wire,color->spec,swap);
438205b261ecSmrg    }
438305b261ecSmrg    return wire;
438405b261ecSmrg}
438505b261ecSmrg
438605b261ecSmrgstatic int
438705b261ecSmrgXkbSizeGeomShapes(XkbGeometryPtr geom)
438805b261ecSmrg{
438905b261ecSmrgregister int		i,size;
439005b261ecSmrgregister XkbShapePtr	shape;
439105b261ecSmrg
439205b261ecSmrg    for (i=size=0,shape=geom->shapes;i<geom->num_shapes;i++,shape++) {
439305b261ecSmrg	register int		n;
439405b261ecSmrg	register XkbOutlinePtr	ol;
439505b261ecSmrg	size+= SIZEOF(xkbShapeWireDesc);
439605b261ecSmrg	for (n=0,ol=shape->outlines;n<shape->num_outlines;n++,ol++) {
439705b261ecSmrg	    size+= SIZEOF(xkbOutlineWireDesc);
439805b261ecSmrg	    size+= ol->num_points*SIZEOF(xkbPointWireDesc);
439905b261ecSmrg	}
440005b261ecSmrg    }
440105b261ecSmrg    return size;
440205b261ecSmrg}
440305b261ecSmrg
440405b261ecSmrgstatic char *
440505b261ecSmrgXkbWriteGeomShapes(char *wire,XkbGeometryPtr geom,Bool swap)
440605b261ecSmrg{
440705b261ecSmrgint			i;
440805b261ecSmrgXkbShapePtr		shape;
440905b261ecSmrgxkbShapeWireDesc *	shapeWire;
441005b261ecSmrg
441105b261ecSmrg    for (i=0,shape=geom->shapes;i<geom->num_shapes;i++,shape++) {
441205b261ecSmrg	register int 		o;
441305b261ecSmrg	XkbOutlinePtr		ol;
441405b261ecSmrg	xkbOutlineWireDesc *	olWire;
441505b261ecSmrg	shapeWire= (xkbShapeWireDesc *)wire;
441605b261ecSmrg	shapeWire->name= shape->name;
441705b261ecSmrg	shapeWire->nOutlines= shape->num_outlines;
441805b261ecSmrg	if (shape->primary!=NULL)
441905b261ecSmrg	     shapeWire->primaryNdx= XkbOutlineIndex(shape,shape->primary);
442005b261ecSmrg	else shapeWire->primaryNdx= XkbNoShape;
442105b261ecSmrg	if (shape->approx!=NULL)
442205b261ecSmrg	     shapeWire->approxNdx= XkbOutlineIndex(shape,shape->approx);
442305b261ecSmrg	else shapeWire->approxNdx= XkbNoShape;
442405b261ecSmrg	if (swap) {
442505b261ecSmrg	    register int n;
442605b261ecSmrg	    swapl(&shapeWire->name,n);
442705b261ecSmrg	}
442805b261ecSmrg	wire= (char *)&shapeWire[1];
442905b261ecSmrg	for (o=0,ol=shape->outlines;o<shape->num_outlines;o++,ol++) {
443005b261ecSmrg	    register int	p;
443105b261ecSmrg	    XkbPointPtr		pt;
443205b261ecSmrg	    xkbPointWireDesc *	ptWire;
443305b261ecSmrg	    olWire= (xkbOutlineWireDesc *)wire;
443405b261ecSmrg	    olWire->nPoints= ol->num_points;
443505b261ecSmrg	    olWire->cornerRadius= ol->corner_radius;
443605b261ecSmrg	    wire= (char *)&olWire[1];
443705b261ecSmrg	    ptWire= (xkbPointWireDesc *)wire;
443805b261ecSmrg	    for (p=0,pt=ol->points;p<ol->num_points;p++,pt++) {
443905b261ecSmrg		ptWire[p].x= pt->x;
444005b261ecSmrg		ptWire[p].y= pt->y;
444105b261ecSmrg		if (swap) {
444205b261ecSmrg		    register int n;
444305b261ecSmrg		    swaps(&ptWire[p].x,n);
444405b261ecSmrg		    swaps(&ptWire[p].y,n);
444505b261ecSmrg		}
444605b261ecSmrg	    }
444705b261ecSmrg	    wire= (char *)&ptWire[ol->num_points];
444805b261ecSmrg	}
444905b261ecSmrg    }
445005b261ecSmrg    return wire;
445105b261ecSmrg}
445205b261ecSmrg
445305b261ecSmrgstatic int
445405b261ecSmrgXkbSizeGeomDoodads(int num_doodads,XkbDoodadPtr doodad)
445505b261ecSmrg{
445605b261ecSmrgregister int	i,size;
445705b261ecSmrg
445805b261ecSmrg    for (i=size=0;i<num_doodads;i++,doodad++) {
445905b261ecSmrg	size+= SIZEOF(xkbAnyDoodadWireDesc);
446005b261ecSmrg	if (doodad->any.type==XkbTextDoodad) {
446105b261ecSmrg	    size+= XkbSizeCountedString(doodad->text.text);
446205b261ecSmrg	    size+= XkbSizeCountedString(doodad->text.font);
446305b261ecSmrg	}
446405b261ecSmrg	else if (doodad->any.type==XkbLogoDoodad) {
446505b261ecSmrg	    size+= XkbSizeCountedString(doodad->logo.logo_name);
446605b261ecSmrg	}
446705b261ecSmrg    }
446805b261ecSmrg    return size;
446905b261ecSmrg}
447005b261ecSmrg
447105b261ecSmrgstatic char *
447205b261ecSmrgXkbWriteGeomDoodads(char *wire,int num_doodads,XkbDoodadPtr doodad,Bool swap)
447305b261ecSmrg{
447405b261ecSmrgregister int		i;
447505b261ecSmrgxkbDoodadWireDesc *	doodadWire;
447605b261ecSmrg
447705b261ecSmrg    for (i=0;i<num_doodads;i++,doodad++) {
447805b261ecSmrg	doodadWire= (xkbDoodadWireDesc *)wire;
447905b261ecSmrg	wire= (char *)&doodadWire[1];
448005b261ecSmrg	bzero(doodadWire,SIZEOF(xkbDoodadWireDesc));
448105b261ecSmrg	doodadWire->any.name= doodad->any.name;
448205b261ecSmrg	doodadWire->any.type= doodad->any.type;
448305b261ecSmrg	doodadWire->any.priority= doodad->any.priority;
448405b261ecSmrg	doodadWire->any.top= doodad->any.top;
448505b261ecSmrg	doodadWire->any.left= doodad->any.left;
448605b261ecSmrg	if (swap) {
448705b261ecSmrg	    register int n;
448805b261ecSmrg	    swapl(&doodadWire->any.name,n);
448905b261ecSmrg	    swaps(&doodadWire->any.top,n);
449005b261ecSmrg	    swaps(&doodadWire->any.left,n);
449105b261ecSmrg	}
449205b261ecSmrg	switch (doodad->any.type) {
449305b261ecSmrg	    case XkbOutlineDoodad:
449405b261ecSmrg	    case XkbSolidDoodad:
449505b261ecSmrg		doodadWire->shape.angle= doodad->shape.angle;
449605b261ecSmrg		doodadWire->shape.colorNdx= doodad->shape.color_ndx;
449705b261ecSmrg		doodadWire->shape.shapeNdx= doodad->shape.shape_ndx;
449805b261ecSmrg		if (swap) {
449905b261ecSmrg		    register int n;
450005b261ecSmrg		    swaps(&doodadWire->shape.angle,n);
450105b261ecSmrg		}
450205b261ecSmrg		break;
450305b261ecSmrg	    case XkbTextDoodad:
450405b261ecSmrg		doodadWire->text.angle= doodad->text.angle;
450505b261ecSmrg		doodadWire->text.width= doodad->text.width;
450605b261ecSmrg		doodadWire->text.height= doodad->text.height;
450705b261ecSmrg		doodadWire->text.colorNdx= doodad->text.color_ndx;
450805b261ecSmrg		if (swap) {
450905b261ecSmrg		    register int n;
451005b261ecSmrg		    swaps(&doodadWire->text.angle,n);
451105b261ecSmrg		    swaps(&doodadWire->text.width,n);
451205b261ecSmrg		    swaps(&doodadWire->text.height,n);
451305b261ecSmrg		}
451405b261ecSmrg		wire= XkbWriteCountedString(wire,doodad->text.text,swap);
451505b261ecSmrg		wire= XkbWriteCountedString(wire,doodad->text.font,swap);
451605b261ecSmrg		break;
451705b261ecSmrg	    case XkbIndicatorDoodad:
451805b261ecSmrg		doodadWire->indicator.shapeNdx= doodad->indicator.shape_ndx;
451905b261ecSmrg		doodadWire->indicator.onColorNdx=doodad->indicator.on_color_ndx;
452005b261ecSmrg		doodadWire->indicator.offColorNdx=
452105b261ecSmrg						doodad->indicator.off_color_ndx;
452205b261ecSmrg		break;
452305b261ecSmrg	    case XkbLogoDoodad:
452405b261ecSmrg		doodadWire->logo.angle= doodad->logo.angle;
452505b261ecSmrg		doodadWire->logo.colorNdx= doodad->logo.color_ndx;
452605b261ecSmrg		doodadWire->logo.shapeNdx= doodad->logo.shape_ndx;
452705b261ecSmrg		wire= XkbWriteCountedString(wire,doodad->logo.logo_name,swap);
452805b261ecSmrg		break;
452905b261ecSmrg	    default:
45304642e01fSmrg		ErrorF("[xkb] Unknown doodad type %d in XkbWriteGeomDoodads\n",
453105b261ecSmrg			doodad->any.type);
45324642e01fSmrg		ErrorF("[xkb] Ignored\n");
453305b261ecSmrg		break;
453405b261ecSmrg	}
453505b261ecSmrg    }
453605b261ecSmrg    return wire;
453705b261ecSmrg}
453805b261ecSmrg
453905b261ecSmrgstatic char *
454005b261ecSmrgXkbWriteGeomOverlay(char *wire,XkbOverlayPtr ol,Bool swap)
454105b261ecSmrg{
454205b261ecSmrgregister int		r;
454305b261ecSmrgXkbOverlayRowPtr	row;
454405b261ecSmrgxkbOverlayWireDesc *	olWire;
454505b261ecSmrg
454605b261ecSmrg   olWire= (xkbOverlayWireDesc *)wire;
454705b261ecSmrg   olWire->name= ol->name;
454805b261ecSmrg   olWire->nRows= ol->num_rows;
454905b261ecSmrg   if (swap) {
455005b261ecSmrg	register int n;
455105b261ecSmrg	swapl(&olWire->name,n);
455205b261ecSmrg   }
455305b261ecSmrg   wire= (char *)&olWire[1];
455405b261ecSmrg   for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
455505b261ecSmrg   	unsigned int		k;
455605b261ecSmrg	XkbOverlayKeyPtr	key;
455705b261ecSmrg	xkbOverlayRowWireDesc *	rowWire;
455805b261ecSmrg	rowWire= (xkbOverlayRowWireDesc *)wire;
455905b261ecSmrg	rowWire->rowUnder= row->row_under;
456005b261ecSmrg	rowWire->nKeys= row->num_keys;
456105b261ecSmrg	wire= (char *)&rowWire[1];
456205b261ecSmrg	for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
456305b261ecSmrg	    xkbOverlayKeyWireDesc *	keyWire;
456405b261ecSmrg	    keyWire= (xkbOverlayKeyWireDesc *)wire;
456505b261ecSmrg	    memcpy(keyWire->over,key->over.name,XkbKeyNameLength);
456605b261ecSmrg	    memcpy(keyWire->under,key->under.name,XkbKeyNameLength);
456705b261ecSmrg	    wire= (char *)&keyWire[1];
456805b261ecSmrg	}
456905b261ecSmrg   }
457005b261ecSmrg   return wire;
457105b261ecSmrg}
457205b261ecSmrg
457305b261ecSmrgstatic int
457405b261ecSmrgXkbSizeGeomSections(XkbGeometryPtr geom)
457505b261ecSmrg{
457605b261ecSmrgregister int 	i,size;
457705b261ecSmrgXkbSectionPtr	section;
457805b261ecSmrg
457905b261ecSmrg    for (i=size=0,section=geom->sections;i<geom->num_sections;i++,section++) {
458005b261ecSmrg	size+= SIZEOF(xkbSectionWireDesc);
458105b261ecSmrg	if (section->rows) {
458205b261ecSmrg	    int		r;
458305b261ecSmrg	    XkbRowPtr	row;
458405b261ecSmrg	    for (r=0,row=section->rows;r<section->num_rows;row++,r++) {
458505b261ecSmrg		size+= SIZEOF(xkbRowWireDesc);
458605b261ecSmrg		size+= row->num_keys*SIZEOF(xkbKeyWireDesc);
458705b261ecSmrg	    }
458805b261ecSmrg	}
458905b261ecSmrg	if (section->doodads)
459005b261ecSmrg	    size+= XkbSizeGeomDoodads(section->num_doodads,section->doodads);
459105b261ecSmrg	if (section->overlays) {
459205b261ecSmrg	    int			o;
459305b261ecSmrg	    XkbOverlayPtr	ol;
459405b261ecSmrg	    for (o=0,ol=section->overlays;o<section->num_overlays;o++,ol++) {
459505b261ecSmrg		int			r;
459605b261ecSmrg		XkbOverlayRowPtr	row;
459705b261ecSmrg		size+= SIZEOF(xkbOverlayWireDesc);
459805b261ecSmrg		for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
459905b261ecSmrg		   size+= SIZEOF(xkbOverlayRowWireDesc);
460005b261ecSmrg		   size+= row->num_keys*SIZEOF(xkbOverlayKeyWireDesc);
460105b261ecSmrg		}
460205b261ecSmrg	    }
460305b261ecSmrg	}
460405b261ecSmrg    }
460505b261ecSmrg    return size;
460605b261ecSmrg}
460705b261ecSmrg
460805b261ecSmrgstatic char *
460905b261ecSmrgXkbWriteGeomSections(char *wire,XkbGeometryPtr geom,Bool swap)
461005b261ecSmrg{
461105b261ecSmrgregister int		i;
461205b261ecSmrgXkbSectionPtr		section;
461305b261ecSmrgxkbSectionWireDesc *	sectionWire;
461405b261ecSmrg
461505b261ecSmrg    for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) {
461605b261ecSmrg	sectionWire= (xkbSectionWireDesc *)wire;
461705b261ecSmrg	sectionWire->name= section->name;
461805b261ecSmrg	sectionWire->top= section->top;
461905b261ecSmrg	sectionWire->left= section->left;
462005b261ecSmrg	sectionWire->width= section->width;
462105b261ecSmrg	sectionWire->height= section->height;
462205b261ecSmrg	sectionWire->angle= section->angle;
462305b261ecSmrg	sectionWire->priority= section->priority;
462405b261ecSmrg	sectionWire->nRows= section->num_rows;
462505b261ecSmrg	sectionWire->nDoodads= section->num_doodads;
462605b261ecSmrg	sectionWire->nOverlays= section->num_overlays;
462705b261ecSmrg	sectionWire->pad= 0;
462805b261ecSmrg	if (swap) {
462905b261ecSmrg	    register int n;
463005b261ecSmrg	    swapl(&sectionWire->name,n);
463105b261ecSmrg	    swaps(&sectionWire->top,n);
463205b261ecSmrg	    swaps(&sectionWire->left,n);
463305b261ecSmrg	    swaps(&sectionWire->width,n);
463405b261ecSmrg	    swaps(&sectionWire->height,n);
463505b261ecSmrg	    swaps(&sectionWire->angle,n);
463605b261ecSmrg	}
463705b261ecSmrg	wire= (char *)&sectionWire[1];
463805b261ecSmrg	if (section->rows) {
463905b261ecSmrg	    int			r;
464005b261ecSmrg	    XkbRowPtr		row;
464105b261ecSmrg	    xkbRowWireDesc *	rowWire;
464205b261ecSmrg	    for (r=0,row=section->rows;r<section->num_rows;r++,row++) {
464305b261ecSmrg		rowWire= (xkbRowWireDesc *)wire;
464405b261ecSmrg		rowWire->top= row->top;
464505b261ecSmrg		rowWire->left= row->left;
464605b261ecSmrg		rowWire->nKeys= row->num_keys;
464705b261ecSmrg		rowWire->vertical= row->vertical;
464805b261ecSmrg		rowWire->pad= 0;
464905b261ecSmrg		if (swap) {
465005b261ecSmrg		    register int n;
465105b261ecSmrg		    swaps(&rowWire->top,n);
465205b261ecSmrg		    swaps(&rowWire->left,n);
465305b261ecSmrg		}
465405b261ecSmrg		wire= (char *)&rowWire[1];
465505b261ecSmrg		if (row->keys) {
465605b261ecSmrg		    int			k;
465705b261ecSmrg		    XkbKeyPtr		key;
465805b261ecSmrg		    xkbKeyWireDesc *	keyWire;
465905b261ecSmrg		    keyWire= (xkbKeyWireDesc *)wire;
466005b261ecSmrg		    for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
466105b261ecSmrg			memcpy(keyWire[k].name,key->name.name,XkbKeyNameLength);
466205b261ecSmrg			keyWire[k].gap= key->gap;
466305b261ecSmrg			keyWire[k].shapeNdx= key->shape_ndx;
466405b261ecSmrg			keyWire[k].colorNdx= key->color_ndx;
466505b261ecSmrg			if (swap) {
466605b261ecSmrg			    register int n;
466705b261ecSmrg			    swaps(&keyWire[k].gap,n);
466805b261ecSmrg			}
466905b261ecSmrg		    }
467005b261ecSmrg		    wire= (char *)&keyWire[row->num_keys];
467105b261ecSmrg		}
467205b261ecSmrg	    }
467305b261ecSmrg	}
467405b261ecSmrg	if (section->doodads) {
467505b261ecSmrg	    wire= XkbWriteGeomDoodads(wire,
467605b261ecSmrg	    			      section->num_doodads,section->doodads,
467705b261ecSmrg				      swap);
467805b261ecSmrg	}
467905b261ecSmrg	if (section->overlays) {
468005b261ecSmrg	    register int o;
468105b261ecSmrg	    for (o=0;o<section->num_overlays;o++) {
468205b261ecSmrg		wire= XkbWriteGeomOverlay(wire,&section->overlays[o],swap);
468305b261ecSmrg	    }
468405b261ecSmrg	}
468505b261ecSmrg    }
468605b261ecSmrg    return wire;
468705b261ecSmrg}
468805b261ecSmrg
468905b261ecSmrgstatic Status
469005b261ecSmrgXkbComputeGetGeometryReplySize(	XkbGeometryPtr		geom,
469105b261ecSmrg				xkbGetGeometryReply *	rep,
469205b261ecSmrg				Atom			name)
469305b261ecSmrg{
469405b261ecSmrgint	len;
469505b261ecSmrg
469605b261ecSmrg    if (geom!=NULL) {
469705b261ecSmrg	len= XkbSizeCountedString(geom->label_font);
469805b261ecSmrg	len+= XkbSizeGeomProperties(geom);
469905b261ecSmrg	len+= XkbSizeGeomColors(geom);
470005b261ecSmrg	len+= XkbSizeGeomShapes(geom);
470105b261ecSmrg	len+= XkbSizeGeomSections(geom);
470205b261ecSmrg	len+= XkbSizeGeomDoodads(geom->num_doodads,geom->doodads);
470305b261ecSmrg	len+= XkbSizeGeomKeyAliases(geom);
470405b261ecSmrg	rep->length= len/4;
470505b261ecSmrg	rep->found= True;
470605b261ecSmrg	rep->name= geom->name;
470705b261ecSmrg	rep->widthMM= geom->width_mm;
470805b261ecSmrg	rep->heightMM= geom->height_mm;
470905b261ecSmrg	rep->nProperties= geom->num_properties;
471005b261ecSmrg	rep->nColors= geom->num_colors;
471105b261ecSmrg	rep->nShapes= geom->num_shapes;
471205b261ecSmrg	rep->nSections= geom->num_sections;
471305b261ecSmrg	rep->nDoodads= geom->num_doodads;
471405b261ecSmrg	rep->nKeyAliases= geom->num_key_aliases;
471505b261ecSmrg	rep->baseColorNdx= XkbGeomColorIndex(geom,geom->base_color);
471605b261ecSmrg	rep->labelColorNdx= XkbGeomColorIndex(geom,geom->label_color);
471705b261ecSmrg    }
471805b261ecSmrg    else {
471905b261ecSmrg	rep->length= 0;
472005b261ecSmrg	rep->found= False;
472105b261ecSmrg	rep->name= name;
472205b261ecSmrg	rep->widthMM= rep->heightMM= 0;
472305b261ecSmrg	rep->nProperties= rep->nColors= rep->nShapes= 0;
472405b261ecSmrg	rep->nSections= rep->nDoodads= 0;
472505b261ecSmrg	rep->nKeyAliases= 0;
472605b261ecSmrg	rep->labelColorNdx= rep->baseColorNdx= 0;
472705b261ecSmrg    }
472805b261ecSmrg    return Success;
472905b261ecSmrg}
473005b261ecSmrg
473105b261ecSmrgstatic int
473205b261ecSmrgXkbSendGeometry(	ClientPtr		client,
473305b261ecSmrg			XkbGeometryPtr		geom,
473405b261ecSmrg			xkbGetGeometryReply *	rep,
473505b261ecSmrg			Bool			freeGeom)
473605b261ecSmrg{
473705b261ecSmrg    char	*desc,*start;
473805b261ecSmrg    int		 len;
473905b261ecSmrg
474005b261ecSmrg    if (geom!=NULL) {
474105b261ecSmrg	len= rep->length*4;
47424642e01fSmrg	start= desc= (char *)xalloc(len);
474305b261ecSmrg	if (!start)
474405b261ecSmrg	    return BadAlloc;
474505b261ecSmrg	desc=  XkbWriteCountedString(desc,geom->label_font,client->swapped);
474605b261ecSmrg	if ( rep->nProperties>0 )
474705b261ecSmrg	    desc = XkbWriteGeomProperties(desc,geom,client->swapped);
474805b261ecSmrg	if ( rep->nColors>0 )
474905b261ecSmrg	    desc = XkbWriteGeomColors(desc,geom,client->swapped);
475005b261ecSmrg	if ( rep->nShapes>0 )
475105b261ecSmrg	    desc = XkbWriteGeomShapes(desc,geom,client->swapped);
475205b261ecSmrg	if ( rep->nSections>0 )
475305b261ecSmrg	    desc = XkbWriteGeomSections(desc,geom,client->swapped);
475405b261ecSmrg	if ( rep->nDoodads>0 )
475505b261ecSmrg	    desc = XkbWriteGeomDoodads(desc,geom->num_doodads,geom->doodads,
475605b261ecSmrg							  client->swapped);
475705b261ecSmrg	if ( rep->nKeyAliases>0 )
475805b261ecSmrg	    desc = XkbWriteGeomKeyAliases(desc,geom,client->swapped);
475905b261ecSmrg	if ((desc-start)!=(len)) {
47604642e01fSmrg	    ErrorF("[xkb] BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n",
476105b261ecSmrg			len, (unsigned long)(desc-start));
476205b261ecSmrg	}
476305b261ecSmrg    }
476405b261ecSmrg    else {
476505b261ecSmrg	len= 0;
476605b261ecSmrg	start= NULL;
476705b261ecSmrg    }
476805b261ecSmrg    if (client->swapped) {
476905b261ecSmrg	register int n;
477005b261ecSmrg	swaps(&rep->sequenceNumber,n);
477105b261ecSmrg	swapl(&rep->length,n);
477205b261ecSmrg	swapl(&rep->name,n);
477305b261ecSmrg	swaps(&rep->widthMM,n);
477405b261ecSmrg	swaps(&rep->heightMM,n);
477505b261ecSmrg	swaps(&rep->nProperties,n);
477605b261ecSmrg	swaps(&rep->nColors,n);
477705b261ecSmrg	swaps(&rep->nShapes,n);
477805b261ecSmrg	swaps(&rep->nSections,n);
477905b261ecSmrg	swaps(&rep->nDoodads,n);
478005b261ecSmrg	swaps(&rep->nKeyAliases,n);
478105b261ecSmrg    }
478205b261ecSmrg    WriteToClient(client, SIZEOF(xkbGetGeometryReply), (char *)rep);
478305b261ecSmrg    if (len>0)
478405b261ecSmrg	WriteToClient(client, len, start);
478505b261ecSmrg    if (start!=NULL)
47864642e01fSmrg	xfree((char *)start);
478705b261ecSmrg    if (freeGeom)
478805b261ecSmrg	XkbFreeGeometry(geom,XkbGeomAllMask,True);
478905b261ecSmrg    return client->noClientException;
479005b261ecSmrg}
479105b261ecSmrg
479205b261ecSmrgint
479305b261ecSmrgProcXkbGetGeometry(ClientPtr client)
479405b261ecSmrg{
479505b261ecSmrg    DeviceIntPtr 	dev;
479605b261ecSmrg    xkbGetGeometryReply rep;
479705b261ecSmrg    XkbGeometryPtr	geom;
479805b261ecSmrg    Bool		shouldFree;
479905b261ecSmrg    Status		status;
480005b261ecSmrg
480105b261ecSmrg    REQUEST(xkbGetGeometryReq);
480205b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetGeometryReq);
480305b261ecSmrg
480405b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
480505b261ecSmrg	return BadAccess;
480605b261ecSmrg
48074642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
480805b261ecSmrg    CHK_ATOM_OR_NONE(stuff->name);
480905b261ecSmrg
481005b261ecSmrg    geom= XkbLookupNamedGeometry(dev,stuff->name,&shouldFree);
481105b261ecSmrg    rep.type= X_Reply;
481205b261ecSmrg    rep.deviceID= dev->id;
481305b261ecSmrg    rep.sequenceNumber= client->sequence;
481405b261ecSmrg    rep.length= 0;
481505b261ecSmrg    status= XkbComputeGetGeometryReplySize(geom,&rep,stuff->name);
481605b261ecSmrg    if (status!=Success)
481705b261ecSmrg	 return status;
481805b261ecSmrg    else return XkbSendGeometry(client,geom,&rep,shouldFree);
481905b261ecSmrg}
482005b261ecSmrg
482105b261ecSmrg/***====================================================================***/
482205b261ecSmrg
482305b261ecSmrgstatic char *
482405b261ecSmrg_GetCountedString(char **wire_inout,Bool swap)
482505b261ecSmrg{
482605b261ecSmrgchar *	wire,*str;
482705b261ecSmrgCARD16	len,*plen;
482805b261ecSmrg
482905b261ecSmrg    wire= *wire_inout;
483005b261ecSmrg    plen= (CARD16 *)wire;
483105b261ecSmrg    if (swap) {
483205b261ecSmrg	register int n;
483305b261ecSmrg	swaps(plen,n);
483405b261ecSmrg    }
483505b261ecSmrg    len= *plen;
483605b261ecSmrg    str= (char *)_XkbAlloc(len+1);
483705b261ecSmrg    if (str) {
483805b261ecSmrg	memcpy(str,&wire[2],len);
483905b261ecSmrg	str[len]= '\0';
484005b261ecSmrg    }
484105b261ecSmrg    wire+= XkbPaddedSize(len+2);
484205b261ecSmrg    *wire_inout= wire;
484305b261ecSmrg    return str;
484405b261ecSmrg}
484505b261ecSmrg
484605b261ecSmrgstatic Status
484705b261ecSmrg_CheckSetDoodad(	char **		wire_inout,
484805b261ecSmrg			XkbGeometryPtr	geom,
484905b261ecSmrg			XkbSectionPtr	section,
485005b261ecSmrg			ClientPtr	client)
485105b261ecSmrg{
485205b261ecSmrgchar *			wire;
485305b261ecSmrgxkbDoodadWireDesc *	dWire;
485405b261ecSmrgXkbDoodadPtr		doodad;
485505b261ecSmrg
485605b261ecSmrg    dWire= (xkbDoodadWireDesc *)(*wire_inout);
485705b261ecSmrg    wire= (char *)&dWire[1];
485805b261ecSmrg    if (client->swapped) {
485905b261ecSmrg	register int n;
486005b261ecSmrg	swapl(&dWire->any.name,n);
486105b261ecSmrg	swaps(&dWire->any.top,n);
486205b261ecSmrg	swaps(&dWire->any.left,n);
486305b261ecSmrg	swaps(&dWire->any.angle,n);
486405b261ecSmrg    }
486505b261ecSmrg    CHK_ATOM_ONLY(dWire->any.name);
486605b261ecSmrg    doodad= XkbAddGeomDoodad(geom,section,dWire->any.name);
486705b261ecSmrg    if (!doodad)
486805b261ecSmrg	return BadAlloc;
486905b261ecSmrg    doodad->any.type= dWire->any.type;
487005b261ecSmrg    doodad->any.priority= dWire->any.priority;
487105b261ecSmrg    doodad->any.top= dWire->any.top;
487205b261ecSmrg    doodad->any.left= dWire->any.left;
487305b261ecSmrg    doodad->any.angle= dWire->any.angle;
487405b261ecSmrg    switch (doodad->any.type) {
487505b261ecSmrg	case XkbOutlineDoodad:
487605b261ecSmrg	case XkbSolidDoodad:
487705b261ecSmrg	    if (dWire->shape.colorNdx>=geom->num_colors) {
487805b261ecSmrg		client->errorValue= _XkbErrCode3(0x40,geom->num_colors,
487905b261ecSmrg							dWire->shape.colorNdx);
488005b261ecSmrg		return BadMatch;
488105b261ecSmrg	    }
488205b261ecSmrg	    if (dWire->shape.shapeNdx>=geom->num_shapes) {
488305b261ecSmrg		client->errorValue= _XkbErrCode3(0x41,geom->num_shapes,
488405b261ecSmrg							dWire->shape.shapeNdx);
488505b261ecSmrg		return BadMatch;
488605b261ecSmrg	    }
488705b261ecSmrg	    doodad->shape.color_ndx= dWire->shape.colorNdx;
488805b261ecSmrg	    doodad->shape.shape_ndx= dWire->shape.shapeNdx;
488905b261ecSmrg	    break;
489005b261ecSmrg	case XkbTextDoodad:
489105b261ecSmrg	    if (dWire->text.colorNdx>=geom->num_colors) {
489205b261ecSmrg		client->errorValue= _XkbErrCode3(0x42,geom->num_colors,
489305b261ecSmrg							dWire->text.colorNdx);
489405b261ecSmrg		return BadMatch;
489505b261ecSmrg	    }
489605b261ecSmrg	    if (client->swapped) {
489705b261ecSmrg		register int n;
489805b261ecSmrg		swaps(&dWire->text.width,n);
489905b261ecSmrg		swaps(&dWire->text.height,n);
490005b261ecSmrg	    }
490105b261ecSmrg	    doodad->text.width= dWire->text.width;
490205b261ecSmrg	    doodad->text.height= dWire->text.height;
490305b261ecSmrg	    doodad->text.color_ndx= dWire->text.colorNdx;
490405b261ecSmrg	    doodad->text.text= _GetCountedString(&wire,client->swapped);
490505b261ecSmrg	    doodad->text.font= _GetCountedString(&wire,client->swapped);
490605b261ecSmrg	    break;
490705b261ecSmrg	case XkbIndicatorDoodad:
490805b261ecSmrg	    if (dWire->indicator.onColorNdx>=geom->num_colors) {
490905b261ecSmrg		client->errorValue= _XkbErrCode3(0x43,geom->num_colors,
491005b261ecSmrg						dWire->indicator.onColorNdx);
491105b261ecSmrg		return BadMatch;
491205b261ecSmrg	    }
491305b261ecSmrg	    if (dWire->indicator.offColorNdx>=geom->num_colors) {
491405b261ecSmrg		client->errorValue= _XkbErrCode3(0x44,geom->num_colors,
491505b261ecSmrg						dWire->indicator.offColorNdx);
491605b261ecSmrg		return BadMatch;
491705b261ecSmrg	    }
491805b261ecSmrg	    if (dWire->indicator.shapeNdx>=geom->num_shapes) {
491905b261ecSmrg		client->errorValue= _XkbErrCode3(0x45,geom->num_shapes,
492005b261ecSmrg						dWire->indicator.shapeNdx);
492105b261ecSmrg		return BadMatch;
492205b261ecSmrg	    }
492305b261ecSmrg	    doodad->indicator.shape_ndx= dWire->indicator.shapeNdx;
492405b261ecSmrg	    doodad->indicator.on_color_ndx= dWire->indicator.onColorNdx;
492505b261ecSmrg	    doodad->indicator.off_color_ndx= dWire->indicator.offColorNdx;
492605b261ecSmrg	    break;
492705b261ecSmrg	case XkbLogoDoodad:
492805b261ecSmrg	    if (dWire->logo.colorNdx>=geom->num_colors) {
492905b261ecSmrg		client->errorValue= _XkbErrCode3(0x46,geom->num_colors,
493005b261ecSmrg							dWire->logo.colorNdx);
493105b261ecSmrg		return BadMatch;
493205b261ecSmrg	    }
493305b261ecSmrg	    if (dWire->logo.shapeNdx>=geom->num_shapes) {
493405b261ecSmrg		client->errorValue= _XkbErrCode3(0x47,geom->num_shapes,
493505b261ecSmrg							dWire->logo.shapeNdx);
493605b261ecSmrg		return BadMatch;
493705b261ecSmrg	    }
493805b261ecSmrg	    doodad->logo.color_ndx= dWire->logo.colorNdx;
493905b261ecSmrg	    doodad->logo.shape_ndx= dWire->logo.shapeNdx;
494005b261ecSmrg	    doodad->logo.logo_name= _GetCountedString(&wire,client->swapped);
494105b261ecSmrg	    break;
494205b261ecSmrg	default:
494305b261ecSmrg	    client->errorValue= _XkbErrCode2(0x4F,dWire->any.type);
494405b261ecSmrg	    return BadValue;
494505b261ecSmrg    }
494605b261ecSmrg    *wire_inout= wire;
494705b261ecSmrg    return Success;
494805b261ecSmrg}
494905b261ecSmrg
495005b261ecSmrgstatic Status
495105b261ecSmrg_CheckSetOverlay(	char **		wire_inout,
495205b261ecSmrg			XkbGeometryPtr	geom,
495305b261ecSmrg			XkbSectionPtr	section,
495405b261ecSmrg			ClientPtr	client)
495505b261ecSmrg{
495605b261ecSmrgregister int		r;
495705b261ecSmrgchar *			wire;
495805b261ecSmrgXkbOverlayPtr		ol;
495905b261ecSmrgxkbOverlayWireDesc *	olWire;
496005b261ecSmrgxkbOverlayRowWireDesc *	rWire;
496105b261ecSmrg
496205b261ecSmrg    wire= *wire_inout;
496305b261ecSmrg    olWire= (xkbOverlayWireDesc *)wire;
496405b261ecSmrg    if (client->swapped) {
496505b261ecSmrg	register int n;
496605b261ecSmrg	swapl(&olWire->name,n);
496705b261ecSmrg    }
496805b261ecSmrg    CHK_ATOM_ONLY(olWire->name);
496905b261ecSmrg    ol= XkbAddGeomOverlay(section,olWire->name,olWire->nRows);
497005b261ecSmrg    rWire= (xkbOverlayRowWireDesc *)&olWire[1];
497105b261ecSmrg    for (r=0;r<olWire->nRows;r++) {
497205b261ecSmrg	register int		k;
497305b261ecSmrg	xkbOverlayKeyWireDesc *	kWire;
497405b261ecSmrg	XkbOverlayRowPtr	row;
497505b261ecSmrg
497605b261ecSmrg	if (rWire->rowUnder>section->num_rows) {
497705b261ecSmrg	    client->errorValue= _XkbErrCode4(0x20,r,section->num_rows,
497805b261ecSmrg							rWire->rowUnder);
497905b261ecSmrg	    return BadMatch;
498005b261ecSmrg	}
498105b261ecSmrg	row= XkbAddGeomOverlayRow(ol,rWire->rowUnder,rWire->nKeys);
498205b261ecSmrg	kWire= (xkbOverlayKeyWireDesc *)&rWire[1];
498305b261ecSmrg	for (k=0;k<rWire->nKeys;k++,kWire++) {
498405b261ecSmrg	    if (XkbAddGeomOverlayKey(ol,row,
498505b261ecSmrg	    		(char *)kWire->over,(char *)kWire->under)==NULL) {
498605b261ecSmrg		client->errorValue= _XkbErrCode3(0x21,r,k);
498705b261ecSmrg		return BadMatch;
498805b261ecSmrg	    }
498905b261ecSmrg	}
499005b261ecSmrg	rWire= (xkbOverlayRowWireDesc *)kWire;
499105b261ecSmrg    }
499205b261ecSmrg    olWire= (xkbOverlayWireDesc *)rWire;
499305b261ecSmrg    wire= (char *)olWire;
499405b261ecSmrg    *wire_inout= wire;
499505b261ecSmrg    return Success;
499605b261ecSmrg}
499705b261ecSmrg
499805b261ecSmrgstatic Status
499905b261ecSmrg_CheckSetSections( 	XkbGeometryPtr		geom,
500005b261ecSmrg			xkbSetGeometryReq *	req,
500105b261ecSmrg			char **			wire_inout,
500205b261ecSmrg			ClientPtr		client)
500305b261ecSmrg{
500405b261ecSmrgStatus			status;
500505b261ecSmrgregister int		s;
500605b261ecSmrgchar *			wire;
500705b261ecSmrgxkbSectionWireDesc *	sWire;
500805b261ecSmrgXkbSectionPtr		section;
500905b261ecSmrg
501005b261ecSmrg    wire= *wire_inout;
501105b261ecSmrg    if (req->nSections<1)
501205b261ecSmrg	return Success;
501305b261ecSmrg    sWire= (xkbSectionWireDesc *)wire;
501405b261ecSmrg    for (s=0;s<req->nSections;s++) {
501505b261ecSmrg	register int		r;
501605b261ecSmrg	xkbRowWireDesc *	rWire;
501705b261ecSmrg	if (client->swapped) {
501805b261ecSmrg	    register int n;
501905b261ecSmrg	    swapl(&sWire->name,n);
502005b261ecSmrg	    swaps(&sWire->top,n);
502105b261ecSmrg	    swaps(&sWire->left,n);
502205b261ecSmrg	    swaps(&sWire->width,n);
502305b261ecSmrg	    swaps(&sWire->height,n);
502405b261ecSmrg	    swaps(&sWire->angle,n);
502505b261ecSmrg	}
502605b261ecSmrg	CHK_ATOM_ONLY(sWire->name);
502705b261ecSmrg	section= XkbAddGeomSection(geom,sWire->name,sWire->nRows,
502805b261ecSmrg					sWire->nDoodads,sWire->nOverlays);
502905b261ecSmrg	if (!section)
503005b261ecSmrg	    return BadAlloc;
503105b261ecSmrg	section->priority=	sWire->priority;
503205b261ecSmrg	section->top=		sWire->top;
503305b261ecSmrg	section->left=		sWire->left;
503405b261ecSmrg	section->width=		sWire->width;
503505b261ecSmrg	section->height=	sWire->height;
503605b261ecSmrg	section->angle=		sWire->angle;
503705b261ecSmrg	rWire= (xkbRowWireDesc *)&sWire[1];
503805b261ecSmrg	for (r=0;r<sWire->nRows;r++) {
503905b261ecSmrg	    register int	k;
504005b261ecSmrg	    XkbRowPtr		row;
504105b261ecSmrg	    xkbKeyWireDesc *	kWire;
504205b261ecSmrg	    if (client->swapped) {
504305b261ecSmrg		register int n;
504405b261ecSmrg		swaps(&rWire->top,n);
504505b261ecSmrg		swaps(&rWire->left,n);
504605b261ecSmrg	    }
504705b261ecSmrg	    row= XkbAddGeomRow(section,rWire->nKeys);
504805b261ecSmrg	    if (!row)
504905b261ecSmrg		return BadAlloc;
505005b261ecSmrg	    row->top= rWire->top;
505105b261ecSmrg	    row->left= rWire->left;
505205b261ecSmrg	    row->vertical= rWire->vertical;
505305b261ecSmrg	    kWire= (xkbKeyWireDesc *)&rWire[1];
505405b261ecSmrg	    for (k=0;k<rWire->nKeys;k++) {
505505b261ecSmrg		XkbKeyPtr	key;
505605b261ecSmrg		key= XkbAddGeomKey(row);
505705b261ecSmrg		if (!key)
505805b261ecSmrg		    return BadAlloc;
505905b261ecSmrg		memcpy(key->name.name,kWire[k].name,XkbKeyNameLength);
506005b261ecSmrg		key->gap= kWire[k].gap;
506105b261ecSmrg		key->shape_ndx= kWire[k].shapeNdx;
506205b261ecSmrg		key->color_ndx= kWire[k].colorNdx;
506305b261ecSmrg		if (key->shape_ndx>=geom->num_shapes) {
506405b261ecSmrg		    client->errorValue= _XkbErrCode3(0x10,key->shape_ndx,
506505b261ecSmrg							  geom->num_shapes);
506605b261ecSmrg		    return BadMatch;
506705b261ecSmrg		}
506805b261ecSmrg		if (key->color_ndx>=geom->num_colors) {
506905b261ecSmrg		    client->errorValue= _XkbErrCode3(0x11,key->color_ndx,
507005b261ecSmrg							  geom->num_colors);
507105b261ecSmrg		    return BadMatch;
507205b261ecSmrg		}
507305b261ecSmrg	    }
507405b261ecSmrg	    rWire= (xkbRowWireDesc *)&kWire[rWire->nKeys];
507505b261ecSmrg	}
507605b261ecSmrg	wire= (char *)rWire;
507705b261ecSmrg	if (sWire->nDoodads>0) {
507805b261ecSmrg	    register int d;
507905b261ecSmrg	    for (d=0;d<sWire->nDoodads;d++) {
508005b261ecSmrg		status=_CheckSetDoodad(&wire,geom,section,client);
508105b261ecSmrg		if (status!=Success)
508205b261ecSmrg		    return status;
508305b261ecSmrg	    }
508405b261ecSmrg	}
508505b261ecSmrg	if (sWire->nOverlays>0) {
508605b261ecSmrg	    register int o;
508705b261ecSmrg	    for (o=0;o<sWire->nOverlays;o++) {
508805b261ecSmrg		status= _CheckSetOverlay(&wire,geom,section,client);
508905b261ecSmrg		if (status!=Success)
509005b261ecSmrg		    return status;
509105b261ecSmrg	    }
509205b261ecSmrg	}
509305b261ecSmrg	sWire= (xkbSectionWireDesc *)wire;
509405b261ecSmrg    }
509505b261ecSmrg    wire= (char *)sWire;
509605b261ecSmrg    *wire_inout= wire;
509705b261ecSmrg    return Success;
509805b261ecSmrg}
509905b261ecSmrg
510005b261ecSmrgstatic Status
510105b261ecSmrg_CheckSetShapes( 	XkbGeometryPtr		geom,
510205b261ecSmrg			xkbSetGeometryReq *	req,
510305b261ecSmrg			char **			wire_inout,
510405b261ecSmrg			ClientPtr		client)
510505b261ecSmrg{
510605b261ecSmrgregister int	i;
510705b261ecSmrgchar *		wire;
510805b261ecSmrg
510905b261ecSmrg    wire= *wire_inout;
511005b261ecSmrg    if (req->nShapes<1) {
511105b261ecSmrg	client->errorValue= _XkbErrCode2(0x06,req->nShapes);
511205b261ecSmrg	return BadValue;
511305b261ecSmrg    }
511405b261ecSmrg    else {
511505b261ecSmrg	xkbShapeWireDesc *	shapeWire;
511605b261ecSmrg	XkbShapePtr		shape;
511705b261ecSmrg	register int		o;
511805b261ecSmrg	shapeWire= (xkbShapeWireDesc *)wire;
511905b261ecSmrg	for (i=0;i<req->nShapes;i++) {
512005b261ecSmrg	    xkbOutlineWireDesc *	olWire;
512105b261ecSmrg	    XkbOutlinePtr		ol;
512205b261ecSmrg	    shape= XkbAddGeomShape(geom,shapeWire->name,shapeWire->nOutlines);
512305b261ecSmrg	    if (!shape)
512405b261ecSmrg		return BadAlloc;
512505b261ecSmrg	    olWire= (xkbOutlineWireDesc *)(&shapeWire[1]);
512605b261ecSmrg	    for (o=0;o<shapeWire->nOutlines;o++) {
512705b261ecSmrg		register int		p;
512805b261ecSmrg		XkbPointPtr		pt;
512905b261ecSmrg		xkbPointWireDesc *	ptWire;
513005b261ecSmrg
513105b261ecSmrg		ol= XkbAddGeomOutline(shape,olWire->nPoints);
513205b261ecSmrg		if (!ol)
513305b261ecSmrg		    return BadAlloc;
513405b261ecSmrg		ol->corner_radius=	olWire->cornerRadius;
513505b261ecSmrg		ptWire= (xkbPointWireDesc *)&olWire[1];
513605b261ecSmrg		for (p=0,pt=ol->points;p<olWire->nPoints;p++,pt++) {
513705b261ecSmrg		    pt->x= ptWire[p].x;
513805b261ecSmrg		    pt->y= ptWire[p].y;
513905b261ecSmrg		    if (client->swapped) {
514005b261ecSmrg			register int n;
514105b261ecSmrg			swaps(&pt->x,n);
514205b261ecSmrg			swaps(&pt->y,n);
514305b261ecSmrg		    }
514405b261ecSmrg		}
514505b261ecSmrg		ol->num_points= olWire->nPoints;
514605b261ecSmrg		olWire= (xkbOutlineWireDesc *)(&ptWire[olWire->nPoints]);
514705b261ecSmrg	    }
514805b261ecSmrg	    if (shapeWire->primaryNdx!=XkbNoShape)
514905b261ecSmrg		shape->primary= &shape->outlines[shapeWire->primaryNdx];
515005b261ecSmrg	    if (shapeWire->approxNdx!=XkbNoShape)
515105b261ecSmrg		shape->approx= &shape->outlines[shapeWire->approxNdx];
515205b261ecSmrg	    shapeWire= (xkbShapeWireDesc *)olWire;
515305b261ecSmrg	}
515405b261ecSmrg	wire= (char *)shapeWire;
515505b261ecSmrg    }
515605b261ecSmrg    if (geom->num_shapes!=req->nShapes) {
515705b261ecSmrg	client->errorValue= _XkbErrCode3(0x07,geom->num_shapes,req->nShapes);
515805b261ecSmrg	return BadMatch;
515905b261ecSmrg    }
516005b261ecSmrg
516105b261ecSmrg    *wire_inout= wire;
516205b261ecSmrg    return Success;
516305b261ecSmrg}
516405b261ecSmrg
516505b261ecSmrgstatic Status
516605b261ecSmrg_CheckSetGeom(	XkbGeometryPtr		geom,
516705b261ecSmrg		xkbSetGeometryReq *	req,
516805b261ecSmrg		ClientPtr 		client)
516905b261ecSmrg{
517005b261ecSmrgregister int	i;
517105b261ecSmrgStatus		status;
517205b261ecSmrgchar *		wire;
517305b261ecSmrg
517405b261ecSmrg    wire= (char *)&req[1];
517505b261ecSmrg    geom->label_font= _GetCountedString(&wire,client->swapped);
517605b261ecSmrg
517705b261ecSmrg    for (i=0;i<req->nProperties;i++) {
517805b261ecSmrg	char *name,*val;
517905b261ecSmrg	name= _GetCountedString(&wire,client->swapped);
518005b261ecSmrg        if (!name)
518105b261ecSmrg            return BadAlloc;
518205b261ecSmrg	val= _GetCountedString(&wire,client->swapped);
518305b261ecSmrg        if (!val) {
518405b261ecSmrg            xfree(name);
518505b261ecSmrg            return BadAlloc;
518605b261ecSmrg        }
518705b261ecSmrg	if (XkbAddGeomProperty(geom,name,val)==NULL) {
518805b261ecSmrg            xfree(name);
518905b261ecSmrg            xfree(val);
519005b261ecSmrg	    return BadAlloc;
519105b261ecSmrg        }
519205b261ecSmrg        xfree(name);
519305b261ecSmrg        xfree(val);
519405b261ecSmrg    }
519505b261ecSmrg
519605b261ecSmrg    if (req->nColors<2) {
519705b261ecSmrg	client->errorValue= _XkbErrCode3(0x01,2,req->nColors);
519805b261ecSmrg	return BadValue;
519905b261ecSmrg    }
520005b261ecSmrg    if (req->baseColorNdx>req->nColors) {
520105b261ecSmrg	client->errorValue=_XkbErrCode3(0x03,req->nColors,req->baseColorNdx);
520205b261ecSmrg	return BadMatch;
520305b261ecSmrg    }
520405b261ecSmrg    if (req->labelColorNdx>req->nColors) {
520505b261ecSmrg	client->errorValue= _XkbErrCode3(0x03,req->nColors,req->labelColorNdx);
520605b261ecSmrg	return BadMatch;
520705b261ecSmrg    }
520805b261ecSmrg    if (req->labelColorNdx==req->baseColorNdx) {
520905b261ecSmrg	client->errorValue= _XkbErrCode3(0x04,req->baseColorNdx,
521005b261ecSmrg                                         req->labelColorNdx);
521105b261ecSmrg	return BadMatch;
521205b261ecSmrg    }
521305b261ecSmrg
521405b261ecSmrg    for (i=0;i<req->nColors;i++) {
521505b261ecSmrg	char *name;
521605b261ecSmrg	name= _GetCountedString(&wire,client->swapped);
521705b261ecSmrg	if (!name)
521805b261ecSmrg            return BadAlloc;
521905b261ecSmrg        if (!XkbAddGeomColor(geom,name,geom->num_colors)) {
522005b261ecSmrg            xfree(name);
522105b261ecSmrg	    return BadAlloc;
522205b261ecSmrg        }
522305b261ecSmrg        xfree(name);
522405b261ecSmrg    }
522505b261ecSmrg    if (req->nColors!=geom->num_colors) {
522605b261ecSmrg	client->errorValue= _XkbErrCode3(0x05,req->nColors,geom->num_colors);
522705b261ecSmrg	return BadMatch;
522805b261ecSmrg    }
522905b261ecSmrg    geom->label_color= &geom->colors[req->labelColorNdx];
523005b261ecSmrg    geom->base_color= &geom->colors[req->baseColorNdx];
523105b261ecSmrg
523205b261ecSmrg    if ((status=_CheckSetShapes(geom,req,&wire,client))!=Success)
523305b261ecSmrg	return status;
523405b261ecSmrg
523505b261ecSmrg    if ((status=_CheckSetSections(geom,req,&wire,client))!=Success)
523605b261ecSmrg	return status;
523705b261ecSmrg
523805b261ecSmrg    for (i=0;i<req->nDoodads;i++) {
523905b261ecSmrg	status=_CheckSetDoodad(&wire,geom,NULL,client);
524005b261ecSmrg	if (status!=Success)
524105b261ecSmrg	    return status;
524205b261ecSmrg    }
524305b261ecSmrg
524405b261ecSmrg    for (i=0;i<req->nKeyAliases;i++) {
524505b261ecSmrg	if (XkbAddGeomKeyAlias(geom,&wire[XkbKeyNameLength],wire)==NULL)
524605b261ecSmrg	    return BadAlloc;
524705b261ecSmrg	wire+= 2*XkbKeyNameLength;
524805b261ecSmrg    }
524905b261ecSmrg    return Success;
525005b261ecSmrg}
525105b261ecSmrg
52524642e01fSmrgstatic int
52534642e01fSmrg_XkbSetGeometry(ClientPtr client, DeviceIntPtr dev, xkbSetGeometryReq *stuff)
525405b261ecSmrg{
525505b261ecSmrg    XkbDescPtr		xkb;
525605b261ecSmrg    Bool		new_name;
525705b261ecSmrg    xkbNewKeyboardNotify	nkn;
52584642e01fSmrg    XkbGeometryPtr	geom,old;
52594642e01fSmrg    XkbGeometrySizesRec	sizes;
52604642e01fSmrg    Status		status;
526105b261ecSmrg
526205b261ecSmrg    xkb= dev->key->xkbInfo->desc;
526305b261ecSmrg    old= xkb->geom;
526405b261ecSmrg    xkb->geom= NULL;
526505b261ecSmrg
52664642e01fSmrg    sizes.which=		XkbGeomAllMask;
526705b261ecSmrg    sizes.num_properties=	stuff->nProperties;
52684642e01fSmrg    sizes.num_colors=	stuff->nColors;
52694642e01fSmrg    sizes.num_shapes=	stuff->nShapes;
52704642e01fSmrg    sizes.num_sections=	stuff->nSections;
52714642e01fSmrg    sizes.num_doodads=	stuff->nDoodads;
527205b261ecSmrg    sizes.num_key_aliases=	stuff->nKeyAliases;
527305b261ecSmrg    if ((status= XkbAllocGeometry(xkb,&sizes))!=Success) {
52744642e01fSmrg        xkb->geom= old;
52754642e01fSmrg        return status;
527605b261ecSmrg    }
527705b261ecSmrg    geom= xkb->geom;
527805b261ecSmrg    geom->name= stuff->name;
527905b261ecSmrg    geom->width_mm= stuff->widthMM;
528005b261ecSmrg    geom->height_mm= stuff->heightMM;
528105b261ecSmrg    if ((status= _CheckSetGeom(geom,stuff,client))!=Success) {
52824642e01fSmrg        XkbFreeGeometry(geom,XkbGeomAllMask,True);
52834642e01fSmrg        xkb->geom= old;
52844642e01fSmrg        return status;
528505b261ecSmrg    }
528605b261ecSmrg    new_name= (xkb->names->geometry!=geom->name);
528705b261ecSmrg    xkb->names->geometry= geom->name;
528805b261ecSmrg    if (old)
52894642e01fSmrg        XkbFreeGeometry(old,XkbGeomAllMask,True);
529005b261ecSmrg    if (new_name) {
52914642e01fSmrg        xkbNamesNotify	nn;
52924642e01fSmrg        bzero(&nn,sizeof(xkbNamesNotify));
52934642e01fSmrg        nn.changed= XkbGeometryNameMask;
52944642e01fSmrg        XkbSendNamesNotify(dev,&nn);
529505b261ecSmrg    }
529605b261ecSmrg    nkn.deviceID= nkn.oldDeviceID= dev->id;
529705b261ecSmrg    nkn.minKeyCode= nkn.oldMinKeyCode= xkb->min_key_code;
529805b261ecSmrg    nkn.maxKeyCode= nkn.oldMaxKeyCode= xkb->max_key_code;
529905b261ecSmrg    nkn.requestMajor=	XkbReqCode;
530005b261ecSmrg    nkn.requestMinor=	X_kbSetGeometry;
530105b261ecSmrg    nkn.changed=	XkbNKN_GeometryMask;
530205b261ecSmrg    XkbSendNewKeyboardNotify(dev,&nkn);
530305b261ecSmrg    return Success;
530405b261ecSmrg}
530505b261ecSmrg
53064642e01fSmrgint
53074642e01fSmrgProcXkbSetGeometry(ClientPtr client)
53084642e01fSmrg{
53094642e01fSmrg    DeviceIntPtr        dev;
53104642e01fSmrg    int                 rc;
53114642e01fSmrg
53124642e01fSmrg    REQUEST(xkbSetGeometryReq);
53134642e01fSmrg    REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq);
53144642e01fSmrg
53154642e01fSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
53164642e01fSmrg	return BadAccess;
53174642e01fSmrg
53184642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
53194642e01fSmrg    CHK_ATOM_OR_NONE(stuff->name);
53204642e01fSmrg
53214642e01fSmrg    rc = _XkbSetGeometry(client, dev, stuff);
53224642e01fSmrg    if (rc != Success)
53234642e01fSmrg        return rc;
53244642e01fSmrg
53254642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd)
53264642e01fSmrg    {
53274642e01fSmrg        DeviceIntPtr other;
53284642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
53294642e01fSmrg        {
53304642e01fSmrg            if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
53314642e01fSmrg            {
53324642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
53334642e01fSmrg                if (rc == Success)
53344642e01fSmrg                    _XkbSetGeometry(client, other, stuff);
53354642e01fSmrg            }
53364642e01fSmrg        }
53374642e01fSmrg    }
53384642e01fSmrg
53394642e01fSmrg    return Success;
53404642e01fSmrg}
53414642e01fSmrg
534205b261ecSmrg/***====================================================================***/
534305b261ecSmrg
534405b261ecSmrgint
534505b261ecSmrgProcXkbPerClientFlags(ClientPtr client)
534605b261ecSmrg{
534705b261ecSmrg    DeviceIntPtr 		dev;
534805b261ecSmrg    xkbPerClientFlagsReply 	rep;
534905b261ecSmrg    XkbInterestPtr		interest;
53504642e01fSmrg    Mask access_mode = DixGetAttrAccess | DixSetAttrAccess;
535105b261ecSmrg
535205b261ecSmrg    REQUEST(xkbPerClientFlagsReq);
535305b261ecSmrg    REQUEST_SIZE_MATCH(xkbPerClientFlagsReq);
535405b261ecSmrg
535505b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
535605b261ecSmrg	return BadAccess;
535705b261ecSmrg
53584642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
535905b261ecSmrg    CHK_MASK_LEGAL(0x01,stuff->change,XkbPCF_AllFlagsMask);
536005b261ecSmrg    CHK_MASK_MATCH(0x02,stuff->change,stuff->value);
536105b261ecSmrg
536205b261ecSmrg    interest = XkbFindClientResource((DevicePtr)dev,client);
536305b261ecSmrg    rep.type= X_Reply;
536405b261ecSmrg    rep.length = 0;
536505b261ecSmrg    rep.sequenceNumber = client->sequence;
536605b261ecSmrg    if (stuff->change) {
536705b261ecSmrg	client->xkbClientFlags&= ~stuff->change;
536805b261ecSmrg	client->xkbClientFlags|= stuff->value;
536905b261ecSmrg    }
537005b261ecSmrg    if (stuff->change&XkbPCF_AutoResetControlsMask) {
537105b261ecSmrg	Bool	want;
537205b261ecSmrg	want= stuff->value&XkbPCF_AutoResetControlsMask;
537305b261ecSmrg	if (interest && !want) {
537405b261ecSmrg	    interest->autoCtrls= interest->autoCtrlValues= 0;
537505b261ecSmrg	}
537605b261ecSmrg	else if (want && (!interest)) {
537705b261ecSmrg	    XID id = FakeClientID(client->index);
537805b261ecSmrg	    AddResource(id,RT_XKBCLIENT,dev);
537905b261ecSmrg	    interest= XkbAddClientResource((DevicePtr)dev,client,id);
538005b261ecSmrg	    if (!interest)
538105b261ecSmrg		return BadAlloc;
538205b261ecSmrg	}
538305b261ecSmrg	if (interest && want ) {
538405b261ecSmrg	    register unsigned affect;
538505b261ecSmrg	    affect= stuff->ctrlsToChange;
538605b261ecSmrg
538705b261ecSmrg	    CHK_MASK_LEGAL(0x03,affect,XkbAllBooleanCtrlsMask);
538805b261ecSmrg	    CHK_MASK_MATCH(0x04,affect,stuff->autoCtrls);
538905b261ecSmrg	    CHK_MASK_MATCH(0x05,stuff->autoCtrls,stuff->autoCtrlValues);
539005b261ecSmrg
539105b261ecSmrg	    interest->autoCtrls&= ~affect;
539205b261ecSmrg	    interest->autoCtrlValues&= ~affect;
539305b261ecSmrg	    interest->autoCtrls|= stuff->autoCtrls&affect;
539405b261ecSmrg	    interest->autoCtrlValues|= stuff->autoCtrlValues&affect;
539505b261ecSmrg	}
539605b261ecSmrg    }
539705b261ecSmrg    rep.supported = XkbPCF_AllFlagsMask;
539805b261ecSmrg    rep.value= client->xkbClientFlags&XkbPCF_AllFlagsMask;
539905b261ecSmrg    if (interest) {
540005b261ecSmrg	rep.autoCtrls= interest->autoCtrls;
540105b261ecSmrg	rep.autoCtrlValues= interest->autoCtrlValues;
540205b261ecSmrg    }
540305b261ecSmrg    else {
540405b261ecSmrg	rep.autoCtrls= rep.autoCtrlValues= 0;
540505b261ecSmrg    }
540605b261ecSmrg    if ( client->swapped ) {
540705b261ecSmrg	register int n;
540805b261ecSmrg	swaps(&rep.sequenceNumber, n);
540905b261ecSmrg	swapl(&rep.supported,n);
541005b261ecSmrg	swapl(&rep.value,n);
541105b261ecSmrg	swapl(&rep.autoCtrls,n);
541205b261ecSmrg	swapl(&rep.autoCtrlValues,n);
541305b261ecSmrg    }
541405b261ecSmrg    WriteToClient(client,SIZEOF(xkbPerClientFlagsReply), (char *)&rep);
541505b261ecSmrg    return client->noClientException;
541605b261ecSmrg}
541705b261ecSmrg
541805b261ecSmrg/***====================================================================***/
541905b261ecSmrg
542005b261ecSmrg/* all latin-1 alphanumerics, plus parens, minus, underscore, slash */
542105b261ecSmrg/* and wildcards */
542205b261ecSmrgstatic unsigned char componentSpecLegal[] = {
542305b261ecSmrg        0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x87,
542405b261ecSmrg        0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07,
542505b261ecSmrg        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
542605b261ecSmrg        0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
542705b261ecSmrg};
542805b261ecSmrg
542905b261ecSmrg/* same as above but accepts percent, plus and bar too */
543005b261ecSmrgstatic unsigned char componentExprLegal[] = {
543105b261ecSmrg        0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0xff, 0x87,
543205b261ecSmrg        0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x17,
543305b261ecSmrg        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
543405b261ecSmrg        0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
543505b261ecSmrg};
543605b261ecSmrg
543705b261ecSmrgstatic char *
543805b261ecSmrgGetComponentSpec(unsigned char **pWire,Bool allowExpr,int *errRtrn)
543905b261ecSmrg{
544005b261ecSmrgint		len;
544105b261ecSmrgregister int	i;
544205b261ecSmrgunsigned char	*wire,*str,*tmp,*legal;
544305b261ecSmrg
544405b261ecSmrg    if (allowExpr)	legal= &componentExprLegal[0];
544505b261ecSmrg    else		legal= &componentSpecLegal[0];
544605b261ecSmrg
544705b261ecSmrg    wire= *pWire;
544805b261ecSmrg    len= (*(unsigned char *)wire++);
544905b261ecSmrg    if (len>0) {
545005b261ecSmrg	str= (unsigned char *)_XkbCalloc(1, len+1);
545105b261ecSmrg	if (str) {
545205b261ecSmrg	    tmp= str;
545305b261ecSmrg	    for (i=0;i<len;i++) {
545405b261ecSmrg		if (legal[(*wire)/8]&(1<<((*wire)%8)))
545505b261ecSmrg		    *tmp++= *wire++;
545605b261ecSmrg		else wire++;
545705b261ecSmrg	    }
545805b261ecSmrg	    if (tmp!=str)
545905b261ecSmrg		*tmp++= '\0';
546005b261ecSmrg	    else {
546105b261ecSmrg		_XkbFree(str);
546205b261ecSmrg		str= NULL;
546305b261ecSmrg	    }
546405b261ecSmrg	}
546505b261ecSmrg	else {
546605b261ecSmrg	    *errRtrn= BadAlloc;
546705b261ecSmrg	}
546805b261ecSmrg    }
546905b261ecSmrg    else {
547005b261ecSmrg	str= NULL;
547105b261ecSmrg    }
547205b261ecSmrg    *pWire= wire;
547305b261ecSmrg    return (char *)str;
547405b261ecSmrg}
547505b261ecSmrg
547605b261ecSmrg/***====================================================================***/
547705b261ecSmrg
547805b261ecSmrgint
547905b261ecSmrgProcXkbListComponents(ClientPtr client)
548005b261ecSmrg{
548105b261ecSmrg    DeviceIntPtr 		dev;
548205b261ecSmrg    xkbListComponentsReply 	rep;
548305b261ecSmrg    unsigned			len;
548405b261ecSmrg    int				status;
548505b261ecSmrg    unsigned char *		str;
548605b261ecSmrg    XkbSrvListInfoRec		list;
548705b261ecSmrg
548805b261ecSmrg    REQUEST(xkbListComponentsReq);
548905b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbListComponentsReq);
549005b261ecSmrg
549105b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
549205b261ecSmrg	return BadAccess;
549305b261ecSmrg
54944642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
549505b261ecSmrg
549605b261ecSmrg    status= Success;
549705b261ecSmrg    str= (unsigned char *)&stuff[1];
549805b261ecSmrg    bzero(&list,sizeof(XkbSrvListInfoRec));
549905b261ecSmrg    list.maxRtrn= stuff->maxNames;
550005b261ecSmrg    list.pattern[_XkbListKeymaps]= GetComponentSpec(&str,False,&status);
550105b261ecSmrg    list.pattern[_XkbListKeycodes]= GetComponentSpec(&str,False,&status);
550205b261ecSmrg    list.pattern[_XkbListTypes]= GetComponentSpec(&str,False,&status);
550305b261ecSmrg    list.pattern[_XkbListCompat]= GetComponentSpec(&str,False,&status);
550405b261ecSmrg    list.pattern[_XkbListSymbols]= GetComponentSpec(&str,False,&status);
550505b261ecSmrg    list.pattern[_XkbListGeometry]= GetComponentSpec(&str,False,&status);
550605b261ecSmrg    if (status!=Success)
550705b261ecSmrg	return status;
550805b261ecSmrg    len= str-((unsigned char *)stuff);
550905b261ecSmrg    if ((XkbPaddedSize(len)/4)!=stuff->length)
551005b261ecSmrg	return BadLength;
551105b261ecSmrg    if ((status=XkbDDXList(dev,&list,client))!=Success) {
551205b261ecSmrg	if (list.pool) {
551305b261ecSmrg	    _XkbFree(list.pool);
551405b261ecSmrg	    list.pool= NULL;
551505b261ecSmrg	}
551605b261ecSmrg	return status;
551705b261ecSmrg    }
551805b261ecSmrg    bzero(&rep,sizeof(xkbListComponentsReply));
551905b261ecSmrg    rep.type= X_Reply;
552005b261ecSmrg    rep.deviceID = dev->id;
552105b261ecSmrg    rep.sequenceNumber = client->sequence;
552205b261ecSmrg    rep.length = XkbPaddedSize(list.nPool)/4;
552305b261ecSmrg    rep.nKeymaps = list.nFound[_XkbListKeymaps];
552405b261ecSmrg    rep.nKeycodes = list.nFound[_XkbListKeycodes];
552505b261ecSmrg    rep.nTypes = list.nFound[_XkbListTypes];
552605b261ecSmrg    rep.nCompatMaps = list.nFound[_XkbListCompat];
552705b261ecSmrg    rep.nSymbols = list.nFound[_XkbListSymbols];
552805b261ecSmrg    rep.nGeometries = list.nFound[_XkbListGeometry];
552905b261ecSmrg    rep.extra=	0;
553005b261ecSmrg    if (list.nTotal>list.maxRtrn)
553105b261ecSmrg	rep.extra = (list.nTotal-list.maxRtrn);
553205b261ecSmrg    if (client->swapped) {
553305b261ecSmrg	register int n;
553405b261ecSmrg	swaps(&rep.sequenceNumber,n);
553505b261ecSmrg	swapl(&rep.length,n);
553605b261ecSmrg	swaps(&rep.nKeymaps,n);
553705b261ecSmrg	swaps(&rep.nKeycodes,n);
553805b261ecSmrg	swaps(&rep.nTypes,n);
553905b261ecSmrg	swaps(&rep.nCompatMaps,n);
554005b261ecSmrg	swaps(&rep.nSymbols,n);
554105b261ecSmrg	swaps(&rep.nGeometries,n);
554205b261ecSmrg	swaps(&rep.extra,n);
554305b261ecSmrg    }
554405b261ecSmrg    WriteToClient(client,SIZEOF(xkbListComponentsReply),(char *)&rep);
554505b261ecSmrg    if (list.nPool && list.pool) {
554605b261ecSmrg	WriteToClient(client,XkbPaddedSize(list.nPool), (char *)list.pool);
554705b261ecSmrg	_XkbFree(list.pool);
554805b261ecSmrg	list.pool= NULL;
554905b261ecSmrg    }
555005b261ecSmrg    return client->noClientException;
555105b261ecSmrg}
555205b261ecSmrg
555305b261ecSmrg/***====================================================================***/
555405b261ecSmrg
555505b261ecSmrgint
555605b261ecSmrgProcXkbGetKbdByName(ClientPtr client)
555705b261ecSmrg{
555805b261ecSmrg    DeviceIntPtr 		dev;
555905b261ecSmrg    DeviceIntPtr                tmpd;
556005b261ecSmrg    xkbGetKbdByNameReply 	rep;
556105b261ecSmrg    xkbGetMapReply		mrep;
556205b261ecSmrg    xkbGetCompatMapReply	crep;
556305b261ecSmrg    xkbGetIndicatorMapReply	irep;
556405b261ecSmrg    xkbGetNamesReply		nrep;
556505b261ecSmrg    xkbGetGeometryReply		grep;
556605b261ecSmrg    XkbComponentNamesRec	names;
55674642e01fSmrg    XkbDescPtr			xkb, new;
556805b261ecSmrg    unsigned char *		str;
556905b261ecSmrg    char 			mapFile[PATH_MAX];
557005b261ecSmrg    unsigned			len;
557105b261ecSmrg    unsigned			fwant,fneed,reported;
557205b261ecSmrg    int				status;
557305b261ecSmrg    Bool			geom_changed;
557405b261ecSmrg    XkbSrvLedInfoPtr            old_sli;
557505b261ecSmrg    XkbSrvLedInfoPtr            sli;
55764642e01fSmrg    Mask access_mode = DixGetAttrAccess | DixManageAccess;
557705b261ecSmrg
557805b261ecSmrg    REQUEST(xkbGetKbdByNameReq);
557905b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq);
558005b261ecSmrg
558105b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
558205b261ecSmrg	return BadAccess;
558305b261ecSmrg
55844642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
558505b261ecSmrg
558605b261ecSmrg    xkb = dev->key->xkbInfo->desc;
558705b261ecSmrg    status= Success;
558805b261ecSmrg    str= (unsigned char *)&stuff[1];
558905b261ecSmrg    names.keymap= GetComponentSpec(&str,True,&status);
559005b261ecSmrg    names.keycodes= GetComponentSpec(&str,True,&status);
559105b261ecSmrg    names.types= GetComponentSpec(&str,True,&status);
559205b261ecSmrg    names.compat= GetComponentSpec(&str,True,&status);
559305b261ecSmrg    names.symbols= GetComponentSpec(&str,True,&status);
559405b261ecSmrg    names.geometry= GetComponentSpec(&str,True,&status);
559505b261ecSmrg    if (status!=Success)
559605b261ecSmrg	return status;
559705b261ecSmrg    len= str-((unsigned char *)stuff);
559805b261ecSmrg    if ((XkbPaddedSize(len)/4)!=stuff->length)
559905b261ecSmrg	return BadLength;
560005b261ecSmrg
560105b261ecSmrg    CHK_MASK_LEGAL(0x01,stuff->want,XkbGBN_AllComponentsMask);
560205b261ecSmrg    CHK_MASK_LEGAL(0x02,stuff->need,XkbGBN_AllComponentsMask);
560305b261ecSmrg
560405b261ecSmrg    if (stuff->load)
560505b261ecSmrg	 fwant= XkbGBN_AllComponentsMask;
560605b261ecSmrg    else fwant= stuff->want|stuff->need;
56074642e01fSmrg    if ((!names.compat)&&
56084642e01fSmrg        (fwant&(XkbGBN_CompatMapMask|XkbGBN_IndicatorMapMask))) {
56094642e01fSmrg        names.compat= _XkbDupString("%");
561005b261ecSmrg    }
56114642e01fSmrg    if ((!names.types)&&(fwant&(XkbGBN_TypesMask))) {
56124642e01fSmrg        names.types= _XkbDupString("%");
56134642e01fSmrg    }
56144642e01fSmrg    if ((!names.symbols)&&(fwant&XkbGBN_SymbolsMask)) {
56154642e01fSmrg        names.symbols= _XkbDupString("%");
56164642e01fSmrg    }
56174642e01fSmrg    geom_changed= ((names.geometry!=NULL)&&(strcmp(names.geometry,"%")!=0));
56184642e01fSmrg    if ((!names.geometry)&&(fwant&XkbGBN_GeometryMask)) {
56194642e01fSmrg        names.geometry= _XkbDupString("%");
56204642e01fSmrg        geom_changed= False;
562105b261ecSmrg    }
562205b261ecSmrg
562305b261ecSmrg    bzero(mapFile,PATH_MAX);
562405b261ecSmrg    rep.type= X_Reply;
562505b261ecSmrg    rep.deviceID = dev->id;
562605b261ecSmrg    rep.sequenceNumber = client->sequence;
562705b261ecSmrg    rep.length = 0;
562805b261ecSmrg    rep.minKeyCode = xkb->min_key_code;
562905b261ecSmrg    rep.maxKeyCode = xkb->max_key_code;
563005b261ecSmrg    rep.loaded=	False;
563105b261ecSmrg    fwant= XkbConvertGetByNameComponents(True,stuff->want)|XkmVirtualModsMask;
563205b261ecSmrg    fneed= XkbConvertGetByNameComponents(True,stuff->need);
563305b261ecSmrg    rep.reported= XkbConvertGetByNameComponents(False,fwant|fneed);
563405b261ecSmrg    if (stuff->load) {
563505b261ecSmrg	fneed|= XkmKeymapRequired;
563605b261ecSmrg	fwant|= XkmKeymapLegal;
563705b261ecSmrg    }
563805b261ecSmrg    if ((fwant|fneed)&XkmSymbolsMask) {
563905b261ecSmrg	fneed|= XkmKeyNamesIndex|XkmTypesIndex;
564005b261ecSmrg	fwant|= XkmIndicatorsIndex;
564105b261ecSmrg    }
564205b261ecSmrg
564305b261ecSmrg    /* We pass dev in here so we can get the old names out if needed. */
56444642e01fSmrg    rep.found = XkbDDXLoadKeymapByNames(dev,&names,fwant,fneed,&new,
564505b261ecSmrg                                        mapFile,PATH_MAX);
564605b261ecSmrg    rep.newKeyboard= False;
564705b261ecSmrg    rep.pad1= rep.pad2= rep.pad3= rep.pad4= 0;
564805b261ecSmrg
564905b261ecSmrg    stuff->want|= stuff->need;
56504642e01fSmrg    if (new==NULL)
565105b261ecSmrg	rep.reported= 0;
565205b261ecSmrg    else {
565305b261ecSmrg	if (stuff->load)
565405b261ecSmrg	    rep.loaded= True;
565505b261ecSmrg	if (stuff->load ||
56564642e01fSmrg		((rep.reported&XkbGBN_SymbolsMask) && (new->compat))) {
565705b261ecSmrg	    XkbChangesRec changes;
565805b261ecSmrg	    bzero(&changes,sizeof(changes));
56594642e01fSmrg	    XkbUpdateDescActions(new,
56604642e01fSmrg			new->min_key_code,XkbNumKeys(new),
566105b261ecSmrg			&changes);
566205b261ecSmrg	}
566305b261ecSmrg
56644642e01fSmrg	if (new->map==NULL)
566505b261ecSmrg	    rep.reported&= ~(XkbGBN_SymbolsMask|XkbGBN_TypesMask);
566605b261ecSmrg	else if (rep.reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask)) {
566705b261ecSmrg	    mrep.type= X_Reply;
566805b261ecSmrg	    mrep.deviceID = dev->id;
566905b261ecSmrg	    mrep.sequenceNumber= client->sequence;
567005b261ecSmrg	    mrep.length = ((SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2);
56714642e01fSmrg	    mrep.minKeyCode = new->min_key_code;
56724642e01fSmrg	    mrep.maxKeyCode = new->max_key_code;
567305b261ecSmrg	    mrep.present = 0;
567405b261ecSmrg	    mrep.totalSyms = mrep.totalActs =
567505b261ecSmrg		mrep.totalKeyBehaviors= mrep.totalKeyExplicit=
567652397711Smrg		mrep.totalModMapKeys= mrep.totalVModMapKeys= 0;
567705b261ecSmrg	    if (rep.reported&(XkbGBN_TypesMask|XkbGBN_ClientSymbolsMask)) {
567805b261ecSmrg		mrep.present|= XkbKeyTypesMask;
567905b261ecSmrg		mrep.firstType = 0;
56804642e01fSmrg		mrep.nTypes = mrep.totalTypes= new->map->num_types;
568105b261ecSmrg	    }
568205b261ecSmrg	    else {
568305b261ecSmrg		mrep.firstType = mrep.nTypes= 0;
568405b261ecSmrg		mrep.totalTypes= 0;
568505b261ecSmrg	    }
568605b261ecSmrg	    if (rep.reported&XkbGBN_ClientSymbolsMask) {
568705b261ecSmrg		mrep.present|= (XkbKeySymsMask|XkbModifierMapMask);
56884642e01fSmrg		mrep.firstKeySym = mrep.firstModMapKey= new->min_key_code;
56894642e01fSmrg		mrep.nKeySyms = mrep.nModMapKeys= XkbNumKeys(new);
569005b261ecSmrg	    }
569105b261ecSmrg	    else {
569205b261ecSmrg		mrep.firstKeySym= mrep.firstModMapKey= 0;
569305b261ecSmrg		mrep.nKeySyms= mrep.nModMapKeys= 0;
569405b261ecSmrg	    }
569505b261ecSmrg	    if (rep.reported&XkbGBN_ServerSymbolsMask) {
569605b261ecSmrg		mrep.present|= XkbAllServerInfoMask;
569705b261ecSmrg		mrep.virtualMods= ~0;
569805b261ecSmrg		mrep.firstKeyAct = mrep.firstKeyBehavior =
56994642e01fSmrg			mrep.firstKeyExplicit = new->min_key_code;
570005b261ecSmrg		mrep.nKeyActs = mrep.nKeyBehaviors =
57014642e01fSmrg			mrep.nKeyExplicit = XkbNumKeys(new);
570252397711Smrg		mrep.firstVModMapKey= new->min_key_code;
570352397711Smrg		mrep.nVModMapKeys= XkbNumKeys(new);
570405b261ecSmrg	    }
570505b261ecSmrg	    else {
570605b261ecSmrg		mrep.virtualMods= 0;
570705b261ecSmrg		mrep.firstKeyAct= mrep.firstKeyBehavior=
570805b261ecSmrg			mrep.firstKeyExplicit = 0;
570905b261ecSmrg		mrep.nKeyActs= mrep.nKeyBehaviors= mrep.nKeyExplicit= 0;
571005b261ecSmrg	    }
57114642e01fSmrg	    XkbComputeGetMapReplySize(new,&mrep);
571205b261ecSmrg	    rep.length+= SIZEOF(xGenericReply)/4+mrep.length;
571305b261ecSmrg	}
57144642e01fSmrg	if (new->compat==NULL)
571505b261ecSmrg	    rep.reported&= ~XkbGBN_CompatMapMask;
571605b261ecSmrg	else if (rep.reported&XkbGBN_CompatMapMask) {
571705b261ecSmrg	    crep.type= X_Reply;
571805b261ecSmrg	    crep.deviceID= dev->id;
571905b261ecSmrg	    crep.sequenceNumber= client->sequence;
572005b261ecSmrg	    crep.length= 0;
572105b261ecSmrg	    crep.groups= XkbAllGroupsMask;
572205b261ecSmrg	    crep.firstSI= 0;
57234642e01fSmrg	    crep.nSI= crep.nTotalSI= new->compat->num_si;
57244642e01fSmrg	    XkbComputeGetCompatMapReplySize(new->compat,&crep);
572505b261ecSmrg	    rep.length+= SIZEOF(xGenericReply)/4+crep.length;
572605b261ecSmrg	}
57274642e01fSmrg	if (new->indicators==NULL)
572805b261ecSmrg	    rep.reported&= ~XkbGBN_IndicatorMapMask;
572905b261ecSmrg	else if (rep.reported&XkbGBN_IndicatorMapMask) {
573005b261ecSmrg	    irep.type= X_Reply;
573105b261ecSmrg	    irep.deviceID= dev->id;
573205b261ecSmrg	    irep.sequenceNumber= client->sequence;
573305b261ecSmrg	    irep.length= 0;
573405b261ecSmrg	    irep.which= XkbAllIndicatorsMask;
57354642e01fSmrg	    XkbComputeGetIndicatorMapReplySize(new->indicators,&irep);
573605b261ecSmrg	    rep.length+= SIZEOF(xGenericReply)/4+irep.length;
573705b261ecSmrg	}
57384642e01fSmrg	if (new->names==NULL)
573905b261ecSmrg	    rep.reported&= ~(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask);
574005b261ecSmrg	else if (rep.reported&(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask)) {
574105b261ecSmrg	    nrep.type= X_Reply;
574205b261ecSmrg	    nrep.deviceID= dev->id;
574305b261ecSmrg	    nrep.sequenceNumber= client->sequence;
574405b261ecSmrg	    nrep.length= 0;
57454642e01fSmrg	    nrep.minKeyCode= new->min_key_code;
57464642e01fSmrg	    nrep.maxKeyCode= new->max_key_code;
574705b261ecSmrg	    if (rep.reported&XkbGBN_OtherNamesMask) {
574805b261ecSmrg		nrep.which= XkbAllNamesMask;
57494642e01fSmrg		if (new->map!=NULL)
57504642e01fSmrg		     nrep.nTypes= new->map->num_types;
575105b261ecSmrg		else nrep.nTypes= 0;
575205b261ecSmrg		nrep.nKTLevels= 0;
575305b261ecSmrg		nrep.groupNames= XkbAllGroupsMask;
575405b261ecSmrg		nrep.virtualMods= XkbAllVirtualModsMask;
575505b261ecSmrg		nrep.indicators= XkbAllIndicatorsMask;
57564642e01fSmrg		nrep.nRadioGroups= new->names->num_rg;
575705b261ecSmrg	    }
575805b261ecSmrg	    else {
575905b261ecSmrg		nrep.which= 0;
576005b261ecSmrg		nrep.nTypes= 0;
576105b261ecSmrg		nrep.nKTLevels= 0;
576205b261ecSmrg		nrep.groupNames= 0;
576305b261ecSmrg		nrep.virtualMods= 0;
576405b261ecSmrg		nrep.indicators= 0;
576505b261ecSmrg		nrep.nRadioGroups= 0;
576605b261ecSmrg	    }
576705b261ecSmrg	    if (rep.reported&XkbGBN_KeyNamesMask) {
576805b261ecSmrg		nrep.which|= XkbKeyNamesMask;
57694642e01fSmrg		nrep.firstKey= new->min_key_code;
57704642e01fSmrg		nrep.nKeys= XkbNumKeys(new);
57714642e01fSmrg		nrep.nKeyAliases= new->names->num_key_aliases;
577205b261ecSmrg		if (nrep.nKeyAliases)
577305b261ecSmrg		    nrep.which|= XkbKeyAliasesMask;
577405b261ecSmrg	    }
577505b261ecSmrg	    else {
577605b261ecSmrg		nrep.which&= ~(XkbKeyNamesMask|XkbKeyAliasesMask);
577705b261ecSmrg		nrep.firstKey= nrep.nKeys= 0;
577805b261ecSmrg		nrep.nKeyAliases= 0;
577905b261ecSmrg	    }
57804642e01fSmrg	    XkbComputeGetNamesReplySize(new,&nrep);
578105b261ecSmrg	    rep.length+= SIZEOF(xGenericReply)/4+nrep.length;
578205b261ecSmrg	}
57834642e01fSmrg	if (new->geom==NULL)
578405b261ecSmrg	    rep.reported&= ~XkbGBN_GeometryMask;
578505b261ecSmrg	else if (rep.reported&XkbGBN_GeometryMask) {
578605b261ecSmrg	    grep.type= X_Reply;
578705b261ecSmrg	    grep.deviceID= dev->id;
578805b261ecSmrg	    grep.sequenceNumber= client->sequence;
578905b261ecSmrg	    grep.length= 0;
579005b261ecSmrg	    grep.found= True;
579105b261ecSmrg	    grep.pad= 0;
579205b261ecSmrg	    grep.widthMM= grep.heightMM= 0;
579305b261ecSmrg	    grep.nProperties= grep.nColors= grep.nShapes= 0;
579405b261ecSmrg	    grep.nSections= grep.nDoodads= 0;
579505b261ecSmrg	    grep.baseColorNdx= grep.labelColorNdx= 0;
57964642e01fSmrg	    XkbComputeGetGeometryReplySize(new->geom,&grep,None);
579705b261ecSmrg	    rep.length+= SIZEOF(xGenericReply)/4+grep.length;
579805b261ecSmrg	}
579905b261ecSmrg    }
580005b261ecSmrg
580105b261ecSmrg    reported= rep.reported;
580205b261ecSmrg    if ( client->swapped ) {
580305b261ecSmrg	register int n;
580405b261ecSmrg	swaps(&rep.sequenceNumber,n);
580505b261ecSmrg	swapl(&rep.length,n);
580605b261ecSmrg	swaps(&rep.found,n);
580705b261ecSmrg	swaps(&rep.reported,n);
580805b261ecSmrg    }
580905b261ecSmrg    WriteToClient(client,SIZEOF(xkbGetKbdByNameReply), (char *)&rep);
581005b261ecSmrg    if (reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask))
58114642e01fSmrg	XkbSendMap(client,new,&mrep);
581205b261ecSmrg    if (reported&XkbGBN_CompatMapMask)
58134642e01fSmrg	XkbSendCompatMap(client,new->compat,&crep);
581405b261ecSmrg    if (reported&XkbGBN_IndicatorMapMask)
58154642e01fSmrg	XkbSendIndicatorMap(client,new->indicators,&irep);
581605b261ecSmrg    if (reported&(XkbGBN_KeyNamesMask|XkbGBN_OtherNamesMask))
58174642e01fSmrg	XkbSendNames(client,new,&nrep);
581805b261ecSmrg    if (reported&XkbGBN_GeometryMask)
58194642e01fSmrg	XkbSendGeometry(client,new->geom,&grep,False);
582005b261ecSmrg    if (rep.loaded) {
582105b261ecSmrg	XkbDescPtr		old_xkb;
582205b261ecSmrg	xkbNewKeyboardNotify 	nkn;
582305b261ecSmrg	int 			i,nG,nTG;
582405b261ecSmrg	old_xkb= xkb;
58254642e01fSmrg	xkb= new;
582605b261ecSmrg	dev->key->xkbInfo->desc= xkb;
58274642e01fSmrg	new= old_xkb; /* so it'll get freed automatically */
582805b261ecSmrg
582905b261ecSmrg	*xkb->ctrls= *old_xkb->ctrls;
583005b261ecSmrg	for (nG=nTG=0,i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
583105b261ecSmrg	    nG= XkbKeyNumGroups(xkb,i);
583205b261ecSmrg	    if (nG>=XkbNumKbdGroups) {
583305b261ecSmrg		nTG= XkbNumKbdGroups;
583405b261ecSmrg		break;
583505b261ecSmrg	    }
583605b261ecSmrg	    if (nG>nTG) {
583705b261ecSmrg		nTG= nG;
583805b261ecSmrg	    }
583905b261ecSmrg	}
584005b261ecSmrg	xkb->ctrls->num_groups= nTG;
584105b261ecSmrg
584205b261ecSmrg        for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
584305b261ecSmrg            if (tmpd == dev ||
584405b261ecSmrg                (dev->id == inputInfo.keyboard->id && tmpd->key &&
584505b261ecSmrg                 tmpd->coreEvents)) {
584605b261ecSmrg
584705b261ecSmrg                memcpy(tmpd->key->modifierMap, xkb->map->modmap,
584805b261ecSmrg                       xkb->max_key_code + 1);
584905b261ecSmrg                if (tmpd != dev)
585005b261ecSmrg                    XkbCopyKeymap(dev->key->xkbInfo->desc,
585105b261ecSmrg                                  tmpd->key->xkbInfo->desc, True);
585205b261ecSmrg                XkbUpdateCoreDescription(tmpd, True);
585305b261ecSmrg
585405b261ecSmrg                if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) {
585505b261ecSmrg                    old_sli = tmpd->kbdfeed->xkb_sli;
585605b261ecSmrg                    tmpd->kbdfeed->xkb_sli = NULL;
585705b261ecSmrg                    sli = XkbAllocSrvLedInfo(tmpd, tmpd->kbdfeed, NULL, 0);
585805b261ecSmrg                    if (sli) {
585905b261ecSmrg                        sli->explicitState = old_sli->explicitState;
586005b261ecSmrg                        sli->effectiveState = old_sli->effectiveState;
586105b261ecSmrg                    }
586205b261ecSmrg                    tmpd->kbdfeed->xkb_sli = sli;
586305b261ecSmrg                    XkbFreeSrvLedInfo(old_sli);
586405b261ecSmrg                }
586505b261ecSmrg            }
586605b261ecSmrg        }
586705b261ecSmrg
586805b261ecSmrg        /* this should be either a MN or an NKN, depending on whether or not
586905b261ecSmrg         * the keycode range changed? */
587005b261ecSmrg	nkn.deviceID= nkn.oldDeviceID= dev->id;
58714642e01fSmrg	nkn.minKeyCode= new->min_key_code;
58724642e01fSmrg	nkn.maxKeyCode= new->max_key_code;
587305b261ecSmrg	nkn.oldMinKeyCode= xkb->min_key_code;
587405b261ecSmrg	nkn.oldMaxKeyCode= xkb->max_key_code;
587505b261ecSmrg	nkn.requestMajor= XkbReqCode;
587605b261ecSmrg	nkn.requestMinor= X_kbGetKbdByName;
587705b261ecSmrg	nkn.changed= XkbNKN_KeycodesMask;
587805b261ecSmrg	if (geom_changed)
587905b261ecSmrg	    nkn.changed|= XkbNKN_GeometryMask;
588005b261ecSmrg	XkbSendNewKeyboardNotify(dev,&nkn);
588105b261ecSmrg    }
58824642e01fSmrg    if ((new!=NULL)&&(new!=xkb)) {
58834642e01fSmrg	XkbFreeKeyboard(new,XkbAllComponentsMask,True);
58844642e01fSmrg	new= NULL;
588505b261ecSmrg    }
588605b261ecSmrg    if (names.keymap)	{ _XkbFree(names.keymap); names.keymap= NULL; }
588705b261ecSmrg    if (names.keycodes)	{ _XkbFree(names.keycodes); names.keycodes= NULL; }
588805b261ecSmrg    if (names.types)	{ _XkbFree(names.types); names.types= NULL; }
588905b261ecSmrg    if (names.compat)	{ _XkbFree(names.compat); names.compat= NULL; }
589005b261ecSmrg    if (names.symbols)	{ _XkbFree(names.symbols); names.symbols= NULL; }
589105b261ecSmrg    if (names.geometry)	{ _XkbFree(names.geometry); names.geometry= NULL; }
589205b261ecSmrg    return client->noClientException;
589305b261ecSmrg}
589405b261ecSmrg
589505b261ecSmrg/***====================================================================***/
589605b261ecSmrg
589705b261ecSmrgstatic int
589805b261ecSmrgComputeDeviceLedInfoSize(	DeviceIntPtr		dev,
589905b261ecSmrg				unsigned int		what,
590005b261ecSmrg				XkbSrvLedInfoPtr	sli)
590105b261ecSmrg{
590205b261ecSmrgint			nNames,nMaps;
590305b261ecSmrgregister unsigned 	n,bit;
590405b261ecSmrg
590505b261ecSmrg    if (sli==NULL)
590605b261ecSmrg	return 0;
590705b261ecSmrg    nNames= nMaps= 0;
590805b261ecSmrg    if ((what&XkbXI_IndicatorNamesMask)==0)
590905b261ecSmrg	sli->namesPresent= 0;
591005b261ecSmrg    if ((what&XkbXI_IndicatorMapsMask)==0)
591105b261ecSmrg	sli->mapsPresent= 0;
591205b261ecSmrg
591305b261ecSmrg    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
591405b261ecSmrg	if (sli->names && sli->names[n]!=None) {
591505b261ecSmrg	    sli->namesPresent|= bit;
591605b261ecSmrg	    nNames++;
591705b261ecSmrg	}
591805b261ecSmrg	if (sli->maps && XkbIM_InUse(&sli->maps[n])) {
591905b261ecSmrg	    sli->mapsPresent|= bit;
592005b261ecSmrg	    nMaps++;
592105b261ecSmrg	}
592205b261ecSmrg    }
592305b261ecSmrg    return (nNames*4)+(nMaps*SIZEOF(xkbIndicatorMapWireDesc));
592405b261ecSmrg}
592505b261ecSmrg
592605b261ecSmrgstatic int
592705b261ecSmrgCheckDeviceLedFBs(	DeviceIntPtr			dev,
592805b261ecSmrg			int				class,
592905b261ecSmrg			int				id,
593005b261ecSmrg			xkbGetDeviceInfoReply *		rep,
593105b261ecSmrg			ClientPtr			client)
593205b261ecSmrg{
593305b261ecSmrgint			nFBs= 0;
593405b261ecSmrgint			length= 0;
593505b261ecSmrgBool			classOk;
593605b261ecSmrg
593705b261ecSmrg    if (class==XkbDfltXIClass) {
593805b261ecSmrg	if (dev->kbdfeed)	class= KbdFeedbackClass;
593905b261ecSmrg	else if (dev->leds)	class= LedFeedbackClass;
594005b261ecSmrg	else {
594105b261ecSmrg	    client->errorValue= _XkbErrCode2(XkbErr_BadClass,class);
594205b261ecSmrg	    return XkbKeyboardErrorCode;
594305b261ecSmrg	}
594405b261ecSmrg    }
594505b261ecSmrg    classOk= False;
594605b261ecSmrg    if ((dev->kbdfeed)&&((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) {
594705b261ecSmrg	KbdFeedbackPtr kf;
594805b261ecSmrg	classOk= True;
594905b261ecSmrg	for (kf= dev->kbdfeed;(kf);kf=kf->next) {
595005b261ecSmrg	    if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=kf->ctrl.id))
595105b261ecSmrg		continue;
595205b261ecSmrg	    nFBs++;
595305b261ecSmrg	    length+= SIZEOF(xkbDeviceLedsWireDesc);
595405b261ecSmrg	    if (!kf->xkb_sli)
595505b261ecSmrg		kf->xkb_sli= XkbAllocSrvLedInfo(dev,kf,NULL,0);
595605b261ecSmrg	    length+= ComputeDeviceLedInfoSize(dev,rep->present,kf->xkb_sli);
595705b261ecSmrg	    if (id!=XkbAllXIIds)
595805b261ecSmrg		break;
595905b261ecSmrg	}
596005b261ecSmrg    }
596105b261ecSmrg    if ((dev->leds)&&((class==LedFeedbackClass)||(class==XkbAllXIClasses))) {
596205b261ecSmrg	LedFeedbackPtr lf;
596305b261ecSmrg	classOk= True;
596405b261ecSmrg	for (lf= dev->leds;(lf);lf=lf->next) {
596505b261ecSmrg	    if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=lf->ctrl.id))
596605b261ecSmrg		continue;
596705b261ecSmrg	    nFBs++;
596805b261ecSmrg	    length+= SIZEOF(xkbDeviceLedsWireDesc);
596905b261ecSmrg	    if (!lf->xkb_sli)
597005b261ecSmrg		lf->xkb_sli= XkbAllocSrvLedInfo(dev,NULL,lf,0);
597105b261ecSmrg	    length+= ComputeDeviceLedInfoSize(dev,rep->present,lf->xkb_sli);
597205b261ecSmrg	    if (id!=XkbAllXIIds)
597305b261ecSmrg		break;
597405b261ecSmrg	}
597505b261ecSmrg    }
597605b261ecSmrg    if (nFBs>0) {
597705b261ecSmrg	if (rep->supported&XkbXI_IndicatorsMask) {
597805b261ecSmrg	    rep->nDeviceLedFBs= nFBs;
597905b261ecSmrg	    rep->length+= (length/4);
598005b261ecSmrg	}
598105b261ecSmrg	return Success;
598205b261ecSmrg    }
598305b261ecSmrg    if (classOk) client->errorValue= _XkbErrCode2(XkbErr_BadId,id);
598405b261ecSmrg    else	 client->errorValue= _XkbErrCode2(XkbErr_BadClass,class);
598505b261ecSmrg    return XkbKeyboardErrorCode;
598605b261ecSmrg}
598705b261ecSmrg
598805b261ecSmrgstatic int
598905b261ecSmrgSendDeviceLedInfo(	XkbSrvLedInfoPtr	sli,
599005b261ecSmrg			ClientPtr		client)
599105b261ecSmrg{
599205b261ecSmrgxkbDeviceLedsWireDesc	wire;
599305b261ecSmrgint			length;
599405b261ecSmrg
599505b261ecSmrg    length= 0;
599605b261ecSmrg    wire.ledClass= 		sli->class;
599705b261ecSmrg    wire.ledID= 		sli->id;
599805b261ecSmrg    wire.namesPresent= 		sli->namesPresent;
599905b261ecSmrg    wire.mapsPresent=   	sli->mapsPresent;
600005b261ecSmrg    wire.physIndicators= 	sli->physIndicators;
600105b261ecSmrg    wire.state=			sli->effectiveState;
600205b261ecSmrg    if (client->swapped) {
600305b261ecSmrg	register int n;
600405b261ecSmrg	swaps(&wire.ledClass,n);
600505b261ecSmrg	swaps(&wire.ledID,n);
600605b261ecSmrg	swapl(&wire.namesPresent,n);
600705b261ecSmrg	swapl(&wire.mapsPresent,n);
600805b261ecSmrg	swapl(&wire.physIndicators,n);
600905b261ecSmrg	swapl(&wire.state,n);
601005b261ecSmrg    }
601105b261ecSmrg    WriteToClient(client,SIZEOF(xkbDeviceLedsWireDesc),(char *)&wire);
601205b261ecSmrg    length+= SIZEOF(xkbDeviceLedsWireDesc);
601305b261ecSmrg    if (sli->namesPresent|sli->mapsPresent) {
601405b261ecSmrg	register unsigned i,bit;
601505b261ecSmrg	if (sli->namesPresent) {
601605b261ecSmrg	    CARD32	awire;
601705b261ecSmrg	    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
601805b261ecSmrg		if (sli->namesPresent&bit) {
601905b261ecSmrg		    awire= (CARD32)sli->names[i];
602005b261ecSmrg		    if (client->swapped) {
602105b261ecSmrg			register int n;
602205b261ecSmrg			swapl(&awire,n);
602305b261ecSmrg		    }
602405b261ecSmrg		    WriteToClient(client,4,(char *)&awire);
602505b261ecSmrg		    length+= 4;
602605b261ecSmrg		}
602705b261ecSmrg	    }
602805b261ecSmrg	}
602905b261ecSmrg	if (sli->mapsPresent) {
603005b261ecSmrg	    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
603105b261ecSmrg		xkbIndicatorMapWireDesc	iwire;
603205b261ecSmrg		if (sli->mapsPresent&bit) {
603305b261ecSmrg		    iwire.flags= 	sli->maps[i].flags;
603405b261ecSmrg		    iwire.whichGroups=	sli->maps[i].which_groups;
603505b261ecSmrg		    iwire.groups=	sli->maps[i].groups;
603605b261ecSmrg		    iwire.whichMods=	sli->maps[i].which_mods;
603705b261ecSmrg		    iwire.mods=		sli->maps[i].mods.mask;
603805b261ecSmrg		    iwire.realMods=	sli->maps[i].mods.real_mods;
603905b261ecSmrg		    iwire.virtualMods=	sli->maps[i].mods.vmods;
604005b261ecSmrg		    iwire.ctrls= 	sli->maps[i].ctrls;
604105b261ecSmrg		    if (client->swapped) {
604205b261ecSmrg			register int n;
604305b261ecSmrg			swaps(&iwire.virtualMods,n);
604405b261ecSmrg			swapl(&iwire.ctrls,n);
604505b261ecSmrg		    }
604605b261ecSmrg		    WriteToClient(client,SIZEOF(xkbIndicatorMapWireDesc),
604705b261ecSmrg								(char *)&iwire);
604805b261ecSmrg		    length+= SIZEOF(xkbIndicatorMapWireDesc);
604905b261ecSmrg		}
605005b261ecSmrg	    }
605105b261ecSmrg	}
605205b261ecSmrg    }
605305b261ecSmrg    return length;
605405b261ecSmrg}
605505b261ecSmrg
605605b261ecSmrgstatic int
605705b261ecSmrgSendDeviceLedFBs(	DeviceIntPtr	dev,
605805b261ecSmrg			int		class,
605905b261ecSmrg			int		id,
606005b261ecSmrg			unsigned	wantLength,
606105b261ecSmrg			ClientPtr	client)
606205b261ecSmrg{
606305b261ecSmrgint			length= 0;
606405b261ecSmrg
606505b261ecSmrg    if (class==XkbDfltXIClass) {
606605b261ecSmrg	if (dev->kbdfeed)	class= KbdFeedbackClass;
606705b261ecSmrg	else if (dev->leds)	class= LedFeedbackClass;
606805b261ecSmrg    }
606905b261ecSmrg    if ((dev->kbdfeed)&&
607005b261ecSmrg	((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) {
607105b261ecSmrg	KbdFeedbackPtr kf;
607205b261ecSmrg	for (kf= dev->kbdfeed;(kf);kf=kf->next) {
607305b261ecSmrg	    if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==kf->ctrl.id)) {
607405b261ecSmrg		length+= SendDeviceLedInfo(kf->xkb_sli,client);
607505b261ecSmrg		if (id!=XkbAllXIIds)
607605b261ecSmrg		    break;
607705b261ecSmrg	    }
607805b261ecSmrg	}
607905b261ecSmrg    }
608005b261ecSmrg    if ((dev->leds)&&
608105b261ecSmrg	((class==LedFeedbackClass)||(class==XkbAllXIClasses))) {
608205b261ecSmrg	LedFeedbackPtr lf;
608305b261ecSmrg	for (lf= dev->leds;(lf);lf=lf->next) {
608405b261ecSmrg	    if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==lf->ctrl.id)) {
608505b261ecSmrg		length+= SendDeviceLedInfo(lf->xkb_sli,client);
608605b261ecSmrg		if (id!=XkbAllXIIds)
608705b261ecSmrg		    break;
608805b261ecSmrg	    }
608905b261ecSmrg	}
609005b261ecSmrg    }
609105b261ecSmrg    if (length==wantLength)
609205b261ecSmrg	 return Success;
609305b261ecSmrg    else return BadLength;
609405b261ecSmrg}
609505b261ecSmrg
609605b261ecSmrgint
609705b261ecSmrgProcXkbGetDeviceInfo(ClientPtr client)
609805b261ecSmrg{
609905b261ecSmrgDeviceIntPtr		dev;
610005b261ecSmrgxkbGetDeviceInfoReply	rep;
610105b261ecSmrgint			status,nDeviceLedFBs;
610205b261ecSmrgunsigned		length,nameLen;
610305b261ecSmrgCARD16			ledClass,ledID;
610405b261ecSmrgunsigned		wanted,supported;
610505b261ecSmrgchar *			str;
610605b261ecSmrg
610705b261ecSmrg    REQUEST(xkbGetDeviceInfoReq);
610805b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq);
610905b261ecSmrg
611005b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
611105b261ecSmrg	return BadAccess;
611205b261ecSmrg
611305b261ecSmrg    wanted= stuff->wanted;
611405b261ecSmrg
61154642e01fSmrg    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
611605b261ecSmrg    CHK_MASK_LEGAL(0x01,wanted,XkbXI_AllDeviceFeaturesMask);
611705b261ecSmrg
611805b261ecSmrg    if ((!dev->button)||((stuff->nBtns<1)&&(!stuff->allBtns)))
611905b261ecSmrg	wanted&= ~XkbXI_ButtonActionsMask;
612005b261ecSmrg    if ((!dev->kbdfeed)&&(!dev->leds))
612105b261ecSmrg	wanted&= ~XkbXI_IndicatorsMask;
612205b261ecSmrg
612305b261ecSmrg    nameLen= XkbSizeCountedString(dev->name);
612405b261ecSmrg    bzero((char *)&rep,SIZEOF(xkbGetDeviceInfoReply));
612505b261ecSmrg    rep.type = X_Reply;
612605b261ecSmrg    rep.deviceID= dev->id;
612705b261ecSmrg    rep.sequenceNumber = client->sequence;
612805b261ecSmrg    rep.length = nameLen/4;
612905b261ecSmrg    rep.present = wanted;
613005b261ecSmrg    rep.supported = XkbXI_AllDeviceFeaturesMask;
613105b261ecSmrg    rep.unsupported = 0;
613205b261ecSmrg    rep.firstBtnWanted = rep.nBtnsWanted = 0;
613305b261ecSmrg    rep.firstBtnRtrn = rep.nBtnsRtrn = 0;
613405b261ecSmrg    if (dev->button)
613505b261ecSmrg	 rep.totalBtns= dev->button->numButtons;
613605b261ecSmrg    else rep.totalBtns= 0;
613705b261ecSmrg    rep.devType=	dev->type;
613805b261ecSmrg    rep.hasOwnState=	(dev->key && dev->key->xkbInfo);
613905b261ecSmrg    rep.nDeviceLedFBs = 0;
614005b261ecSmrg    if (dev->kbdfeed)	rep.dfltKbdFB= dev->kbdfeed->ctrl.id;
614105b261ecSmrg    else		rep.dfltKbdFB= XkbXINone;
614205b261ecSmrg    if (dev->leds)	rep.dfltLedFB= dev->leds->ctrl.id;
614305b261ecSmrg    else		rep.dfltLedFB= XkbXINone;
614405b261ecSmrg
614505b261ecSmrg    ledClass= stuff->ledClass;
614605b261ecSmrg    ledID= stuff->ledID;
614705b261ecSmrg
614805b261ecSmrg    rep.firstBtnWanted= rep.nBtnsWanted= 0;
614905b261ecSmrg    rep.firstBtnRtrn= rep.nBtnsRtrn= 0;
615005b261ecSmrg    if (wanted&XkbXI_ButtonActionsMask) {
615105b261ecSmrg	if (stuff->allBtns) {
615205b261ecSmrg	    stuff->firstBtn= 0;
615305b261ecSmrg	    stuff->nBtns= dev->button->numButtons;
615405b261ecSmrg	}
615505b261ecSmrg
615605b261ecSmrg	if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) {
615705b261ecSmrg	    client->errorValue = _XkbErrCode4(0x02,dev->button->numButtons,
615805b261ecSmrg							stuff->firstBtn,
615905b261ecSmrg							stuff->nBtns);
616005b261ecSmrg	    return BadValue;
616105b261ecSmrg	}
616205b261ecSmrg	else {
616305b261ecSmrg	    rep.firstBtnWanted= stuff->firstBtn;
616405b261ecSmrg	    rep.nBtnsWanted= stuff->nBtns;
616505b261ecSmrg	    if (dev->button->xkb_acts!=NULL) {
616605b261ecSmrg		XkbAction *act;
616705b261ecSmrg		register int i;
616805b261ecSmrg
616905b261ecSmrg		rep.firstBtnRtrn= stuff->firstBtn;
617005b261ecSmrg		rep.nBtnsRtrn= stuff->nBtns;
617105b261ecSmrg		act= &dev->button->xkb_acts[rep.firstBtnWanted];
617205b261ecSmrg		for (i=0;i<rep.nBtnsRtrn;i++,act++) {
617305b261ecSmrg		    if (act->type!=XkbSA_NoAction)
617405b261ecSmrg			break;
617505b261ecSmrg		}
617605b261ecSmrg		rep.firstBtnRtrn+=	i;
617705b261ecSmrg		rep.nBtnsRtrn-=		i;
617805b261ecSmrg		act= &dev->button->xkb_acts[rep.firstBtnRtrn+rep.nBtnsRtrn-1];
617905b261ecSmrg		for (i=0;i<rep.nBtnsRtrn;i++,act--) {
618005b261ecSmrg		    if (act->type!=XkbSA_NoAction)
618105b261ecSmrg			break;
618205b261ecSmrg		}
618305b261ecSmrg		rep.nBtnsRtrn-=		i;
618405b261ecSmrg	    }
618505b261ecSmrg	    rep.length+= (rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc))/4;
618605b261ecSmrg	}
618705b261ecSmrg    }
618805b261ecSmrg
618905b261ecSmrg    if (wanted&XkbXI_IndicatorsMask) {
619005b261ecSmrg	status= CheckDeviceLedFBs(dev,ledClass,ledID,&rep,client);
619105b261ecSmrg	if (status!=Success)
619205b261ecSmrg	    return status;
619305b261ecSmrg    }
619405b261ecSmrg    length= rep.length*4;
619505b261ecSmrg    supported= rep.supported;
619605b261ecSmrg    nDeviceLedFBs = rep.nDeviceLedFBs;
619705b261ecSmrg    if (client->swapped) {
619805b261ecSmrg	register int n;
619905b261ecSmrg	swaps(&rep.sequenceNumber,n);
620005b261ecSmrg	swapl(&rep.length,n);
620105b261ecSmrg	swaps(&rep.present,n);
620205b261ecSmrg	swaps(&rep.supported,n);
620305b261ecSmrg	swaps(&rep.unsupported,n);
620405b261ecSmrg	swaps(&rep.nDeviceLedFBs,n);
620505b261ecSmrg	swapl(&rep.type,n);
620605b261ecSmrg    }
620705b261ecSmrg    WriteToClient(client,SIZEOF(xkbGetDeviceInfoReply), (char *)&rep);
620805b261ecSmrg
62094642e01fSmrg    str= (char*) xalloc(nameLen);
621005b261ecSmrg    if (!str)
621105b261ecSmrg	return BadAlloc;
621205b261ecSmrg    XkbWriteCountedString(str,dev->name,client->swapped);
621305b261ecSmrg    WriteToClient(client,nameLen,str);
62144642e01fSmrg    xfree(str);
621505b261ecSmrg    length-= nameLen;
621605b261ecSmrg
621705b261ecSmrg    if (rep.nBtnsRtrn>0) {
621805b261ecSmrg	int			sz;
621905b261ecSmrg	xkbActionWireDesc *	awire;
622005b261ecSmrg	sz= rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc);
622105b261ecSmrg	awire= (xkbActionWireDesc *)&dev->button->xkb_acts[rep.firstBtnRtrn];
622205b261ecSmrg	WriteToClient(client,sz,(char *)awire);
622305b261ecSmrg	length-= sz;
622405b261ecSmrg    }
622505b261ecSmrg    if (nDeviceLedFBs>0) {
622605b261ecSmrg	status= SendDeviceLedFBs(dev,ledClass,ledID,length,client);
622705b261ecSmrg	if (status!=Success)
622805b261ecSmrg	    return status;
622905b261ecSmrg    }
623005b261ecSmrg    else if (length!=0)  {
62314642e01fSmrg	ErrorF("[xkb] Internal Error!  BadLength in ProcXkbGetDeviceInfo\n");
62324642e01fSmrg	ErrorF("[xkb]                  Wrote %d fewer bytes than expected\n",length);
623305b261ecSmrg	return BadLength;
623405b261ecSmrg    }
623505b261ecSmrg    if (stuff->wanted&(~supported)) {
623605b261ecSmrg	xkbExtensionDeviceNotify ed;
623705b261ecSmrg	bzero((char *)&ed,SIZEOF(xkbExtensionDeviceNotify));
623805b261ecSmrg	ed.ledClass=		ledClass;
623905b261ecSmrg	ed.ledID=		ledID;
624005b261ecSmrg	ed.ledsDefined= 	0;
624105b261ecSmrg	ed.ledState=		0;
624205b261ecSmrg	ed.firstBtn= ed.nBtns=	0;
624305b261ecSmrg	ed.reason=		XkbXI_UnsupportedFeatureMask;
624405b261ecSmrg	ed.supported=		supported;
624505b261ecSmrg	ed.unsupported=		stuff->wanted&(~supported);
624605b261ecSmrg	XkbSendExtensionDeviceNotify(dev,client,&ed);
624705b261ecSmrg    }
624805b261ecSmrg    return client->noClientException;
624905b261ecSmrg}
625005b261ecSmrg
625105b261ecSmrgstatic char *
625205b261ecSmrgCheckSetDeviceIndicators(	char *		wire,
625305b261ecSmrg				DeviceIntPtr	dev,
625405b261ecSmrg				int		num,
625505b261ecSmrg				int *		status_rtrn,
625605b261ecSmrg				ClientPtr	client)
625705b261ecSmrg{
625805b261ecSmrgxkbDeviceLedsWireDesc *	ledWire;
625905b261ecSmrgint			i;
626005b261ecSmrgXkbSrvLedInfoPtr 	sli;
626105b261ecSmrg
626205b261ecSmrg    ledWire= (xkbDeviceLedsWireDesc *)wire;
626305b261ecSmrg    for (i=0;i<num;i++) {
626405b261ecSmrg	if (client->swapped) {
626505b261ecSmrg	   register int n;
626605b261ecSmrg	   swaps(&ledWire->ledClass,n);
626705b261ecSmrg	   swaps(&ledWire->ledID,n);
626805b261ecSmrg	   swapl(&ledWire->namesPresent,n);
626905b261ecSmrg	   swapl(&ledWire->mapsPresent,n);
627005b261ecSmrg	   swapl(&ledWire->physIndicators,n);
627105b261ecSmrg	}
627205b261ecSmrg
627305b261ecSmrg        sli= XkbFindSrvLedInfo(dev,ledWire->ledClass,ledWire->ledID,
627405b261ecSmrg							XkbXI_IndicatorsMask);
627505b261ecSmrg	if (sli!=NULL) {
627605b261ecSmrg	    register int n;
627705b261ecSmrg	    register unsigned bit;
627805b261ecSmrg	    int nMaps,nNames;
627905b261ecSmrg	    CARD32 *atomWire;
628005b261ecSmrg	    xkbIndicatorMapWireDesc *mapWire;
628105b261ecSmrg
628205b261ecSmrg	    nMaps= nNames= 0;
628305b261ecSmrg	    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
628405b261ecSmrg		if (ledWire->namesPresent&bit)
628505b261ecSmrg		    nNames++;
628605b261ecSmrg		if (ledWire->mapsPresent&bit)
628705b261ecSmrg		    nMaps++;
628805b261ecSmrg	    }
628905b261ecSmrg	    atomWire= (CARD32 *)&ledWire[1];
629005b261ecSmrg	    if (nNames>0) {
629105b261ecSmrg		for (n=0;n<nNames;n++) {
629205b261ecSmrg		    if (client->swapped) {
629305b261ecSmrg			register int t;
629405b261ecSmrg			swapl(atomWire,t);
629505b261ecSmrg		    }
629605b261ecSmrg		    CHK_ATOM_OR_NONE3(((Atom)(*atomWire)),client->errorValue,
629705b261ecSmrg							*status_rtrn,NULL);
629805b261ecSmrg		    atomWire++;
629905b261ecSmrg		}
630005b261ecSmrg	    }
630105b261ecSmrg	    mapWire= (xkbIndicatorMapWireDesc *)atomWire;
630205b261ecSmrg	    if (nMaps>0) {
630305b261ecSmrg		for (n=0;n<nMaps;n++) {
630405b261ecSmrg		    if (client->swapped) {
630505b261ecSmrg			register int t;
630605b261ecSmrg			swaps(&mapWire->virtualMods,t);
630705b261ecSmrg			swapl(&mapWire->ctrls,t);
630805b261ecSmrg		    }
630905b261ecSmrg		    CHK_MASK_LEGAL3(0x21,mapWire->whichGroups,
631005b261ecSmrg						XkbIM_UseAnyGroup,
631105b261ecSmrg						client->errorValue,
631205b261ecSmrg						*status_rtrn,NULL);
631305b261ecSmrg		    CHK_MASK_LEGAL3(0x22,mapWire->whichMods,XkbIM_UseAnyMods,
631405b261ecSmrg						client->errorValue,
631505b261ecSmrg						*status_rtrn,NULL);
631605b261ecSmrg		    mapWire++;
631705b261ecSmrg		}
631805b261ecSmrg	    }
631905b261ecSmrg	    ledWire= (xkbDeviceLedsWireDesc *)mapWire;
632005b261ecSmrg	}
632105b261ecSmrg	else {
632205b261ecSmrg	    /* SHOULD NEVER HAPPEN */
632305b261ecSmrg	    return (char *)ledWire;
632405b261ecSmrg	}
632505b261ecSmrg    }
632605b261ecSmrg    return (char *)ledWire;
632705b261ecSmrg}
632805b261ecSmrg
632905b261ecSmrgstatic char *
633005b261ecSmrgSetDeviceIndicators(	char *			wire,
633105b261ecSmrg			DeviceIntPtr		dev,
633205b261ecSmrg			unsigned		changed,
633305b261ecSmrg			int			num,
633405b261ecSmrg			int *			status_rtrn,
633505b261ecSmrg			ClientPtr		client,
633605b261ecSmrg			xkbExtensionDeviceNotify *ev)
633705b261ecSmrg{
633805b261ecSmrgxkbDeviceLedsWireDesc *		ledWire;
633905b261ecSmrgint				i;
634005b261ecSmrgXkbEventCauseRec		cause;
634105b261ecSmrgunsigned			namec,mapc,statec;
634205b261ecSmrgxkbExtensionDeviceNotify	ed;
634305b261ecSmrgXkbChangesRec			changes;
634405b261ecSmrgDeviceIntPtr			kbd;
634505b261ecSmrg
634605b261ecSmrg    bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify));
634705b261ecSmrg    bzero((char *)&changes,sizeof(XkbChangesRec));
634805b261ecSmrg    XkbSetCauseXkbReq(&cause,X_kbSetDeviceInfo,client);
634905b261ecSmrg    ledWire= (xkbDeviceLedsWireDesc *)wire;
635005b261ecSmrg    for (i=0;i<num;i++) {
635105b261ecSmrg	register int			n;
635205b261ecSmrg	register unsigned 		bit;
635305b261ecSmrg	CARD32 *			atomWire;
635405b261ecSmrg	xkbIndicatorMapWireDesc *	mapWire;
635505b261ecSmrg	XkbSrvLedInfoPtr		sli;
635605b261ecSmrg
635705b261ecSmrg	namec= mapc= statec= 0;
635805b261ecSmrg    	sli= XkbFindSrvLedInfo(dev,ledWire->ledClass,ledWire->ledID,
635905b261ecSmrg						XkbXI_IndicatorMapsMask);
636005b261ecSmrg	if (!sli) {
636105b261ecSmrg	    /* SHOULD NEVER HAPPEN!! */
636205b261ecSmrg	    return (char *)ledWire;
636305b261ecSmrg	}
636405b261ecSmrg
636505b261ecSmrg	atomWire= (CARD32 *)&ledWire[1];
636605b261ecSmrg	if (changed&XkbXI_IndicatorNamesMask) {
636705b261ecSmrg	    namec= sli->namesPresent|ledWire->namesPresent;
636805b261ecSmrg	    bzero((char *)sli->names,XkbNumIndicators*sizeof(Atom));
636905b261ecSmrg	}
637005b261ecSmrg	if (ledWire->namesPresent) {
637105b261ecSmrg	    sli->namesPresent= ledWire->namesPresent;
637205b261ecSmrg	    bzero((char *)sli->names,XkbNumIndicators*sizeof(Atom));
637305b261ecSmrg	    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
637405b261ecSmrg		if (ledWire->namesPresent&bit) {
637505b261ecSmrg		     sli->names[n]= (Atom)*atomWire;
637605b261ecSmrg		     if (sli->names[n]==None)
637705b261ecSmrg			ledWire->namesPresent&= ~bit;
637805b261ecSmrg		     atomWire++;
637905b261ecSmrg		}
638005b261ecSmrg	    }
638105b261ecSmrg	}
638205b261ecSmrg	mapWire= (xkbIndicatorMapWireDesc *)atomWire;
638305b261ecSmrg	if (changed&XkbXI_IndicatorMapsMask) {
638405b261ecSmrg	    mapc= sli->mapsPresent|ledWire->mapsPresent;
638505b261ecSmrg	    sli->mapsPresent= ledWire->mapsPresent;
638605b261ecSmrg	    bzero((char*)sli->maps,XkbNumIndicators*sizeof(XkbIndicatorMapRec));
638705b261ecSmrg	}
638805b261ecSmrg	if (ledWire->mapsPresent) {
638905b261ecSmrg	    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
639005b261ecSmrg		if (ledWire->mapsPresent&bit) {
639105b261ecSmrg		    sli->maps[n].flags=		mapWire->flags;
639205b261ecSmrg		    sli->maps[n].which_groups=	mapWire->whichGroups;
639305b261ecSmrg		    sli->maps[n].groups=	mapWire->groups;
639405b261ecSmrg		    sli->maps[n].which_mods=	mapWire->whichMods;
639505b261ecSmrg		    sli->maps[n].mods.mask=	mapWire->mods;
639605b261ecSmrg		    sli->maps[n].mods.real_mods=mapWire->realMods;
639705b261ecSmrg		    sli->maps[n].mods.vmods=	mapWire->virtualMods;
639805b261ecSmrg		    sli->maps[n].ctrls=		mapWire->ctrls;
639905b261ecSmrg		    mapWire++;
640005b261ecSmrg		}
640105b261ecSmrg	    }
640205b261ecSmrg	}
640305b261ecSmrg	if (changed&XkbXI_IndicatorStateMask) {
640405b261ecSmrg	    statec= sli->effectiveState^ledWire->state;
640505b261ecSmrg	    sli->explicitState&= ~statec;
640605b261ecSmrg	    sli->explicitState|= (ledWire->state&statec);
640705b261ecSmrg	}
640805b261ecSmrg	if (namec)
640905b261ecSmrg	    XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause);
641005b261ecSmrg	if (mapc)
641105b261ecSmrg	    XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause);
641205b261ecSmrg	if (statec)
641305b261ecSmrg	    XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause);
641405b261ecSmrg
641505b261ecSmrg	kbd= dev;
641605b261ecSmrg	if ((sli->flags&XkbSLI_HasOwnState)==0)
64174642e01fSmrg	    kbd = inputInfo.keyboard;
641805b261ecSmrg
641905b261ecSmrg	XkbFlushLedEvents(dev,kbd,sli,&ed,&changes,&cause);
642005b261ecSmrg	ledWire= (xkbDeviceLedsWireDesc *)mapWire;
642105b261ecSmrg    }
642205b261ecSmrg    return (char *)ledWire;
642305b261ecSmrg}
642405b261ecSmrg
642505b261ecSmrg
64264642e01fSmrgstatic int
64274642e01fSmrg_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev,
64284642e01fSmrg                  xkbSetDeviceInfoReq *stuff)
64294642e01fSmrg{
64304642e01fSmrg    char                       *wire;
643105b261ecSmrg
643205b261ecSmrg    wire= (char *)&stuff[1];
64334642e01fSmrg    if (stuff->change&XkbXI_ButtonActionsMask) {
643405b261ecSmrg	if (!dev->button) {
643505b261ecSmrg	    client->errorValue = _XkbErrCode2(XkbErr_BadClass,ButtonClass);
643605b261ecSmrg	    return XkbKeyboardErrorCode;
643705b261ecSmrg	}
643805b261ecSmrg	if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) {
643905b261ecSmrg	    client->errorValue= _XkbErrCode4(0x02,stuff->firstBtn,stuff->nBtns,
644005b261ecSmrg						dev->button->numButtons);
644105b261ecSmrg	    return BadMatch;
644205b261ecSmrg	}
644305b261ecSmrg	wire+= (stuff->nBtns*SIZEOF(xkbActionWireDesc));
644405b261ecSmrg    }
644505b261ecSmrg    if (stuff->change&XkbXI_IndicatorsMask) {
644605b261ecSmrg	int status= Success;
644705b261ecSmrg	wire= CheckSetDeviceIndicators(wire,dev,stuff->nDeviceLedFBs,
644805b261ecSmrg							&status,client);
644905b261ecSmrg	if (status!=Success)
645005b261ecSmrg	    return status;
645105b261ecSmrg    }
645205b261ecSmrg    if (((wire-((char *)stuff))/4)!=stuff->length)
645305b261ecSmrg	return BadLength;
645405b261ecSmrg
64554642e01fSmrg    return Success;
64564642e01fSmrg}
64574642e01fSmrg
64584642e01fSmrgstatic int
64594642e01fSmrg_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev,
64604642e01fSmrg                       xkbSetDeviceInfoReq *stuff)
64614642e01fSmrg{
64624642e01fSmrg    char                       *wire;
64634642e01fSmrg    xkbExtensionDeviceNotify    ed;
64644642e01fSmrg
646505b261ecSmrg    bzero((char *)&ed,SIZEOF(xkbExtensionDeviceNotify));
646605b261ecSmrg    ed.deviceID=	dev->id;
646705b261ecSmrg    wire= (char *)&stuff[1];
64684642e01fSmrg    if (stuff->change&XkbXI_ButtonActionsMask) {
646905b261ecSmrg	int			nBtns,sz,i;
647005b261ecSmrg	XkbAction *		acts;
647105b261ecSmrg	DeviceIntPtr		kbd;
647205b261ecSmrg
647305b261ecSmrg	nBtns= dev->button->numButtons;
647405b261ecSmrg	acts= dev->button->xkb_acts;
647505b261ecSmrg	if (acts==NULL) {
647605b261ecSmrg	    acts= _XkbTypedCalloc(nBtns,XkbAction);
647705b261ecSmrg	    if (!acts)
647805b261ecSmrg		return BadAlloc;
647905b261ecSmrg	    dev->button->xkb_acts= acts;
648005b261ecSmrg	}
648105b261ecSmrg	sz= stuff->nBtns*SIZEOF(xkbActionWireDesc);
648205b261ecSmrg	memcpy((char *)&acts[stuff->firstBtn],(char *)wire,sz);
648305b261ecSmrg	wire+= sz;
648405b261ecSmrg	ed.reason|=	XkbXI_ButtonActionsMask;
648505b261ecSmrg	ed.firstBtn=	stuff->firstBtn;
648605b261ecSmrg	ed.nBtns=	stuff->nBtns;
648705b261ecSmrg
648805b261ecSmrg	if (dev->key)	kbd= dev;
64894642e01fSmrg	else		kbd= inputInfo.keyboard;
649005b261ecSmrg	acts= &dev->button->xkb_acts[stuff->firstBtn];
649105b261ecSmrg	for (i=0;i<stuff->nBtns;i++,acts++) {
649205b261ecSmrg	    if (acts->type!=XkbSA_NoAction)
649305b261ecSmrg		XkbSetActionKeyMods(kbd->key->xkbInfo->desc,acts,0);
649405b261ecSmrg	}
649505b261ecSmrg    }
649605b261ecSmrg    if (stuff->change&XkbXI_IndicatorsMask) {
649705b261ecSmrg	int status= Success;
64984642e01fSmrg	wire= SetDeviceIndicators(wire,dev,stuff->change,
64994642e01fSmrg				  stuff->nDeviceLedFBs, &status,client,&ed);
650005b261ecSmrg	if (status!=Success)
650105b261ecSmrg	    return status;
650205b261ecSmrg    }
650305b261ecSmrg    if ((stuff->change)&&(ed.reason))
650405b261ecSmrg	XkbSendExtensionDeviceNotify(dev,client,&ed);
65054642e01fSmrg    return Success;
65064642e01fSmrg}
65074642e01fSmrg
65084642e01fSmrgint
65094642e01fSmrgProcXkbSetDeviceInfo(ClientPtr client)
65104642e01fSmrg{
65114642e01fSmrg    DeviceIntPtr        dev;
65124642e01fSmrg    int                 rc;
65134642e01fSmrg
65144642e01fSmrg    REQUEST(xkbSetDeviceInfoReq);
65154642e01fSmrg    REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq);
65164642e01fSmrg
65174642e01fSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
65184642e01fSmrg	return BadAccess;
65194642e01fSmrg
65204642e01fSmrg    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
65214642e01fSmrg    CHK_MASK_LEGAL(0x01,stuff->change,XkbXI_AllFeaturesMask);
65224642e01fSmrg
65234642e01fSmrg    rc = _XkbSetDeviceInfoCheck(client, dev, stuff);
65244642e01fSmrg
65254642e01fSmrg    if (rc != Success)
65264642e01fSmrg        return rc;
65274642e01fSmrg
65284642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd || stuff->deviceSpec == XkbUseCorePtr)
65294642e01fSmrg    {
65304642e01fSmrg        DeviceIntPtr other;
65314642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
65324642e01fSmrg        {
65334642e01fSmrg            if (((other != dev) && !other->isMaster && (other->u.master == dev)) &&
65344642e01fSmrg                ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
65354642e01fSmrg                (stuff->deviceSpec == XkbUseCorePtr && other->button)))
65364642e01fSmrg            {
65374642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
65384642e01fSmrg                if (rc == Success)
65394642e01fSmrg                {
65404642e01fSmrg                    rc = _XkbSetDeviceInfoCheck(client, other, stuff);
65414642e01fSmrg                    if (rc != Success)
65424642e01fSmrg                        return rc;
65434642e01fSmrg                }
65444642e01fSmrg            }
65454642e01fSmrg        }
65464642e01fSmrg    }
65474642e01fSmrg
65484642e01fSmrg    /* checks done, apply */
65494642e01fSmrg    rc = _XkbSetDeviceInfo(client, dev, stuff);
65504642e01fSmrg    if (rc != Success)
65514642e01fSmrg        return rc;
65524642e01fSmrg
65534642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd || stuff->deviceSpec == XkbUseCorePtr)
65544642e01fSmrg    {
65554642e01fSmrg        DeviceIntPtr other;
65564642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
65574642e01fSmrg        {
65584642e01fSmrg            if (((other != dev) && !other->isMaster && (other->u.master == dev)) &&
65594642e01fSmrg                ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
65604642e01fSmrg                (stuff->deviceSpec == XkbUseCorePtr && other->button)))
65614642e01fSmrg            {
65624642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
65634642e01fSmrg                if (rc == Success)
65644642e01fSmrg                {
65654642e01fSmrg                    rc = _XkbSetDeviceInfo(client, other, stuff);
65664642e01fSmrg                    if (rc != Success)
65674642e01fSmrg                        return rc;
65684642e01fSmrg                }
65694642e01fSmrg            }
65704642e01fSmrg        }
65714642e01fSmrg    }
65724642e01fSmrg
657305b261ecSmrg    return client->noClientException;
657405b261ecSmrg}
657505b261ecSmrg
657605b261ecSmrg/***====================================================================***/
657705b261ecSmrg
657805b261ecSmrgint
657905b261ecSmrgProcXkbSetDebuggingFlags(ClientPtr client)
658005b261ecSmrg{
658105b261ecSmrgCARD32 				newFlags,newCtrls,extraLength;
658205b261ecSmrgxkbSetDebuggingFlagsReply 	rep;
65834642e01fSmrgint rc;
658405b261ecSmrg
658505b261ecSmrg    REQUEST(xkbSetDebuggingFlagsReq);
658605b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq);
658705b261ecSmrg
65884642e01fSmrg    rc = XaceHook(XACE_SERVER_ACCESS, client, DixDebugAccess);
65894642e01fSmrg    if (rc != Success)
65904642e01fSmrg	return rc;
65914642e01fSmrg
659205b261ecSmrg    newFlags=  xkbDebugFlags&(~stuff->affectFlags);
659305b261ecSmrg    newFlags|= (stuff->flags&stuff->affectFlags);
659405b261ecSmrg    newCtrls=  xkbDebugCtrls&(~stuff->affectCtrls);
659505b261ecSmrg    newCtrls|= (stuff->ctrls&stuff->affectCtrls);
659605b261ecSmrg    if (xkbDebugFlags || newFlags || stuff->msgLength) {
65974642e01fSmrg	ErrorF("[xkb] XkbDebug: Setting debug flags to 0x%lx\n",(long)newFlags);
659805b261ecSmrg	if (newCtrls!=xkbDebugCtrls)
65994642e01fSmrg	    ErrorF("[xkb] XkbDebug: Setting debug controls to 0x%lx\n",(long)newCtrls);
660005b261ecSmrg    }
660105b261ecSmrg    extraLength= (stuff->length<<2)-sz_xkbSetDebuggingFlagsReq;
660205b261ecSmrg    if (stuff->msgLength>0) {
660305b261ecSmrg	char *msg;
660405b261ecSmrg	if (extraLength<XkbPaddedSize(stuff->msgLength)) {
66054642e01fSmrg	    ErrorF("[xkb] XkbDebug: msgLength= %d, length= %ld (should be %d)\n",
660605b261ecSmrg			stuff->msgLength,(long)extraLength,
660705b261ecSmrg			XkbPaddedSize(stuff->msgLength));
660805b261ecSmrg	    return BadLength;
660905b261ecSmrg	}
661005b261ecSmrg	msg= (char *)&stuff[1];
661105b261ecSmrg	if (msg[stuff->msgLength-1]!='\0') {
66124642e01fSmrg	    ErrorF("[xkb] XkbDebug: message not null-terminated\n");
661305b261ecSmrg	    return BadValue;
661405b261ecSmrg	}
66154642e01fSmrg	ErrorF("[xkb] XkbDebug: %s\n",msg);
661605b261ecSmrg    }
661705b261ecSmrg    xkbDebugFlags = newFlags;
661805b261ecSmrg    xkbDebugCtrls = newCtrls;
661905b261ecSmrg
662005b261ecSmrg    XkbDisableLockActions= (xkbDebugCtrls&XkbDF_DisableLocks);
662105b261ecSmrg
662205b261ecSmrg    rep.type= X_Reply;
662305b261ecSmrg    rep.length = 0;
662405b261ecSmrg    rep.sequenceNumber = client->sequence;
662505b261ecSmrg    rep.currentFlags = newFlags;
662605b261ecSmrg    rep.currentCtrls = newCtrls;
662705b261ecSmrg    rep.supportedFlags = ~0;
662805b261ecSmrg    rep.supportedCtrls = ~0;
662905b261ecSmrg    if ( client->swapped ) {
663005b261ecSmrg	register int n;
663105b261ecSmrg	swaps(&rep.sequenceNumber, n);
663205b261ecSmrg	swapl(&rep.currentFlags, n);
663305b261ecSmrg	swapl(&rep.currentCtrls, n);
663405b261ecSmrg	swapl(&rep.supportedFlags, n);
663505b261ecSmrg	swapl(&rep.supportedCtrls, n);
663605b261ecSmrg    }
663705b261ecSmrg    WriteToClient(client,SIZEOF(xkbSetDebuggingFlagsReply), (char *)&rep);
663805b261ecSmrg    return client->noClientException;
663905b261ecSmrg}
664005b261ecSmrg
664105b261ecSmrg/***====================================================================***/
664205b261ecSmrg
664305b261ecSmrgstatic int
664405b261ecSmrgProcXkbDispatch (ClientPtr client)
664505b261ecSmrg{
664605b261ecSmrg    REQUEST(xReq);
664705b261ecSmrg    switch (stuff->data)
664805b261ecSmrg    {
664905b261ecSmrg    case X_kbUseExtension:
665005b261ecSmrg	return ProcXkbUseExtension(client);
665105b261ecSmrg    case X_kbSelectEvents:
665205b261ecSmrg	return ProcXkbSelectEvents(client);
665305b261ecSmrg    case X_kbBell:
665405b261ecSmrg	return ProcXkbBell(client);
665505b261ecSmrg    case X_kbGetState:
665605b261ecSmrg	return ProcXkbGetState(client);
665705b261ecSmrg    case X_kbLatchLockState:
665805b261ecSmrg	return ProcXkbLatchLockState(client);
665905b261ecSmrg    case X_kbGetControls:
666005b261ecSmrg	return ProcXkbGetControls(client);
666105b261ecSmrg    case X_kbSetControls:
666205b261ecSmrg	return ProcXkbSetControls(client);
666305b261ecSmrg    case X_kbGetMap:
666405b261ecSmrg	return ProcXkbGetMap(client);
666505b261ecSmrg    case X_kbSetMap:
666605b261ecSmrg	return ProcXkbSetMap(client);
666705b261ecSmrg    case X_kbGetCompatMap:
666805b261ecSmrg	return ProcXkbGetCompatMap(client);
666905b261ecSmrg    case X_kbSetCompatMap:
667005b261ecSmrg	return ProcXkbSetCompatMap(client);
667105b261ecSmrg    case X_kbGetIndicatorState:
667205b261ecSmrg	return ProcXkbGetIndicatorState(client);
667305b261ecSmrg    case X_kbGetIndicatorMap:
667405b261ecSmrg	return ProcXkbGetIndicatorMap(client);
667505b261ecSmrg    case X_kbSetIndicatorMap:
667605b261ecSmrg	return ProcXkbSetIndicatorMap(client);
667705b261ecSmrg    case X_kbGetNamedIndicator:
667805b261ecSmrg	return ProcXkbGetNamedIndicator(client);
667905b261ecSmrg    case X_kbSetNamedIndicator:
668005b261ecSmrg	return ProcXkbSetNamedIndicator(client);
668105b261ecSmrg    case X_kbGetNames:
668205b261ecSmrg	return ProcXkbGetNames(client);
668305b261ecSmrg    case X_kbSetNames:
668405b261ecSmrg	return ProcXkbSetNames(client);
668505b261ecSmrg    case X_kbGetGeometry:
668605b261ecSmrg	return ProcXkbGetGeometry(client);
668705b261ecSmrg    case X_kbSetGeometry:
668805b261ecSmrg	return ProcXkbSetGeometry(client);
668905b261ecSmrg    case X_kbPerClientFlags:
669005b261ecSmrg	return ProcXkbPerClientFlags(client);
669105b261ecSmrg    case X_kbListComponents:
669205b261ecSmrg	return ProcXkbListComponents(client);
669305b261ecSmrg    case X_kbGetKbdByName:
669405b261ecSmrg	return ProcXkbGetKbdByName(client);
669505b261ecSmrg    case X_kbGetDeviceInfo:
669605b261ecSmrg	return ProcXkbGetDeviceInfo(client);
669705b261ecSmrg    case X_kbSetDeviceInfo:
669805b261ecSmrg	return ProcXkbSetDeviceInfo(client);
669905b261ecSmrg    case X_kbSetDebuggingFlags:
670005b261ecSmrg	return ProcXkbSetDebuggingFlags(client);
670105b261ecSmrg    default:
670205b261ecSmrg	return BadRequest;
670305b261ecSmrg    }
670405b261ecSmrg}
670505b261ecSmrg
670605b261ecSmrgstatic int
670705b261ecSmrgXkbClientGone(pointer data,XID id)
670805b261ecSmrg{
670905b261ecSmrg    DevicePtr	pXDev = (DevicePtr)data;
671005b261ecSmrg
671105b261ecSmrg    if (!XkbRemoveResourceClient(pXDev,id)) {
67124642e01fSmrg	ErrorF("[xkb] Internal Error! bad RemoveResourceClient in XkbClientGone\n");
671305b261ecSmrg    }
671405b261ecSmrg    return 1;
671505b261ecSmrg}
671605b261ecSmrg
671705b261ecSmrgvoid
671805b261ecSmrgXkbExtensionInit(void)
671905b261ecSmrg{
672005b261ecSmrg    ExtensionEntry *extEntry;
672105b261ecSmrg
672205b261ecSmrg    if ((extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors,
672305b261ecSmrg				 ProcXkbDispatch, SProcXkbDispatch,
67244642e01fSmrg				 NULL, StandardMinorOpcode))) {
672505b261ecSmrg	XkbReqCode = (unsigned char)extEntry->base;
672605b261ecSmrg	XkbEventBase = (unsigned char)extEntry->eventBase;
672705b261ecSmrg	XkbErrorBase = (unsigned char)extEntry->errorBase;
672805b261ecSmrg	XkbKeyboardErrorCode = XkbErrorBase+XkbKeyboard;
672905b261ecSmrg	RT_XKBCLIENT = CreateNewResourceType(XkbClientGone);
673005b261ecSmrg    }
673105b261ecSmrg    return;
673205b261ecSmrg}
673305b261ecSmrg
673405b261ecSmrg
6735