xkb.c revision 4642e01f
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    }
131405b261ecSmrg    for (nRtrn=i=0;i<rep->nVModMapKeys-1;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];
133305b261ecSmrg    for (i=0;i<rep->nVModMapKeys-1;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) &&
34414642e01fSmrg                (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) == Success))
34424642e01fSmrg            {
34434642e01fSmrg                rc = _XkbCreateIndicatorMap(other, stuff->indicator,
34444642e01fSmrg                                            stuff->ledClass, stuff->ledID,
34454642e01fSmrg                                            &map, &led, TRUE);
34464642e01fSmrg                if (rc != Success || !map)
34474642e01fSmrg                    return rc;
34484642e01fSmrg            }
34494642e01fSmrg        }
34504642e01fSmrg    }
34514642e01fSmrg
34524642e01fSmrg    /* All checks passed, let's do it */
34534642e01fSmrg    rc = _XkbSetNamedIndicator(client, dev, stuff);
34544642e01fSmrg    if (rc != Success)
34554642e01fSmrg        return rc;
34564642e01fSmrg
34574642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd ||
34584642e01fSmrg        stuff->deviceSpec == XkbUseCorePtr)
34594642e01fSmrg    {
34604642e01fSmrg        DeviceIntPtr other;
34614642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
34624642e01fSmrg        {
34634642e01fSmrg            if ((other != dev) && !other->isMaster && (other->u.master == dev) &&
34644642e01fSmrg                (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) == Success))
34654642e01fSmrg            {
34664642e01fSmrg                _XkbSetNamedIndicator(client, other, stuff);
34674642e01fSmrg            }
34684642e01fSmrg        }
34694642e01fSmrg    }
34704642e01fSmrg
347105b261ecSmrg    return client->noClientException;
347205b261ecSmrg}
347305b261ecSmrg
347405b261ecSmrg/***====================================================================***/
347505b261ecSmrg
347605b261ecSmrgstatic CARD32
347705b261ecSmrg_XkbCountAtoms(Atom *atoms,int maxAtoms,int *count)
347805b261ecSmrg{
347905b261ecSmrgregister unsigned int i,bit,nAtoms;
348005b261ecSmrgregister CARD32 atomsPresent;
348105b261ecSmrg
348205b261ecSmrg    for (i=nAtoms=atomsPresent=0,bit=1;i<maxAtoms;i++,bit<<=1) {
348305b261ecSmrg	if (atoms[i]!=None) {
348405b261ecSmrg	    atomsPresent|= bit;
348505b261ecSmrg	    nAtoms++;
348605b261ecSmrg	}
348705b261ecSmrg    }
348805b261ecSmrg    if (count)
348905b261ecSmrg	*count= nAtoms;
349005b261ecSmrg    return atomsPresent;
349105b261ecSmrg}
349205b261ecSmrg
349305b261ecSmrgstatic char *
349405b261ecSmrg_XkbWriteAtoms(char *wire,Atom *atoms,int maxAtoms,int swap)
349505b261ecSmrg{
349605b261ecSmrgregister unsigned int i;
349705b261ecSmrgAtom *atm;
349805b261ecSmrg
349905b261ecSmrg    atm = (Atom *)wire;
350005b261ecSmrg    for (i=0;i<maxAtoms;i++) {
350105b261ecSmrg	if (atoms[i]!=None) {
350205b261ecSmrg	    *atm= atoms[i];
350305b261ecSmrg	    if (swap) {
350405b261ecSmrg		register int n;
350505b261ecSmrg		swapl(atm,n);
350605b261ecSmrg	    }
350705b261ecSmrg	    atm++;
350805b261ecSmrg	}
350905b261ecSmrg    }
351005b261ecSmrg    return (char *)atm;
351105b261ecSmrg}
351205b261ecSmrg
351305b261ecSmrgstatic Status
351405b261ecSmrgXkbComputeGetNamesReplySize(XkbDescPtr xkb,xkbGetNamesReply *rep)
351505b261ecSmrg{
351605b261ecSmrgregister unsigned	which,length;
351705b261ecSmrgregister int		i;
351805b261ecSmrg
351905b261ecSmrg    rep->minKeyCode= xkb->min_key_code;
352005b261ecSmrg    rep->maxKeyCode= xkb->max_key_code;
352105b261ecSmrg    which= rep->which;
352205b261ecSmrg    length= 0;
352305b261ecSmrg    if (xkb->names!=NULL) {
352405b261ecSmrg	 if (which&XkbKeycodesNameMask)		length++;
352505b261ecSmrg	 if (which&XkbGeometryNameMask)		length++;
352605b261ecSmrg	 if (which&XkbSymbolsNameMask)		length++;
352705b261ecSmrg	 if (which&XkbPhysSymbolsNameMask)	length++;
352805b261ecSmrg	 if (which&XkbTypesNameMask)		length++;
352905b261ecSmrg	 if (which&XkbCompatNameMask)		length++;
353005b261ecSmrg    }
353105b261ecSmrg    else which&= ~XkbComponentNamesMask;
353205b261ecSmrg
353305b261ecSmrg    if (xkb->map!=NULL) {
353405b261ecSmrg	if (which&XkbKeyTypeNamesMask)
353505b261ecSmrg	    length+= xkb->map->num_types;
353605b261ecSmrg	rep->nTypes= xkb->map->num_types;
353705b261ecSmrg	if (which&XkbKTLevelNamesMask) {
353805b261ecSmrg	    XkbKeyTypePtr	pType = xkb->map->types;
353905b261ecSmrg	    int			nKTLevels = 0;
354005b261ecSmrg
354105b261ecSmrg	    length+= XkbPaddedSize(xkb->map->num_types)/4;
354205b261ecSmrg	    for (i=0;i<xkb->map->num_types;i++,pType++) {
354305b261ecSmrg		if (pType->level_names!=NULL)
354405b261ecSmrg		    nKTLevels+= pType->num_levels;
354505b261ecSmrg	    }
354605b261ecSmrg	    rep->nKTLevels= nKTLevels;
354705b261ecSmrg	    length+= nKTLevels;
354805b261ecSmrg	}
354905b261ecSmrg    }
355005b261ecSmrg    else {
355105b261ecSmrg	rep->nTypes=    0;
355205b261ecSmrg	rep->nKTLevels= 0;
355305b261ecSmrg	which&= ~(XkbKeyTypeNamesMask|XkbKTLevelNamesMask);
355405b261ecSmrg    }
355505b261ecSmrg
355605b261ecSmrg    rep->minKeyCode= xkb->min_key_code;
355705b261ecSmrg    rep->maxKeyCode= xkb->max_key_code;
355805b261ecSmrg    rep->indicators= 0;
355905b261ecSmrg    rep->virtualMods= 0;
356005b261ecSmrg    rep->groupNames= 0;
356105b261ecSmrg    if (xkb->names!=NULL) {
356205b261ecSmrg	if (which&XkbIndicatorNamesMask) {
356305b261ecSmrg	    int nLeds;
356405b261ecSmrg	    rep->indicators=
356505b261ecSmrg		_XkbCountAtoms(xkb->names->indicators,XkbNumIndicators,&nLeds);
356605b261ecSmrg	    length+= nLeds;
356705b261ecSmrg	    if (nLeds==0)
356805b261ecSmrg		which&= ~XkbIndicatorNamesMask;
356905b261ecSmrg	}
357005b261ecSmrg
357105b261ecSmrg	if (which&XkbVirtualModNamesMask) {
357205b261ecSmrg	    int nVMods;
357305b261ecSmrg	    rep->virtualMods=
357405b261ecSmrg		_XkbCountAtoms(xkb->names->vmods,XkbNumVirtualMods,&nVMods);
357505b261ecSmrg	    length+= nVMods;
357605b261ecSmrg	    if (nVMods==0)
357705b261ecSmrg		which&= ~XkbVirtualModNamesMask;
357805b261ecSmrg	}
357905b261ecSmrg
358005b261ecSmrg	if (which&XkbGroupNamesMask) {
358105b261ecSmrg	    int nGroups;
358205b261ecSmrg	    rep->groupNames=
358305b261ecSmrg		_XkbCountAtoms(xkb->names->groups,XkbNumKbdGroups,&nGroups);
358405b261ecSmrg	    length+= nGroups;
358505b261ecSmrg	    if (nGroups==0)
358605b261ecSmrg		which&= ~XkbGroupNamesMask;
358705b261ecSmrg	}
358805b261ecSmrg
358905b261ecSmrg	if ((which&XkbKeyNamesMask)&&(xkb->names->keys))
359005b261ecSmrg	     length+= rep->nKeys;
359105b261ecSmrg	else which&= ~XkbKeyNamesMask;
359205b261ecSmrg
359305b261ecSmrg	if ((which&XkbKeyAliasesMask)&&
359405b261ecSmrg	    (xkb->names->key_aliases)&&(xkb->names->num_key_aliases>0)) {
359505b261ecSmrg	    rep->nKeyAliases= xkb->names->num_key_aliases;
359605b261ecSmrg	    length+= rep->nKeyAliases*2;
359705b261ecSmrg	}
359805b261ecSmrg	else {
359905b261ecSmrg	    which&= ~XkbKeyAliasesMask;
360005b261ecSmrg	    rep->nKeyAliases= 0;
360105b261ecSmrg	}
360205b261ecSmrg
360305b261ecSmrg	if ((which&XkbRGNamesMask)&&(xkb->names->num_rg>0))
360405b261ecSmrg	     length+= xkb->names->num_rg;
360505b261ecSmrg	else which&= ~XkbRGNamesMask;
360605b261ecSmrg    }
360705b261ecSmrg    else {
360805b261ecSmrg	which&= ~(XkbIndicatorNamesMask|XkbVirtualModNamesMask);
360905b261ecSmrg	which&= ~(XkbGroupNamesMask|XkbKeyNamesMask|XkbKeyAliasesMask);
361005b261ecSmrg	which&= ~XkbRGNamesMask;
361105b261ecSmrg    }
361205b261ecSmrg
361305b261ecSmrg    rep->length= length;
361405b261ecSmrg    rep->which= which;
361505b261ecSmrg    return Success;
361605b261ecSmrg}
361705b261ecSmrg
361805b261ecSmrgstatic int
361905b261ecSmrgXkbSendNames(ClientPtr client,XkbDescPtr xkb,xkbGetNamesReply *rep)
362005b261ecSmrg{
362105b261ecSmrgregister unsigned 	i,length,which;
362205b261ecSmrgchar *			start;
362305b261ecSmrgchar *			desc;
362405b261ecSmrgregister int            n;
362505b261ecSmrg
362605b261ecSmrg    length= rep->length*4;
362705b261ecSmrg    which= rep->which;
362805b261ecSmrg    if (client->swapped) {
362905b261ecSmrg	swaps(&rep->sequenceNumber,n);
363005b261ecSmrg	swapl(&rep->length,n);
363105b261ecSmrg	swapl(&rep->which,n);
363205b261ecSmrg	swaps(&rep->virtualMods,n);
363305b261ecSmrg	swapl(&rep->indicators,n);
363405b261ecSmrg    }
363505b261ecSmrg
36364642e01fSmrg    start = desc = (char *)xalloc(length);
363705b261ecSmrg    if ( !start )
363805b261ecSmrg	return BadAlloc;
363905b261ecSmrg    if (xkb->names) {
364005b261ecSmrg        if (which&XkbKeycodesNameMask) {
364105b261ecSmrg            *((CARD32 *)desc)= xkb->names->keycodes;
364205b261ecSmrg            if (client->swapped) {
364305b261ecSmrg                swapl(desc,n);
364405b261ecSmrg            }
364505b261ecSmrg            desc+= 4;
364605b261ecSmrg        }
364705b261ecSmrg        if (which&XkbGeometryNameMask)  {
364805b261ecSmrg            *((CARD32 *)desc)= xkb->names->geometry;
364905b261ecSmrg            if (client->swapped) {
365005b261ecSmrg                swapl(desc,n);
365105b261ecSmrg            }
365205b261ecSmrg            desc+= 4;
365305b261ecSmrg        }
365405b261ecSmrg        if (which&XkbSymbolsNameMask) {
365505b261ecSmrg            *((CARD32 *)desc)= xkb->names->symbols;
365605b261ecSmrg            if (client->swapped) {
365705b261ecSmrg                swapl(desc,n);
365805b261ecSmrg            }
365905b261ecSmrg            desc+= 4;
366005b261ecSmrg        }
366105b261ecSmrg        if (which&XkbPhysSymbolsNameMask) {
366205b261ecSmrg            register CARD32 *atm= (CARD32 *)desc;
366305b261ecSmrg            atm[0]= (CARD32)xkb->names->phys_symbols;
366405b261ecSmrg            if (client->swapped) {
366505b261ecSmrg                swapl(&atm[0],n);
366605b261ecSmrg            }
366705b261ecSmrg            desc+= 4;
366805b261ecSmrg        }
366905b261ecSmrg        if (which&XkbTypesNameMask) {
367005b261ecSmrg            *((CARD32 *)desc)= (CARD32)xkb->names->types;
367105b261ecSmrg            if (client->swapped) {
367205b261ecSmrg                swapl(desc,n);
367305b261ecSmrg            }
367405b261ecSmrg            desc+= 4;
367505b261ecSmrg        }
367605b261ecSmrg        if (which&XkbCompatNameMask) {
367705b261ecSmrg            *((CARD32 *)desc)= (CARD32)xkb->names->compat;
367805b261ecSmrg            if (client->swapped) {
367905b261ecSmrg                swapl(desc,n);
368005b261ecSmrg            }
368105b261ecSmrg            desc+= 4;
368205b261ecSmrg        }
368305b261ecSmrg        if (which&XkbKeyTypeNamesMask) {
368405b261ecSmrg            register CARD32 *atm= (CARD32 *)desc;
368505b261ecSmrg            register XkbKeyTypePtr type= xkb->map->types;
368605b261ecSmrg
368705b261ecSmrg            for (i=0;i<xkb->map->num_types;i++,atm++,type++) {
368805b261ecSmrg                *atm= (CARD32)type->name;
368905b261ecSmrg                if (client->swapped) {
369005b261ecSmrg                    swapl(atm,n);
369105b261ecSmrg                }
369205b261ecSmrg            }
369305b261ecSmrg            desc= (char *)atm;
369405b261ecSmrg        }
369505b261ecSmrg        if (which&XkbKTLevelNamesMask && xkb->map) {
369605b261ecSmrg            XkbKeyTypePtr type = xkb->map->types;
369705b261ecSmrg            register CARD32 *atm;
369805b261ecSmrg            for (i=0;i<rep->nTypes;i++,type++) {
369905b261ecSmrg                *desc++ = type->num_levels;
370005b261ecSmrg            }
370105b261ecSmrg            desc+= XkbPaddedSize(rep->nTypes)-rep->nTypes;
370205b261ecSmrg
370305b261ecSmrg            atm= (CARD32 *)desc;
370405b261ecSmrg            type = xkb->map->types;
370505b261ecSmrg            for (i=0;i<xkb->map->num_types;i++,type++) {
370605b261ecSmrg                register unsigned l;
370705b261ecSmrg                if (type->level_names) {
370805b261ecSmrg                    for (l=0;l<type->num_levels;l++,atm++) {
370905b261ecSmrg                        *atm= type->level_names[l];
371005b261ecSmrg                        if (client->swapped) {
371105b261ecSmrg                            swapl(atm,n);
371205b261ecSmrg                        }
371305b261ecSmrg                    }
371405b261ecSmrg                    desc+= type->num_levels*4;
371505b261ecSmrg                }
371605b261ecSmrg            }
371705b261ecSmrg        }
371805b261ecSmrg        if (which&XkbIndicatorNamesMask) {
371905b261ecSmrg            desc= _XkbWriteAtoms(desc,xkb->names->indicators,XkbNumIndicators,
372005b261ecSmrg                                 client->swapped);
372105b261ecSmrg        }
372205b261ecSmrg        if (which&XkbVirtualModNamesMask) {
372305b261ecSmrg            desc= _XkbWriteAtoms(desc,xkb->names->vmods,XkbNumVirtualMods,
372405b261ecSmrg                                 client->swapped);
372505b261ecSmrg        }
372605b261ecSmrg        if (which&XkbGroupNamesMask) {
372705b261ecSmrg            desc= _XkbWriteAtoms(desc,xkb->names->groups,XkbNumKbdGroups,
372805b261ecSmrg                                 client->swapped);
372905b261ecSmrg        }
373005b261ecSmrg        if (which&XkbKeyNamesMask) {
373105b261ecSmrg            for (i=0;i<rep->nKeys;i++,desc+= sizeof(XkbKeyNameRec)) {
373205b261ecSmrg                *((XkbKeyNamePtr)desc)= xkb->names->keys[i+rep->firstKey];
373305b261ecSmrg            }
373405b261ecSmrg        }
373505b261ecSmrg        if (which&XkbKeyAliasesMask) {
373605b261ecSmrg            XkbKeyAliasPtr	pAl;
373705b261ecSmrg            pAl= xkb->names->key_aliases;
373805b261ecSmrg            for (i=0;i<rep->nKeyAliases;i++,pAl++,desc+=2*XkbKeyNameLength) {
373905b261ecSmrg                *((XkbKeyAliasPtr)desc)= *pAl;
374005b261ecSmrg            }
374105b261ecSmrg        }
374205b261ecSmrg        if ((which&XkbRGNamesMask)&&(rep->nRadioGroups>0)) {
374305b261ecSmrg            register CARD32	*atm= (CARD32 *)desc;
374405b261ecSmrg            for (i=0;i<rep->nRadioGroups;i++,atm++) {
374505b261ecSmrg                *atm= (CARD32)xkb->names->radio_groups[i];
374605b261ecSmrg                if (client->swapped) {
374705b261ecSmrg                    swapl(atm,n);
374805b261ecSmrg                }
374905b261ecSmrg            }
375005b261ecSmrg            desc+= rep->nRadioGroups*4;
375105b261ecSmrg        }
375205b261ecSmrg    }
375305b261ecSmrg
375405b261ecSmrg    if ((desc-start)!=(length)) {
37554642e01fSmrg	ErrorF("[xkb] BOGUS LENGTH in write names, expected %d, got %ld\n",
375605b261ecSmrg					length, (unsigned long)(desc-start));
375705b261ecSmrg    }
375805b261ecSmrg    WriteToClient(client, SIZEOF(xkbGetNamesReply), (char *)rep);
375905b261ecSmrg    WriteToClient(client, length, start);
37604642e01fSmrg    xfree((char *)start);
376105b261ecSmrg    return client->noClientException;
376205b261ecSmrg}
376305b261ecSmrg
376405b261ecSmrgint
376505b261ecSmrgProcXkbGetNames(ClientPtr client)
376605b261ecSmrg{
376705b261ecSmrg    DeviceIntPtr	dev;
376805b261ecSmrg    XkbDescPtr		xkb;
376905b261ecSmrg    xkbGetNamesReply 	rep;
377005b261ecSmrg
377105b261ecSmrg    REQUEST(xkbGetNamesReq);
377205b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetNamesReq);
377305b261ecSmrg
377405b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
377505b261ecSmrg	return BadAccess;
377605b261ecSmrg
37774642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
377805b261ecSmrg    CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask);
377905b261ecSmrg
378005b261ecSmrg    xkb = dev->key->xkbInfo->desc;
378105b261ecSmrg    rep.type= X_Reply;
378205b261ecSmrg    rep.sequenceNumber= client->sequence;
378305b261ecSmrg    rep.length = 0;
378405b261ecSmrg    rep.deviceID = dev->id;
378505b261ecSmrg    rep.which = stuff->which;
378605b261ecSmrg    rep.nTypes = xkb->map->num_types;
378705b261ecSmrg    rep.firstKey = xkb->min_key_code;
378805b261ecSmrg    rep.nKeys = XkbNumKeys(xkb);
378905b261ecSmrg    if (xkb->names!=NULL) {
379005b261ecSmrg	rep.nKeyAliases= xkb->names->num_key_aliases;
379105b261ecSmrg	rep.nRadioGroups = xkb->names->num_rg;
379205b261ecSmrg    }
379305b261ecSmrg    else {
379405b261ecSmrg	rep.nKeyAliases= rep.nRadioGroups= 0;
379505b261ecSmrg    }
379605b261ecSmrg    XkbComputeGetNamesReplySize(xkb,&rep);
379705b261ecSmrg    return XkbSendNames(client,xkb,&rep);
379805b261ecSmrg}
379905b261ecSmrg
380005b261ecSmrg/***====================================================================***/
380105b261ecSmrg
380205b261ecSmrgstatic CARD32 *
380305b261ecSmrg_XkbCheckAtoms(CARD32 *wire,int nAtoms,int swapped,Atom *pError)
380405b261ecSmrg{
380505b261ecSmrgregister int i;
380605b261ecSmrg
380705b261ecSmrg    for (i=0;i<nAtoms;i++,wire++) {
380805b261ecSmrg	if (swapped) {
380905b261ecSmrg	    register int n;
381005b261ecSmrg	    swapl(wire,n);
381105b261ecSmrg	}
381205b261ecSmrg	if ((((Atom)*wire)!=None)&&(!ValidAtom((Atom)*wire))) {
381305b261ecSmrg	    *pError= ((Atom)*wire);
381405b261ecSmrg	    return NULL;
381505b261ecSmrg	}
381605b261ecSmrg    }
381705b261ecSmrg    return wire;
381805b261ecSmrg}
381905b261ecSmrg
382005b261ecSmrgstatic CARD32 *
382105b261ecSmrg_XkbCheckMaskedAtoms(CARD32 *wire,int nAtoms,CARD32 present,int swapped,
382205b261ecSmrg								Atom *pError)
382305b261ecSmrg{
382405b261ecSmrgregister unsigned i,bit;
382505b261ecSmrg
382605b261ecSmrg    for (i=0,bit=1;(i<nAtoms)&&(present);i++,bit<<=1) {
382705b261ecSmrg	if ((present&bit)==0)
382805b261ecSmrg	    continue;
382905b261ecSmrg	if (swapped) {
383005b261ecSmrg	    register int n;
383105b261ecSmrg	    swapl(wire,n);
383205b261ecSmrg	}
383305b261ecSmrg	if ((((Atom)*wire)!=None)&&(!ValidAtom(((Atom)*wire)))) {
383405b261ecSmrg	    *pError= (Atom)*wire;
383505b261ecSmrg	    return NULL;
383605b261ecSmrg	}
383705b261ecSmrg	wire++;
383805b261ecSmrg    }
383905b261ecSmrg    return wire;
384005b261ecSmrg}
384105b261ecSmrg
384205b261ecSmrgstatic Atom *
384305b261ecSmrg_XkbCopyMaskedAtoms(	Atom	*wire,
384405b261ecSmrg    			Atom	*dest,
384505b261ecSmrg			int   	 nAtoms,
384605b261ecSmrg			CARD32	 present)
384705b261ecSmrg{
384805b261ecSmrgregister int i,bit;
384905b261ecSmrg
385005b261ecSmrg    for (i=0,bit=1;(i<nAtoms)&&(present);i++,bit<<=1) {
385105b261ecSmrg	if ((present&bit)==0)
385205b261ecSmrg	    continue;
385305b261ecSmrg	dest[i]= *wire++;
385405b261ecSmrg    }
385505b261ecSmrg    return wire;
385605b261ecSmrg}
385705b261ecSmrg
385805b261ecSmrgstatic Bool
385905b261ecSmrg_XkbCheckTypeName(Atom name,int typeNdx)
386005b261ecSmrg{
386105b261ecSmrgchar *	str;
386205b261ecSmrg
386305b261ecSmrg    str= NameForAtom(name);
386405b261ecSmrg    if ((strcmp(str,"ONE_LEVEL")==0)||(strcmp(str,"TWO_LEVEL")==0)||
386505b261ecSmrg	(strcmp(str,"ALPHABETIC")==0)||(strcmp(str,"KEYPAD")==0))
386605b261ecSmrg	return False;
386705b261ecSmrg    return True;
386805b261ecSmrg}
386905b261ecSmrg
38704642e01fSmrg/**
38714642e01fSmrg * Check the device-dependent data in the request against the device. Returns
38724642e01fSmrg * Success, or the appropriate error code.
38734642e01fSmrg */
38744642e01fSmrgstatic int
38754642e01fSmrg_XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
38764642e01fSmrg                  xkbSetNamesReq *stuff, CARD32 *data)
387705b261ecSmrg{
387805b261ecSmrg    XkbDescRec		*xkb;
387905b261ecSmrg    XkbNamesRec		*names;
388005b261ecSmrg    CARD32		*tmp;
388105b261ecSmrg    Atom		 bad;
388205b261ecSmrg
38834642e01fSmrg    tmp = data;
38844642e01fSmrg    xkb = dev->key->xkbInfo->desc;
38854642e01fSmrg    names = xkb->names;
38864642e01fSmrg
38874642e01fSmrg
38884642e01fSmrg    if (stuff->which & XkbKeyTypeNamesMask) {
38894642e01fSmrg        int i;
38904642e01fSmrg        CARD32	*old;
38914642e01fSmrg        if ( stuff->nTypes<1 ) {
38924642e01fSmrg            client->errorValue = _XkbErrCode2(0x02,stuff->nTypes);
38934642e01fSmrg            return BadValue;
38944642e01fSmrg        }
38954642e01fSmrg        if ((unsigned)(stuff->firstType+stuff->nTypes-1)>=xkb->map->num_types) {
38964642e01fSmrg            client->errorValue = _XkbErrCode4(0x03,stuff->firstType,
38974642e01fSmrg                    stuff->nTypes,
38984642e01fSmrg                    xkb->map->num_types);
38994642e01fSmrg            return BadValue;
39004642e01fSmrg        }
39014642e01fSmrg        if (((unsigned)stuff->firstType)<=XkbLastRequiredType) {
39024642e01fSmrg            client->errorValue = _XkbErrCode2(0x04,stuff->firstType);
39034642e01fSmrg            return BadAccess;
39044642e01fSmrg        }
39054642e01fSmrg        old= tmp;
39064642e01fSmrg        tmp= _XkbCheckAtoms(tmp,stuff->nTypes,client->swapped,&bad);
39074642e01fSmrg        if (!tmp) {
39084642e01fSmrg            client->errorValue= bad;
39094642e01fSmrg            return BadAtom;
39104642e01fSmrg        }
39114642e01fSmrg        for (i=0;i<stuff->nTypes;i++,old++) {
39124642e01fSmrg            if (!_XkbCheckTypeName((Atom)*old,stuff->firstType+i))
39134642e01fSmrg                client->errorValue= _XkbErrCode2(0x05,i);
39144642e01fSmrg        }
39154642e01fSmrg    }
39164642e01fSmrg    if (stuff->which&XkbKTLevelNamesMask) {
39174642e01fSmrg        unsigned i;
39184642e01fSmrg        XkbKeyTypePtr	type;
39194642e01fSmrg        CARD8 *		width;
39204642e01fSmrg        if ( stuff->nKTLevels<1 ) {
39214642e01fSmrg            client->errorValue = _XkbErrCode2(0x05,stuff->nKTLevels);
39224642e01fSmrg            return BadValue;
39234642e01fSmrg        }
39244642e01fSmrg        if ((unsigned)(stuff->firstKTLevel+stuff->nKTLevels-1)>=
39254642e01fSmrg                xkb->map->num_types) {
39264642e01fSmrg            client->errorValue = _XkbErrCode4(0x06,stuff->firstKTLevel,
39274642e01fSmrg                    stuff->nKTLevels,xkb->map->num_types);
39284642e01fSmrg            return BadValue;
39294642e01fSmrg        }
39304642e01fSmrg        width = (CARD8 *)tmp;
39314642e01fSmrg        tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels));
39324642e01fSmrg        type = &xkb->map->types[stuff->firstKTLevel];
39334642e01fSmrg        for (i=0;i<stuff->nKTLevels;i++,type++) {
39344642e01fSmrg            if (width[i]==0)
39354642e01fSmrg                continue;
39364642e01fSmrg            else if (width[i]!=type->num_levels) {
39374642e01fSmrg                client->errorValue= _XkbErrCode4(0x07,i+stuff->firstKTLevel,
39384642e01fSmrg                        type->num_levels,width[i]);
39394642e01fSmrg                return BadMatch;
39404642e01fSmrg            }
39414642e01fSmrg            tmp= _XkbCheckAtoms(tmp,width[i],client->swapped,&bad);
39424642e01fSmrg            if (!tmp) {
39434642e01fSmrg                client->errorValue= bad;
39444642e01fSmrg                return BadAtom;
39454642e01fSmrg            }
39464642e01fSmrg        }
39474642e01fSmrg    }
39484642e01fSmrg    if (stuff->which&XkbIndicatorNamesMask) {
39494642e01fSmrg        if (stuff->indicators==0) {
39504642e01fSmrg            client->errorValue= 0x08;
39514642e01fSmrg            return BadMatch;
39524642e01fSmrg        }
39534642e01fSmrg        tmp= _XkbCheckMaskedAtoms(tmp,XkbNumIndicators,stuff->indicators,
39544642e01fSmrg                client->swapped,&bad);
39554642e01fSmrg        if (!tmp) {
39564642e01fSmrg            client->errorValue= bad;
39574642e01fSmrg            return BadAtom;
39584642e01fSmrg        }
39594642e01fSmrg    }
39604642e01fSmrg    if (stuff->which&XkbVirtualModNamesMask) {
39614642e01fSmrg        if (stuff->virtualMods==0) {
39624642e01fSmrg            client->errorValue= 0x09;
39634642e01fSmrg            return BadMatch;
39644642e01fSmrg        }
39654642e01fSmrg        tmp= _XkbCheckMaskedAtoms(tmp,XkbNumVirtualMods,
39664642e01fSmrg                (CARD32)stuff->virtualMods,
39674642e01fSmrg                client->swapped,&bad);
39684642e01fSmrg        if (!tmp) {
39694642e01fSmrg            client->errorValue = bad;
39704642e01fSmrg            return BadAtom;
39714642e01fSmrg        }
39724642e01fSmrg    }
39734642e01fSmrg    if (stuff->which&XkbGroupNamesMask) {
39744642e01fSmrg        if (stuff->groupNames==0) {
39754642e01fSmrg            client->errorValue= 0x0a;
39764642e01fSmrg            return BadMatch;
39774642e01fSmrg        }
39784642e01fSmrg        tmp= _XkbCheckMaskedAtoms(tmp,XkbNumKbdGroups,
39794642e01fSmrg                (CARD32)stuff->groupNames,
39804642e01fSmrg                client->swapped,&bad);
39814642e01fSmrg        if (!tmp) {
39824642e01fSmrg            client->errorValue = bad;
39834642e01fSmrg            return BadAtom;
39844642e01fSmrg        }
39854642e01fSmrg    }
39864642e01fSmrg    if (stuff->which&XkbKeyNamesMask) {
39874642e01fSmrg        if (stuff->firstKey<(unsigned)xkb->min_key_code) {
39884642e01fSmrg            client->errorValue= _XkbErrCode3(0x0b,xkb->min_key_code,
39894642e01fSmrg                    stuff->firstKey);
39904642e01fSmrg            return BadValue;
39914642e01fSmrg        }
39924642e01fSmrg        if (((unsigned)(stuff->firstKey+stuff->nKeys-1)>xkb->max_key_code)||
39934642e01fSmrg                (stuff->nKeys<1)) {
39944642e01fSmrg            client->errorValue= _XkbErrCode4(0x0c,xkb->max_key_code,
39954642e01fSmrg                    stuff->firstKey,stuff->nKeys);
39964642e01fSmrg            return BadValue;
39974642e01fSmrg        }
39984642e01fSmrg        tmp+= stuff->nKeys;
39994642e01fSmrg    }
40004642e01fSmrg    if ((stuff->which&XkbKeyAliasesMask)&&(stuff->nKeyAliases>0)) {
40014642e01fSmrg        tmp+= stuff->nKeyAliases*2;
40024642e01fSmrg    }
40034642e01fSmrg    if (stuff->which&XkbRGNamesMask) {
40044642e01fSmrg        if ( stuff->nRadioGroups<1 ) {
40054642e01fSmrg            client->errorValue= _XkbErrCode2(0x0d,stuff->nRadioGroups);
40064642e01fSmrg            return BadValue;
40074642e01fSmrg        }
40084642e01fSmrg        tmp= _XkbCheckAtoms(tmp,stuff->nRadioGroups,client->swapped,&bad);
40094642e01fSmrg        if (!tmp) {
40104642e01fSmrg            client->errorValue= bad;
40114642e01fSmrg            return BadAtom;
40124642e01fSmrg        }
40134642e01fSmrg    }
40144642e01fSmrg    if ((tmp-((CARD32 *)stuff))!=stuff->length) {
40154642e01fSmrg        client->errorValue = stuff->length;
40164642e01fSmrg        return BadLength;
40174642e01fSmrg    }
40184642e01fSmrg
40194642e01fSmrg
40204642e01fSmrg
40214642e01fSmrg    return Success;
40224642e01fSmrg}
40234642e01fSmrg
40244642e01fSmrgstatic int
40254642e01fSmrg_XkbSetNames(ClientPtr client, DeviceIntPtr dev, xkbSetNamesReq *stuff)
40264642e01fSmrg{
40274642e01fSmrg    XkbDescRec		*xkb;
40284642e01fSmrg    XkbNamesRec		*names;
40294642e01fSmrg    CARD32		*tmp;
40304642e01fSmrg    xkbNamesNotify	 nn;
40314642e01fSmrg
40324642e01fSmrg    tmp = (CARD32 *)&stuff[1];
40334642e01fSmrg    xkb = dev->key->xkbInfo->desc;
40344642e01fSmrg    names = xkb->names;
40354642e01fSmrg
40364642e01fSmrg    if (XkbAllocNames(xkb,stuff->which,stuff->nRadioGroups,
40374642e01fSmrg                stuff->nKeyAliases)!=Success) {
40384642e01fSmrg        return BadAlloc;
40394642e01fSmrg    }
40404642e01fSmrg
40414642e01fSmrg    bzero(&nn,sizeof(xkbNamesNotify));
40424642e01fSmrg    nn.changed= stuff->which;
40434642e01fSmrg    tmp = (CARD32 *)&stuff[1];
40444642e01fSmrg    if (stuff->which&XkbKeycodesNameMask)
40454642e01fSmrg        names->keycodes= *tmp++;
40464642e01fSmrg    if (stuff->which&XkbGeometryNameMask)
40474642e01fSmrg        names->geometry= *tmp++;
40484642e01fSmrg    if (stuff->which&XkbSymbolsNameMask)
40494642e01fSmrg        names->symbols= *tmp++;
40504642e01fSmrg    if (stuff->which&XkbPhysSymbolsNameMask)
40514642e01fSmrg        names->phys_symbols= *tmp++;
40524642e01fSmrg    if (stuff->which&XkbTypesNameMask)
40534642e01fSmrg        names->types= *tmp++;
40544642e01fSmrg    if (stuff->which&XkbCompatNameMask)
40554642e01fSmrg        names->compat= *tmp++;
40564642e01fSmrg    if ((stuff->which&XkbKeyTypeNamesMask)&&(stuff->nTypes>0)) {
40574642e01fSmrg        register unsigned i;
40584642e01fSmrg        register XkbKeyTypePtr type;
40594642e01fSmrg
40604642e01fSmrg        type= &xkb->map->types[stuff->firstType];
40614642e01fSmrg        for (i=0;i<stuff->nTypes;i++,type++) {
40624642e01fSmrg            type->name= *tmp++;
40634642e01fSmrg        }
40644642e01fSmrg        nn.firstType= stuff->firstType;
40654642e01fSmrg        nn.nTypes= stuff->nTypes;
40664642e01fSmrg    }
40674642e01fSmrg    if (stuff->which&XkbKTLevelNamesMask) {
40684642e01fSmrg        register XkbKeyTypePtr	type;
40694642e01fSmrg        register unsigned i;
40704642e01fSmrg        CARD8 *width;
40714642e01fSmrg
40724642e01fSmrg        width = (CARD8 *)tmp;
40734642e01fSmrg        tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels));
40744642e01fSmrg        type= &xkb->map->types[stuff->firstKTLevel];
40754642e01fSmrg        for (i=0;i<stuff->nKTLevels;i++,type++) {
40764642e01fSmrg            if (width[i]>0) {
40774642e01fSmrg                if (type->level_names) {
40784642e01fSmrg                    register unsigned n;
40794642e01fSmrg                    for (n=0;n<width[i];n++) {
40804642e01fSmrg                        type->level_names[n]= tmp[n];
40814642e01fSmrg                    }
40824642e01fSmrg                }
40834642e01fSmrg                tmp+= width[i];
40844642e01fSmrg            }
40854642e01fSmrg        }
40864642e01fSmrg        nn.firstLevelName= 0;
40874642e01fSmrg        nn.nLevelNames= stuff->nTypes;
40884642e01fSmrg    }
40894642e01fSmrg    if (stuff->which&XkbIndicatorNamesMask) {
40904642e01fSmrg        tmp= _XkbCopyMaskedAtoms(tmp,names->indicators,XkbNumIndicators,
40914642e01fSmrg                stuff->indicators);
40924642e01fSmrg        nn.changedIndicators= stuff->indicators;
40934642e01fSmrg    }
40944642e01fSmrg    if (stuff->which&XkbVirtualModNamesMask) {
40954642e01fSmrg        tmp= _XkbCopyMaskedAtoms(tmp,names->vmods,XkbNumVirtualMods,
40964642e01fSmrg                stuff->virtualMods);
40974642e01fSmrg        nn.changedVirtualMods= stuff->virtualMods;
40984642e01fSmrg    }
40994642e01fSmrg    if (stuff->which&XkbGroupNamesMask) {
41004642e01fSmrg        tmp= _XkbCopyMaskedAtoms(tmp,names->groups,XkbNumKbdGroups,
41014642e01fSmrg                stuff->groupNames);
41024642e01fSmrg        nn.changedVirtualMods= stuff->groupNames;
41034642e01fSmrg    }
41044642e01fSmrg    if (stuff->which&XkbKeyNamesMask) {
41054642e01fSmrg        memcpy((char*)&names->keys[stuff->firstKey],(char *)tmp,
41064642e01fSmrg                stuff->nKeys*XkbKeyNameLength);
41074642e01fSmrg        tmp+= stuff->nKeys;
41084642e01fSmrg        nn.firstKey= stuff->firstKey;
41094642e01fSmrg        nn.nKeys= stuff->nKeys;
41104642e01fSmrg    }
41114642e01fSmrg    if (stuff->which&XkbKeyAliasesMask) {
41124642e01fSmrg        if (stuff->nKeyAliases>0) {
41134642e01fSmrg            register int na= stuff->nKeyAliases;
41144642e01fSmrg            if (XkbAllocNames(xkb,XkbKeyAliasesMask,0,na)!=Success)
41154642e01fSmrg                return BadAlloc;
41164642e01fSmrg            memcpy((char *)names->key_aliases,(char *)tmp,
41174642e01fSmrg                    stuff->nKeyAliases*sizeof(XkbKeyAliasRec));
41184642e01fSmrg            tmp+= stuff->nKeyAliases*2;
41194642e01fSmrg        }
41204642e01fSmrg        else if (names->key_aliases!=NULL) {
41214642e01fSmrg            _XkbFree(names->key_aliases);
41224642e01fSmrg            names->key_aliases= NULL;
41234642e01fSmrg            names->num_key_aliases= 0;
41244642e01fSmrg        }
41254642e01fSmrg        nn.nAliases= names->num_key_aliases;
41264642e01fSmrg    }
41274642e01fSmrg    if (stuff->which&XkbRGNamesMask) {
41284642e01fSmrg        if (stuff->nRadioGroups>0) {
41294642e01fSmrg            register unsigned i,nrg;
41304642e01fSmrg            nrg= stuff->nRadioGroups;
41314642e01fSmrg            if (XkbAllocNames(xkb,XkbRGNamesMask,nrg,0)!=Success)
41324642e01fSmrg                return BadAlloc;
41334642e01fSmrg
41344642e01fSmrg            for (i=0;i<stuff->nRadioGroups;i++) {
41354642e01fSmrg                names->radio_groups[i]= tmp[i];
41364642e01fSmrg            }
41374642e01fSmrg            tmp+= stuff->nRadioGroups;
41384642e01fSmrg        }
41394642e01fSmrg        else if (names->radio_groups) {
41404642e01fSmrg            _XkbFree(names->radio_groups);
41414642e01fSmrg            names->radio_groups= NULL;
41424642e01fSmrg            names->num_rg= 0;
41434642e01fSmrg        }
41444642e01fSmrg        nn.nRadioGroups= names->num_rg;
41454642e01fSmrg    }
41464642e01fSmrg    if (nn.changed) {
41474642e01fSmrg        Bool needExtEvent;
41484642e01fSmrg        needExtEvent= (nn.changed&XkbIndicatorNamesMask)!=0;
41494642e01fSmrg        XkbSendNamesNotify(dev,&nn);
41504642e01fSmrg        if (needExtEvent) {
41514642e01fSmrg            XkbSrvLedInfoPtr		sli;
41524642e01fSmrg            xkbExtensionDeviceNotify	edev;
41534642e01fSmrg            register int		i;
41544642e01fSmrg            register unsigned		bit;
41554642e01fSmrg
41564642e01fSmrg            sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,
41574642e01fSmrg                    XkbXI_IndicatorsMask);
41584642e01fSmrg            sli->namesPresent= 0;
41594642e01fSmrg            for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
41604642e01fSmrg                if (names->indicators[i]!=None)
41614642e01fSmrg                    sli->namesPresent|= bit;
41624642e01fSmrg            }
41634642e01fSmrg            bzero(&edev,sizeof(xkbExtensionDeviceNotify));
41644642e01fSmrg            edev.reason=	XkbXI_IndicatorNamesMask;
41654642e01fSmrg            edev.ledClass=	KbdFeedbackClass;
41664642e01fSmrg            edev.ledID=		dev->kbdfeed->ctrl.id;
41674642e01fSmrg            edev.ledsDefined= 	sli->namesPresent|sli->mapsPresent;
41684642e01fSmrg            edev.ledState=	sli->effectiveState;
41694642e01fSmrg            edev.firstBtn=	0;
41704642e01fSmrg            edev.nBtns=		0;
41714642e01fSmrg            edev.supported=	XkbXI_AllFeaturesMask;
41724642e01fSmrg            edev.unsupported=	0;
41734642e01fSmrg            XkbSendExtensionDeviceNotify(dev,client,&edev);
41744642e01fSmrg        }
41754642e01fSmrg    }
41764642e01fSmrg    return Success;
41774642e01fSmrg}
41784642e01fSmrg
41794642e01fSmrgint
41804642e01fSmrgProcXkbSetNames(ClientPtr client)
41814642e01fSmrg{
41824642e01fSmrg    DeviceIntPtr	 dev;
41834642e01fSmrg    CARD32		*tmp;
41844642e01fSmrg    Atom                 bad;
41854642e01fSmrg    int                  rc;
41864642e01fSmrg
418705b261ecSmrg    REQUEST(xkbSetNamesReq);
418805b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetNamesReq);
418905b261ecSmrg
419005b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
419105b261ecSmrg	return BadAccess;
419205b261ecSmrg
41934642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
419405b261ecSmrg    CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask);
419505b261ecSmrg
41964642e01fSmrg    /* check device-independent stuff */
419705b261ecSmrg    tmp = (CARD32 *)&stuff[1];
419805b261ecSmrg
419905b261ecSmrg    if (stuff->which&XkbKeycodesNameMask) {
420005b261ecSmrg	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
420105b261ecSmrg	if (!tmp) {
420205b261ecSmrg	    client->errorValue = bad;
420305b261ecSmrg	    return BadAtom;
420405b261ecSmrg	}
420505b261ecSmrg    }
420605b261ecSmrg    if (stuff->which&XkbGeometryNameMask) {
420705b261ecSmrg	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
420805b261ecSmrg	if (!tmp) {
420905b261ecSmrg	    client->errorValue = bad;
421005b261ecSmrg	    return BadAtom;
421105b261ecSmrg	}
421205b261ecSmrg    }
421305b261ecSmrg    if (stuff->which&XkbSymbolsNameMask) {
421405b261ecSmrg	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
421505b261ecSmrg	if (!tmp) {
421605b261ecSmrg	    client->errorValue = bad;
421705b261ecSmrg	    return BadAtom;
421805b261ecSmrg	}
421905b261ecSmrg    }
422005b261ecSmrg    if (stuff->which&XkbPhysSymbolsNameMask) {
422105b261ecSmrg	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
422205b261ecSmrg	if (!tmp) {
422305b261ecSmrg	    client->errorValue= bad;
422405b261ecSmrg	    return BadAtom;
422505b261ecSmrg	}
422605b261ecSmrg    }
422705b261ecSmrg    if (stuff->which&XkbTypesNameMask) {
422805b261ecSmrg	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
422905b261ecSmrg	if (!tmp) {
423005b261ecSmrg	    client->errorValue = bad;
423105b261ecSmrg	    return BadAtom;
423205b261ecSmrg	}
423305b261ecSmrg    }
423405b261ecSmrg    if (stuff->which&XkbCompatNameMask) {
423505b261ecSmrg	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
423605b261ecSmrg	if (!tmp) {
423705b261ecSmrg	    client->errorValue = bad;
423805b261ecSmrg	    return BadAtom;
423905b261ecSmrg	}
424005b261ecSmrg    }
42414642e01fSmrg
42424642e01fSmrg    /* start of device-dependent tests */
42434642e01fSmrg    rc = _XkbSetNamesCheck(client, dev, stuff, tmp);
42444642e01fSmrg    if (rc != Success)
42454642e01fSmrg        return rc;
42464642e01fSmrg
42474642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd)
42484642e01fSmrg    {
42494642e01fSmrg        DeviceIntPtr other;
42504642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
42514642e01fSmrg        {
42524642e01fSmrg            if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
42534642e01fSmrg            {
42544642e01fSmrg
42554642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
42564642e01fSmrg                if (rc == Success)
42574642e01fSmrg                {
42584642e01fSmrg                    rc = _XkbSetNamesCheck(client, other, stuff, tmp);
42594642e01fSmrg                    if (rc != Success)
42604642e01fSmrg                        return rc;
42614642e01fSmrg                }
42624642e01fSmrg            }
42634642e01fSmrg        }
426405b261ecSmrg    }
426505b261ecSmrg
426605b261ecSmrg    /* everything is okay -- update names */
426705b261ecSmrg
42684642e01fSmrg    rc = _XkbSetNames(client, dev, stuff);
42694642e01fSmrg    if (rc != Success)
42704642e01fSmrg        return rc;
427105b261ecSmrg
42724642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd)
42734642e01fSmrg    {
42744642e01fSmrg        DeviceIntPtr other;
42754642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
42764642e01fSmrg        {
42774642e01fSmrg            if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
42784642e01fSmrg            {
42794642e01fSmrg
42804642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
42814642e01fSmrg                if (rc == Success)
42824642e01fSmrg                    _XkbSetNames(client, other, stuff);
42834642e01fSmrg            }
42844642e01fSmrg        }
428505b261ecSmrg    }
42864642e01fSmrg
42874642e01fSmrg    /* everything is okay -- update names */
42884642e01fSmrg
428905b261ecSmrg    return client->noClientException;
429005b261ecSmrg}
429105b261ecSmrg
429205b261ecSmrg/***====================================================================***/
429305b261ecSmrg
42944642e01fSmrg#include "xkbgeom.h"
429505b261ecSmrg
429605b261ecSmrg#define	XkbSizeCountedString(s)  ((s)?((((2+strlen(s))+3)/4)*4):4)
429705b261ecSmrg
429805b261ecSmrgstatic char *
429905b261ecSmrgXkbWriteCountedString(char *wire,char *str,Bool swap)
430005b261ecSmrg{
430105b261ecSmrgCARD16	len,*pLen;
430205b261ecSmrg
430305b261ecSmrg    len= (str?strlen(str):0);
430405b261ecSmrg    pLen= (CARD16 *)wire;
430505b261ecSmrg    *pLen= len;
430605b261ecSmrg    if (swap) {
430705b261ecSmrg	register int n;
430805b261ecSmrg	swaps(pLen,n);
430905b261ecSmrg    }
431005b261ecSmrg    memcpy(&wire[2],str,len);
431105b261ecSmrg    wire+= ((2+len+3)/4)*4;
431205b261ecSmrg    return wire;
431305b261ecSmrg}
431405b261ecSmrg
431505b261ecSmrgstatic int
431605b261ecSmrgXkbSizeGeomProperties(XkbGeometryPtr geom)
431705b261ecSmrg{
431805b261ecSmrgregister int 	i,size;
431905b261ecSmrgXkbPropertyPtr	prop;
432005b261ecSmrg
432105b261ecSmrg    for (size=i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
432205b261ecSmrg	size+= XkbSizeCountedString(prop->name);
432305b261ecSmrg	size+= XkbSizeCountedString(prop->value);
432405b261ecSmrg    }
432505b261ecSmrg    return size;
432605b261ecSmrg}
432705b261ecSmrg
432805b261ecSmrgstatic char *
432905b261ecSmrgXkbWriteGeomProperties(char *wire,XkbGeometryPtr geom,Bool swap)
433005b261ecSmrg{
433105b261ecSmrgregister int 	i;
433205b261ecSmrgregister XkbPropertyPtr	prop;
433305b261ecSmrg
433405b261ecSmrg    for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
433505b261ecSmrg	wire= XkbWriteCountedString(wire,prop->name,swap);
433605b261ecSmrg	wire= XkbWriteCountedString(wire,prop->value,swap);
433705b261ecSmrg    }
433805b261ecSmrg    return wire;
433905b261ecSmrg}
434005b261ecSmrg
434105b261ecSmrgstatic int
434205b261ecSmrgXkbSizeGeomKeyAliases(XkbGeometryPtr geom)
434305b261ecSmrg{
434405b261ecSmrg    return geom->num_key_aliases*(2*XkbKeyNameLength);
434505b261ecSmrg}
434605b261ecSmrg
434705b261ecSmrgstatic char *
434805b261ecSmrgXkbWriteGeomKeyAliases(char *wire,XkbGeometryPtr geom,Bool swap)
434905b261ecSmrg{
435005b261ecSmrgregister int sz;
435105b261ecSmrg
435205b261ecSmrg    sz= geom->num_key_aliases*(XkbKeyNameLength*2);
435305b261ecSmrg    if (sz>0) {
435405b261ecSmrg	memcpy(wire,(char *)geom->key_aliases,sz);
435505b261ecSmrg	wire+= sz;
435605b261ecSmrg    }
435705b261ecSmrg    return wire;
435805b261ecSmrg}
435905b261ecSmrg
436005b261ecSmrgstatic int
436105b261ecSmrgXkbSizeGeomColors(XkbGeometryPtr geom)
436205b261ecSmrg{
436305b261ecSmrgregister int 		i,size;
436405b261ecSmrgregister XkbColorPtr	color;
436505b261ecSmrg
436605b261ecSmrg    for (i=size=0,color=geom->colors;i<geom->num_colors;i++,color++) {
436705b261ecSmrg	size+= XkbSizeCountedString(color->spec);
436805b261ecSmrg    }
436905b261ecSmrg    return size;
437005b261ecSmrg}
437105b261ecSmrg
437205b261ecSmrgstatic char *
437305b261ecSmrgXkbWriteGeomColors(char *wire,XkbGeometryPtr geom,Bool swap)
437405b261ecSmrg{
437505b261ecSmrgregister int		i;
437605b261ecSmrgregister XkbColorPtr	color;
437705b261ecSmrg
437805b261ecSmrg    for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) {
437905b261ecSmrg	wire= XkbWriteCountedString(wire,color->spec,swap);
438005b261ecSmrg    }
438105b261ecSmrg    return wire;
438205b261ecSmrg}
438305b261ecSmrg
438405b261ecSmrgstatic int
438505b261ecSmrgXkbSizeGeomShapes(XkbGeometryPtr geom)
438605b261ecSmrg{
438705b261ecSmrgregister int		i,size;
438805b261ecSmrgregister XkbShapePtr	shape;
438905b261ecSmrg
439005b261ecSmrg    for (i=size=0,shape=geom->shapes;i<geom->num_shapes;i++,shape++) {
439105b261ecSmrg	register int		n;
439205b261ecSmrg	register XkbOutlinePtr	ol;
439305b261ecSmrg	size+= SIZEOF(xkbShapeWireDesc);
439405b261ecSmrg	for (n=0,ol=shape->outlines;n<shape->num_outlines;n++,ol++) {
439505b261ecSmrg	    size+= SIZEOF(xkbOutlineWireDesc);
439605b261ecSmrg	    size+= ol->num_points*SIZEOF(xkbPointWireDesc);
439705b261ecSmrg	}
439805b261ecSmrg    }
439905b261ecSmrg    return size;
440005b261ecSmrg}
440105b261ecSmrg
440205b261ecSmrgstatic char *
440305b261ecSmrgXkbWriteGeomShapes(char *wire,XkbGeometryPtr geom,Bool swap)
440405b261ecSmrg{
440505b261ecSmrgint			i;
440605b261ecSmrgXkbShapePtr		shape;
440705b261ecSmrgxkbShapeWireDesc *	shapeWire;
440805b261ecSmrg
440905b261ecSmrg    for (i=0,shape=geom->shapes;i<geom->num_shapes;i++,shape++) {
441005b261ecSmrg	register int 		o;
441105b261ecSmrg	XkbOutlinePtr		ol;
441205b261ecSmrg	xkbOutlineWireDesc *	olWire;
441305b261ecSmrg	shapeWire= (xkbShapeWireDesc *)wire;
441405b261ecSmrg	shapeWire->name= shape->name;
441505b261ecSmrg	shapeWire->nOutlines= shape->num_outlines;
441605b261ecSmrg	if (shape->primary!=NULL)
441705b261ecSmrg	     shapeWire->primaryNdx= XkbOutlineIndex(shape,shape->primary);
441805b261ecSmrg	else shapeWire->primaryNdx= XkbNoShape;
441905b261ecSmrg	if (shape->approx!=NULL)
442005b261ecSmrg	     shapeWire->approxNdx= XkbOutlineIndex(shape,shape->approx);
442105b261ecSmrg	else shapeWire->approxNdx= XkbNoShape;
442205b261ecSmrg	if (swap) {
442305b261ecSmrg	    register int n;
442405b261ecSmrg	    swapl(&shapeWire->name,n);
442505b261ecSmrg	}
442605b261ecSmrg	wire= (char *)&shapeWire[1];
442705b261ecSmrg	for (o=0,ol=shape->outlines;o<shape->num_outlines;o++,ol++) {
442805b261ecSmrg	    register int	p;
442905b261ecSmrg	    XkbPointPtr		pt;
443005b261ecSmrg	    xkbPointWireDesc *	ptWire;
443105b261ecSmrg	    olWire= (xkbOutlineWireDesc *)wire;
443205b261ecSmrg	    olWire->nPoints= ol->num_points;
443305b261ecSmrg	    olWire->cornerRadius= ol->corner_radius;
443405b261ecSmrg	    wire= (char *)&olWire[1];
443505b261ecSmrg	    ptWire= (xkbPointWireDesc *)wire;
443605b261ecSmrg	    for (p=0,pt=ol->points;p<ol->num_points;p++,pt++) {
443705b261ecSmrg		ptWire[p].x= pt->x;
443805b261ecSmrg		ptWire[p].y= pt->y;
443905b261ecSmrg		if (swap) {
444005b261ecSmrg		    register int n;
444105b261ecSmrg		    swaps(&ptWire[p].x,n);
444205b261ecSmrg		    swaps(&ptWire[p].y,n);
444305b261ecSmrg		}
444405b261ecSmrg	    }
444505b261ecSmrg	    wire= (char *)&ptWire[ol->num_points];
444605b261ecSmrg	}
444705b261ecSmrg    }
444805b261ecSmrg    return wire;
444905b261ecSmrg}
445005b261ecSmrg
445105b261ecSmrgstatic int
445205b261ecSmrgXkbSizeGeomDoodads(int num_doodads,XkbDoodadPtr doodad)
445305b261ecSmrg{
445405b261ecSmrgregister int	i,size;
445505b261ecSmrg
445605b261ecSmrg    for (i=size=0;i<num_doodads;i++,doodad++) {
445705b261ecSmrg	size+= SIZEOF(xkbAnyDoodadWireDesc);
445805b261ecSmrg	if (doodad->any.type==XkbTextDoodad) {
445905b261ecSmrg	    size+= XkbSizeCountedString(doodad->text.text);
446005b261ecSmrg	    size+= XkbSizeCountedString(doodad->text.font);
446105b261ecSmrg	}
446205b261ecSmrg	else if (doodad->any.type==XkbLogoDoodad) {
446305b261ecSmrg	    size+= XkbSizeCountedString(doodad->logo.logo_name);
446405b261ecSmrg	}
446505b261ecSmrg    }
446605b261ecSmrg    return size;
446705b261ecSmrg}
446805b261ecSmrg
446905b261ecSmrgstatic char *
447005b261ecSmrgXkbWriteGeomDoodads(char *wire,int num_doodads,XkbDoodadPtr doodad,Bool swap)
447105b261ecSmrg{
447205b261ecSmrgregister int		i;
447305b261ecSmrgxkbDoodadWireDesc *	doodadWire;
447405b261ecSmrg
447505b261ecSmrg    for (i=0;i<num_doodads;i++,doodad++) {
447605b261ecSmrg	doodadWire= (xkbDoodadWireDesc *)wire;
447705b261ecSmrg	wire= (char *)&doodadWire[1];
447805b261ecSmrg	bzero(doodadWire,SIZEOF(xkbDoodadWireDesc));
447905b261ecSmrg	doodadWire->any.name= doodad->any.name;
448005b261ecSmrg	doodadWire->any.type= doodad->any.type;
448105b261ecSmrg	doodadWire->any.priority= doodad->any.priority;
448205b261ecSmrg	doodadWire->any.top= doodad->any.top;
448305b261ecSmrg	doodadWire->any.left= doodad->any.left;
448405b261ecSmrg	if (swap) {
448505b261ecSmrg	    register int n;
448605b261ecSmrg	    swapl(&doodadWire->any.name,n);
448705b261ecSmrg	    swaps(&doodadWire->any.top,n);
448805b261ecSmrg	    swaps(&doodadWire->any.left,n);
448905b261ecSmrg	}
449005b261ecSmrg	switch (doodad->any.type) {
449105b261ecSmrg	    case XkbOutlineDoodad:
449205b261ecSmrg	    case XkbSolidDoodad:
449305b261ecSmrg		doodadWire->shape.angle= doodad->shape.angle;
449405b261ecSmrg		doodadWire->shape.colorNdx= doodad->shape.color_ndx;
449505b261ecSmrg		doodadWire->shape.shapeNdx= doodad->shape.shape_ndx;
449605b261ecSmrg		if (swap) {
449705b261ecSmrg		    register int n;
449805b261ecSmrg		    swaps(&doodadWire->shape.angle,n);
449905b261ecSmrg		}
450005b261ecSmrg		break;
450105b261ecSmrg	    case XkbTextDoodad:
450205b261ecSmrg		doodadWire->text.angle= doodad->text.angle;
450305b261ecSmrg		doodadWire->text.width= doodad->text.width;
450405b261ecSmrg		doodadWire->text.height= doodad->text.height;
450505b261ecSmrg		doodadWire->text.colorNdx= doodad->text.color_ndx;
450605b261ecSmrg		if (swap) {
450705b261ecSmrg		    register int n;
450805b261ecSmrg		    swaps(&doodadWire->text.angle,n);
450905b261ecSmrg		    swaps(&doodadWire->text.width,n);
451005b261ecSmrg		    swaps(&doodadWire->text.height,n);
451105b261ecSmrg		}
451205b261ecSmrg		wire= XkbWriteCountedString(wire,doodad->text.text,swap);
451305b261ecSmrg		wire= XkbWriteCountedString(wire,doodad->text.font,swap);
451405b261ecSmrg		break;
451505b261ecSmrg	    case XkbIndicatorDoodad:
451605b261ecSmrg		doodadWire->indicator.shapeNdx= doodad->indicator.shape_ndx;
451705b261ecSmrg		doodadWire->indicator.onColorNdx=doodad->indicator.on_color_ndx;
451805b261ecSmrg		doodadWire->indicator.offColorNdx=
451905b261ecSmrg						doodad->indicator.off_color_ndx;
452005b261ecSmrg		break;
452105b261ecSmrg	    case XkbLogoDoodad:
452205b261ecSmrg		doodadWire->logo.angle= doodad->logo.angle;
452305b261ecSmrg		doodadWire->logo.colorNdx= doodad->logo.color_ndx;
452405b261ecSmrg		doodadWire->logo.shapeNdx= doodad->logo.shape_ndx;
452505b261ecSmrg		wire= XkbWriteCountedString(wire,doodad->logo.logo_name,swap);
452605b261ecSmrg		break;
452705b261ecSmrg	    default:
45284642e01fSmrg		ErrorF("[xkb] Unknown doodad type %d in XkbWriteGeomDoodads\n",
452905b261ecSmrg			doodad->any.type);
45304642e01fSmrg		ErrorF("[xkb] Ignored\n");
453105b261ecSmrg		break;
453205b261ecSmrg	}
453305b261ecSmrg    }
453405b261ecSmrg    return wire;
453505b261ecSmrg}
453605b261ecSmrg
453705b261ecSmrgstatic char *
453805b261ecSmrgXkbWriteGeomOverlay(char *wire,XkbOverlayPtr ol,Bool swap)
453905b261ecSmrg{
454005b261ecSmrgregister int		r;
454105b261ecSmrgXkbOverlayRowPtr	row;
454205b261ecSmrgxkbOverlayWireDesc *	olWire;
454305b261ecSmrg
454405b261ecSmrg   olWire= (xkbOverlayWireDesc *)wire;
454505b261ecSmrg   olWire->name= ol->name;
454605b261ecSmrg   olWire->nRows= ol->num_rows;
454705b261ecSmrg   if (swap) {
454805b261ecSmrg	register int n;
454905b261ecSmrg	swapl(&olWire->name,n);
455005b261ecSmrg   }
455105b261ecSmrg   wire= (char *)&olWire[1];
455205b261ecSmrg   for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
455305b261ecSmrg   	unsigned int		k;
455405b261ecSmrg	XkbOverlayKeyPtr	key;
455505b261ecSmrg	xkbOverlayRowWireDesc *	rowWire;
455605b261ecSmrg	rowWire= (xkbOverlayRowWireDesc *)wire;
455705b261ecSmrg	rowWire->rowUnder= row->row_under;
455805b261ecSmrg	rowWire->nKeys= row->num_keys;
455905b261ecSmrg	wire= (char *)&rowWire[1];
456005b261ecSmrg	for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
456105b261ecSmrg	    xkbOverlayKeyWireDesc *	keyWire;
456205b261ecSmrg	    keyWire= (xkbOverlayKeyWireDesc *)wire;
456305b261ecSmrg	    memcpy(keyWire->over,key->over.name,XkbKeyNameLength);
456405b261ecSmrg	    memcpy(keyWire->under,key->under.name,XkbKeyNameLength);
456505b261ecSmrg	    wire= (char *)&keyWire[1];
456605b261ecSmrg	}
456705b261ecSmrg   }
456805b261ecSmrg   return wire;
456905b261ecSmrg}
457005b261ecSmrg
457105b261ecSmrgstatic int
457205b261ecSmrgXkbSizeGeomSections(XkbGeometryPtr geom)
457305b261ecSmrg{
457405b261ecSmrgregister int 	i,size;
457505b261ecSmrgXkbSectionPtr	section;
457605b261ecSmrg
457705b261ecSmrg    for (i=size=0,section=geom->sections;i<geom->num_sections;i++,section++) {
457805b261ecSmrg	size+= SIZEOF(xkbSectionWireDesc);
457905b261ecSmrg	if (section->rows) {
458005b261ecSmrg	    int		r;
458105b261ecSmrg	    XkbRowPtr	row;
458205b261ecSmrg	    for (r=0,row=section->rows;r<section->num_rows;row++,r++) {
458305b261ecSmrg		size+= SIZEOF(xkbRowWireDesc);
458405b261ecSmrg		size+= row->num_keys*SIZEOF(xkbKeyWireDesc);
458505b261ecSmrg	    }
458605b261ecSmrg	}
458705b261ecSmrg	if (section->doodads)
458805b261ecSmrg	    size+= XkbSizeGeomDoodads(section->num_doodads,section->doodads);
458905b261ecSmrg	if (section->overlays) {
459005b261ecSmrg	    int			o;
459105b261ecSmrg	    XkbOverlayPtr	ol;
459205b261ecSmrg	    for (o=0,ol=section->overlays;o<section->num_overlays;o++,ol++) {
459305b261ecSmrg		int			r;
459405b261ecSmrg		XkbOverlayRowPtr	row;
459505b261ecSmrg		size+= SIZEOF(xkbOverlayWireDesc);
459605b261ecSmrg		for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
459705b261ecSmrg		   size+= SIZEOF(xkbOverlayRowWireDesc);
459805b261ecSmrg		   size+= row->num_keys*SIZEOF(xkbOverlayKeyWireDesc);
459905b261ecSmrg		}
460005b261ecSmrg	    }
460105b261ecSmrg	}
460205b261ecSmrg    }
460305b261ecSmrg    return size;
460405b261ecSmrg}
460505b261ecSmrg
460605b261ecSmrgstatic char *
460705b261ecSmrgXkbWriteGeomSections(char *wire,XkbGeometryPtr geom,Bool swap)
460805b261ecSmrg{
460905b261ecSmrgregister int		i;
461005b261ecSmrgXkbSectionPtr		section;
461105b261ecSmrgxkbSectionWireDesc *	sectionWire;
461205b261ecSmrg
461305b261ecSmrg    for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) {
461405b261ecSmrg	sectionWire= (xkbSectionWireDesc *)wire;
461505b261ecSmrg	sectionWire->name= section->name;
461605b261ecSmrg	sectionWire->top= section->top;
461705b261ecSmrg	sectionWire->left= section->left;
461805b261ecSmrg	sectionWire->width= section->width;
461905b261ecSmrg	sectionWire->height= section->height;
462005b261ecSmrg	sectionWire->angle= section->angle;
462105b261ecSmrg	sectionWire->priority= section->priority;
462205b261ecSmrg	sectionWire->nRows= section->num_rows;
462305b261ecSmrg	sectionWire->nDoodads= section->num_doodads;
462405b261ecSmrg	sectionWire->nOverlays= section->num_overlays;
462505b261ecSmrg	sectionWire->pad= 0;
462605b261ecSmrg	if (swap) {
462705b261ecSmrg	    register int n;
462805b261ecSmrg	    swapl(&sectionWire->name,n);
462905b261ecSmrg	    swaps(&sectionWire->top,n);
463005b261ecSmrg	    swaps(&sectionWire->left,n);
463105b261ecSmrg	    swaps(&sectionWire->width,n);
463205b261ecSmrg	    swaps(&sectionWire->height,n);
463305b261ecSmrg	    swaps(&sectionWire->angle,n);
463405b261ecSmrg	}
463505b261ecSmrg	wire= (char *)&sectionWire[1];
463605b261ecSmrg	if (section->rows) {
463705b261ecSmrg	    int			r;
463805b261ecSmrg	    XkbRowPtr		row;
463905b261ecSmrg	    xkbRowWireDesc *	rowWire;
464005b261ecSmrg	    for (r=0,row=section->rows;r<section->num_rows;r++,row++) {
464105b261ecSmrg		rowWire= (xkbRowWireDesc *)wire;
464205b261ecSmrg		rowWire->top= row->top;
464305b261ecSmrg		rowWire->left= row->left;
464405b261ecSmrg		rowWire->nKeys= row->num_keys;
464505b261ecSmrg		rowWire->vertical= row->vertical;
464605b261ecSmrg		rowWire->pad= 0;
464705b261ecSmrg		if (swap) {
464805b261ecSmrg		    register int n;
464905b261ecSmrg		    swaps(&rowWire->top,n);
465005b261ecSmrg		    swaps(&rowWire->left,n);
465105b261ecSmrg		}
465205b261ecSmrg		wire= (char *)&rowWire[1];
465305b261ecSmrg		if (row->keys) {
465405b261ecSmrg		    int			k;
465505b261ecSmrg		    XkbKeyPtr		key;
465605b261ecSmrg		    xkbKeyWireDesc *	keyWire;
465705b261ecSmrg		    keyWire= (xkbKeyWireDesc *)wire;
465805b261ecSmrg		    for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
465905b261ecSmrg			memcpy(keyWire[k].name,key->name.name,XkbKeyNameLength);
466005b261ecSmrg			keyWire[k].gap= key->gap;
466105b261ecSmrg			keyWire[k].shapeNdx= key->shape_ndx;
466205b261ecSmrg			keyWire[k].colorNdx= key->color_ndx;
466305b261ecSmrg			if (swap) {
466405b261ecSmrg			    register int n;
466505b261ecSmrg			    swaps(&keyWire[k].gap,n);
466605b261ecSmrg			}
466705b261ecSmrg		    }
466805b261ecSmrg		    wire= (char *)&keyWire[row->num_keys];
466905b261ecSmrg		}
467005b261ecSmrg	    }
467105b261ecSmrg	}
467205b261ecSmrg	if (section->doodads) {
467305b261ecSmrg	    wire= XkbWriteGeomDoodads(wire,
467405b261ecSmrg	    			      section->num_doodads,section->doodads,
467505b261ecSmrg				      swap);
467605b261ecSmrg	}
467705b261ecSmrg	if (section->overlays) {
467805b261ecSmrg	    register int o;
467905b261ecSmrg	    for (o=0;o<section->num_overlays;o++) {
468005b261ecSmrg		wire= XkbWriteGeomOverlay(wire,&section->overlays[o],swap);
468105b261ecSmrg	    }
468205b261ecSmrg	}
468305b261ecSmrg    }
468405b261ecSmrg    return wire;
468505b261ecSmrg}
468605b261ecSmrg
468705b261ecSmrgstatic Status
468805b261ecSmrgXkbComputeGetGeometryReplySize(	XkbGeometryPtr		geom,
468905b261ecSmrg				xkbGetGeometryReply *	rep,
469005b261ecSmrg				Atom			name)
469105b261ecSmrg{
469205b261ecSmrgint	len;
469305b261ecSmrg
469405b261ecSmrg    if (geom!=NULL) {
469505b261ecSmrg	len= XkbSizeCountedString(geom->label_font);
469605b261ecSmrg	len+= XkbSizeGeomProperties(geom);
469705b261ecSmrg	len+= XkbSizeGeomColors(geom);
469805b261ecSmrg	len+= XkbSizeGeomShapes(geom);
469905b261ecSmrg	len+= XkbSizeGeomSections(geom);
470005b261ecSmrg	len+= XkbSizeGeomDoodads(geom->num_doodads,geom->doodads);
470105b261ecSmrg	len+= XkbSizeGeomKeyAliases(geom);
470205b261ecSmrg	rep->length= len/4;
470305b261ecSmrg	rep->found= True;
470405b261ecSmrg	rep->name= geom->name;
470505b261ecSmrg	rep->widthMM= geom->width_mm;
470605b261ecSmrg	rep->heightMM= geom->height_mm;
470705b261ecSmrg	rep->nProperties= geom->num_properties;
470805b261ecSmrg	rep->nColors= geom->num_colors;
470905b261ecSmrg	rep->nShapes= geom->num_shapes;
471005b261ecSmrg	rep->nSections= geom->num_sections;
471105b261ecSmrg	rep->nDoodads= geom->num_doodads;
471205b261ecSmrg	rep->nKeyAliases= geom->num_key_aliases;
471305b261ecSmrg	rep->baseColorNdx= XkbGeomColorIndex(geom,geom->base_color);
471405b261ecSmrg	rep->labelColorNdx= XkbGeomColorIndex(geom,geom->label_color);
471505b261ecSmrg    }
471605b261ecSmrg    else {
471705b261ecSmrg	rep->length= 0;
471805b261ecSmrg	rep->found= False;
471905b261ecSmrg	rep->name= name;
472005b261ecSmrg	rep->widthMM= rep->heightMM= 0;
472105b261ecSmrg	rep->nProperties= rep->nColors= rep->nShapes= 0;
472205b261ecSmrg	rep->nSections= rep->nDoodads= 0;
472305b261ecSmrg	rep->nKeyAliases= 0;
472405b261ecSmrg	rep->labelColorNdx= rep->baseColorNdx= 0;
472505b261ecSmrg    }
472605b261ecSmrg    return Success;
472705b261ecSmrg}
472805b261ecSmrg
472905b261ecSmrgstatic int
473005b261ecSmrgXkbSendGeometry(	ClientPtr		client,
473105b261ecSmrg			XkbGeometryPtr		geom,
473205b261ecSmrg			xkbGetGeometryReply *	rep,
473305b261ecSmrg			Bool			freeGeom)
473405b261ecSmrg{
473505b261ecSmrg    char	*desc,*start;
473605b261ecSmrg    int		 len;
473705b261ecSmrg
473805b261ecSmrg    if (geom!=NULL) {
473905b261ecSmrg	len= rep->length*4;
47404642e01fSmrg	start= desc= (char *)xalloc(len);
474105b261ecSmrg	if (!start)
474205b261ecSmrg	    return BadAlloc;
474305b261ecSmrg	desc=  XkbWriteCountedString(desc,geom->label_font,client->swapped);
474405b261ecSmrg	if ( rep->nProperties>0 )
474505b261ecSmrg	    desc = XkbWriteGeomProperties(desc,geom,client->swapped);
474605b261ecSmrg	if ( rep->nColors>0 )
474705b261ecSmrg	    desc = XkbWriteGeomColors(desc,geom,client->swapped);
474805b261ecSmrg	if ( rep->nShapes>0 )
474905b261ecSmrg	    desc = XkbWriteGeomShapes(desc,geom,client->swapped);
475005b261ecSmrg	if ( rep->nSections>0 )
475105b261ecSmrg	    desc = XkbWriteGeomSections(desc,geom,client->swapped);
475205b261ecSmrg	if ( rep->nDoodads>0 )
475305b261ecSmrg	    desc = XkbWriteGeomDoodads(desc,geom->num_doodads,geom->doodads,
475405b261ecSmrg							  client->swapped);
475505b261ecSmrg	if ( rep->nKeyAliases>0 )
475605b261ecSmrg	    desc = XkbWriteGeomKeyAliases(desc,geom,client->swapped);
475705b261ecSmrg	if ((desc-start)!=(len)) {
47584642e01fSmrg	    ErrorF("[xkb] BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n",
475905b261ecSmrg			len, (unsigned long)(desc-start));
476005b261ecSmrg	}
476105b261ecSmrg    }
476205b261ecSmrg    else {
476305b261ecSmrg	len= 0;
476405b261ecSmrg	start= NULL;
476505b261ecSmrg    }
476605b261ecSmrg    if (client->swapped) {
476705b261ecSmrg	register int n;
476805b261ecSmrg	swaps(&rep->sequenceNumber,n);
476905b261ecSmrg	swapl(&rep->length,n);
477005b261ecSmrg	swapl(&rep->name,n);
477105b261ecSmrg	swaps(&rep->widthMM,n);
477205b261ecSmrg	swaps(&rep->heightMM,n);
477305b261ecSmrg	swaps(&rep->nProperties,n);
477405b261ecSmrg	swaps(&rep->nColors,n);
477505b261ecSmrg	swaps(&rep->nShapes,n);
477605b261ecSmrg	swaps(&rep->nSections,n);
477705b261ecSmrg	swaps(&rep->nDoodads,n);
477805b261ecSmrg	swaps(&rep->nKeyAliases,n);
477905b261ecSmrg    }
478005b261ecSmrg    WriteToClient(client, SIZEOF(xkbGetGeometryReply), (char *)rep);
478105b261ecSmrg    if (len>0)
478205b261ecSmrg	WriteToClient(client, len, start);
478305b261ecSmrg    if (start!=NULL)
47844642e01fSmrg	xfree((char *)start);
478505b261ecSmrg    if (freeGeom)
478605b261ecSmrg	XkbFreeGeometry(geom,XkbGeomAllMask,True);
478705b261ecSmrg    return client->noClientException;
478805b261ecSmrg}
478905b261ecSmrg
479005b261ecSmrgint
479105b261ecSmrgProcXkbGetGeometry(ClientPtr client)
479205b261ecSmrg{
479305b261ecSmrg    DeviceIntPtr 	dev;
479405b261ecSmrg    xkbGetGeometryReply rep;
479505b261ecSmrg    XkbGeometryPtr	geom;
479605b261ecSmrg    Bool		shouldFree;
479705b261ecSmrg    Status		status;
479805b261ecSmrg
479905b261ecSmrg    REQUEST(xkbGetGeometryReq);
480005b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetGeometryReq);
480105b261ecSmrg
480205b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
480305b261ecSmrg	return BadAccess;
480405b261ecSmrg
48054642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
480605b261ecSmrg    CHK_ATOM_OR_NONE(stuff->name);
480705b261ecSmrg
480805b261ecSmrg    geom= XkbLookupNamedGeometry(dev,stuff->name,&shouldFree);
480905b261ecSmrg    rep.type= X_Reply;
481005b261ecSmrg    rep.deviceID= dev->id;
481105b261ecSmrg    rep.sequenceNumber= client->sequence;
481205b261ecSmrg    rep.length= 0;
481305b261ecSmrg    status= XkbComputeGetGeometryReplySize(geom,&rep,stuff->name);
481405b261ecSmrg    if (status!=Success)
481505b261ecSmrg	 return status;
481605b261ecSmrg    else return XkbSendGeometry(client,geom,&rep,shouldFree);
481705b261ecSmrg}
481805b261ecSmrg
481905b261ecSmrg/***====================================================================***/
482005b261ecSmrg
482105b261ecSmrgstatic char *
482205b261ecSmrg_GetCountedString(char **wire_inout,Bool swap)
482305b261ecSmrg{
482405b261ecSmrgchar *	wire,*str;
482505b261ecSmrgCARD16	len,*plen;
482605b261ecSmrg
482705b261ecSmrg    wire= *wire_inout;
482805b261ecSmrg    plen= (CARD16 *)wire;
482905b261ecSmrg    if (swap) {
483005b261ecSmrg	register int n;
483105b261ecSmrg	swaps(plen,n);
483205b261ecSmrg    }
483305b261ecSmrg    len= *plen;
483405b261ecSmrg    str= (char *)_XkbAlloc(len+1);
483505b261ecSmrg    if (str) {
483605b261ecSmrg	memcpy(str,&wire[2],len);
483705b261ecSmrg	str[len]= '\0';
483805b261ecSmrg    }
483905b261ecSmrg    wire+= XkbPaddedSize(len+2);
484005b261ecSmrg    *wire_inout= wire;
484105b261ecSmrg    return str;
484205b261ecSmrg}
484305b261ecSmrg
484405b261ecSmrgstatic Status
484505b261ecSmrg_CheckSetDoodad(	char **		wire_inout,
484605b261ecSmrg			XkbGeometryPtr	geom,
484705b261ecSmrg			XkbSectionPtr	section,
484805b261ecSmrg			ClientPtr	client)
484905b261ecSmrg{
485005b261ecSmrgchar *			wire;
485105b261ecSmrgxkbDoodadWireDesc *	dWire;
485205b261ecSmrgXkbDoodadPtr		doodad;
485305b261ecSmrg
485405b261ecSmrg    dWire= (xkbDoodadWireDesc *)(*wire_inout);
485505b261ecSmrg    wire= (char *)&dWire[1];
485605b261ecSmrg    if (client->swapped) {
485705b261ecSmrg	register int n;
485805b261ecSmrg	swapl(&dWire->any.name,n);
485905b261ecSmrg	swaps(&dWire->any.top,n);
486005b261ecSmrg	swaps(&dWire->any.left,n);
486105b261ecSmrg	swaps(&dWire->any.angle,n);
486205b261ecSmrg    }
486305b261ecSmrg    CHK_ATOM_ONLY(dWire->any.name);
486405b261ecSmrg    doodad= XkbAddGeomDoodad(geom,section,dWire->any.name);
486505b261ecSmrg    if (!doodad)
486605b261ecSmrg	return BadAlloc;
486705b261ecSmrg    doodad->any.type= dWire->any.type;
486805b261ecSmrg    doodad->any.priority= dWire->any.priority;
486905b261ecSmrg    doodad->any.top= dWire->any.top;
487005b261ecSmrg    doodad->any.left= dWire->any.left;
487105b261ecSmrg    doodad->any.angle= dWire->any.angle;
487205b261ecSmrg    switch (doodad->any.type) {
487305b261ecSmrg	case XkbOutlineDoodad:
487405b261ecSmrg	case XkbSolidDoodad:
487505b261ecSmrg	    if (dWire->shape.colorNdx>=geom->num_colors) {
487605b261ecSmrg		client->errorValue= _XkbErrCode3(0x40,geom->num_colors,
487705b261ecSmrg							dWire->shape.colorNdx);
487805b261ecSmrg		return BadMatch;
487905b261ecSmrg	    }
488005b261ecSmrg	    if (dWire->shape.shapeNdx>=geom->num_shapes) {
488105b261ecSmrg		client->errorValue= _XkbErrCode3(0x41,geom->num_shapes,
488205b261ecSmrg							dWire->shape.shapeNdx);
488305b261ecSmrg		return BadMatch;
488405b261ecSmrg	    }
488505b261ecSmrg	    doodad->shape.color_ndx= dWire->shape.colorNdx;
488605b261ecSmrg	    doodad->shape.shape_ndx= dWire->shape.shapeNdx;
488705b261ecSmrg	    break;
488805b261ecSmrg	case XkbTextDoodad:
488905b261ecSmrg	    if (dWire->text.colorNdx>=geom->num_colors) {
489005b261ecSmrg		client->errorValue= _XkbErrCode3(0x42,geom->num_colors,
489105b261ecSmrg							dWire->text.colorNdx);
489205b261ecSmrg		return BadMatch;
489305b261ecSmrg	    }
489405b261ecSmrg	    if (client->swapped) {
489505b261ecSmrg		register int n;
489605b261ecSmrg		swaps(&dWire->text.width,n);
489705b261ecSmrg		swaps(&dWire->text.height,n);
489805b261ecSmrg	    }
489905b261ecSmrg	    doodad->text.width= dWire->text.width;
490005b261ecSmrg	    doodad->text.height= dWire->text.height;
490105b261ecSmrg	    doodad->text.color_ndx= dWire->text.colorNdx;
490205b261ecSmrg	    doodad->text.text= _GetCountedString(&wire,client->swapped);
490305b261ecSmrg	    doodad->text.font= _GetCountedString(&wire,client->swapped);
490405b261ecSmrg	    break;
490505b261ecSmrg	case XkbIndicatorDoodad:
490605b261ecSmrg	    if (dWire->indicator.onColorNdx>=geom->num_colors) {
490705b261ecSmrg		client->errorValue= _XkbErrCode3(0x43,geom->num_colors,
490805b261ecSmrg						dWire->indicator.onColorNdx);
490905b261ecSmrg		return BadMatch;
491005b261ecSmrg	    }
491105b261ecSmrg	    if (dWire->indicator.offColorNdx>=geom->num_colors) {
491205b261ecSmrg		client->errorValue= _XkbErrCode3(0x44,geom->num_colors,
491305b261ecSmrg						dWire->indicator.offColorNdx);
491405b261ecSmrg		return BadMatch;
491505b261ecSmrg	    }
491605b261ecSmrg	    if (dWire->indicator.shapeNdx>=geom->num_shapes) {
491705b261ecSmrg		client->errorValue= _XkbErrCode3(0x45,geom->num_shapes,
491805b261ecSmrg						dWire->indicator.shapeNdx);
491905b261ecSmrg		return BadMatch;
492005b261ecSmrg	    }
492105b261ecSmrg	    doodad->indicator.shape_ndx= dWire->indicator.shapeNdx;
492205b261ecSmrg	    doodad->indicator.on_color_ndx= dWire->indicator.onColorNdx;
492305b261ecSmrg	    doodad->indicator.off_color_ndx= dWire->indicator.offColorNdx;
492405b261ecSmrg	    break;
492505b261ecSmrg	case XkbLogoDoodad:
492605b261ecSmrg	    if (dWire->logo.colorNdx>=geom->num_colors) {
492705b261ecSmrg		client->errorValue= _XkbErrCode3(0x46,geom->num_colors,
492805b261ecSmrg							dWire->logo.colorNdx);
492905b261ecSmrg		return BadMatch;
493005b261ecSmrg	    }
493105b261ecSmrg	    if (dWire->logo.shapeNdx>=geom->num_shapes) {
493205b261ecSmrg		client->errorValue= _XkbErrCode3(0x47,geom->num_shapes,
493305b261ecSmrg							dWire->logo.shapeNdx);
493405b261ecSmrg		return BadMatch;
493505b261ecSmrg	    }
493605b261ecSmrg	    doodad->logo.color_ndx= dWire->logo.colorNdx;
493705b261ecSmrg	    doodad->logo.shape_ndx= dWire->logo.shapeNdx;
493805b261ecSmrg	    doodad->logo.logo_name= _GetCountedString(&wire,client->swapped);
493905b261ecSmrg	    break;
494005b261ecSmrg	default:
494105b261ecSmrg	    client->errorValue= _XkbErrCode2(0x4F,dWire->any.type);
494205b261ecSmrg	    return BadValue;
494305b261ecSmrg    }
494405b261ecSmrg    *wire_inout= wire;
494505b261ecSmrg    return Success;
494605b261ecSmrg}
494705b261ecSmrg
494805b261ecSmrgstatic Status
494905b261ecSmrg_CheckSetOverlay(	char **		wire_inout,
495005b261ecSmrg			XkbGeometryPtr	geom,
495105b261ecSmrg			XkbSectionPtr	section,
495205b261ecSmrg			ClientPtr	client)
495305b261ecSmrg{
495405b261ecSmrgregister int		r;
495505b261ecSmrgchar *			wire;
495605b261ecSmrgXkbOverlayPtr		ol;
495705b261ecSmrgxkbOverlayWireDesc *	olWire;
495805b261ecSmrgxkbOverlayRowWireDesc *	rWire;
495905b261ecSmrg
496005b261ecSmrg    wire= *wire_inout;
496105b261ecSmrg    olWire= (xkbOverlayWireDesc *)wire;
496205b261ecSmrg    if (client->swapped) {
496305b261ecSmrg	register int n;
496405b261ecSmrg	swapl(&olWire->name,n);
496505b261ecSmrg    }
496605b261ecSmrg    CHK_ATOM_ONLY(olWire->name);
496705b261ecSmrg    ol= XkbAddGeomOverlay(section,olWire->name,olWire->nRows);
496805b261ecSmrg    rWire= (xkbOverlayRowWireDesc *)&olWire[1];
496905b261ecSmrg    for (r=0;r<olWire->nRows;r++) {
497005b261ecSmrg	register int		k;
497105b261ecSmrg	xkbOverlayKeyWireDesc *	kWire;
497205b261ecSmrg	XkbOverlayRowPtr	row;
497305b261ecSmrg
497405b261ecSmrg	if (rWire->rowUnder>section->num_rows) {
497505b261ecSmrg	    client->errorValue= _XkbErrCode4(0x20,r,section->num_rows,
497605b261ecSmrg							rWire->rowUnder);
497705b261ecSmrg	    return BadMatch;
497805b261ecSmrg	}
497905b261ecSmrg	row= XkbAddGeomOverlayRow(ol,rWire->rowUnder,rWire->nKeys);
498005b261ecSmrg	kWire= (xkbOverlayKeyWireDesc *)&rWire[1];
498105b261ecSmrg	for (k=0;k<rWire->nKeys;k++,kWire++) {
498205b261ecSmrg	    if (XkbAddGeomOverlayKey(ol,row,
498305b261ecSmrg	    		(char *)kWire->over,(char *)kWire->under)==NULL) {
498405b261ecSmrg		client->errorValue= _XkbErrCode3(0x21,r,k);
498505b261ecSmrg		return BadMatch;
498605b261ecSmrg	    }
498705b261ecSmrg	}
498805b261ecSmrg	rWire= (xkbOverlayRowWireDesc *)kWire;
498905b261ecSmrg    }
499005b261ecSmrg    olWire= (xkbOverlayWireDesc *)rWire;
499105b261ecSmrg    wire= (char *)olWire;
499205b261ecSmrg    *wire_inout= wire;
499305b261ecSmrg    return Success;
499405b261ecSmrg}
499505b261ecSmrg
499605b261ecSmrgstatic Status
499705b261ecSmrg_CheckSetSections( 	XkbGeometryPtr		geom,
499805b261ecSmrg			xkbSetGeometryReq *	req,
499905b261ecSmrg			char **			wire_inout,
500005b261ecSmrg			ClientPtr		client)
500105b261ecSmrg{
500205b261ecSmrgStatus			status;
500305b261ecSmrgregister int		s;
500405b261ecSmrgchar *			wire;
500505b261ecSmrgxkbSectionWireDesc *	sWire;
500605b261ecSmrgXkbSectionPtr		section;
500705b261ecSmrg
500805b261ecSmrg    wire= *wire_inout;
500905b261ecSmrg    if (req->nSections<1)
501005b261ecSmrg	return Success;
501105b261ecSmrg    sWire= (xkbSectionWireDesc *)wire;
501205b261ecSmrg    for (s=0;s<req->nSections;s++) {
501305b261ecSmrg	register int		r;
501405b261ecSmrg	xkbRowWireDesc *	rWire;
501505b261ecSmrg	if (client->swapped) {
501605b261ecSmrg	    register int n;
501705b261ecSmrg	    swapl(&sWire->name,n);
501805b261ecSmrg	    swaps(&sWire->top,n);
501905b261ecSmrg	    swaps(&sWire->left,n);
502005b261ecSmrg	    swaps(&sWire->width,n);
502105b261ecSmrg	    swaps(&sWire->height,n);
502205b261ecSmrg	    swaps(&sWire->angle,n);
502305b261ecSmrg	}
502405b261ecSmrg	CHK_ATOM_ONLY(sWire->name);
502505b261ecSmrg	section= XkbAddGeomSection(geom,sWire->name,sWire->nRows,
502605b261ecSmrg					sWire->nDoodads,sWire->nOverlays);
502705b261ecSmrg	if (!section)
502805b261ecSmrg	    return BadAlloc;
502905b261ecSmrg	section->priority=	sWire->priority;
503005b261ecSmrg	section->top=		sWire->top;
503105b261ecSmrg	section->left=		sWire->left;
503205b261ecSmrg	section->width=		sWire->width;
503305b261ecSmrg	section->height=	sWire->height;
503405b261ecSmrg	section->angle=		sWire->angle;
503505b261ecSmrg	rWire= (xkbRowWireDesc *)&sWire[1];
503605b261ecSmrg	for (r=0;r<sWire->nRows;r++) {
503705b261ecSmrg	    register int	k;
503805b261ecSmrg	    XkbRowPtr		row;
503905b261ecSmrg	    xkbKeyWireDesc *	kWire;
504005b261ecSmrg	    if (client->swapped) {
504105b261ecSmrg		register int n;
504205b261ecSmrg		swaps(&rWire->top,n);
504305b261ecSmrg		swaps(&rWire->left,n);
504405b261ecSmrg	    }
504505b261ecSmrg	    row= XkbAddGeomRow(section,rWire->nKeys);
504605b261ecSmrg	    if (!row)
504705b261ecSmrg		return BadAlloc;
504805b261ecSmrg	    row->top= rWire->top;
504905b261ecSmrg	    row->left= rWire->left;
505005b261ecSmrg	    row->vertical= rWire->vertical;
505105b261ecSmrg	    kWire= (xkbKeyWireDesc *)&rWire[1];
505205b261ecSmrg	    for (k=0;k<rWire->nKeys;k++) {
505305b261ecSmrg		XkbKeyPtr	key;
505405b261ecSmrg		key= XkbAddGeomKey(row);
505505b261ecSmrg		if (!key)
505605b261ecSmrg		    return BadAlloc;
505705b261ecSmrg		memcpy(key->name.name,kWire[k].name,XkbKeyNameLength);
505805b261ecSmrg		key->gap= kWire[k].gap;
505905b261ecSmrg		key->shape_ndx= kWire[k].shapeNdx;
506005b261ecSmrg		key->color_ndx= kWire[k].colorNdx;
506105b261ecSmrg		if (key->shape_ndx>=geom->num_shapes) {
506205b261ecSmrg		    client->errorValue= _XkbErrCode3(0x10,key->shape_ndx,
506305b261ecSmrg							  geom->num_shapes);
506405b261ecSmrg		    return BadMatch;
506505b261ecSmrg		}
506605b261ecSmrg		if (key->color_ndx>=geom->num_colors) {
506705b261ecSmrg		    client->errorValue= _XkbErrCode3(0x11,key->color_ndx,
506805b261ecSmrg							  geom->num_colors);
506905b261ecSmrg		    return BadMatch;
507005b261ecSmrg		}
507105b261ecSmrg	    }
507205b261ecSmrg	    rWire= (xkbRowWireDesc *)&kWire[rWire->nKeys];
507305b261ecSmrg	}
507405b261ecSmrg	wire= (char *)rWire;
507505b261ecSmrg	if (sWire->nDoodads>0) {
507605b261ecSmrg	    register int d;
507705b261ecSmrg	    for (d=0;d<sWire->nDoodads;d++) {
507805b261ecSmrg		status=_CheckSetDoodad(&wire,geom,section,client);
507905b261ecSmrg		if (status!=Success)
508005b261ecSmrg		    return status;
508105b261ecSmrg	    }
508205b261ecSmrg	}
508305b261ecSmrg	if (sWire->nOverlays>0) {
508405b261ecSmrg	    register int o;
508505b261ecSmrg	    for (o=0;o<sWire->nOverlays;o++) {
508605b261ecSmrg		status= _CheckSetOverlay(&wire,geom,section,client);
508705b261ecSmrg		if (status!=Success)
508805b261ecSmrg		    return status;
508905b261ecSmrg	    }
509005b261ecSmrg	}
509105b261ecSmrg	sWire= (xkbSectionWireDesc *)wire;
509205b261ecSmrg    }
509305b261ecSmrg    wire= (char *)sWire;
509405b261ecSmrg    *wire_inout= wire;
509505b261ecSmrg    return Success;
509605b261ecSmrg}
509705b261ecSmrg
509805b261ecSmrgstatic Status
509905b261ecSmrg_CheckSetShapes( 	XkbGeometryPtr		geom,
510005b261ecSmrg			xkbSetGeometryReq *	req,
510105b261ecSmrg			char **			wire_inout,
510205b261ecSmrg			ClientPtr		client)
510305b261ecSmrg{
510405b261ecSmrgregister int	i;
510505b261ecSmrgchar *		wire;
510605b261ecSmrg
510705b261ecSmrg    wire= *wire_inout;
510805b261ecSmrg    if (req->nShapes<1) {
510905b261ecSmrg	client->errorValue= _XkbErrCode2(0x06,req->nShapes);
511005b261ecSmrg	return BadValue;
511105b261ecSmrg    }
511205b261ecSmrg    else {
511305b261ecSmrg	xkbShapeWireDesc *	shapeWire;
511405b261ecSmrg	XkbShapePtr		shape;
511505b261ecSmrg	register int		o;
511605b261ecSmrg	shapeWire= (xkbShapeWireDesc *)wire;
511705b261ecSmrg	for (i=0;i<req->nShapes;i++) {
511805b261ecSmrg	    xkbOutlineWireDesc *	olWire;
511905b261ecSmrg	    XkbOutlinePtr		ol;
512005b261ecSmrg	    shape= XkbAddGeomShape(geom,shapeWire->name,shapeWire->nOutlines);
512105b261ecSmrg	    if (!shape)
512205b261ecSmrg		return BadAlloc;
512305b261ecSmrg	    olWire= (xkbOutlineWireDesc *)(&shapeWire[1]);
512405b261ecSmrg	    for (o=0;o<shapeWire->nOutlines;o++) {
512505b261ecSmrg		register int		p;
512605b261ecSmrg		XkbPointPtr		pt;
512705b261ecSmrg		xkbPointWireDesc *	ptWire;
512805b261ecSmrg
512905b261ecSmrg		ol= XkbAddGeomOutline(shape,olWire->nPoints);
513005b261ecSmrg		if (!ol)
513105b261ecSmrg		    return BadAlloc;
513205b261ecSmrg		ol->corner_radius=	olWire->cornerRadius;
513305b261ecSmrg		ptWire= (xkbPointWireDesc *)&olWire[1];
513405b261ecSmrg		for (p=0,pt=ol->points;p<olWire->nPoints;p++,pt++) {
513505b261ecSmrg		    pt->x= ptWire[p].x;
513605b261ecSmrg		    pt->y= ptWire[p].y;
513705b261ecSmrg		    if (client->swapped) {
513805b261ecSmrg			register int n;
513905b261ecSmrg			swaps(&pt->x,n);
514005b261ecSmrg			swaps(&pt->y,n);
514105b261ecSmrg		    }
514205b261ecSmrg		}
514305b261ecSmrg		ol->num_points= olWire->nPoints;
514405b261ecSmrg		olWire= (xkbOutlineWireDesc *)(&ptWire[olWire->nPoints]);
514505b261ecSmrg	    }
514605b261ecSmrg	    if (shapeWire->primaryNdx!=XkbNoShape)
514705b261ecSmrg		shape->primary= &shape->outlines[shapeWire->primaryNdx];
514805b261ecSmrg	    if (shapeWire->approxNdx!=XkbNoShape)
514905b261ecSmrg		shape->approx= &shape->outlines[shapeWire->approxNdx];
515005b261ecSmrg	    shapeWire= (xkbShapeWireDesc *)olWire;
515105b261ecSmrg	}
515205b261ecSmrg	wire= (char *)shapeWire;
515305b261ecSmrg    }
515405b261ecSmrg    if (geom->num_shapes!=req->nShapes) {
515505b261ecSmrg	client->errorValue= _XkbErrCode3(0x07,geom->num_shapes,req->nShapes);
515605b261ecSmrg	return BadMatch;
515705b261ecSmrg    }
515805b261ecSmrg
515905b261ecSmrg    *wire_inout= wire;
516005b261ecSmrg    return Success;
516105b261ecSmrg}
516205b261ecSmrg
516305b261ecSmrgstatic Status
516405b261ecSmrg_CheckSetGeom(	XkbGeometryPtr		geom,
516505b261ecSmrg		xkbSetGeometryReq *	req,
516605b261ecSmrg		ClientPtr 		client)
516705b261ecSmrg{
516805b261ecSmrgregister int	i;
516905b261ecSmrgStatus		status;
517005b261ecSmrgchar *		wire;
517105b261ecSmrg
517205b261ecSmrg    wire= (char *)&req[1];
517305b261ecSmrg    geom->label_font= _GetCountedString(&wire,client->swapped);
517405b261ecSmrg
517505b261ecSmrg    for (i=0;i<req->nProperties;i++) {
517605b261ecSmrg	char *name,*val;
517705b261ecSmrg	name= _GetCountedString(&wire,client->swapped);
517805b261ecSmrg        if (!name)
517905b261ecSmrg            return BadAlloc;
518005b261ecSmrg	val= _GetCountedString(&wire,client->swapped);
518105b261ecSmrg        if (!val) {
518205b261ecSmrg            xfree(name);
518305b261ecSmrg            return BadAlloc;
518405b261ecSmrg        }
518505b261ecSmrg	if (XkbAddGeomProperty(geom,name,val)==NULL) {
518605b261ecSmrg            xfree(name);
518705b261ecSmrg            xfree(val);
518805b261ecSmrg	    return BadAlloc;
518905b261ecSmrg        }
519005b261ecSmrg        xfree(name);
519105b261ecSmrg        xfree(val);
519205b261ecSmrg    }
519305b261ecSmrg
519405b261ecSmrg    if (req->nColors<2) {
519505b261ecSmrg	client->errorValue= _XkbErrCode3(0x01,2,req->nColors);
519605b261ecSmrg	return BadValue;
519705b261ecSmrg    }
519805b261ecSmrg    if (req->baseColorNdx>req->nColors) {
519905b261ecSmrg	client->errorValue=_XkbErrCode3(0x03,req->nColors,req->baseColorNdx);
520005b261ecSmrg	return BadMatch;
520105b261ecSmrg    }
520205b261ecSmrg    if (req->labelColorNdx>req->nColors) {
520305b261ecSmrg	client->errorValue= _XkbErrCode3(0x03,req->nColors,req->labelColorNdx);
520405b261ecSmrg	return BadMatch;
520505b261ecSmrg    }
520605b261ecSmrg    if (req->labelColorNdx==req->baseColorNdx) {
520705b261ecSmrg	client->errorValue= _XkbErrCode3(0x04,req->baseColorNdx,
520805b261ecSmrg                                         req->labelColorNdx);
520905b261ecSmrg	return BadMatch;
521005b261ecSmrg    }
521105b261ecSmrg
521205b261ecSmrg    for (i=0;i<req->nColors;i++) {
521305b261ecSmrg	char *name;
521405b261ecSmrg	name= _GetCountedString(&wire,client->swapped);
521505b261ecSmrg	if (!name)
521605b261ecSmrg            return BadAlloc;
521705b261ecSmrg        if (!XkbAddGeomColor(geom,name,geom->num_colors)) {
521805b261ecSmrg            xfree(name);
521905b261ecSmrg	    return BadAlloc;
522005b261ecSmrg        }
522105b261ecSmrg        xfree(name);
522205b261ecSmrg    }
522305b261ecSmrg    if (req->nColors!=geom->num_colors) {
522405b261ecSmrg	client->errorValue= _XkbErrCode3(0x05,req->nColors,geom->num_colors);
522505b261ecSmrg	return BadMatch;
522605b261ecSmrg    }
522705b261ecSmrg    geom->label_color= &geom->colors[req->labelColorNdx];
522805b261ecSmrg    geom->base_color= &geom->colors[req->baseColorNdx];
522905b261ecSmrg
523005b261ecSmrg    if ((status=_CheckSetShapes(geom,req,&wire,client))!=Success)
523105b261ecSmrg	return status;
523205b261ecSmrg
523305b261ecSmrg    if ((status=_CheckSetSections(geom,req,&wire,client))!=Success)
523405b261ecSmrg	return status;
523505b261ecSmrg
523605b261ecSmrg    for (i=0;i<req->nDoodads;i++) {
523705b261ecSmrg	status=_CheckSetDoodad(&wire,geom,NULL,client);
523805b261ecSmrg	if (status!=Success)
523905b261ecSmrg	    return status;
524005b261ecSmrg    }
524105b261ecSmrg
524205b261ecSmrg    for (i=0;i<req->nKeyAliases;i++) {
524305b261ecSmrg	if (XkbAddGeomKeyAlias(geom,&wire[XkbKeyNameLength],wire)==NULL)
524405b261ecSmrg	    return BadAlloc;
524505b261ecSmrg	wire+= 2*XkbKeyNameLength;
524605b261ecSmrg    }
524705b261ecSmrg    return Success;
524805b261ecSmrg}
524905b261ecSmrg
52504642e01fSmrgstatic int
52514642e01fSmrg_XkbSetGeometry(ClientPtr client, DeviceIntPtr dev, xkbSetGeometryReq *stuff)
525205b261ecSmrg{
525305b261ecSmrg    XkbDescPtr		xkb;
525405b261ecSmrg    Bool		new_name;
525505b261ecSmrg    xkbNewKeyboardNotify	nkn;
52564642e01fSmrg    XkbGeometryPtr	geom,old;
52574642e01fSmrg    XkbGeometrySizesRec	sizes;
52584642e01fSmrg    Status		status;
525905b261ecSmrg
526005b261ecSmrg    xkb= dev->key->xkbInfo->desc;
526105b261ecSmrg    old= xkb->geom;
526205b261ecSmrg    xkb->geom= NULL;
526305b261ecSmrg
52644642e01fSmrg    sizes.which=		XkbGeomAllMask;
526505b261ecSmrg    sizes.num_properties=	stuff->nProperties;
52664642e01fSmrg    sizes.num_colors=	stuff->nColors;
52674642e01fSmrg    sizes.num_shapes=	stuff->nShapes;
52684642e01fSmrg    sizes.num_sections=	stuff->nSections;
52694642e01fSmrg    sizes.num_doodads=	stuff->nDoodads;
527005b261ecSmrg    sizes.num_key_aliases=	stuff->nKeyAliases;
527105b261ecSmrg    if ((status= XkbAllocGeometry(xkb,&sizes))!=Success) {
52724642e01fSmrg        xkb->geom= old;
52734642e01fSmrg        return status;
527405b261ecSmrg    }
527505b261ecSmrg    geom= xkb->geom;
527605b261ecSmrg    geom->name= stuff->name;
527705b261ecSmrg    geom->width_mm= stuff->widthMM;
527805b261ecSmrg    geom->height_mm= stuff->heightMM;
527905b261ecSmrg    if ((status= _CheckSetGeom(geom,stuff,client))!=Success) {
52804642e01fSmrg        XkbFreeGeometry(geom,XkbGeomAllMask,True);
52814642e01fSmrg        xkb->geom= old;
52824642e01fSmrg        return status;
528305b261ecSmrg    }
528405b261ecSmrg    new_name= (xkb->names->geometry!=geom->name);
528505b261ecSmrg    xkb->names->geometry= geom->name;
528605b261ecSmrg    if (old)
52874642e01fSmrg        XkbFreeGeometry(old,XkbGeomAllMask,True);
528805b261ecSmrg    if (new_name) {
52894642e01fSmrg        xkbNamesNotify	nn;
52904642e01fSmrg        bzero(&nn,sizeof(xkbNamesNotify));
52914642e01fSmrg        nn.changed= XkbGeometryNameMask;
52924642e01fSmrg        XkbSendNamesNotify(dev,&nn);
529305b261ecSmrg    }
529405b261ecSmrg    nkn.deviceID= nkn.oldDeviceID= dev->id;
529505b261ecSmrg    nkn.minKeyCode= nkn.oldMinKeyCode= xkb->min_key_code;
529605b261ecSmrg    nkn.maxKeyCode= nkn.oldMaxKeyCode= xkb->max_key_code;
529705b261ecSmrg    nkn.requestMajor=	XkbReqCode;
529805b261ecSmrg    nkn.requestMinor=	X_kbSetGeometry;
529905b261ecSmrg    nkn.changed=	XkbNKN_GeometryMask;
530005b261ecSmrg    XkbSendNewKeyboardNotify(dev,&nkn);
530105b261ecSmrg    return Success;
530205b261ecSmrg}
530305b261ecSmrg
53044642e01fSmrgint
53054642e01fSmrgProcXkbSetGeometry(ClientPtr client)
53064642e01fSmrg{
53074642e01fSmrg    DeviceIntPtr        dev;
53084642e01fSmrg    int                 rc;
53094642e01fSmrg
53104642e01fSmrg    REQUEST(xkbSetGeometryReq);
53114642e01fSmrg    REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq);
53124642e01fSmrg
53134642e01fSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
53144642e01fSmrg	return BadAccess;
53154642e01fSmrg
53164642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
53174642e01fSmrg    CHK_ATOM_OR_NONE(stuff->name);
53184642e01fSmrg
53194642e01fSmrg    rc = _XkbSetGeometry(client, dev, stuff);
53204642e01fSmrg    if (rc != Success)
53214642e01fSmrg        return rc;
53224642e01fSmrg
53234642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd)
53244642e01fSmrg    {
53254642e01fSmrg        DeviceIntPtr other;
53264642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
53274642e01fSmrg        {
53284642e01fSmrg            if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
53294642e01fSmrg            {
53304642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
53314642e01fSmrg                if (rc == Success)
53324642e01fSmrg                    _XkbSetGeometry(client, other, stuff);
53334642e01fSmrg            }
53344642e01fSmrg        }
53354642e01fSmrg    }
53364642e01fSmrg
53374642e01fSmrg    return Success;
53384642e01fSmrg}
53394642e01fSmrg
534005b261ecSmrg/***====================================================================***/
534105b261ecSmrg
534205b261ecSmrgint
534305b261ecSmrgProcXkbPerClientFlags(ClientPtr client)
534405b261ecSmrg{
534505b261ecSmrg    DeviceIntPtr 		dev;
534605b261ecSmrg    xkbPerClientFlagsReply 	rep;
534705b261ecSmrg    XkbInterestPtr		interest;
53484642e01fSmrg    Mask access_mode = DixGetAttrAccess | DixSetAttrAccess;
534905b261ecSmrg
535005b261ecSmrg    REQUEST(xkbPerClientFlagsReq);
535105b261ecSmrg    REQUEST_SIZE_MATCH(xkbPerClientFlagsReq);
535205b261ecSmrg
535305b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
535405b261ecSmrg	return BadAccess;
535505b261ecSmrg
53564642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
535705b261ecSmrg    CHK_MASK_LEGAL(0x01,stuff->change,XkbPCF_AllFlagsMask);
535805b261ecSmrg    CHK_MASK_MATCH(0x02,stuff->change,stuff->value);
535905b261ecSmrg
536005b261ecSmrg    interest = XkbFindClientResource((DevicePtr)dev,client);
536105b261ecSmrg    rep.type= X_Reply;
536205b261ecSmrg    rep.length = 0;
536305b261ecSmrg    rep.sequenceNumber = client->sequence;
536405b261ecSmrg    if (stuff->change) {
536505b261ecSmrg	client->xkbClientFlags&= ~stuff->change;
536605b261ecSmrg	client->xkbClientFlags|= stuff->value;
536705b261ecSmrg    }
536805b261ecSmrg    if (stuff->change&XkbPCF_AutoResetControlsMask) {
536905b261ecSmrg	Bool	want;
537005b261ecSmrg	want= stuff->value&XkbPCF_AutoResetControlsMask;
537105b261ecSmrg	if (interest && !want) {
537205b261ecSmrg	    interest->autoCtrls= interest->autoCtrlValues= 0;
537305b261ecSmrg	}
537405b261ecSmrg	else if (want && (!interest)) {
537505b261ecSmrg	    XID id = FakeClientID(client->index);
537605b261ecSmrg	    AddResource(id,RT_XKBCLIENT,dev);
537705b261ecSmrg	    interest= XkbAddClientResource((DevicePtr)dev,client,id);
537805b261ecSmrg	    if (!interest)
537905b261ecSmrg		return BadAlloc;
538005b261ecSmrg	}
538105b261ecSmrg	if (interest && want ) {
538205b261ecSmrg	    register unsigned affect;
538305b261ecSmrg	    affect= stuff->ctrlsToChange;
538405b261ecSmrg
538505b261ecSmrg	    CHK_MASK_LEGAL(0x03,affect,XkbAllBooleanCtrlsMask);
538605b261ecSmrg	    CHK_MASK_MATCH(0x04,affect,stuff->autoCtrls);
538705b261ecSmrg	    CHK_MASK_MATCH(0x05,stuff->autoCtrls,stuff->autoCtrlValues);
538805b261ecSmrg
538905b261ecSmrg	    interest->autoCtrls&= ~affect;
539005b261ecSmrg	    interest->autoCtrlValues&= ~affect;
539105b261ecSmrg	    interest->autoCtrls|= stuff->autoCtrls&affect;
539205b261ecSmrg	    interest->autoCtrlValues|= stuff->autoCtrlValues&affect;
539305b261ecSmrg	}
539405b261ecSmrg    }
539505b261ecSmrg    rep.supported = XkbPCF_AllFlagsMask;
539605b261ecSmrg    rep.value= client->xkbClientFlags&XkbPCF_AllFlagsMask;
539705b261ecSmrg    if (interest) {
539805b261ecSmrg	rep.autoCtrls= interest->autoCtrls;
539905b261ecSmrg	rep.autoCtrlValues= interest->autoCtrlValues;
540005b261ecSmrg    }
540105b261ecSmrg    else {
540205b261ecSmrg	rep.autoCtrls= rep.autoCtrlValues= 0;
540305b261ecSmrg    }
540405b261ecSmrg    if ( client->swapped ) {
540505b261ecSmrg	register int n;
540605b261ecSmrg	swaps(&rep.sequenceNumber, n);
540705b261ecSmrg	swapl(&rep.supported,n);
540805b261ecSmrg	swapl(&rep.value,n);
540905b261ecSmrg	swapl(&rep.autoCtrls,n);
541005b261ecSmrg	swapl(&rep.autoCtrlValues,n);
541105b261ecSmrg    }
541205b261ecSmrg    WriteToClient(client,SIZEOF(xkbPerClientFlagsReply), (char *)&rep);
541305b261ecSmrg    return client->noClientException;
541405b261ecSmrg}
541505b261ecSmrg
541605b261ecSmrg/***====================================================================***/
541705b261ecSmrg
541805b261ecSmrg/* all latin-1 alphanumerics, plus parens, minus, underscore, slash */
541905b261ecSmrg/* and wildcards */
542005b261ecSmrgstatic unsigned char componentSpecLegal[] = {
542105b261ecSmrg        0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x87,
542205b261ecSmrg        0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07,
542305b261ecSmrg        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
542405b261ecSmrg        0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
542505b261ecSmrg};
542605b261ecSmrg
542705b261ecSmrg/* same as above but accepts percent, plus and bar too */
542805b261ecSmrgstatic unsigned char componentExprLegal[] = {
542905b261ecSmrg        0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0xff, 0x87,
543005b261ecSmrg        0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x17,
543105b261ecSmrg        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
543205b261ecSmrg        0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
543305b261ecSmrg};
543405b261ecSmrg
543505b261ecSmrgstatic char *
543605b261ecSmrgGetComponentSpec(unsigned char **pWire,Bool allowExpr,int *errRtrn)
543705b261ecSmrg{
543805b261ecSmrgint		len;
543905b261ecSmrgregister int	i;
544005b261ecSmrgunsigned char	*wire,*str,*tmp,*legal;
544105b261ecSmrg
544205b261ecSmrg    if (allowExpr)	legal= &componentExprLegal[0];
544305b261ecSmrg    else		legal= &componentSpecLegal[0];
544405b261ecSmrg
544505b261ecSmrg    wire= *pWire;
544605b261ecSmrg    len= (*(unsigned char *)wire++);
544705b261ecSmrg    if (len>0) {
544805b261ecSmrg	str= (unsigned char *)_XkbCalloc(1, len+1);
544905b261ecSmrg	if (str) {
545005b261ecSmrg	    tmp= str;
545105b261ecSmrg	    for (i=0;i<len;i++) {
545205b261ecSmrg		if (legal[(*wire)/8]&(1<<((*wire)%8)))
545305b261ecSmrg		    *tmp++= *wire++;
545405b261ecSmrg		else wire++;
545505b261ecSmrg	    }
545605b261ecSmrg	    if (tmp!=str)
545705b261ecSmrg		*tmp++= '\0';
545805b261ecSmrg	    else {
545905b261ecSmrg		_XkbFree(str);
546005b261ecSmrg		str= NULL;
546105b261ecSmrg	    }
546205b261ecSmrg	}
546305b261ecSmrg	else {
546405b261ecSmrg	    *errRtrn= BadAlloc;
546505b261ecSmrg	}
546605b261ecSmrg    }
546705b261ecSmrg    else {
546805b261ecSmrg	str= NULL;
546905b261ecSmrg    }
547005b261ecSmrg    *pWire= wire;
547105b261ecSmrg    return (char *)str;
547205b261ecSmrg}
547305b261ecSmrg
547405b261ecSmrg/***====================================================================***/
547505b261ecSmrg
547605b261ecSmrgint
547705b261ecSmrgProcXkbListComponents(ClientPtr client)
547805b261ecSmrg{
547905b261ecSmrg    DeviceIntPtr 		dev;
548005b261ecSmrg    xkbListComponentsReply 	rep;
548105b261ecSmrg    unsigned			len;
548205b261ecSmrg    int				status;
548305b261ecSmrg    unsigned char *		str;
548405b261ecSmrg    XkbSrvListInfoRec		list;
548505b261ecSmrg
548605b261ecSmrg    REQUEST(xkbListComponentsReq);
548705b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbListComponentsReq);
548805b261ecSmrg
548905b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
549005b261ecSmrg	return BadAccess;
549105b261ecSmrg
54924642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
549305b261ecSmrg
549405b261ecSmrg    status= Success;
549505b261ecSmrg    str= (unsigned char *)&stuff[1];
549605b261ecSmrg    bzero(&list,sizeof(XkbSrvListInfoRec));
549705b261ecSmrg    list.maxRtrn= stuff->maxNames;
549805b261ecSmrg    list.pattern[_XkbListKeymaps]= GetComponentSpec(&str,False,&status);
549905b261ecSmrg    list.pattern[_XkbListKeycodes]= GetComponentSpec(&str,False,&status);
550005b261ecSmrg    list.pattern[_XkbListTypes]= GetComponentSpec(&str,False,&status);
550105b261ecSmrg    list.pattern[_XkbListCompat]= GetComponentSpec(&str,False,&status);
550205b261ecSmrg    list.pattern[_XkbListSymbols]= GetComponentSpec(&str,False,&status);
550305b261ecSmrg    list.pattern[_XkbListGeometry]= GetComponentSpec(&str,False,&status);
550405b261ecSmrg    if (status!=Success)
550505b261ecSmrg	return status;
550605b261ecSmrg    len= str-((unsigned char *)stuff);
550705b261ecSmrg    if ((XkbPaddedSize(len)/4)!=stuff->length)
550805b261ecSmrg	return BadLength;
550905b261ecSmrg    if ((status=XkbDDXList(dev,&list,client))!=Success) {
551005b261ecSmrg	if (list.pool) {
551105b261ecSmrg	    _XkbFree(list.pool);
551205b261ecSmrg	    list.pool= NULL;
551305b261ecSmrg	}
551405b261ecSmrg	return status;
551505b261ecSmrg    }
551605b261ecSmrg    bzero(&rep,sizeof(xkbListComponentsReply));
551705b261ecSmrg    rep.type= X_Reply;
551805b261ecSmrg    rep.deviceID = dev->id;
551905b261ecSmrg    rep.sequenceNumber = client->sequence;
552005b261ecSmrg    rep.length = XkbPaddedSize(list.nPool)/4;
552105b261ecSmrg    rep.nKeymaps = list.nFound[_XkbListKeymaps];
552205b261ecSmrg    rep.nKeycodes = list.nFound[_XkbListKeycodes];
552305b261ecSmrg    rep.nTypes = list.nFound[_XkbListTypes];
552405b261ecSmrg    rep.nCompatMaps = list.nFound[_XkbListCompat];
552505b261ecSmrg    rep.nSymbols = list.nFound[_XkbListSymbols];
552605b261ecSmrg    rep.nGeometries = list.nFound[_XkbListGeometry];
552705b261ecSmrg    rep.extra=	0;
552805b261ecSmrg    if (list.nTotal>list.maxRtrn)
552905b261ecSmrg	rep.extra = (list.nTotal-list.maxRtrn);
553005b261ecSmrg    if (client->swapped) {
553105b261ecSmrg	register int n;
553205b261ecSmrg	swaps(&rep.sequenceNumber,n);
553305b261ecSmrg	swapl(&rep.length,n);
553405b261ecSmrg	swaps(&rep.nKeymaps,n);
553505b261ecSmrg	swaps(&rep.nKeycodes,n);
553605b261ecSmrg	swaps(&rep.nTypes,n);
553705b261ecSmrg	swaps(&rep.nCompatMaps,n);
553805b261ecSmrg	swaps(&rep.nSymbols,n);
553905b261ecSmrg	swaps(&rep.nGeometries,n);
554005b261ecSmrg	swaps(&rep.extra,n);
554105b261ecSmrg    }
554205b261ecSmrg    WriteToClient(client,SIZEOF(xkbListComponentsReply),(char *)&rep);
554305b261ecSmrg    if (list.nPool && list.pool) {
554405b261ecSmrg	WriteToClient(client,XkbPaddedSize(list.nPool), (char *)list.pool);
554505b261ecSmrg	_XkbFree(list.pool);
554605b261ecSmrg	list.pool= NULL;
554705b261ecSmrg    }
554805b261ecSmrg    return client->noClientException;
554905b261ecSmrg}
555005b261ecSmrg
555105b261ecSmrg/***====================================================================***/
555205b261ecSmrg
555305b261ecSmrgint
555405b261ecSmrgProcXkbGetKbdByName(ClientPtr client)
555505b261ecSmrg{
555605b261ecSmrg    DeviceIntPtr 		dev;
555705b261ecSmrg    DeviceIntPtr                tmpd;
555805b261ecSmrg    xkbGetKbdByNameReply 	rep;
555905b261ecSmrg    xkbGetMapReply		mrep;
556005b261ecSmrg    xkbGetCompatMapReply	crep;
556105b261ecSmrg    xkbGetIndicatorMapReply	irep;
556205b261ecSmrg    xkbGetNamesReply		nrep;
556305b261ecSmrg    xkbGetGeometryReply		grep;
556405b261ecSmrg    XkbComponentNamesRec	names;
55654642e01fSmrg    XkbDescPtr			xkb, new;
556605b261ecSmrg    unsigned char *		str;
556705b261ecSmrg    char 			mapFile[PATH_MAX];
556805b261ecSmrg    unsigned			len;
556905b261ecSmrg    unsigned			fwant,fneed,reported;
557005b261ecSmrg    int				status;
557105b261ecSmrg    Bool			geom_changed;
557205b261ecSmrg    XkbSrvLedInfoPtr            old_sli;
557305b261ecSmrg    XkbSrvLedInfoPtr            sli;
55744642e01fSmrg    Mask access_mode = DixGetAttrAccess | DixManageAccess;
557505b261ecSmrg
557605b261ecSmrg    REQUEST(xkbGetKbdByNameReq);
557705b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq);
557805b261ecSmrg
557905b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
558005b261ecSmrg	return BadAccess;
558105b261ecSmrg
55824642e01fSmrg    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
558305b261ecSmrg
558405b261ecSmrg    xkb = dev->key->xkbInfo->desc;
558505b261ecSmrg    status= Success;
558605b261ecSmrg    str= (unsigned char *)&stuff[1];
558705b261ecSmrg    names.keymap= GetComponentSpec(&str,True,&status);
558805b261ecSmrg    names.keycodes= GetComponentSpec(&str,True,&status);
558905b261ecSmrg    names.types= GetComponentSpec(&str,True,&status);
559005b261ecSmrg    names.compat= GetComponentSpec(&str,True,&status);
559105b261ecSmrg    names.symbols= GetComponentSpec(&str,True,&status);
559205b261ecSmrg    names.geometry= GetComponentSpec(&str,True,&status);
559305b261ecSmrg    if (status!=Success)
559405b261ecSmrg	return status;
559505b261ecSmrg    len= str-((unsigned char *)stuff);
559605b261ecSmrg    if ((XkbPaddedSize(len)/4)!=stuff->length)
559705b261ecSmrg	return BadLength;
559805b261ecSmrg
559905b261ecSmrg    CHK_MASK_LEGAL(0x01,stuff->want,XkbGBN_AllComponentsMask);
560005b261ecSmrg    CHK_MASK_LEGAL(0x02,stuff->need,XkbGBN_AllComponentsMask);
560105b261ecSmrg
560205b261ecSmrg    if (stuff->load)
560305b261ecSmrg	 fwant= XkbGBN_AllComponentsMask;
560405b261ecSmrg    else fwant= stuff->want|stuff->need;
56054642e01fSmrg    if ((!names.compat)&&
56064642e01fSmrg        (fwant&(XkbGBN_CompatMapMask|XkbGBN_IndicatorMapMask))) {
56074642e01fSmrg        names.compat= _XkbDupString("%");
560805b261ecSmrg    }
56094642e01fSmrg    if ((!names.types)&&(fwant&(XkbGBN_TypesMask))) {
56104642e01fSmrg        names.types= _XkbDupString("%");
56114642e01fSmrg    }
56124642e01fSmrg    if ((!names.symbols)&&(fwant&XkbGBN_SymbolsMask)) {
56134642e01fSmrg        names.symbols= _XkbDupString("%");
56144642e01fSmrg    }
56154642e01fSmrg    geom_changed= ((names.geometry!=NULL)&&(strcmp(names.geometry,"%")!=0));
56164642e01fSmrg    if ((!names.geometry)&&(fwant&XkbGBN_GeometryMask)) {
56174642e01fSmrg        names.geometry= _XkbDupString("%");
56184642e01fSmrg        geom_changed= False;
561905b261ecSmrg    }
562005b261ecSmrg
562105b261ecSmrg    bzero(mapFile,PATH_MAX);
562205b261ecSmrg    rep.type= X_Reply;
562305b261ecSmrg    rep.deviceID = dev->id;
562405b261ecSmrg    rep.sequenceNumber = client->sequence;
562505b261ecSmrg    rep.length = 0;
562605b261ecSmrg    rep.minKeyCode = xkb->min_key_code;
562705b261ecSmrg    rep.maxKeyCode = xkb->max_key_code;
562805b261ecSmrg    rep.loaded=	False;
562905b261ecSmrg    fwant= XkbConvertGetByNameComponents(True,stuff->want)|XkmVirtualModsMask;
563005b261ecSmrg    fneed= XkbConvertGetByNameComponents(True,stuff->need);
563105b261ecSmrg    rep.reported= XkbConvertGetByNameComponents(False,fwant|fneed);
563205b261ecSmrg    if (stuff->load) {
563305b261ecSmrg	fneed|= XkmKeymapRequired;
563405b261ecSmrg	fwant|= XkmKeymapLegal;
563505b261ecSmrg    }
563605b261ecSmrg    if ((fwant|fneed)&XkmSymbolsMask) {
563705b261ecSmrg	fneed|= XkmKeyNamesIndex|XkmTypesIndex;
563805b261ecSmrg	fwant|= XkmIndicatorsIndex;
563905b261ecSmrg    }
564005b261ecSmrg
564105b261ecSmrg    /* We pass dev in here so we can get the old names out if needed. */
56424642e01fSmrg    rep.found = XkbDDXLoadKeymapByNames(dev,&names,fwant,fneed,&new,
564305b261ecSmrg                                        mapFile,PATH_MAX);
564405b261ecSmrg    rep.newKeyboard= False;
564505b261ecSmrg    rep.pad1= rep.pad2= rep.pad3= rep.pad4= 0;
564605b261ecSmrg
564705b261ecSmrg    stuff->want|= stuff->need;
56484642e01fSmrg    if (new==NULL)
564905b261ecSmrg	rep.reported= 0;
565005b261ecSmrg    else {
565105b261ecSmrg	if (stuff->load)
565205b261ecSmrg	    rep.loaded= True;
565305b261ecSmrg	if (stuff->load ||
56544642e01fSmrg		((rep.reported&XkbGBN_SymbolsMask) && (new->compat))) {
565505b261ecSmrg	    XkbChangesRec changes;
565605b261ecSmrg	    bzero(&changes,sizeof(changes));
56574642e01fSmrg	    XkbUpdateDescActions(new,
56584642e01fSmrg			new->min_key_code,XkbNumKeys(new),
565905b261ecSmrg			&changes);
566005b261ecSmrg	}
566105b261ecSmrg
56624642e01fSmrg	if (new->map==NULL)
566305b261ecSmrg	    rep.reported&= ~(XkbGBN_SymbolsMask|XkbGBN_TypesMask);
566405b261ecSmrg	else if (rep.reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask)) {
566505b261ecSmrg	    mrep.type= X_Reply;
566605b261ecSmrg	    mrep.deviceID = dev->id;
566705b261ecSmrg	    mrep.sequenceNumber= client->sequence;
566805b261ecSmrg	    mrep.length = ((SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2);
56694642e01fSmrg	    mrep.minKeyCode = new->min_key_code;
56704642e01fSmrg	    mrep.maxKeyCode = new->max_key_code;
567105b261ecSmrg	    mrep.present = 0;
567205b261ecSmrg	    mrep.totalSyms = mrep.totalActs =
567305b261ecSmrg		mrep.totalKeyBehaviors= mrep.totalKeyExplicit=
567405b261ecSmrg		mrep.totalModMapKeys= 0;
567505b261ecSmrg	    if (rep.reported&(XkbGBN_TypesMask|XkbGBN_ClientSymbolsMask)) {
567605b261ecSmrg		mrep.present|= XkbKeyTypesMask;
567705b261ecSmrg		mrep.firstType = 0;
56784642e01fSmrg		mrep.nTypes = mrep.totalTypes= new->map->num_types;
567905b261ecSmrg	    }
568005b261ecSmrg	    else {
568105b261ecSmrg		mrep.firstType = mrep.nTypes= 0;
568205b261ecSmrg		mrep.totalTypes= 0;
568305b261ecSmrg	    }
568405b261ecSmrg	    if (rep.reported&XkbGBN_ClientSymbolsMask) {
568505b261ecSmrg		mrep.present|= (XkbKeySymsMask|XkbModifierMapMask);
56864642e01fSmrg		mrep.firstKeySym = mrep.firstModMapKey= new->min_key_code;
56874642e01fSmrg		mrep.nKeySyms = mrep.nModMapKeys= XkbNumKeys(new);
568805b261ecSmrg	    }
568905b261ecSmrg	    else {
569005b261ecSmrg		mrep.firstKeySym= mrep.firstModMapKey= 0;
569105b261ecSmrg		mrep.nKeySyms= mrep.nModMapKeys= 0;
569205b261ecSmrg	    }
569305b261ecSmrg	    if (rep.reported&XkbGBN_ServerSymbolsMask) {
569405b261ecSmrg		mrep.present|= XkbAllServerInfoMask;
569505b261ecSmrg		mrep.virtualMods= ~0;
569605b261ecSmrg		mrep.firstKeyAct = mrep.firstKeyBehavior =
56974642e01fSmrg			mrep.firstKeyExplicit = new->min_key_code;
569805b261ecSmrg		mrep.nKeyActs = mrep.nKeyBehaviors =
56994642e01fSmrg			mrep.nKeyExplicit = XkbNumKeys(new);
570005b261ecSmrg	    }
570105b261ecSmrg	    else {
570205b261ecSmrg		mrep.virtualMods= 0;
570305b261ecSmrg		mrep.firstKeyAct= mrep.firstKeyBehavior=
570405b261ecSmrg			mrep.firstKeyExplicit = 0;
570505b261ecSmrg		mrep.nKeyActs= mrep.nKeyBehaviors= mrep.nKeyExplicit= 0;
570605b261ecSmrg	    }
57074642e01fSmrg	    XkbComputeGetMapReplySize(new,&mrep);
570805b261ecSmrg	    rep.length+= SIZEOF(xGenericReply)/4+mrep.length;
570905b261ecSmrg	}
57104642e01fSmrg	if (new->compat==NULL)
571105b261ecSmrg	    rep.reported&= ~XkbGBN_CompatMapMask;
571205b261ecSmrg	else if (rep.reported&XkbGBN_CompatMapMask) {
571305b261ecSmrg	    crep.type= X_Reply;
571405b261ecSmrg	    crep.deviceID= dev->id;
571505b261ecSmrg	    crep.sequenceNumber= client->sequence;
571605b261ecSmrg	    crep.length= 0;
571705b261ecSmrg	    crep.groups= XkbAllGroupsMask;
571805b261ecSmrg	    crep.firstSI= 0;
57194642e01fSmrg	    crep.nSI= crep.nTotalSI= new->compat->num_si;
57204642e01fSmrg	    XkbComputeGetCompatMapReplySize(new->compat,&crep);
572105b261ecSmrg	    rep.length+= SIZEOF(xGenericReply)/4+crep.length;
572205b261ecSmrg	}
57234642e01fSmrg	if (new->indicators==NULL)
572405b261ecSmrg	    rep.reported&= ~XkbGBN_IndicatorMapMask;
572505b261ecSmrg	else if (rep.reported&XkbGBN_IndicatorMapMask) {
572605b261ecSmrg	    irep.type= X_Reply;
572705b261ecSmrg	    irep.deviceID= dev->id;
572805b261ecSmrg	    irep.sequenceNumber= client->sequence;
572905b261ecSmrg	    irep.length= 0;
573005b261ecSmrg	    irep.which= XkbAllIndicatorsMask;
57314642e01fSmrg	    XkbComputeGetIndicatorMapReplySize(new->indicators,&irep);
573205b261ecSmrg	    rep.length+= SIZEOF(xGenericReply)/4+irep.length;
573305b261ecSmrg	}
57344642e01fSmrg	if (new->names==NULL)
573505b261ecSmrg	    rep.reported&= ~(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask);
573605b261ecSmrg	else if (rep.reported&(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask)) {
573705b261ecSmrg	    nrep.type= X_Reply;
573805b261ecSmrg	    nrep.deviceID= dev->id;
573905b261ecSmrg	    nrep.sequenceNumber= client->sequence;
574005b261ecSmrg	    nrep.length= 0;
57414642e01fSmrg	    nrep.minKeyCode= new->min_key_code;
57424642e01fSmrg	    nrep.maxKeyCode= new->max_key_code;
574305b261ecSmrg	    if (rep.reported&XkbGBN_OtherNamesMask) {
574405b261ecSmrg		nrep.which= XkbAllNamesMask;
57454642e01fSmrg		if (new->map!=NULL)
57464642e01fSmrg		     nrep.nTypes= new->map->num_types;
574705b261ecSmrg		else nrep.nTypes= 0;
574805b261ecSmrg		nrep.nKTLevels= 0;
574905b261ecSmrg		nrep.groupNames= XkbAllGroupsMask;
575005b261ecSmrg		nrep.virtualMods= XkbAllVirtualModsMask;
575105b261ecSmrg		nrep.indicators= XkbAllIndicatorsMask;
57524642e01fSmrg		nrep.nRadioGroups= new->names->num_rg;
575305b261ecSmrg	    }
575405b261ecSmrg	    else {
575505b261ecSmrg		nrep.which= 0;
575605b261ecSmrg		nrep.nTypes= 0;
575705b261ecSmrg		nrep.nKTLevels= 0;
575805b261ecSmrg		nrep.groupNames= 0;
575905b261ecSmrg		nrep.virtualMods= 0;
576005b261ecSmrg		nrep.indicators= 0;
576105b261ecSmrg		nrep.nRadioGroups= 0;
576205b261ecSmrg	    }
576305b261ecSmrg	    if (rep.reported&XkbGBN_KeyNamesMask) {
576405b261ecSmrg		nrep.which|= XkbKeyNamesMask;
57654642e01fSmrg		nrep.firstKey= new->min_key_code;
57664642e01fSmrg		nrep.nKeys= XkbNumKeys(new);
57674642e01fSmrg		nrep.nKeyAliases= new->names->num_key_aliases;
576805b261ecSmrg		if (nrep.nKeyAliases)
576905b261ecSmrg		    nrep.which|= XkbKeyAliasesMask;
577005b261ecSmrg	    }
577105b261ecSmrg	    else {
577205b261ecSmrg		nrep.which&= ~(XkbKeyNamesMask|XkbKeyAliasesMask);
577305b261ecSmrg		nrep.firstKey= nrep.nKeys= 0;
577405b261ecSmrg		nrep.nKeyAliases= 0;
577505b261ecSmrg	    }
57764642e01fSmrg	    XkbComputeGetNamesReplySize(new,&nrep);
577705b261ecSmrg	    rep.length+= SIZEOF(xGenericReply)/4+nrep.length;
577805b261ecSmrg	}
57794642e01fSmrg	if (new->geom==NULL)
578005b261ecSmrg	    rep.reported&= ~XkbGBN_GeometryMask;
578105b261ecSmrg	else if (rep.reported&XkbGBN_GeometryMask) {
578205b261ecSmrg	    grep.type= X_Reply;
578305b261ecSmrg	    grep.deviceID= dev->id;
578405b261ecSmrg	    grep.sequenceNumber= client->sequence;
578505b261ecSmrg	    grep.length= 0;
578605b261ecSmrg	    grep.found= True;
578705b261ecSmrg	    grep.pad= 0;
578805b261ecSmrg	    grep.widthMM= grep.heightMM= 0;
578905b261ecSmrg	    grep.nProperties= grep.nColors= grep.nShapes= 0;
579005b261ecSmrg	    grep.nSections= grep.nDoodads= 0;
579105b261ecSmrg	    grep.baseColorNdx= grep.labelColorNdx= 0;
57924642e01fSmrg	    XkbComputeGetGeometryReplySize(new->geom,&grep,None);
579305b261ecSmrg	    rep.length+= SIZEOF(xGenericReply)/4+grep.length;
579405b261ecSmrg	}
579505b261ecSmrg    }
579605b261ecSmrg
579705b261ecSmrg    reported= rep.reported;
579805b261ecSmrg    if ( client->swapped ) {
579905b261ecSmrg	register int n;
580005b261ecSmrg	swaps(&rep.sequenceNumber,n);
580105b261ecSmrg	swapl(&rep.length,n);
580205b261ecSmrg	swaps(&rep.found,n);
580305b261ecSmrg	swaps(&rep.reported,n);
580405b261ecSmrg    }
580505b261ecSmrg    WriteToClient(client,SIZEOF(xkbGetKbdByNameReply), (char *)&rep);
580605b261ecSmrg    if (reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask))
58074642e01fSmrg	XkbSendMap(client,new,&mrep);
580805b261ecSmrg    if (reported&XkbGBN_CompatMapMask)
58094642e01fSmrg	XkbSendCompatMap(client,new->compat,&crep);
581005b261ecSmrg    if (reported&XkbGBN_IndicatorMapMask)
58114642e01fSmrg	XkbSendIndicatorMap(client,new->indicators,&irep);
581205b261ecSmrg    if (reported&(XkbGBN_KeyNamesMask|XkbGBN_OtherNamesMask))
58134642e01fSmrg	XkbSendNames(client,new,&nrep);
581405b261ecSmrg    if (reported&XkbGBN_GeometryMask)
58154642e01fSmrg	XkbSendGeometry(client,new->geom,&grep,False);
581605b261ecSmrg    if (rep.loaded) {
581705b261ecSmrg	XkbDescPtr		old_xkb;
581805b261ecSmrg	xkbNewKeyboardNotify 	nkn;
581905b261ecSmrg	int 			i,nG,nTG;
582005b261ecSmrg	old_xkb= xkb;
58214642e01fSmrg	xkb= new;
582205b261ecSmrg	dev->key->xkbInfo->desc= xkb;
58234642e01fSmrg	new= old_xkb; /* so it'll get freed automatically */
582405b261ecSmrg
582505b261ecSmrg	*xkb->ctrls= *old_xkb->ctrls;
582605b261ecSmrg	for (nG=nTG=0,i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
582705b261ecSmrg	    nG= XkbKeyNumGroups(xkb,i);
582805b261ecSmrg	    if (nG>=XkbNumKbdGroups) {
582905b261ecSmrg		nTG= XkbNumKbdGroups;
583005b261ecSmrg		break;
583105b261ecSmrg	    }
583205b261ecSmrg	    if (nG>nTG) {
583305b261ecSmrg		nTG= nG;
583405b261ecSmrg	    }
583505b261ecSmrg	}
583605b261ecSmrg	xkb->ctrls->num_groups= nTG;
583705b261ecSmrg
583805b261ecSmrg        for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
583905b261ecSmrg            if (tmpd == dev ||
584005b261ecSmrg                (dev->id == inputInfo.keyboard->id && tmpd->key &&
584105b261ecSmrg                 tmpd->coreEvents)) {
584205b261ecSmrg
584305b261ecSmrg                memcpy(tmpd->key->modifierMap, xkb->map->modmap,
584405b261ecSmrg                       xkb->max_key_code + 1);
584505b261ecSmrg                if (tmpd != dev)
584605b261ecSmrg                    XkbCopyKeymap(dev->key->xkbInfo->desc,
584705b261ecSmrg                                  tmpd->key->xkbInfo->desc, True);
584805b261ecSmrg                XkbUpdateCoreDescription(tmpd, True);
584905b261ecSmrg
585005b261ecSmrg                if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) {
585105b261ecSmrg                    old_sli = tmpd->kbdfeed->xkb_sli;
585205b261ecSmrg                    tmpd->kbdfeed->xkb_sli = NULL;
585305b261ecSmrg                    sli = XkbAllocSrvLedInfo(tmpd, tmpd->kbdfeed, NULL, 0);
585405b261ecSmrg                    if (sli) {
585505b261ecSmrg                        sli->explicitState = old_sli->explicitState;
585605b261ecSmrg                        sli->effectiveState = old_sli->effectiveState;
585705b261ecSmrg                    }
585805b261ecSmrg                    tmpd->kbdfeed->xkb_sli = sli;
585905b261ecSmrg                    XkbFreeSrvLedInfo(old_sli);
586005b261ecSmrg                }
586105b261ecSmrg            }
586205b261ecSmrg        }
586305b261ecSmrg
586405b261ecSmrg        /* this should be either a MN or an NKN, depending on whether or not
586505b261ecSmrg         * the keycode range changed? */
586605b261ecSmrg	nkn.deviceID= nkn.oldDeviceID= dev->id;
58674642e01fSmrg	nkn.minKeyCode= new->min_key_code;
58684642e01fSmrg	nkn.maxKeyCode= new->max_key_code;
586905b261ecSmrg	nkn.oldMinKeyCode= xkb->min_key_code;
587005b261ecSmrg	nkn.oldMaxKeyCode= xkb->max_key_code;
587105b261ecSmrg	nkn.requestMajor= XkbReqCode;
587205b261ecSmrg	nkn.requestMinor= X_kbGetKbdByName;
587305b261ecSmrg	nkn.changed= XkbNKN_KeycodesMask;
587405b261ecSmrg	if (geom_changed)
587505b261ecSmrg	    nkn.changed|= XkbNKN_GeometryMask;
587605b261ecSmrg	XkbSendNewKeyboardNotify(dev,&nkn);
587705b261ecSmrg    }
58784642e01fSmrg    if ((new!=NULL)&&(new!=xkb)) {
58794642e01fSmrg	XkbFreeKeyboard(new,XkbAllComponentsMask,True);
58804642e01fSmrg	new= NULL;
588105b261ecSmrg    }
588205b261ecSmrg    if (names.keymap)	{ _XkbFree(names.keymap); names.keymap= NULL; }
588305b261ecSmrg    if (names.keycodes)	{ _XkbFree(names.keycodes); names.keycodes= NULL; }
588405b261ecSmrg    if (names.types)	{ _XkbFree(names.types); names.types= NULL; }
588505b261ecSmrg    if (names.compat)	{ _XkbFree(names.compat); names.compat= NULL; }
588605b261ecSmrg    if (names.symbols)	{ _XkbFree(names.symbols); names.symbols= NULL; }
588705b261ecSmrg    if (names.geometry)	{ _XkbFree(names.geometry); names.geometry= NULL; }
588805b261ecSmrg    return client->noClientException;
588905b261ecSmrg}
589005b261ecSmrg
589105b261ecSmrg/***====================================================================***/
589205b261ecSmrg
589305b261ecSmrgstatic int
589405b261ecSmrgComputeDeviceLedInfoSize(	DeviceIntPtr		dev,
589505b261ecSmrg				unsigned int		what,
589605b261ecSmrg				XkbSrvLedInfoPtr	sli)
589705b261ecSmrg{
589805b261ecSmrgint			nNames,nMaps;
589905b261ecSmrgregister unsigned 	n,bit;
590005b261ecSmrg
590105b261ecSmrg    if (sli==NULL)
590205b261ecSmrg	return 0;
590305b261ecSmrg    nNames= nMaps= 0;
590405b261ecSmrg    if ((what&XkbXI_IndicatorNamesMask)==0)
590505b261ecSmrg	sli->namesPresent= 0;
590605b261ecSmrg    if ((what&XkbXI_IndicatorMapsMask)==0)
590705b261ecSmrg	sli->mapsPresent= 0;
590805b261ecSmrg
590905b261ecSmrg    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
591005b261ecSmrg	if (sli->names && sli->names[n]!=None) {
591105b261ecSmrg	    sli->namesPresent|= bit;
591205b261ecSmrg	    nNames++;
591305b261ecSmrg	}
591405b261ecSmrg	if (sli->maps && XkbIM_InUse(&sli->maps[n])) {
591505b261ecSmrg	    sli->mapsPresent|= bit;
591605b261ecSmrg	    nMaps++;
591705b261ecSmrg	}
591805b261ecSmrg    }
591905b261ecSmrg    return (nNames*4)+(nMaps*SIZEOF(xkbIndicatorMapWireDesc));
592005b261ecSmrg}
592105b261ecSmrg
592205b261ecSmrgstatic int
592305b261ecSmrgCheckDeviceLedFBs(	DeviceIntPtr			dev,
592405b261ecSmrg			int				class,
592505b261ecSmrg			int				id,
592605b261ecSmrg			xkbGetDeviceInfoReply *		rep,
592705b261ecSmrg			ClientPtr			client)
592805b261ecSmrg{
592905b261ecSmrgint			nFBs= 0;
593005b261ecSmrgint			length= 0;
593105b261ecSmrgBool			classOk;
593205b261ecSmrg
593305b261ecSmrg    if (class==XkbDfltXIClass) {
593405b261ecSmrg	if (dev->kbdfeed)	class= KbdFeedbackClass;
593505b261ecSmrg	else if (dev->leds)	class= LedFeedbackClass;
593605b261ecSmrg	else {
593705b261ecSmrg	    client->errorValue= _XkbErrCode2(XkbErr_BadClass,class);
593805b261ecSmrg	    return XkbKeyboardErrorCode;
593905b261ecSmrg	}
594005b261ecSmrg    }
594105b261ecSmrg    classOk= False;
594205b261ecSmrg    if ((dev->kbdfeed)&&((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) {
594305b261ecSmrg	KbdFeedbackPtr kf;
594405b261ecSmrg	classOk= True;
594505b261ecSmrg	for (kf= dev->kbdfeed;(kf);kf=kf->next) {
594605b261ecSmrg	    if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=kf->ctrl.id))
594705b261ecSmrg		continue;
594805b261ecSmrg	    nFBs++;
594905b261ecSmrg	    length+= SIZEOF(xkbDeviceLedsWireDesc);
595005b261ecSmrg	    if (!kf->xkb_sli)
595105b261ecSmrg		kf->xkb_sli= XkbAllocSrvLedInfo(dev,kf,NULL,0);
595205b261ecSmrg	    length+= ComputeDeviceLedInfoSize(dev,rep->present,kf->xkb_sli);
595305b261ecSmrg	    if (id!=XkbAllXIIds)
595405b261ecSmrg		break;
595505b261ecSmrg	}
595605b261ecSmrg    }
595705b261ecSmrg    if ((dev->leds)&&((class==LedFeedbackClass)||(class==XkbAllXIClasses))) {
595805b261ecSmrg	LedFeedbackPtr lf;
595905b261ecSmrg	classOk= True;
596005b261ecSmrg	for (lf= dev->leds;(lf);lf=lf->next) {
596105b261ecSmrg	    if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=lf->ctrl.id))
596205b261ecSmrg		continue;
596305b261ecSmrg	    nFBs++;
596405b261ecSmrg	    length+= SIZEOF(xkbDeviceLedsWireDesc);
596505b261ecSmrg	    if (!lf->xkb_sli)
596605b261ecSmrg		lf->xkb_sli= XkbAllocSrvLedInfo(dev,NULL,lf,0);
596705b261ecSmrg	    length+= ComputeDeviceLedInfoSize(dev,rep->present,lf->xkb_sli);
596805b261ecSmrg	    if (id!=XkbAllXIIds)
596905b261ecSmrg		break;
597005b261ecSmrg	}
597105b261ecSmrg    }
597205b261ecSmrg    if (nFBs>0) {
597305b261ecSmrg	if (rep->supported&XkbXI_IndicatorsMask) {
597405b261ecSmrg	    rep->nDeviceLedFBs= nFBs;
597505b261ecSmrg	    rep->length+= (length/4);
597605b261ecSmrg	}
597705b261ecSmrg	return Success;
597805b261ecSmrg    }
597905b261ecSmrg    if (classOk) client->errorValue= _XkbErrCode2(XkbErr_BadId,id);
598005b261ecSmrg    else	 client->errorValue= _XkbErrCode2(XkbErr_BadClass,class);
598105b261ecSmrg    return XkbKeyboardErrorCode;
598205b261ecSmrg}
598305b261ecSmrg
598405b261ecSmrgstatic int
598505b261ecSmrgSendDeviceLedInfo(	XkbSrvLedInfoPtr	sli,
598605b261ecSmrg			ClientPtr		client)
598705b261ecSmrg{
598805b261ecSmrgxkbDeviceLedsWireDesc	wire;
598905b261ecSmrgint			length;
599005b261ecSmrg
599105b261ecSmrg    length= 0;
599205b261ecSmrg    wire.ledClass= 		sli->class;
599305b261ecSmrg    wire.ledID= 		sli->id;
599405b261ecSmrg    wire.namesPresent= 		sli->namesPresent;
599505b261ecSmrg    wire.mapsPresent=   	sli->mapsPresent;
599605b261ecSmrg    wire.physIndicators= 	sli->physIndicators;
599705b261ecSmrg    wire.state=			sli->effectiveState;
599805b261ecSmrg    if (client->swapped) {
599905b261ecSmrg	register int n;
600005b261ecSmrg	swaps(&wire.ledClass,n);
600105b261ecSmrg	swaps(&wire.ledID,n);
600205b261ecSmrg	swapl(&wire.namesPresent,n);
600305b261ecSmrg	swapl(&wire.mapsPresent,n);
600405b261ecSmrg	swapl(&wire.physIndicators,n);
600505b261ecSmrg	swapl(&wire.state,n);
600605b261ecSmrg    }
600705b261ecSmrg    WriteToClient(client,SIZEOF(xkbDeviceLedsWireDesc),(char *)&wire);
600805b261ecSmrg    length+= SIZEOF(xkbDeviceLedsWireDesc);
600905b261ecSmrg    if (sli->namesPresent|sli->mapsPresent) {
601005b261ecSmrg	register unsigned i,bit;
601105b261ecSmrg	if (sli->namesPresent) {
601205b261ecSmrg	    CARD32	awire;
601305b261ecSmrg	    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
601405b261ecSmrg		if (sli->namesPresent&bit) {
601505b261ecSmrg		    awire= (CARD32)sli->names[i];
601605b261ecSmrg		    if (client->swapped) {
601705b261ecSmrg			register int n;
601805b261ecSmrg			swapl(&awire,n);
601905b261ecSmrg		    }
602005b261ecSmrg		    WriteToClient(client,4,(char *)&awire);
602105b261ecSmrg		    length+= 4;
602205b261ecSmrg		}
602305b261ecSmrg	    }
602405b261ecSmrg	}
602505b261ecSmrg	if (sli->mapsPresent) {
602605b261ecSmrg	    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
602705b261ecSmrg		xkbIndicatorMapWireDesc	iwire;
602805b261ecSmrg		if (sli->mapsPresent&bit) {
602905b261ecSmrg		    iwire.flags= 	sli->maps[i].flags;
603005b261ecSmrg		    iwire.whichGroups=	sli->maps[i].which_groups;
603105b261ecSmrg		    iwire.groups=	sli->maps[i].groups;
603205b261ecSmrg		    iwire.whichMods=	sli->maps[i].which_mods;
603305b261ecSmrg		    iwire.mods=		sli->maps[i].mods.mask;
603405b261ecSmrg		    iwire.realMods=	sli->maps[i].mods.real_mods;
603505b261ecSmrg		    iwire.virtualMods=	sli->maps[i].mods.vmods;
603605b261ecSmrg		    iwire.ctrls= 	sli->maps[i].ctrls;
603705b261ecSmrg		    if (client->swapped) {
603805b261ecSmrg			register int n;
603905b261ecSmrg			swaps(&iwire.virtualMods,n);
604005b261ecSmrg			swapl(&iwire.ctrls,n);
604105b261ecSmrg		    }
604205b261ecSmrg		    WriteToClient(client,SIZEOF(xkbIndicatorMapWireDesc),
604305b261ecSmrg								(char *)&iwire);
604405b261ecSmrg		    length+= SIZEOF(xkbIndicatorMapWireDesc);
604505b261ecSmrg		}
604605b261ecSmrg	    }
604705b261ecSmrg	}
604805b261ecSmrg    }
604905b261ecSmrg    return length;
605005b261ecSmrg}
605105b261ecSmrg
605205b261ecSmrgstatic int
605305b261ecSmrgSendDeviceLedFBs(	DeviceIntPtr	dev,
605405b261ecSmrg			int		class,
605505b261ecSmrg			int		id,
605605b261ecSmrg			unsigned	wantLength,
605705b261ecSmrg			ClientPtr	client)
605805b261ecSmrg{
605905b261ecSmrgint			length= 0;
606005b261ecSmrg
606105b261ecSmrg    if (class==XkbDfltXIClass) {
606205b261ecSmrg	if (dev->kbdfeed)	class= KbdFeedbackClass;
606305b261ecSmrg	else if (dev->leds)	class= LedFeedbackClass;
606405b261ecSmrg    }
606505b261ecSmrg    if ((dev->kbdfeed)&&
606605b261ecSmrg	((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) {
606705b261ecSmrg	KbdFeedbackPtr kf;
606805b261ecSmrg	for (kf= dev->kbdfeed;(kf);kf=kf->next) {
606905b261ecSmrg	    if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==kf->ctrl.id)) {
607005b261ecSmrg		length+= SendDeviceLedInfo(kf->xkb_sli,client);
607105b261ecSmrg		if (id!=XkbAllXIIds)
607205b261ecSmrg		    break;
607305b261ecSmrg	    }
607405b261ecSmrg	}
607505b261ecSmrg    }
607605b261ecSmrg    if ((dev->leds)&&
607705b261ecSmrg	((class==LedFeedbackClass)||(class==XkbAllXIClasses))) {
607805b261ecSmrg	LedFeedbackPtr lf;
607905b261ecSmrg	for (lf= dev->leds;(lf);lf=lf->next) {
608005b261ecSmrg	    if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==lf->ctrl.id)) {
608105b261ecSmrg		length+= SendDeviceLedInfo(lf->xkb_sli,client);
608205b261ecSmrg		if (id!=XkbAllXIIds)
608305b261ecSmrg		    break;
608405b261ecSmrg	    }
608505b261ecSmrg	}
608605b261ecSmrg    }
608705b261ecSmrg    if (length==wantLength)
608805b261ecSmrg	 return Success;
608905b261ecSmrg    else return BadLength;
609005b261ecSmrg}
609105b261ecSmrg
609205b261ecSmrgint
609305b261ecSmrgProcXkbGetDeviceInfo(ClientPtr client)
609405b261ecSmrg{
609505b261ecSmrgDeviceIntPtr		dev;
609605b261ecSmrgxkbGetDeviceInfoReply	rep;
609705b261ecSmrgint			status,nDeviceLedFBs;
609805b261ecSmrgunsigned		length,nameLen;
609905b261ecSmrgCARD16			ledClass,ledID;
610005b261ecSmrgunsigned		wanted,supported;
610105b261ecSmrgchar *			str;
610205b261ecSmrg
610305b261ecSmrg    REQUEST(xkbGetDeviceInfoReq);
610405b261ecSmrg    REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq);
610505b261ecSmrg
610605b261ecSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
610705b261ecSmrg	return BadAccess;
610805b261ecSmrg
610905b261ecSmrg    wanted= stuff->wanted;
611005b261ecSmrg
61114642e01fSmrg    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
611205b261ecSmrg    CHK_MASK_LEGAL(0x01,wanted,XkbXI_AllDeviceFeaturesMask);
611305b261ecSmrg
611405b261ecSmrg    if ((!dev->button)||((stuff->nBtns<1)&&(!stuff->allBtns)))
611505b261ecSmrg	wanted&= ~XkbXI_ButtonActionsMask;
611605b261ecSmrg    if ((!dev->kbdfeed)&&(!dev->leds))
611705b261ecSmrg	wanted&= ~XkbXI_IndicatorsMask;
611805b261ecSmrg
611905b261ecSmrg    nameLen= XkbSizeCountedString(dev->name);
612005b261ecSmrg    bzero((char *)&rep,SIZEOF(xkbGetDeviceInfoReply));
612105b261ecSmrg    rep.type = X_Reply;
612205b261ecSmrg    rep.deviceID= dev->id;
612305b261ecSmrg    rep.sequenceNumber = client->sequence;
612405b261ecSmrg    rep.length = nameLen/4;
612505b261ecSmrg    rep.present = wanted;
612605b261ecSmrg    rep.supported = XkbXI_AllDeviceFeaturesMask;
612705b261ecSmrg    rep.unsupported = 0;
612805b261ecSmrg    rep.firstBtnWanted = rep.nBtnsWanted = 0;
612905b261ecSmrg    rep.firstBtnRtrn = rep.nBtnsRtrn = 0;
613005b261ecSmrg    if (dev->button)
613105b261ecSmrg	 rep.totalBtns= dev->button->numButtons;
613205b261ecSmrg    else rep.totalBtns= 0;
613305b261ecSmrg    rep.devType=	dev->type;
613405b261ecSmrg    rep.hasOwnState=	(dev->key && dev->key->xkbInfo);
613505b261ecSmrg    rep.nDeviceLedFBs = 0;
613605b261ecSmrg    if (dev->kbdfeed)	rep.dfltKbdFB= dev->kbdfeed->ctrl.id;
613705b261ecSmrg    else		rep.dfltKbdFB= XkbXINone;
613805b261ecSmrg    if (dev->leds)	rep.dfltLedFB= dev->leds->ctrl.id;
613905b261ecSmrg    else		rep.dfltLedFB= XkbXINone;
614005b261ecSmrg
614105b261ecSmrg    ledClass= stuff->ledClass;
614205b261ecSmrg    ledID= stuff->ledID;
614305b261ecSmrg
614405b261ecSmrg    rep.firstBtnWanted= rep.nBtnsWanted= 0;
614505b261ecSmrg    rep.firstBtnRtrn= rep.nBtnsRtrn= 0;
614605b261ecSmrg    if (wanted&XkbXI_ButtonActionsMask) {
614705b261ecSmrg	if (stuff->allBtns) {
614805b261ecSmrg	    stuff->firstBtn= 0;
614905b261ecSmrg	    stuff->nBtns= dev->button->numButtons;
615005b261ecSmrg	}
615105b261ecSmrg
615205b261ecSmrg	if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) {
615305b261ecSmrg	    client->errorValue = _XkbErrCode4(0x02,dev->button->numButtons,
615405b261ecSmrg							stuff->firstBtn,
615505b261ecSmrg							stuff->nBtns);
615605b261ecSmrg	    return BadValue;
615705b261ecSmrg	}
615805b261ecSmrg	else {
615905b261ecSmrg	    rep.firstBtnWanted= stuff->firstBtn;
616005b261ecSmrg	    rep.nBtnsWanted= stuff->nBtns;
616105b261ecSmrg	    if (dev->button->xkb_acts!=NULL) {
616205b261ecSmrg		XkbAction *act;
616305b261ecSmrg		register int i;
616405b261ecSmrg
616505b261ecSmrg		rep.firstBtnRtrn= stuff->firstBtn;
616605b261ecSmrg		rep.nBtnsRtrn= stuff->nBtns;
616705b261ecSmrg		act= &dev->button->xkb_acts[rep.firstBtnWanted];
616805b261ecSmrg		for (i=0;i<rep.nBtnsRtrn;i++,act++) {
616905b261ecSmrg		    if (act->type!=XkbSA_NoAction)
617005b261ecSmrg			break;
617105b261ecSmrg		}
617205b261ecSmrg		rep.firstBtnRtrn+=	i;
617305b261ecSmrg		rep.nBtnsRtrn-=		i;
617405b261ecSmrg		act= &dev->button->xkb_acts[rep.firstBtnRtrn+rep.nBtnsRtrn-1];
617505b261ecSmrg		for (i=0;i<rep.nBtnsRtrn;i++,act--) {
617605b261ecSmrg		    if (act->type!=XkbSA_NoAction)
617705b261ecSmrg			break;
617805b261ecSmrg		}
617905b261ecSmrg		rep.nBtnsRtrn-=		i;
618005b261ecSmrg	    }
618105b261ecSmrg	    rep.length+= (rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc))/4;
618205b261ecSmrg	}
618305b261ecSmrg    }
618405b261ecSmrg
618505b261ecSmrg    if (wanted&XkbXI_IndicatorsMask) {
618605b261ecSmrg	status= CheckDeviceLedFBs(dev,ledClass,ledID,&rep,client);
618705b261ecSmrg	if (status!=Success)
618805b261ecSmrg	    return status;
618905b261ecSmrg    }
619005b261ecSmrg    length= rep.length*4;
619105b261ecSmrg    supported= rep.supported;
619205b261ecSmrg    nDeviceLedFBs = rep.nDeviceLedFBs;
619305b261ecSmrg    if (client->swapped) {
619405b261ecSmrg	register int n;
619505b261ecSmrg	swaps(&rep.sequenceNumber,n);
619605b261ecSmrg	swapl(&rep.length,n);
619705b261ecSmrg	swaps(&rep.present,n);
619805b261ecSmrg	swaps(&rep.supported,n);
619905b261ecSmrg	swaps(&rep.unsupported,n);
620005b261ecSmrg	swaps(&rep.nDeviceLedFBs,n);
620105b261ecSmrg	swapl(&rep.type,n);
620205b261ecSmrg    }
620305b261ecSmrg    WriteToClient(client,SIZEOF(xkbGetDeviceInfoReply), (char *)&rep);
620405b261ecSmrg
62054642e01fSmrg    str= (char*) xalloc(nameLen);
620605b261ecSmrg    if (!str)
620705b261ecSmrg	return BadAlloc;
620805b261ecSmrg    XkbWriteCountedString(str,dev->name,client->swapped);
620905b261ecSmrg    WriteToClient(client,nameLen,str);
62104642e01fSmrg    xfree(str);
621105b261ecSmrg    length-= nameLen;
621205b261ecSmrg
621305b261ecSmrg    if (rep.nBtnsRtrn>0) {
621405b261ecSmrg	int			sz;
621505b261ecSmrg	xkbActionWireDesc *	awire;
621605b261ecSmrg	sz= rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc);
621705b261ecSmrg	awire= (xkbActionWireDesc *)&dev->button->xkb_acts[rep.firstBtnRtrn];
621805b261ecSmrg	WriteToClient(client,sz,(char *)awire);
621905b261ecSmrg	length-= sz;
622005b261ecSmrg    }
622105b261ecSmrg    if (nDeviceLedFBs>0) {
622205b261ecSmrg	status= SendDeviceLedFBs(dev,ledClass,ledID,length,client);
622305b261ecSmrg	if (status!=Success)
622405b261ecSmrg	    return status;
622505b261ecSmrg    }
622605b261ecSmrg    else if (length!=0)  {
62274642e01fSmrg	ErrorF("[xkb] Internal Error!  BadLength in ProcXkbGetDeviceInfo\n");
62284642e01fSmrg	ErrorF("[xkb]                  Wrote %d fewer bytes than expected\n",length);
622905b261ecSmrg	return BadLength;
623005b261ecSmrg    }
623105b261ecSmrg    if (stuff->wanted&(~supported)) {
623205b261ecSmrg	xkbExtensionDeviceNotify ed;
623305b261ecSmrg	bzero((char *)&ed,SIZEOF(xkbExtensionDeviceNotify));
623405b261ecSmrg	ed.ledClass=		ledClass;
623505b261ecSmrg	ed.ledID=		ledID;
623605b261ecSmrg	ed.ledsDefined= 	0;
623705b261ecSmrg	ed.ledState=		0;
623805b261ecSmrg	ed.firstBtn= ed.nBtns=	0;
623905b261ecSmrg	ed.reason=		XkbXI_UnsupportedFeatureMask;
624005b261ecSmrg	ed.supported=		supported;
624105b261ecSmrg	ed.unsupported=		stuff->wanted&(~supported);
624205b261ecSmrg	XkbSendExtensionDeviceNotify(dev,client,&ed);
624305b261ecSmrg    }
624405b261ecSmrg    return client->noClientException;
624505b261ecSmrg}
624605b261ecSmrg
624705b261ecSmrgstatic char *
624805b261ecSmrgCheckSetDeviceIndicators(	char *		wire,
624905b261ecSmrg				DeviceIntPtr	dev,
625005b261ecSmrg				int		num,
625105b261ecSmrg				int *		status_rtrn,
625205b261ecSmrg				ClientPtr	client)
625305b261ecSmrg{
625405b261ecSmrgxkbDeviceLedsWireDesc *	ledWire;
625505b261ecSmrgint			i;
625605b261ecSmrgXkbSrvLedInfoPtr 	sli;
625705b261ecSmrg
625805b261ecSmrg    ledWire= (xkbDeviceLedsWireDesc *)wire;
625905b261ecSmrg    for (i=0;i<num;i++) {
626005b261ecSmrg	if (client->swapped) {
626105b261ecSmrg	   register int n;
626205b261ecSmrg	   swaps(&ledWire->ledClass,n);
626305b261ecSmrg	   swaps(&ledWire->ledID,n);
626405b261ecSmrg	   swapl(&ledWire->namesPresent,n);
626505b261ecSmrg	   swapl(&ledWire->mapsPresent,n);
626605b261ecSmrg	   swapl(&ledWire->physIndicators,n);
626705b261ecSmrg	}
626805b261ecSmrg
626905b261ecSmrg        sli= XkbFindSrvLedInfo(dev,ledWire->ledClass,ledWire->ledID,
627005b261ecSmrg							XkbXI_IndicatorsMask);
627105b261ecSmrg	if (sli!=NULL) {
627205b261ecSmrg	    register int n;
627305b261ecSmrg	    register unsigned bit;
627405b261ecSmrg	    int nMaps,nNames;
627505b261ecSmrg	    CARD32 *atomWire;
627605b261ecSmrg	    xkbIndicatorMapWireDesc *mapWire;
627705b261ecSmrg
627805b261ecSmrg	    nMaps= nNames= 0;
627905b261ecSmrg	    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
628005b261ecSmrg		if (ledWire->namesPresent&bit)
628105b261ecSmrg		    nNames++;
628205b261ecSmrg		if (ledWire->mapsPresent&bit)
628305b261ecSmrg		    nMaps++;
628405b261ecSmrg	    }
628505b261ecSmrg	    atomWire= (CARD32 *)&ledWire[1];
628605b261ecSmrg	    if (nNames>0) {
628705b261ecSmrg		for (n=0;n<nNames;n++) {
628805b261ecSmrg		    if (client->swapped) {
628905b261ecSmrg			register int t;
629005b261ecSmrg			swapl(atomWire,t);
629105b261ecSmrg		    }
629205b261ecSmrg		    CHK_ATOM_OR_NONE3(((Atom)(*atomWire)),client->errorValue,
629305b261ecSmrg							*status_rtrn,NULL);
629405b261ecSmrg		    atomWire++;
629505b261ecSmrg		}
629605b261ecSmrg	    }
629705b261ecSmrg	    mapWire= (xkbIndicatorMapWireDesc *)atomWire;
629805b261ecSmrg	    if (nMaps>0) {
629905b261ecSmrg		for (n=0;n<nMaps;n++) {
630005b261ecSmrg		    if (client->swapped) {
630105b261ecSmrg			register int t;
630205b261ecSmrg			swaps(&mapWire->virtualMods,t);
630305b261ecSmrg			swapl(&mapWire->ctrls,t);
630405b261ecSmrg		    }
630505b261ecSmrg		    CHK_MASK_LEGAL3(0x21,mapWire->whichGroups,
630605b261ecSmrg						XkbIM_UseAnyGroup,
630705b261ecSmrg						client->errorValue,
630805b261ecSmrg						*status_rtrn,NULL);
630905b261ecSmrg		    CHK_MASK_LEGAL3(0x22,mapWire->whichMods,XkbIM_UseAnyMods,
631005b261ecSmrg						client->errorValue,
631105b261ecSmrg						*status_rtrn,NULL);
631205b261ecSmrg		    mapWire++;
631305b261ecSmrg		}
631405b261ecSmrg	    }
631505b261ecSmrg	    ledWire= (xkbDeviceLedsWireDesc *)mapWire;
631605b261ecSmrg	}
631705b261ecSmrg	else {
631805b261ecSmrg	    /* SHOULD NEVER HAPPEN */
631905b261ecSmrg	    return (char *)ledWire;
632005b261ecSmrg	}
632105b261ecSmrg    }
632205b261ecSmrg    return (char *)ledWire;
632305b261ecSmrg}
632405b261ecSmrg
632505b261ecSmrgstatic char *
632605b261ecSmrgSetDeviceIndicators(	char *			wire,
632705b261ecSmrg			DeviceIntPtr		dev,
632805b261ecSmrg			unsigned		changed,
632905b261ecSmrg			int			num,
633005b261ecSmrg			int *			status_rtrn,
633105b261ecSmrg			ClientPtr		client,
633205b261ecSmrg			xkbExtensionDeviceNotify *ev)
633305b261ecSmrg{
633405b261ecSmrgxkbDeviceLedsWireDesc *		ledWire;
633505b261ecSmrgint				i;
633605b261ecSmrgXkbEventCauseRec		cause;
633705b261ecSmrgunsigned			namec,mapc,statec;
633805b261ecSmrgxkbExtensionDeviceNotify	ed;
633905b261ecSmrgXkbChangesRec			changes;
634005b261ecSmrgDeviceIntPtr			kbd;
634105b261ecSmrg
634205b261ecSmrg    bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify));
634305b261ecSmrg    bzero((char *)&changes,sizeof(XkbChangesRec));
634405b261ecSmrg    XkbSetCauseXkbReq(&cause,X_kbSetDeviceInfo,client);
634505b261ecSmrg    ledWire= (xkbDeviceLedsWireDesc *)wire;
634605b261ecSmrg    for (i=0;i<num;i++) {
634705b261ecSmrg	register int			n;
634805b261ecSmrg	register unsigned 		bit;
634905b261ecSmrg	CARD32 *			atomWire;
635005b261ecSmrg	xkbIndicatorMapWireDesc *	mapWire;
635105b261ecSmrg	XkbSrvLedInfoPtr		sli;
635205b261ecSmrg
635305b261ecSmrg	namec= mapc= statec= 0;
635405b261ecSmrg    	sli= XkbFindSrvLedInfo(dev,ledWire->ledClass,ledWire->ledID,
635505b261ecSmrg						XkbXI_IndicatorMapsMask);
635605b261ecSmrg	if (!sli) {
635705b261ecSmrg	    /* SHOULD NEVER HAPPEN!! */
635805b261ecSmrg	    return (char *)ledWire;
635905b261ecSmrg	}
636005b261ecSmrg
636105b261ecSmrg	atomWire= (CARD32 *)&ledWire[1];
636205b261ecSmrg	if (changed&XkbXI_IndicatorNamesMask) {
636305b261ecSmrg	    namec= sli->namesPresent|ledWire->namesPresent;
636405b261ecSmrg	    bzero((char *)sli->names,XkbNumIndicators*sizeof(Atom));
636505b261ecSmrg	}
636605b261ecSmrg	if (ledWire->namesPresent) {
636705b261ecSmrg	    sli->namesPresent= ledWire->namesPresent;
636805b261ecSmrg	    bzero((char *)sli->names,XkbNumIndicators*sizeof(Atom));
636905b261ecSmrg	    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
637005b261ecSmrg		if (ledWire->namesPresent&bit) {
637105b261ecSmrg		     sli->names[n]= (Atom)*atomWire;
637205b261ecSmrg		     if (sli->names[n]==None)
637305b261ecSmrg			ledWire->namesPresent&= ~bit;
637405b261ecSmrg		     atomWire++;
637505b261ecSmrg		}
637605b261ecSmrg	    }
637705b261ecSmrg	}
637805b261ecSmrg	mapWire= (xkbIndicatorMapWireDesc *)atomWire;
637905b261ecSmrg	if (changed&XkbXI_IndicatorMapsMask) {
638005b261ecSmrg	    mapc= sli->mapsPresent|ledWire->mapsPresent;
638105b261ecSmrg	    sli->mapsPresent= ledWire->mapsPresent;
638205b261ecSmrg	    bzero((char*)sli->maps,XkbNumIndicators*sizeof(XkbIndicatorMapRec));
638305b261ecSmrg	}
638405b261ecSmrg	if (ledWire->mapsPresent) {
638505b261ecSmrg	    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
638605b261ecSmrg		if (ledWire->mapsPresent&bit) {
638705b261ecSmrg		    sli->maps[n].flags=		mapWire->flags;
638805b261ecSmrg		    sli->maps[n].which_groups=	mapWire->whichGroups;
638905b261ecSmrg		    sli->maps[n].groups=	mapWire->groups;
639005b261ecSmrg		    sli->maps[n].which_mods=	mapWire->whichMods;
639105b261ecSmrg		    sli->maps[n].mods.mask=	mapWire->mods;
639205b261ecSmrg		    sli->maps[n].mods.real_mods=mapWire->realMods;
639305b261ecSmrg		    sli->maps[n].mods.vmods=	mapWire->virtualMods;
639405b261ecSmrg		    sli->maps[n].ctrls=		mapWire->ctrls;
639505b261ecSmrg		    mapWire++;
639605b261ecSmrg		}
639705b261ecSmrg	    }
639805b261ecSmrg	}
639905b261ecSmrg	if (changed&XkbXI_IndicatorStateMask) {
640005b261ecSmrg	    statec= sli->effectiveState^ledWire->state;
640105b261ecSmrg	    sli->explicitState&= ~statec;
640205b261ecSmrg	    sli->explicitState|= (ledWire->state&statec);
640305b261ecSmrg	}
640405b261ecSmrg	if (namec)
640505b261ecSmrg	    XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause);
640605b261ecSmrg	if (mapc)
640705b261ecSmrg	    XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause);
640805b261ecSmrg	if (statec)
640905b261ecSmrg	    XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause);
641005b261ecSmrg
641105b261ecSmrg	kbd= dev;
641205b261ecSmrg	if ((sli->flags&XkbSLI_HasOwnState)==0)
64134642e01fSmrg	    kbd = inputInfo.keyboard;
641405b261ecSmrg
641505b261ecSmrg	XkbFlushLedEvents(dev,kbd,sli,&ed,&changes,&cause);
641605b261ecSmrg	ledWire= (xkbDeviceLedsWireDesc *)mapWire;
641705b261ecSmrg    }
641805b261ecSmrg    return (char *)ledWire;
641905b261ecSmrg}
642005b261ecSmrg
642105b261ecSmrg
64224642e01fSmrgstatic int
64234642e01fSmrg_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev,
64244642e01fSmrg                  xkbSetDeviceInfoReq *stuff)
64254642e01fSmrg{
64264642e01fSmrg    char                       *wire;
642705b261ecSmrg
642805b261ecSmrg    wire= (char *)&stuff[1];
64294642e01fSmrg    if (stuff->change&XkbXI_ButtonActionsMask) {
643005b261ecSmrg	if (!dev->button) {
643105b261ecSmrg	    client->errorValue = _XkbErrCode2(XkbErr_BadClass,ButtonClass);
643205b261ecSmrg	    return XkbKeyboardErrorCode;
643305b261ecSmrg	}
643405b261ecSmrg	if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) {
643505b261ecSmrg	    client->errorValue= _XkbErrCode4(0x02,stuff->firstBtn,stuff->nBtns,
643605b261ecSmrg						dev->button->numButtons);
643705b261ecSmrg	    return BadMatch;
643805b261ecSmrg	}
643905b261ecSmrg	wire+= (stuff->nBtns*SIZEOF(xkbActionWireDesc));
644005b261ecSmrg    }
644105b261ecSmrg    if (stuff->change&XkbXI_IndicatorsMask) {
644205b261ecSmrg	int status= Success;
644305b261ecSmrg	wire= CheckSetDeviceIndicators(wire,dev,stuff->nDeviceLedFBs,
644405b261ecSmrg							&status,client);
644505b261ecSmrg	if (status!=Success)
644605b261ecSmrg	    return status;
644705b261ecSmrg    }
644805b261ecSmrg    if (((wire-((char *)stuff))/4)!=stuff->length)
644905b261ecSmrg	return BadLength;
645005b261ecSmrg
64514642e01fSmrg    return Success;
64524642e01fSmrg}
64534642e01fSmrg
64544642e01fSmrgstatic int
64554642e01fSmrg_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev,
64564642e01fSmrg                       xkbSetDeviceInfoReq *stuff)
64574642e01fSmrg{
64584642e01fSmrg    char                       *wire;
64594642e01fSmrg    xkbExtensionDeviceNotify    ed;
64604642e01fSmrg
646105b261ecSmrg    bzero((char *)&ed,SIZEOF(xkbExtensionDeviceNotify));
646205b261ecSmrg    ed.deviceID=	dev->id;
646305b261ecSmrg    wire= (char *)&stuff[1];
64644642e01fSmrg    if (stuff->change&XkbXI_ButtonActionsMask) {
646505b261ecSmrg	int			nBtns,sz,i;
646605b261ecSmrg	XkbAction *		acts;
646705b261ecSmrg	DeviceIntPtr		kbd;
646805b261ecSmrg
646905b261ecSmrg	nBtns= dev->button->numButtons;
647005b261ecSmrg	acts= dev->button->xkb_acts;
647105b261ecSmrg	if (acts==NULL) {
647205b261ecSmrg	    acts= _XkbTypedCalloc(nBtns,XkbAction);
647305b261ecSmrg	    if (!acts)
647405b261ecSmrg		return BadAlloc;
647505b261ecSmrg	    dev->button->xkb_acts= acts;
647605b261ecSmrg	}
647705b261ecSmrg	sz= stuff->nBtns*SIZEOF(xkbActionWireDesc);
647805b261ecSmrg	memcpy((char *)&acts[stuff->firstBtn],(char *)wire,sz);
647905b261ecSmrg	wire+= sz;
648005b261ecSmrg	ed.reason|=	XkbXI_ButtonActionsMask;
648105b261ecSmrg	ed.firstBtn=	stuff->firstBtn;
648205b261ecSmrg	ed.nBtns=	stuff->nBtns;
648305b261ecSmrg
648405b261ecSmrg	if (dev->key)	kbd= dev;
64854642e01fSmrg	else		kbd= inputInfo.keyboard;
648605b261ecSmrg	acts= &dev->button->xkb_acts[stuff->firstBtn];
648705b261ecSmrg	for (i=0;i<stuff->nBtns;i++,acts++) {
648805b261ecSmrg	    if (acts->type!=XkbSA_NoAction)
648905b261ecSmrg		XkbSetActionKeyMods(kbd->key->xkbInfo->desc,acts,0);
649005b261ecSmrg	}
649105b261ecSmrg    }
649205b261ecSmrg    if (stuff->change&XkbXI_IndicatorsMask) {
649305b261ecSmrg	int status= Success;
64944642e01fSmrg	wire= SetDeviceIndicators(wire,dev,stuff->change,
64954642e01fSmrg				  stuff->nDeviceLedFBs, &status,client,&ed);
649605b261ecSmrg	if (status!=Success)
649705b261ecSmrg	    return status;
649805b261ecSmrg    }
649905b261ecSmrg    if ((stuff->change)&&(ed.reason))
650005b261ecSmrg	XkbSendExtensionDeviceNotify(dev,client,&ed);
65014642e01fSmrg    return Success;
65024642e01fSmrg}
65034642e01fSmrg
65044642e01fSmrgint
65054642e01fSmrgProcXkbSetDeviceInfo(ClientPtr client)
65064642e01fSmrg{
65074642e01fSmrg    DeviceIntPtr        dev;
65084642e01fSmrg    int                 rc;
65094642e01fSmrg
65104642e01fSmrg    REQUEST(xkbSetDeviceInfoReq);
65114642e01fSmrg    REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq);
65124642e01fSmrg
65134642e01fSmrg    if (!(client->xkbClientFlags&_XkbClientInitialized))
65144642e01fSmrg	return BadAccess;
65154642e01fSmrg
65164642e01fSmrg    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
65174642e01fSmrg    CHK_MASK_LEGAL(0x01,stuff->change,XkbXI_AllFeaturesMask);
65184642e01fSmrg
65194642e01fSmrg    rc = _XkbSetDeviceInfoCheck(client, dev, stuff);
65204642e01fSmrg
65214642e01fSmrg    if (rc != Success)
65224642e01fSmrg        return rc;
65234642e01fSmrg
65244642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd || stuff->deviceSpec == XkbUseCorePtr)
65254642e01fSmrg    {
65264642e01fSmrg        DeviceIntPtr other;
65274642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
65284642e01fSmrg        {
65294642e01fSmrg            if (((other != dev) && !other->isMaster && (other->u.master == dev)) &&
65304642e01fSmrg                ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
65314642e01fSmrg                (stuff->deviceSpec == XkbUseCorePtr && other->button)))
65324642e01fSmrg            {
65334642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
65344642e01fSmrg                if (rc == Success)
65354642e01fSmrg                {
65364642e01fSmrg                    rc = _XkbSetDeviceInfoCheck(client, other, stuff);
65374642e01fSmrg                    if (rc != Success)
65384642e01fSmrg                        return rc;
65394642e01fSmrg                }
65404642e01fSmrg            }
65414642e01fSmrg        }
65424642e01fSmrg    }
65434642e01fSmrg
65444642e01fSmrg    /* checks done, apply */
65454642e01fSmrg    rc = _XkbSetDeviceInfo(client, dev, stuff);
65464642e01fSmrg    if (rc != Success)
65474642e01fSmrg        return rc;
65484642e01fSmrg
65494642e01fSmrg    if (stuff->deviceSpec == XkbUseCoreKbd || stuff->deviceSpec == XkbUseCorePtr)
65504642e01fSmrg    {
65514642e01fSmrg        DeviceIntPtr other;
65524642e01fSmrg        for (other = inputInfo.devices; other; other = other->next)
65534642e01fSmrg        {
65544642e01fSmrg            if (((other != dev) && !other->isMaster && (other->u.master == dev)) &&
65554642e01fSmrg                ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
65564642e01fSmrg                (stuff->deviceSpec == XkbUseCorePtr && other->button)))
65574642e01fSmrg            {
65584642e01fSmrg                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
65594642e01fSmrg                if (rc == Success)
65604642e01fSmrg                {
65614642e01fSmrg                    rc = _XkbSetDeviceInfo(client, other, stuff);
65624642e01fSmrg                    if (rc != Success)
65634642e01fSmrg                        return rc;
65644642e01fSmrg                }
65654642e01fSmrg            }
65664642e01fSmrg        }
65674642e01fSmrg    }
65684642e01fSmrg
656905b261ecSmrg    return client->noClientException;
657005b261ecSmrg}
657105b261ecSmrg
657205b261ecSmrg/***====================================================================***/
657305b261ecSmrg
657405b261ecSmrgint
657505b261ecSmrgProcXkbSetDebuggingFlags(ClientPtr client)
657605b261ecSmrg{
657705b261ecSmrgCARD32 				newFlags,newCtrls,extraLength;
657805b261ecSmrgxkbSetDebuggingFlagsReply 	rep;
65794642e01fSmrgint rc;
658005b261ecSmrg
658105b261ecSmrg    REQUEST(xkbSetDebuggingFlagsReq);
658205b261ecSmrg    REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq);
658305b261ecSmrg
65844642e01fSmrg    rc = XaceHook(XACE_SERVER_ACCESS, client, DixDebugAccess);
65854642e01fSmrg    if (rc != Success)
65864642e01fSmrg	return rc;
65874642e01fSmrg
658805b261ecSmrg    newFlags=  xkbDebugFlags&(~stuff->affectFlags);
658905b261ecSmrg    newFlags|= (stuff->flags&stuff->affectFlags);
659005b261ecSmrg    newCtrls=  xkbDebugCtrls&(~stuff->affectCtrls);
659105b261ecSmrg    newCtrls|= (stuff->ctrls&stuff->affectCtrls);
659205b261ecSmrg    if (xkbDebugFlags || newFlags || stuff->msgLength) {
65934642e01fSmrg	ErrorF("[xkb] XkbDebug: Setting debug flags to 0x%lx\n",(long)newFlags);
659405b261ecSmrg	if (newCtrls!=xkbDebugCtrls)
65954642e01fSmrg	    ErrorF("[xkb] XkbDebug: Setting debug controls to 0x%lx\n",(long)newCtrls);
659605b261ecSmrg    }
659705b261ecSmrg    extraLength= (stuff->length<<2)-sz_xkbSetDebuggingFlagsReq;
659805b261ecSmrg    if (stuff->msgLength>0) {
659905b261ecSmrg	char *msg;
660005b261ecSmrg	if (extraLength<XkbPaddedSize(stuff->msgLength)) {
66014642e01fSmrg	    ErrorF("[xkb] XkbDebug: msgLength= %d, length= %ld (should be %d)\n",
660205b261ecSmrg			stuff->msgLength,(long)extraLength,
660305b261ecSmrg			XkbPaddedSize(stuff->msgLength));
660405b261ecSmrg	    return BadLength;
660505b261ecSmrg	}
660605b261ecSmrg	msg= (char *)&stuff[1];
660705b261ecSmrg	if (msg[stuff->msgLength-1]!='\0') {
66084642e01fSmrg	    ErrorF("[xkb] XkbDebug: message not null-terminated\n");
660905b261ecSmrg	    return BadValue;
661005b261ecSmrg	}
66114642e01fSmrg	ErrorF("[xkb] XkbDebug: %s\n",msg);
661205b261ecSmrg    }
661305b261ecSmrg    xkbDebugFlags = newFlags;
661405b261ecSmrg    xkbDebugCtrls = newCtrls;
661505b261ecSmrg
661605b261ecSmrg    XkbDisableLockActions= (xkbDebugCtrls&XkbDF_DisableLocks);
661705b261ecSmrg
661805b261ecSmrg    rep.type= X_Reply;
661905b261ecSmrg    rep.length = 0;
662005b261ecSmrg    rep.sequenceNumber = client->sequence;
662105b261ecSmrg    rep.currentFlags = newFlags;
662205b261ecSmrg    rep.currentCtrls = newCtrls;
662305b261ecSmrg    rep.supportedFlags = ~0;
662405b261ecSmrg    rep.supportedCtrls = ~0;
662505b261ecSmrg    if ( client->swapped ) {
662605b261ecSmrg	register int n;
662705b261ecSmrg	swaps(&rep.sequenceNumber, n);
662805b261ecSmrg	swapl(&rep.currentFlags, n);
662905b261ecSmrg	swapl(&rep.currentCtrls, n);
663005b261ecSmrg	swapl(&rep.supportedFlags, n);
663105b261ecSmrg	swapl(&rep.supportedCtrls, n);
663205b261ecSmrg    }
663305b261ecSmrg    WriteToClient(client,SIZEOF(xkbSetDebuggingFlagsReply), (char *)&rep);
663405b261ecSmrg    return client->noClientException;
663505b261ecSmrg}
663605b261ecSmrg
663705b261ecSmrg/***====================================================================***/
663805b261ecSmrg
663905b261ecSmrgstatic int
664005b261ecSmrgProcXkbDispatch (ClientPtr client)
664105b261ecSmrg{
664205b261ecSmrg    REQUEST(xReq);
664305b261ecSmrg    switch (stuff->data)
664405b261ecSmrg    {
664505b261ecSmrg    case X_kbUseExtension:
664605b261ecSmrg	return ProcXkbUseExtension(client);
664705b261ecSmrg    case X_kbSelectEvents:
664805b261ecSmrg	return ProcXkbSelectEvents(client);
664905b261ecSmrg    case X_kbBell:
665005b261ecSmrg	return ProcXkbBell(client);
665105b261ecSmrg    case X_kbGetState:
665205b261ecSmrg	return ProcXkbGetState(client);
665305b261ecSmrg    case X_kbLatchLockState:
665405b261ecSmrg	return ProcXkbLatchLockState(client);
665505b261ecSmrg    case X_kbGetControls:
665605b261ecSmrg	return ProcXkbGetControls(client);
665705b261ecSmrg    case X_kbSetControls:
665805b261ecSmrg	return ProcXkbSetControls(client);
665905b261ecSmrg    case X_kbGetMap:
666005b261ecSmrg	return ProcXkbGetMap(client);
666105b261ecSmrg    case X_kbSetMap:
666205b261ecSmrg	return ProcXkbSetMap(client);
666305b261ecSmrg    case X_kbGetCompatMap:
666405b261ecSmrg	return ProcXkbGetCompatMap(client);
666505b261ecSmrg    case X_kbSetCompatMap:
666605b261ecSmrg	return ProcXkbSetCompatMap(client);
666705b261ecSmrg    case X_kbGetIndicatorState:
666805b261ecSmrg	return ProcXkbGetIndicatorState(client);
666905b261ecSmrg    case X_kbGetIndicatorMap:
667005b261ecSmrg	return ProcXkbGetIndicatorMap(client);
667105b261ecSmrg    case X_kbSetIndicatorMap:
667205b261ecSmrg	return ProcXkbSetIndicatorMap(client);
667305b261ecSmrg    case X_kbGetNamedIndicator:
667405b261ecSmrg	return ProcXkbGetNamedIndicator(client);
667505b261ecSmrg    case X_kbSetNamedIndicator:
667605b261ecSmrg	return ProcXkbSetNamedIndicator(client);
667705b261ecSmrg    case X_kbGetNames:
667805b261ecSmrg	return ProcXkbGetNames(client);
667905b261ecSmrg    case X_kbSetNames:
668005b261ecSmrg	return ProcXkbSetNames(client);
668105b261ecSmrg    case X_kbGetGeometry:
668205b261ecSmrg	return ProcXkbGetGeometry(client);
668305b261ecSmrg    case X_kbSetGeometry:
668405b261ecSmrg	return ProcXkbSetGeometry(client);
668505b261ecSmrg    case X_kbPerClientFlags:
668605b261ecSmrg	return ProcXkbPerClientFlags(client);
668705b261ecSmrg    case X_kbListComponents:
668805b261ecSmrg	return ProcXkbListComponents(client);
668905b261ecSmrg    case X_kbGetKbdByName:
669005b261ecSmrg	return ProcXkbGetKbdByName(client);
669105b261ecSmrg    case X_kbGetDeviceInfo:
669205b261ecSmrg	return ProcXkbGetDeviceInfo(client);
669305b261ecSmrg    case X_kbSetDeviceInfo:
669405b261ecSmrg	return ProcXkbSetDeviceInfo(client);
669505b261ecSmrg    case X_kbSetDebuggingFlags:
669605b261ecSmrg	return ProcXkbSetDebuggingFlags(client);
669705b261ecSmrg    default:
669805b261ecSmrg	return BadRequest;
669905b261ecSmrg    }
670005b261ecSmrg}
670105b261ecSmrg
670205b261ecSmrgstatic int
670305b261ecSmrgXkbClientGone(pointer data,XID id)
670405b261ecSmrg{
670505b261ecSmrg    DevicePtr	pXDev = (DevicePtr)data;
670605b261ecSmrg
670705b261ecSmrg    if (!XkbRemoveResourceClient(pXDev,id)) {
67084642e01fSmrg	ErrorF("[xkb] Internal Error! bad RemoveResourceClient in XkbClientGone\n");
670905b261ecSmrg    }
671005b261ecSmrg    return 1;
671105b261ecSmrg}
671205b261ecSmrg
671305b261ecSmrgvoid
671405b261ecSmrgXkbExtensionInit(void)
671505b261ecSmrg{
671605b261ecSmrg    ExtensionEntry *extEntry;
671705b261ecSmrg
671805b261ecSmrg    if ((extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors,
671905b261ecSmrg				 ProcXkbDispatch, SProcXkbDispatch,
67204642e01fSmrg				 NULL, StandardMinorOpcode))) {
672105b261ecSmrg	XkbReqCode = (unsigned char)extEntry->base;
672205b261ecSmrg	XkbEventBase = (unsigned char)extEntry->eventBase;
672305b261ecSmrg	XkbErrorBase = (unsigned char)extEntry->errorBase;
672405b261ecSmrg	XkbKeyboardErrorCode = XkbErrorBase+XkbKeyboard;
672505b261ecSmrg	RT_XKBCLIENT = CreateNewResourceType(XkbClientGone);
672605b261ecSmrg    }
672705b261ecSmrg    return;
672805b261ecSmrg}
672905b261ecSmrg
673005b261ecSmrg
6731