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