ProcXkbSelectEvents(ClientPtr client)
{
    unsigned		legal;
    DeviceIntPtr 	dev;
    XkbInterestPtr	masks;
    REQUEST(xkbSelectEventsReq);

    REQUEST_AT_LEAST_SIZE(xkbSelectEventsReq);

    if (!(client->xkbClientFlags&_XkbClientInitialized))
	return BadAccess;

    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixUseAccess);

    if (((stuff->affectWhich&XkbMapNotifyMask)!=0)&&(stuff->affectMap)) {
	client->mapNotifyMask&= ~stuff->affectMap;
	client->mapNotifyMask|= (stuff->affectMap&stuff->map);
    }
    if ((stuff->affectWhich&(~XkbMapNotifyMask))==0)
	return client->noClientException;

    masks = XkbFindClientResource((DevicePtr)dev,client);
    if (!masks){
	XID id = FakeClientID(client->index);
	AddResource(id,RT_XKBCLIENT,dev);
	masks= XkbAddClientResource((DevicePtr)dev,client,id);
    }
    if (masks) {
	union {
	    CARD8	*c8;
	    CARD16	*c16;
	    CARD32	*c32;
	} from,to;
	register unsigned bit,ndx,maskLeft,dataLeft,size;

	from.c8= (CARD8 *)&stuff[1];
	dataLeft= (stuff->length*4)-SIZEOF(xkbSelectEventsReq);
	maskLeft= (stuff->affectWhich&(~XkbMapNotifyMask));
	for (ndx=0,bit=1; (maskLeft!=0); ndx++, bit<<=1) {
	    if ((bit&maskLeft)==0)
		continue;
	    maskLeft&= ~bit;
	    switch (ndx) {
		case XkbNewKeyboardNotify:
		    to.c16= &client->newKeyboardNotifyMask;
		    legal= XkbAllNewKeyboardEventsMask;
		    size= 2;
		    break;
		case XkbStateNotify:
		    to.c16= &masks->stateNotifyMask;
		    legal= XkbAllStateEventsMask;
		    size= 2;
		    break;
		case XkbControlsNotify:
		    to.c32= &masks->ctrlsNotifyMask;
		    legal= XkbAllControlEventsMask;
		    size= 4;
		    break;
		case XkbIndicatorStateNotify:
		    to.c32= &masks->iStateNotifyMask;
		    legal= XkbAllIndicatorEventsMask;
		    size= 4;
		    break;
		case XkbIndicatorMapNotify:
		    to.c32= &masks->iMapNotifyMask;
		    legal= XkbAllIndicatorEventsMask;
		    size= 4;
		    break;
		case XkbNamesNotify:
		    to.c16= &masks->namesNotifyMask;
		    legal= XkbAllNameEventsMask;
		    size= 2;
		    break;
		case XkbCompatMapNotify:
		    to.c8= &masks->compatNotifyMask;
		    legal= XkbAllCompatMapEventsMask;
		    size= 1;
		    break;
		case XkbBellNotify:
		    to.c8= &masks->bellNotifyMask;
		    legal= XkbAllBellEventsMask;
		    size= 1;
		    break;
		case XkbActionMessage:
		    to.c8= &masks->actionMessageMask;
		    legal= XkbAllActionMessagesMask;
		    size= 1;
		    break;
		case XkbAccessXNotify:
		    to.c16= &masks->accessXNotifyMask;
		    legal= XkbAllAccessXEventsMask;
		    size= 2;
		    break;
		case XkbExtensionDeviceNotify:
		    to.c16= &masks->extDevNotifyMask;
		    legal= XkbAllExtensionDeviceEventsMask;
		    size= 2;
		    break;
		default:
		    client->errorValue = _XkbErrCode2(33,bit);
		    return BadValue;
	    }

	    if (stuff->clear&bit) {
		if (size==2)		to.c16[0]= 0;
		else if (size==4)	to.c32[0]= 0;
		else			to.c8[0]=  0;
	    }
	    else if (stuff->selectAll&bit) {
		if (size==2)		to.c16[0]= ~0;
		else if (size==4)	to.c32[0]= ~0;
		else			to.c8[0]=  ~0;
	    }
	    else {
		if (dataLeft<(size*2))
		    return BadLength;
		if (size==2) {
		    CHK_MASK_MATCH(ndx,from.c16[0],from.c16[1]);
		    CHK_MASK_LEGAL(ndx,from.c16[0],legal);
		    to.c16[0]&= ~from.c16[0];
		    to.c16[0]|= (from.c16[0]&from.c16[1]);
		}
		else if (size==4) {
		    CHK_MASK_MATCH(ndx,from.c32[0],from.c32[1]);
		    CHK_MASK_LEGAL(ndx,from.c32[0],legal);
		    to.c32[0]&= ~from.c32[0];
		    to.c32[0]|= (from.c32[0]&from.c32[1]);
		}
		else  {
		    CHK_MASK_MATCH(ndx,from.c8[0],from.c8[1]);
		    CHK_MASK_LEGAL(ndx,from.c8[0],legal);
		    to.c8[0]&= ~from.c8[0];
		    to.c8[0]|= (from.c8[0]&from.c8[1]);
		    size= 2;
		}
		from.c8+= (size*2);
		dataLeft-= (size*2);
	    }
	}
	if (dataLeft>2) {
	    ErrorF("[xkb] Extra data (%d bytes) after SelectEvents\n",dataLeft);
	    return BadLength;
	}
	return client->noClientException;
    }
    return BadAlloc;
}


xkb: ProcXkbSetDeviceInfo should work on all attached SDs.

If called with XkbUseCoreKbd, run through all attached SDs and replicate the
call. This way, we keep the SDs in sync with the MD as long as core clients
control the MDs.

ProcXkbGetIndicatorMap(ClientPtr client)
{
xkbGetIndicatorMapReply rep;
DeviceIntPtr		dev;
XkbDescPtr		xkb;
XkbIndicatorPtr		leds;

    REQUEST(xkbGetIndicatorMapReq);
    REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq);

    if (!(client->xkbClientFlags&_XkbClientInitialized))
	return BadAccess;

    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);

    xkb= dev->key->xkbInfo->desc;
    leds= xkb->indicators;

    rep.type = X_Reply;
    rep.sequenceNumber = client->sequence;
    rep.length = 0;
    rep.deviceID = dev->id;
    rep.which = stuff->which;
    XkbComputeGetIndicatorMapReplySize(leds,&rep);
    return XkbSendIndicatorMap(client,leds,&rep);
}

A flaw was found in the Xorg-x11-server. The specific flaw exists within the handling of ProcXkbSetDeviceInfo requests. The issue results from the lack of proper validation of user-supplied data, which can result in a memory access past the end of an allocated buffer. This flaw allows an attacker to escalate privileges and execute arbitrary code in the context of root.


XkbWriteKeyTypes(	XkbDescPtr		xkb,
			xkbGetMapReply *	rep,
			char *			buf,
			ClientPtr 		client)
{
    XkbKeyTypePtr	type;
    unsigned		i;
    xkbKeyTypeWireDesc *wire;

    type= &xkb->map->types[rep->firstType];
    for (i=0;i<rep->nTypes;i++,type++) {
	register unsigned n;
	wire= (xkbKeyTypeWireDesc *)buf;
	wire->mask = type->mods.mask;
	wire->realMods = type->mods.real_mods;
	wire->virtualMods = type->mods.vmods;
	wire->numLevels = type->num_levels;
	wire->nMapEntries = type->map_count;
	wire->preserve = (type->preserve!=NULL);
	if (client->swapped) {
	    register int n;
	    swaps(&wire->virtualMods,n);
	}

	buf= (char *)&wire[1];
	if (wire->nMapEntries>0) {
	    xkbKTMapEntryWireDesc *	wire;
	    XkbKTMapEntryPtr		entry;
	    wire= (xkbKTMapEntryWireDesc *)buf;
	    entry= type->map;
	    for (n=0;n<type->map_count;n++,wire++,entry++) {
		wire->active= entry->active;
		wire->mask= entry->mods.mask;
		wire->level= entry->level;
		wire->realMods= entry->mods.real_mods;
		wire->virtualMods= entry->mods.vmods;
		if (client->swapped) {
		    register int n;
		    swaps(&wire->virtualMods,n);
		}
	    }
	    buf= (char *)wire;
	    if (type->preserve!=NULL) {
		xkbModsWireDesc *	pwire;
		XkbModsPtr		preserve;
		pwire= (xkbModsWireDesc *)buf;
		preserve= type->preserve;
		for (n=0;n<type->map_count;n++,pwire++,preserve++) {
		    pwire->mask= preserve->mask;
		    pwire->realMods= preserve->real_mods;
		    pwire->virtualMods= preserve->vmods;
		    if (client->swapped) {
			register int n;
			swaps(&pwire->virtualMods,n);
		    }
		}
		buf= (char *)pwire;
	    }
	}
    }
    return buf;
}


_XkbSetGeometry(ClientPtr client, DeviceIntPtr dev, xkbSetGeometryReq *stuff)
{
    XkbDescPtr		xkb;
    Bool		new_name;
    xkbNewKeyboardNotify	nkn;
    XkbGeometryPtr	geom,old;
    XkbGeometrySizesRec	sizes;
    Status		status;

    xkb= dev->key->xkbInfo->desc;
    old= xkb->geom;
    xkb->geom= NULL;

    sizes.which=		XkbGeomAllMask;
    sizes.num_properties=	stuff->nProperties;
    sizes.num_colors=	stuff->nColors;
    sizes.num_shapes=	stuff->nShapes;
    sizes.num_sections=	stuff->nSections;
    sizes.num_doodads=	stuff->nDoodads;
    sizes.num_key_aliases=	stuff->nKeyAliases;
    if ((status= XkbAllocGeometry(xkb,&sizes))!=Success) {
        xkb->geom= old;
        return status;
    }
    geom= xkb->geom;
    geom->name= stuff->name;
    geom->width_mm= stuff->widthMM;
    geom->height_mm= stuff->heightMM;
    if ((status= _CheckSetGeom(geom,stuff,client))!=Success) {
        XkbFreeGeometry(geom,XkbGeomAllMask,True);
        xkb->geom= old;
        return status;
    }
    new_name= (xkb->names->geometry!=geom->name);
    xkb->names->geometry= geom->name;
    if (old)
        XkbFreeGeometry(old,XkbGeomAllMask,True);
    if (new_name) {
        xkbNamesNotify	nn;
        bzero(&nn,sizeof(xkbNamesNotify));
        nn.changed= XkbGeometryNameMask;
        XkbSendNamesNotify(dev,&nn);
    }
    nkn.deviceID= nkn.oldDeviceID= dev->id;
    nkn.minKeyCode= nkn.oldMinKeyCode= xkb->min_key_code;
    nkn.maxKeyCode= nkn.oldMaxKeyCode= xkb->max_key_code;
    nkn.requestMajor=	XkbReqCode;
    nkn.requestMinor=	X_kbSetGeometry;
    nkn.changed=	XkbNKN_GeometryMask;
    XkbSendNewKeyboardNotify(dev,&nkn);
    return Success;
}


ProcXkbSetDeviceInfo(ClientPtr client)
{
    unsigned int        change;
    DeviceIntPtr        dev;
    int                 rc;

    REQUEST(xkbSetDeviceInfoReq);
    REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq);

    if (!(client->xkbClientFlags&_XkbClientInitialized))
	return BadAccess;

    change = stuff->change;

    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
    CHK_MASK_LEGAL(0x01,change,XkbXI_AllFeaturesMask);

    rc = _XkbSetDeviceInfoCheck(client, dev, stuff);

    if (rc != Success)
        return rc;

    if (stuff->deviceSpec == XkbUseCoreKbd || stuff->deviceSpec == XkbUseCorePtr)
    {
        DeviceIntPtr other;
        for (other = inputInfo.devices; other; other = other->next)
        {
            if (((other != dev) && !other->isMaster && (other->u.master == dev)) &&
                ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
                (stuff->deviceSpec == XkbUseCorePtr && other->button)))
            {
                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
                if (rc == Success)
                {
                    rc = _XkbSetDeviceInfoCheck(client, other, stuff);
                    if (rc != Success)
                        return rc;
                }
            }
        }
    }

    /* checks done, apply */
    rc = _XkbSetDeviceInfo(client, dev, stuff);
    if (rc != Success)
        return rc;

    if (stuff->deviceSpec == XkbUseCoreKbd || stuff->deviceSpec == XkbUseCorePtr)
    {
        DeviceIntPtr other;
        for (other = inputInfo.devices; other; other = other->next)
        {
            if (((other != dev) && !other->isMaster && (other->u.master == dev)) &&
                ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
                (stuff->deviceSpec == XkbUseCorePtr && other->button)))
            {
                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
                if (rc == Success)
                {
                    rc = _XkbSetDeviceInfo(client, other, stuff);
                    if (rc != Success)
                        return rc;
                }
            }
        }
    }

    return client->noClientException;
}


_XkbCheckTypeName(Atom name,int typeNdx)
{
char *	str;

    str= NameForAtom(name);
    if ((strcmp(str,"ONE_LEVEL")==0)||(strcmp(str,"TWO_LEVEL")==0)||
	(strcmp(str,"ALPHABETIC")==0)||(strcmp(str,"KEYPAD")==0))
	return False;
    return True;
}


CheckKeySyms(	ClientPtr		client,
		XkbDescPtr		xkb,
		xkbSetMapReq *		req,
		int			nTypes,
		CARD8 *	 		mapWidths,
		CARD16 *	 	symsPerKey,
		xkbSymMapWireDesc **	wireRtrn,
		int *			errorRtrn)
{
register unsigned	i;
XkbSymMapPtr		map;
xkbSymMapWireDesc*	wire = *wireRtrn;

    if (!(XkbKeySymsMask&req->present))
	return 1;
    CHK_REQ_KEY_RANGE2(0x11,req->firstKeySym,req->nKeySyms,req,(*errorRtrn),0);
    map = &xkb->map->key_sym_map[xkb->min_key_code];
    for (i=xkb->min_key_code;i<(unsigned)req->firstKeySym;i++,map++) {
	register int g,ng,w;
	ng= XkbNumGroups(map->group_info);
	for (w=g=0;g<ng;g++) {
	    if (map->kt_index[g]>=(unsigned)nTypes) {
		*errorRtrn = _XkbErrCode4(0x13,i,g,map->kt_index[g]);
		return 0;
	    }
	    if (mapWidths[map->kt_index[g]]>w)
		w= mapWidths[map->kt_index[g]];
	}
	symsPerKey[i] = w*ng;
    }
    for (i=0;i<req->nKeySyms;i++) {
	KeySym *pSyms;
	register unsigned nG;
	if (client->swapped) {
	    swaps(&wire->nSyms,nG);
	}
	nG = XkbNumGroups(wire->groupInfo);
	if (nG>XkbNumKbdGroups) {
	    *errorRtrn = _XkbErrCode3(0x14,i+req->firstKeySym,nG);
	    return 0;
	}
	if (nG>0) {
	    register int g,w;
	    for (g=w=0;g<nG;g++) {
		if (wire->ktIndex[g]>=(unsigned)nTypes) {
		    *errorRtrn= _XkbErrCode4(0x15,i+req->firstKeySym,g,
		    					   wire->ktIndex[g]);
		    return 0;
		}
		if (mapWidths[wire->ktIndex[g]]>w)
		    w= mapWidths[wire->ktIndex[g]];
	    }
	    if (wire->width!=w) {
		*errorRtrn= _XkbErrCode3(0x16,i+req->firstKeySym,wire->width);
		return 0;
	    }
	    w*= nG;
	    symsPerKey[i+req->firstKeySym] = w;
	    if (w!=wire->nSyms) {
		*errorRtrn=_XkbErrCode4(0x16,i+req->firstKeySym,wire->nSyms,w);
		return 0;
	    }
	}
	else if (wire->nSyms!=0) {
	    *errorRtrn = _XkbErrCode3(0x17,i+req->firstKeySym,wire->nSyms);
	    return 0;
	}
	pSyms = (KeySym *)&wire[1];
	wire = (xkbSymMapWireDesc *)&pSyms[wire->nSyms];
    }

    map = &xkb->map->key_sym_map[i];
    for (;i<=(unsigned)xkb->max_key_code;i++,map++) {
	register int g,nG,w;
	nG= XkbKeyNumGroups(xkb,i);
	for (w=g=0;g<nG;g++)  {
	    if (map->kt_index[g]>=(unsigned)nTypes) {
		*errorRtrn = _XkbErrCode4(0x18,i,g,map->kt_index[g]);
		return 0;
	    }
	    if (mapWidths[map->kt_index[g]]>w)
		    w= mapWidths[map->kt_index[g]];
	}
	symsPerKey[i] = w*nG;
    }
    *wireRtrn = wire;
    return 1;
}


_XkbSetCompatMap(ClientPtr client, DeviceIntPtr dev,
                 xkbSetCompatMapReq *req, char* data, BOOL dryRun)
{
    XkbSrvInfoPtr       xkbi;
    XkbDescPtr          xkb;
    XkbCompatMapPtr     compat;
    int                 nGroups;
    unsigned            i,bit;

    xkbi = dev->key->xkbInfo;
    xkb = xkbi->desc;
    compat = xkb->compat;

    if ((req->nSI>0)||(req->truncateSI)) {
	xkbSymInterpretWireDesc *wire;
	if (req->firstSI>compat->num_si) {
	    client->errorValue = _XkbErrCode2(0x02,compat->num_si);
	    return BadValue;
	}
	wire= (xkbSymInterpretWireDesc *)data;
	wire+= req->nSI;
	data = (char *)wire;
    }

    nGroups= 0;
    if (req->groups!=0) {
	for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
	    if ( req->groups&bit )
		nGroups++;
	}
    }
    data+= nGroups*SIZEOF(xkbModsWireDesc);
    if (((data-((char *)req))/4)!=req->length) {
	return BadLength;
    }

    /* Done all the checks we can do */
    if (dryRun)
        return Success;

    data = (char *)&req[1];
    if (req->nSI>0) {
	xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data;
	XkbSymInterpretPtr	sym;
	if ((unsigned)(req->firstSI+req->nSI)>compat->num_si) {
	    compat->num_si= req->firstSI+req->nSI;
	    compat->sym_interpret= _XkbTypedRealloc(compat->sym_interpret,
						   compat->num_si,
						   XkbSymInterpretRec);
	    if (!compat->sym_interpret) {
		compat->num_si= 0;
		return BadAlloc;
	    }
	}
	else if (req->truncateSI) {
	    compat->num_si = req->firstSI+req->nSI;
	}
	sym = &compat->sym_interpret[req->firstSI];
	for (i=0;i<req->nSI;i++,wire++,sym++) {
	    if (client->swapped) {
		int n;
		swapl(&wire->sym,n);
	    }
	    sym->sym= wire->sym;
	    sym->mods= wire->mods;
	    sym->match= wire->match;
	    sym->flags= wire->flags;
	    sym->virtual_mod= wire->virtualMod;
	    memcpy((char *)&sym->act,(char *)&wire->act,
                   SIZEOF(xkbActionWireDesc));
	}
	data = (char *)wire;
    }
    else if (req->truncateSI) {
	compat->num_si = req->firstSI;
    }

    if (req->groups!=0) {
	unsigned i, bit;
	xkbModsWireDesc *wire = (xkbModsWireDesc *)data;
	for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
	    if (req->groups & bit) {
		if (client->swapped) {
		    int n;
		    swaps(&wire->virtualMods,n);
		}
		compat->groups[i].mask= wire->realMods;
		compat->groups[i].real_mods= wire->realMods;
		compat->groups[i].vmods= wire->virtualMods;
		if (wire->virtualMods!=0) {
		    unsigned tmp;
		    tmp= XkbMaskForVMask(xkb,wire->virtualMods);
		    compat->groups[i].mask|= tmp;
		}
		data+= SIZEOF(xkbModsWireDesc);
		wire= (xkbModsWireDesc *)data;
	    }
	}
    }
    i= XkbPaddedSize((data-((char *)req)));
    if ((i/4)!=req->length) {
	ErrorF("[xkb] Internal length error on read in _XkbSetCompatMap\n");
	return BadLength;
    }

    if (dev->xkb_interest) {
	xkbCompatMapNotify ev;
	ev.deviceID = dev->id;
	ev.changedGroups = req->groups;
	ev.firstSI = req->firstSI;
	ev.nSI = req->nSI;
	ev.nTotalSI = compat->num_si;
	XkbSendCompatMapNotify(dev,&ev);
    }

    if (req->recomputeActions) {
	XkbChangesRec		change;
	unsigned		check;
	XkbEventCauseRec	cause;

	XkbSetCauseXkbReq(&cause,X_kbSetCompatMap,client);
	bzero(&change,sizeof(XkbChangesRec));
	XkbUpdateActions(dev,xkb->min_key_code,XkbNumKeys(xkb),&change,&check,
									&cause);
	if (check)
	    XkbCheckSecondaryEffects(xkbi,check,&change,&cause);
	XkbUpdateCoreDescription(dev,False);
	XkbSendNotification(dev,&change,&cause);
    }
    return Success;
}


XkbWriteGeomSections(char *wire,XkbGeometryPtr geom,Bool swap)
{
register int		i;
XkbSectionPtr		section;
xkbSectionWireDesc *	sectionWire;

    for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) {
	sectionWire= (xkbSectionWireDesc *)wire;
	sectionWire->name= section->name;
	sectionWire->top= section->top;
	sectionWire->left= section->left;
	sectionWire->width= section->width;
	sectionWire->height= section->height;
	sectionWire->angle= section->angle;
	sectionWire->priority= section->priority;
	sectionWire->nRows= section->num_rows;
	sectionWire->nDoodads= section->num_doodads;
	sectionWire->nOverlays= section->num_overlays;
	sectionWire->pad= 0;
	if (swap) {
	    register int n;
	    swapl(&sectionWire->name,n);
	    swaps(&sectionWire->top,n);
	    swaps(&sectionWire->left,n);
	    swaps(&sectionWire->width,n);
	    swaps(&sectionWire->height,n);
	    swaps(&sectionWire->angle,n);
	}
	wire= (char *)&sectionWire[1];
	if (section->rows) {
	    int			r;
	    XkbRowPtr		row;
	    xkbRowWireDesc *	rowWire;
	    for (r=0,row=section->rows;r<section->num_rows;r++,row++) {
		rowWire= (xkbRowWireDesc *)wire;
		rowWire->top= row->top;
		rowWire->left= row->left;
		rowWire->nKeys= row->num_keys;
		rowWire->vertical= row->vertical;
		rowWire->pad= 0;
		if (swap) {
		    register int n;
		    swaps(&rowWire->top,n);
		    swaps(&rowWire->left,n);
		}
		wire= (char *)&rowWire[1];
		if (row->keys) {
		    int			k;
		    XkbKeyPtr		key;
		    xkbKeyWireDesc *	keyWire;
		    keyWire= (xkbKeyWireDesc *)wire;
		    for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
			memcpy(keyWire[k].name,key->name.name,XkbKeyNameLength);
			keyWire[k].gap= key->gap;
			keyWire[k].shapeNdx= key->shape_ndx;
			keyWire[k].colorNdx= key->color_ndx;
			if (swap) {
			    register int n;
			    swaps(&keyWire[k].gap,n);
			}
		    }
		    wire= (char *)&keyWire[row->num_keys];
		}
	    }
	}
	if (section->doodads) {
	    wire= XkbWriteGeomDoodads(wire,
	    			      section->num_doodads,section->doodads,
				      swap);
	}
	if (section->overlays) {
	    register int o;
	    for (o=0;o<section->num_overlays;o++) {
		wire= XkbWriteGeomOverlay(wire,&section->overlays[o],swap);
	    }
	}
    }
    return wire;
}


XkbSendNames(ClientPtr client,XkbDescPtr xkb,xkbGetNamesReply *rep)
{
register unsigned 	i,length,which;
char *			start;
char *			desc;
register int            n;

    length= rep->length*4;
    which= rep->which;
    if (client->swapped) {
	swaps(&rep->sequenceNumber,n);
	swapl(&rep->length,n);
	swapl(&rep->which,n);
	swaps(&rep->virtualMods,n);
	swapl(&rep->indicators,n);
    }

    start = desc = (char *)xalloc(length);
    if ( !start )
	return BadAlloc;
    if (xkb->names) {
        if (which&XkbKeycodesNameMask) {
            *((CARD32 *)desc)= xkb->names->keycodes;
            if (client->swapped) {
                swapl(desc,n);
            }
            desc+= 4;
        }
        if (which&XkbGeometryNameMask)  {
            *((CARD32 *)desc)= xkb->names->geometry;
            if (client->swapped) {
                swapl(desc,n);
            }
            desc+= 4;
        }
        if (which&XkbSymbolsNameMask) {
            *((CARD32 *)desc)= xkb->names->symbols;
            if (client->swapped) {
                swapl(desc,n);
            }
            desc+= 4;
        }
        if (which&XkbPhysSymbolsNameMask) {
            register CARD32 *atm= (CARD32 *)desc;
            atm[0]= (CARD32)xkb->names->phys_symbols;
            if (client->swapped) {
                swapl(&atm[0],n);
            }
            desc+= 4;
        }
        if (which&XkbTypesNameMask) {
            *((CARD32 *)desc)= (CARD32)xkb->names->types;
            if (client->swapped) {
                swapl(desc,n);
            }
            desc+= 4;
        }
        if (which&XkbCompatNameMask) {
            *((CARD32 *)desc)= (CARD32)xkb->names->compat;
            if (client->swapped) {
                swapl(desc,n);
            }
            desc+= 4;
        }
        if (which&XkbKeyTypeNamesMask) {
            register CARD32 *atm= (CARD32 *)desc;
            register XkbKeyTypePtr type= xkb->map->types;

            for (i=0;i<xkb->map->num_types;i++,atm++,type++) {
                *atm= (CARD32)type->name;
                if (client->swapped) {
                    swapl(atm,n);
                }
            }
            desc= (char *)atm;
        }
        if (which&XkbKTLevelNamesMask && xkb->map) {
            XkbKeyTypePtr type = xkb->map->types;
            register CARD32 *atm;
            for (i=0;i<rep->nTypes;i++,type++) {
                *desc++ = type->num_levels;
            }
            desc+= XkbPaddedSize(rep->nTypes)-rep->nTypes;

            atm= (CARD32 *)desc;
            type = xkb->map->types;
            for (i=0;i<xkb->map->num_types;i++,type++) {
                register unsigned l;
                if (type->level_names) {
                    for (l=0;l<type->num_levels;l++,atm++) {
                        *atm= type->level_names[l];
                        if (client->swapped) {
                            swapl(atm,n);
                        }
                    }
                    desc+= type->num_levels*4;
                }
            }
        }
        if (which&XkbIndicatorNamesMask) {
            desc= _XkbWriteAtoms(desc,xkb->names->indicators,XkbNumIndicators,
                                 client->swapped);
        }
        if (which&XkbVirtualModNamesMask) {
            desc= _XkbWriteAtoms(desc,xkb->names->vmods,XkbNumVirtualMods,
                                 client->swapped);
        }
        if (which&XkbGroupNamesMask) {
            desc= _XkbWriteAtoms(desc,xkb->names->groups,XkbNumKbdGroups,
                                 client->swapped);
        }
        if (which&XkbKeyNamesMask) {
            for (i=0;i<rep->nKeys;i++,desc+= sizeof(XkbKeyNameRec)) {
                *((XkbKeyNamePtr)desc)= xkb->names->keys[i+rep->firstKey];
            }
        }
        if (which&XkbKeyAliasesMask) {
            XkbKeyAliasPtr	pAl;
            pAl= xkb->names->key_aliases;
            for (i=0;i<rep->nKeyAliases;i++,pAl++,desc+=2*XkbKeyNameLength) {
                *((XkbKeyAliasPtr)desc)= *pAl;
            }
        }
        if ((which&XkbRGNamesMask)&&(rep->nRadioGroups>0)) {
            register CARD32	*atm= (CARD32 *)desc;
            for (i=0;i<rep->nRadioGroups;i++,atm++) {
                *atm= (CARD32)xkb->names->radio_groups[i];
                if (client->swapped) {
                    swapl(atm,n);
                }
            }
            desc+= rep->nRadioGroups*4;
        }
    }

    if ((desc-start)!=(length)) {
	ErrorF("[xkb] BOGUS LENGTH in write names, expected %d, got %ld\n",
					length, (unsigned long)(desc-start));
    }
    WriteToClient(client, SIZEOF(xkbGetNamesReply), (char *)rep);
    WriteToClient(client, length, start);
    xfree((char *)start);
    return client->noClientException;
}


ProcXkbBell(ClientPtr client)
{
    REQUEST(xkbBellReq);
    DeviceIntPtr dev;
    WindowPtr	 pWin;
    int rc;

    REQUEST_SIZE_MATCH(xkbBellReq);

    if (!(client->xkbClientFlags&_XkbClientInitialized))
	return BadAccess;

    CHK_BELL_DEVICE(dev, stuff->deviceSpec, client, DixBellAccess);
    CHK_ATOM_OR_NONE(stuff->name);

    /* device-independent checks request for sane values */
    if ((stuff->forceSound)&&(stuff->eventOnly)) {
	client->errorValue=_XkbErrCode3(0x1,stuff->forceSound,stuff->eventOnly);
	return BadMatch;
    }
    if (stuff->percent < -100 || stuff->percent > 100) {
	client->errorValue = _XkbErrCode2(0x2,stuff->percent);
	return BadValue;
    }
    if (stuff->duration<-1) {
	client->errorValue = _XkbErrCode2(0x3,stuff->duration);
	return BadValue;
    }
    if (stuff->pitch<-1) {
	client->errorValue = _XkbErrCode2(0x4,stuff->pitch);
	return BadValue;
    }

    if (stuff->bellClass == XkbDfltXIClass) {
	if (dev->kbdfeed!=NULL)
	     stuff->bellClass= KbdFeedbackClass;
	else stuff->bellClass= BellFeedbackClass;
    }

    if (stuff->window!=None) {
	rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
	if (rc != Success) {
	    client->errorValue= stuff->window;
	    return rc;
	}
    }
    else pWin= NULL;

    /* Client wants to ring a bell on the core keyboard?
       Ring the bell on the core keyboard (which does nothing, but if that
       fails the client is screwed anyway), and then on all extension devices.
       Fail if the core keyboard fails but not the extension devices.  this
       may cause some keyboards to ding and others to stay silent. Fix
       your client to use explicit keyboards to avoid this.

       dev is the device the client requested.
     */
    rc = _XkbBell(client, dev, pWin, stuff->bellClass, stuff->bellID,
                  stuff->pitch, stuff->duration, stuff->percent,
                  stuff->forceSound, stuff->eventOnly, stuff->name);

    if ((rc == Success) && ((stuff->deviceSpec == XkbUseCoreKbd) ||
                            (stuff->deviceSpec == XkbUseCorePtr)))
    {
        DeviceIntPtr other;
        for (other = inputInfo.devices; other; other = other->next)
        {
            if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
            {
                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixBellAccess);
                if (rc == Success)
                    _XkbBell(client, other, pWin, stuff->bellClass,
                             stuff->bellID, stuff->pitch, stuff->duration,
                             stuff->percent, stuff->forceSound,
                             stuff->eventOnly, stuff->name);
            }
        }
        rc = Success; /* reset to success, that's what we got for the VCK */
    }

    return rc;
}


ProcXkbGetMap(ClientPtr client)
{
    DeviceIntPtr	 dev;
    xkbGetMapReply	 rep;
    XkbDescRec		*xkb;
    int			 n,status;

    REQUEST(xkbGetMapReq);
    REQUEST_SIZE_MATCH(xkbGetMapReq);

    if (!(client->xkbClientFlags&_XkbClientInitialized))
	return BadAccess;

    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
    CHK_MASK_OVERLAP(0x01,stuff->full,stuff->partial);
    CHK_MASK_LEGAL(0x02,stuff->full,XkbAllMapComponentsMask);
    CHK_MASK_LEGAL(0x03,stuff->partial,XkbAllMapComponentsMask);

    xkb= dev->key->xkbInfo->desc;
    bzero(&rep,sizeof(xkbGetMapReply));
    rep.type= X_Reply;
    rep.sequenceNumber= client->sequence;
    rep.length = (SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2;
    rep.deviceID = dev->id;
    rep.present = stuff->partial|stuff->full;
    rep.minKeyCode = xkb->min_key_code;
    rep.maxKeyCode = xkb->max_key_code;
    if ( stuff->full&XkbKeyTypesMask ) {
	rep.firstType = 0;
	rep.nTypes = xkb->map->num_types;
    }
    else if (stuff->partial&XkbKeyTypesMask) {
	if (((unsigned)stuff->firstType+stuff->nTypes)>xkb->map->num_types) {
	    client->errorValue = _XkbErrCode4(0x04,xkb->map->num_types,
					stuff->firstType,stuff->nTypes);
	    return BadValue;
	}
	rep.firstType = stuff->firstType;
	rep.nTypes = stuff->nTypes;
    }
    else rep.nTypes = 0;
    rep.totalTypes = xkb->map->num_types;

    n= XkbNumKeys(xkb);
    if ( stuff->full&XkbKeySymsMask ) {
	rep.firstKeySym = xkb->min_key_code;
	rep.nKeySyms = n;
    }
    else if (stuff->partial&XkbKeySymsMask) {
	CHK_KEY_RANGE(0x05,stuff->firstKeySym,stuff->nKeySyms,xkb);
	rep.firstKeySym = stuff->firstKeySym;
	rep.nKeySyms = stuff->nKeySyms;
    }
    else rep.nKeySyms = 0;
    rep.totalSyms= 0;

    if ( stuff->full&XkbKeyActionsMask ) {
	rep.firstKeyAct= xkb->min_key_code;
	rep.nKeyActs= n;
    }
    else if (stuff->partial&XkbKeyActionsMask) {
	CHK_KEY_RANGE(0x07,stuff->firstKeyAct,stuff->nKeyActs,xkb);
	rep.firstKeyAct= stuff->firstKeyAct;
	rep.nKeyActs= stuff->nKeyActs;
    }
    else rep.nKeyActs= 0;
    rep.totalActs= 0;

    if ( stuff->full&XkbKeyBehaviorsMask ) {
	rep.firstKeyBehavior = xkb->min_key_code;
	rep.nKeyBehaviors = n;
    }
    else if (stuff->partial&XkbKeyBehaviorsMask) {
	CHK_KEY_RANGE(0x09,stuff->firstKeyBehavior,stuff->nKeyBehaviors,xkb);
	rep.firstKeyBehavior= stuff->firstKeyBehavior;
	rep.nKeyBehaviors= stuff->nKeyBehaviors;
    }
    else rep.nKeyBehaviors = 0;
    rep.totalKeyBehaviors= 0;

    if (stuff->full&XkbVirtualModsMask)
	rep.virtualMods= ~0;
    else if (stuff->partial&XkbVirtualModsMask)
	rep.virtualMods= stuff->virtualMods;

    if (stuff->full&XkbExplicitComponentsMask) {
	rep.firstKeyExplicit= xkb->min_key_code;
	rep.nKeyExplicit= n;
    }
    else if (stuff->partial&XkbExplicitComponentsMask) {
	CHK_KEY_RANGE(0x0B,stuff->firstKeyExplicit,stuff->nKeyExplicit,xkb);
	rep.firstKeyExplicit= stuff->firstKeyExplicit;
	rep.nKeyExplicit= stuff->nKeyExplicit;
    }
    else rep.nKeyExplicit = 0;
    rep.totalKeyExplicit=  0;

    if (stuff->full&XkbModifierMapMask) {
	rep.firstModMapKey= xkb->min_key_code;
	rep.nModMapKeys= n;
    }
    else if (stuff->partial&XkbModifierMapMask) {
	CHK_KEY_RANGE(0x0D,stuff->firstModMapKey,stuff->nModMapKeys,xkb);
	rep.firstModMapKey= stuff->firstModMapKey;
	rep.nModMapKeys= stuff->nModMapKeys;
    }
    else rep.nModMapKeys = 0;
    rep.totalModMapKeys= 0;

    if (stuff->full&XkbVirtualModMapMask) {
	rep.firstVModMapKey= xkb->min_key_code;
	rep.nVModMapKeys= n;
    }
    else if (stuff->partial&XkbVirtualModMapMask) {
	CHK_KEY_RANGE(0x0F,stuff->firstVModMapKey,stuff->nVModMapKeys,xkb);
	rep.firstVModMapKey= stuff->firstVModMapKey;
	rep.nVModMapKeys= stuff->nVModMapKeys;
    }
    else rep.nVModMapKeys = 0;
    rep.totalVModMapKeys= 0;

    if ((status=XkbComputeGetMapReplySize(xkb,&rep))!=Success)
	return status;
    return XkbSendMap(client,xkb,&rep);
}


_XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq *req, char* values)
{
    XkbSrvInfoPtr       xkbi;
    XkbDescPtr          xkb;
    int                 error;
    int                 nTypes = 0, nActions;
    CARD8               mapWidths[XkbMaxLegalKeyCode + 1];
    CARD16              symsPerKey[XkbMaxLegalKeyCode + 1];

    xkbi= dev->key->xkbInfo;
    xkb = xkbi->desc;

    if ((xkb->min_key_code != req->minKeyCode)||
        (xkb->max_key_code != req->maxKeyCode)) {
	if (client->vMajor!=1) { /* pre 1.0 versions of Xlib have a bug */
	    req->minKeyCode= xkb->min_key_code;
	    req->maxKeyCode= xkb->max_key_code;
	}
	else {
	    if (!XkbIsLegalKeycode(req->minKeyCode)) {
		client->errorValue = _XkbErrCode3(2, req->minKeyCode, req->maxKeyCode);
		return BadValue;
	    }
	    if (req->minKeyCode > req->maxKeyCode) {
		client->errorValue = _XkbErrCode3(3, req->minKeyCode, req->maxKeyCode);
		return BadMatch;
	    }
	}
    }

    if ((req->present & XkbKeyTypesMask) &&
	(!CheckKeyTypes(client,xkb,req,(xkbKeyTypeWireDesc **)&values,
						&nTypes,mapWidths))) {
	client->errorValue = nTypes;
	return BadValue;
    }
    if ((req->present & XkbKeySymsMask) &&
	(!CheckKeySyms(client,xkb,req,nTypes,mapWidths,symsPerKey,
					(xkbSymMapWireDesc **)&values,&error))) {
	client->errorValue = error;
	return BadValue;
    }

    if ((req->present & XkbKeyActionsMask) &&
	(!CheckKeyActions(xkb,req,nTypes,mapWidths,symsPerKey,
						(CARD8 **)&values,&nActions))) {
	client->errorValue = nActions;
	return BadValue;
    }

    if ((req->present & XkbKeyBehaviorsMask) &&
	(!CheckKeyBehaviors(xkb,req,(xkbBehaviorWireDesc**)&values,&error))) {
	client->errorValue = error;
	return BadValue;
    }

    if ((req->present & XkbVirtualModsMask) &&
	(!CheckVirtualMods(xkb,req,(CARD8 **)&values,&error))) {
	client->errorValue= error;
	return BadValue;
    }
    if ((req->present&XkbExplicitComponentsMask) &&
	(!CheckKeyExplicit(xkb,req,(CARD8 **)&values,&error))) {
	client->errorValue= error;
	return BadValue;
    }
    if ((req->present&XkbModifierMapMask) &&
	(!CheckModifierMap(xkb,req,(CARD8 **)&values,&error))) {
	client->errorValue= error;
	return BadValue;
    }
    if ((req->present&XkbVirtualModMapMask) &&
	(!CheckVirtualModMap(xkb,req,(xkbVModMapWireDesc **)&values,&error))) {
	client->errorValue= error;
	return BadValue;
    }

    if (((values-((char *)req))/4)!= req->length) {
	ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after check)\n");
	client->errorValue = values-((char *)&req[1]);
	return BadLength;
    }

    return Success;
}


_GetCountedString(char **wire_inout,Bool swap)
{
char *	wire,*str;
CARD16	len,*plen;

    wire= *wire_inout;
    plen= (CARD16 *)wire;
    if (swap) {
	register int n;
	swaps(plen,n);
    }
    len= *plen;
    str= (char *)_XkbAlloc(len+1);
    if (str) {
	memcpy(str,&wire[2],len);
	str[len]= '\0';
    }
    wire+= XkbPaddedSize(len+2);
    *wire_inout= wire;
    return str;
}


XkbSendGeometry(	ClientPtr		client,
			XkbGeometryPtr		geom,
			xkbGetGeometryReply *	rep,
			Bool			freeGeom)
{
    char	*desc,*start;
    int		 len;

    if (geom!=NULL) {
	len= rep->length*4;
	start= desc= (char *)xalloc(len);
	if (!start)
	    return BadAlloc;
	desc=  XkbWriteCountedString(desc,geom->label_font,client->swapped);
	if ( rep->nProperties>0 )
	    desc = XkbWriteGeomProperties(desc,geom,client->swapped);
	if ( rep->nColors>0 )
	    desc = XkbWriteGeomColors(desc,geom,client->swapped);
	if ( rep->nShapes>0 )
	    desc = XkbWriteGeomShapes(desc,geom,client->swapped);
	if ( rep->nSections>0 )
	    desc = XkbWriteGeomSections(desc,geom,client->swapped);
	if ( rep->nDoodads>0 )
	    desc = XkbWriteGeomDoodads(desc,geom->num_doodads,geom->doodads,
							  client->swapped);
	if ( rep->nKeyAliases>0 )
	    desc = XkbWriteGeomKeyAliases(desc,geom,client->swapped);
	if ((desc-start)!=(len)) {
	    ErrorF("[xkb] BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n",
			len, (unsigned long)(desc-start));
	}
    }
    else {
	len= 0;
	start= NULL;
    }
    if (client->swapped) {
	register int n;
	swaps(&rep->sequenceNumber,n);
	swapl(&rep->length,n);
	swapl(&rep->name,n);
	swaps(&rep->widthMM,n);
	swaps(&rep->heightMM,n);
	swaps(&rep->nProperties,n);
	swaps(&rep->nColors,n);
	swaps(&rep->nShapes,n);
	swaps(&rep->nSections,n);
	swaps(&rep->nDoodads,n);
	swaps(&rep->nKeyAliases,n);
    }
    WriteToClient(client, SIZEOF(xkbGetGeometryReply), (char *)rep);
    if (len>0)
	WriteToClient(client, len, start);
    if (start!=NULL)
	xfree((char *)start);
    if (freeGeom)
	XkbFreeGeometry(geom,XkbGeomAllMask,True);
    return client->noClientException;
}


XkbComputeGetGeometryReplySize(	XkbGeometryPtr		geom,
				xkbGetGeometryReply *	rep,
				Atom			name)
{
int	len;

    if (geom!=NULL) {
	len= XkbSizeCountedString(geom->label_font);
	len+= XkbSizeGeomProperties(geom);
	len+= XkbSizeGeomColors(geom);
	len+= XkbSizeGeomShapes(geom);
	len+= XkbSizeGeomSections(geom);
	len+= XkbSizeGeomDoodads(geom->num_doodads,geom->doodads);
	len+= XkbSizeGeomKeyAliases(geom);
	rep->length= len/4;
	rep->found= True;
	rep->name= geom->name;
	rep->widthMM= geom->width_mm;
	rep->heightMM= geom->height_mm;
	rep->nProperties= geom->num_properties;
	rep->nColors= geom->num_colors;
	rep->nShapes= geom->num_shapes;
	rep->nSections= geom->num_sections;
	rep->nDoodads= geom->num_doodads;
	rep->nKeyAliases= geom->num_key_aliases;
	rep->baseColorNdx= XkbGeomColorIndex(geom,geom->base_color);
	rep->labelColorNdx= XkbGeomColorIndex(geom,geom->label_color);
    }
    else {
	rep->length= 0;
	rep->found= False;
	rep->name= name;
	rep->widthMM= rep->heightMM= 0;
	rep->nProperties= rep->nColors= rep->nShapes= 0;
	rep->nSections= rep->nDoodads= 0;
	rep->nKeyAliases= 0;
	rep->labelColorNdx= rep->baseColorNdx= 0;
    }
    return Success;
}


ProcXkbGetCompatMap(ClientPtr client)
{
    xkbGetCompatMapReply 	rep;
    DeviceIntPtr 		dev;
    XkbDescPtr			xkb;
    XkbCompatMapPtr		compat;

    REQUEST(xkbGetCompatMapReq);
    REQUEST_SIZE_MATCH(xkbGetCompatMapReq);

    if (!(client->xkbClientFlags&_XkbClientInitialized))
	return BadAccess;

    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);

    xkb = dev->key->xkbInfo->desc;
    compat= xkb->compat;

    rep.type = X_Reply;
    rep.deviceID = dev->id;
    rep.sequenceNumber = client->sequence;
    rep.length = 0;
    rep.firstSI = stuff->firstSI;
    rep.nSI = stuff->nSI;
    if (stuff->getAllSI) {
	rep.firstSI = 0;
	rep.nSI = compat->num_si;
    }
    else if ((((unsigned)stuff->nSI)>0)&&
		((unsigned)(stuff->firstSI+stuff->nSI-1)>=compat->num_si)) {
	client->errorValue = _XkbErrCode2(0x05,compat->num_si);
	return BadValue;
    }
    rep.nTotalSI = compat->num_si;
    rep.groups= stuff->groups;
    XkbComputeGetCompatMapReplySize(compat,&rep);
    return XkbSendCompatMap(client,compat,&rep);
}


_XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
                  xkbSetNamesReq *stuff, CARD32 *data)
{
    XkbDescRec		*xkb;
    XkbNamesRec		*names;
    CARD32		*tmp;
    Atom		 bad;

    tmp = data;
    xkb = dev->key->xkbInfo->desc;
    names = xkb->names;

    if (stuff->which & XkbKeyTypeNamesMask) {
        int i;
        CARD32	*old;
        if ( stuff->nTypes<1 ) {
            client->errorValue = _XkbErrCode2(0x02,stuff->nTypes);
            return BadValue;
        }
        if ((unsigned)(stuff->firstType+stuff->nTypes-1)>=xkb->map->num_types) {
            client->errorValue = _XkbErrCode4(0x03,stuff->firstType,
                    stuff->nTypes,
                    xkb->map->num_types);
            return BadValue;
        }
        if (((unsigned)stuff->firstType)<=XkbLastRequiredType) {
            client->errorValue = _XkbErrCode2(0x04,stuff->firstType);
            return BadAccess;
        }
        old= tmp;
        tmp= _XkbCheckAtoms(tmp,stuff->nTypes,client->swapped,&bad);
        if (!tmp) {
            client->errorValue= bad;
            return BadAtom;
        }
        for (i=0;i<stuff->nTypes;i++,old++) {
            if (!_XkbCheckTypeName((Atom)*old,stuff->firstType+i))
                client->errorValue= _XkbErrCode2(0x05,i);
        }
    }
    if (stuff->which&XkbKTLevelNamesMask) {
        unsigned i;
        XkbKeyTypePtr	type;
        CARD8 *		width;
        if ( stuff->nKTLevels<1 ) {
            client->errorValue = _XkbErrCode2(0x05,stuff->nKTLevels);
            return BadValue;
        }
        if ((unsigned)(stuff->firstKTLevel+stuff->nKTLevels-1)>=
                xkb->map->num_types) {
            client->errorValue = _XkbErrCode4(0x06,stuff->firstKTLevel,
                    stuff->nKTLevels,xkb->map->num_types);
            return BadValue;
        }
        width = (CARD8 *)tmp;
        tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels));
        type = &xkb->map->types[stuff->firstKTLevel];
        for (i=0;i<stuff->nKTLevels;i++,type++) {
            if (width[i]==0)
                continue;
            else if (width[i]!=type->num_levels) {
                client->errorValue= _XkbErrCode4(0x07,i+stuff->firstKTLevel,
                        type->num_levels,width[i]);
                return BadMatch;
            }
            tmp= _XkbCheckAtoms(tmp,width[i],client->swapped,&bad);
            if (!tmp) {
                client->errorValue= bad;
                return BadAtom;
            }
        }
    }
    if (stuff->which&XkbIndicatorNamesMask) {
        if (stuff->indicators==0) {
            client->errorValue= 0x08;
            return BadMatch;
        }
        tmp= _XkbCheckMaskedAtoms(tmp,XkbNumIndicators,stuff->indicators,
                client->swapped,&bad);
        if (!tmp) {
            client->errorValue= bad;
            return BadAtom;
        }
    }
    if (stuff->which&XkbVirtualModNamesMask) {
        if (stuff->virtualMods==0) {
            client->errorValue= 0x09;
            return BadMatch;
        }
        tmp= _XkbCheckMaskedAtoms(tmp,XkbNumVirtualMods,
                (CARD32)stuff->virtualMods,
                client->swapped,&bad);
        if (!tmp) {
            client->errorValue = bad;
            return BadAtom;
        }
    }
    if (stuff->which&XkbGroupNamesMask) {
        if (stuff->groupNames==0) {
            client->errorValue= 0x0a;
            return BadMatch;
        }
        tmp= _XkbCheckMaskedAtoms(tmp,XkbNumKbdGroups,
                (CARD32)stuff->groupNames,
                client->swapped,&bad);
        if (!tmp) {
            client->errorValue = bad;
            return BadAtom;
        }
    }
    if (stuff->which&XkbKeyNamesMask) {
        if (stuff->firstKey<(unsigned)xkb->min_key_code) {
            client->errorValue= _XkbErrCode3(0x0b,xkb->min_key_code,
                    stuff->firstKey);
            return BadValue;
        }
        if (((unsigned)(stuff->firstKey+stuff->nKeys-1)>xkb->max_key_code)||
                (stuff->nKeys<1)) {
            client->errorValue= _XkbErrCode4(0x0c,xkb->max_key_code,
                    stuff->firstKey,stuff->nKeys);
            return BadValue;
        }
        tmp+= stuff->nKeys;
    }
    if ((stuff->which&XkbKeyAliasesMask)&&(stuff->nKeyAliases>0)) {
        tmp+= stuff->nKeyAliases*2;
    }
    if (stuff->which&XkbRGNamesMask) {
        if ( stuff->nRadioGroups<1 ) {
            client->errorValue= _XkbErrCode2(0x0d,stuff->nRadioGroups);
            return BadValue;
        }
        tmp= _XkbCheckAtoms(tmp,stuff->nRadioGroups,client->swapped,&bad);
        if (!tmp) {
            client->errorValue= bad;
            return BadAtom;
        }
    }
    if ((tmp-((CARD32 *)stuff))!=stuff->length) {
        client->errorValue = stuff->length;
        return BadLength;
    }

    return Success;
}


_CheckSetGeom(	XkbGeometryPtr		geom,
		xkbSetGeometryReq *	req,
		ClientPtr 		client)
{
register int	i;
Status		status;
char *		wire;

    wire= (char *)&req[1];
    geom->label_font= _GetCountedString(&wire,client->swapped);

    for (i=0;i<req->nProperties;i++) {
	char *name,*val;
	name= _GetCountedString(&wire,client->swapped);
        if (!name)
            return BadAlloc;
	val= _GetCountedString(&wire,client->swapped);
        if (!val) {
            xfree(name);
            return BadAlloc;
        }
	if (XkbAddGeomProperty(geom,name,val)==NULL) {
            xfree(name);
            xfree(val);
	    return BadAlloc;
        }
        xfree(name);
        xfree(val);
    }

    if (req->nColors<2) {
	client->errorValue= _XkbErrCode3(0x01,2,req->nColors);
	return BadValue;
    }
    if (req->baseColorNdx>req->nColors) {
	client->errorValue=_XkbErrCode3(0x03,req->nColors,req->baseColorNdx);
	return BadMatch;
    }
    if (req->labelColorNdx>req->nColors) {
	client->errorValue= _XkbErrCode3(0x03,req->nColors,req->labelColorNdx);
	return BadMatch;
    }
    if (req->labelColorNdx==req->baseColorNdx) {
	client->errorValue= _XkbErrCode3(0x04,req->baseColorNdx,
                                         req->labelColorNdx);
	return BadMatch;
    }

    for (i=0;i<req->nColors;i++) {
	char *name;
	name= _GetCountedString(&wire,client->swapped);
	if (!name)
            return BadAlloc;
        if (!XkbAddGeomColor(geom,name,geom->num_colors)) {
            xfree(name);
	    return BadAlloc;
        }
        xfree(name);
    }
    if (req->nColors!=geom->num_colors) {
	client->errorValue= _XkbErrCode3(0x05,req->nColors,geom->num_colors);
	return BadMatch;
    }
    geom->label_color= &geom->colors[req->labelColorNdx];
    geom->base_color= &geom->colors[req->baseColorNdx];

    if ((status=_CheckSetShapes(geom,req,&wire,client))!=Success)
	return status;

    if ((status=_CheckSetSections(geom,req,&wire,client))!=Success)
	return status;

    for (i=0;i<req->nDoodads;i++) {
	status=_CheckSetDoodad(&wire,geom,NULL,client);
	if (status!=Success)
	    return status;
    }

    for (i=0;i<req->nKeyAliases;i++) {
	if (XkbAddGeomKeyAlias(geom,&wire[XkbKeyNameLength],wire)==NULL)
	    return BadAlloc;
	wire+= 2*XkbKeyNameLength;
    }
    return Success;
}


_XkbFindNamedIndicatorMap(XkbSrvLedInfoPtr sli, Atom indicator,
                          int *led_return)
{
    XkbIndicatorMapPtr  map;
    int                 led;

    /* search for the right indicator */
    map = NULL;
    if (sli->names && sli->maps) {
	for (led = 0; (led < XkbNumIndicators) && (map == NULL); led++) {
	    if (sli->names[led] == indicator) {
		map= &sli->maps[led];
		break;
	    }
	}
    }

    *led_return = led;
    return map;
}


ProcXkbLatchLockState(ClientPtr client)
{
    int status;
    DeviceIntPtr dev, tmpd;
    XkbStateRec	oldState,*newState;
    CARD16 changed;
    xkbStateNotify sn;
    XkbEventCauseRec cause;

    REQUEST(xkbLatchLockStateReq);
    REQUEST_SIZE_MATCH(xkbLatchLockStateReq);

    if (!(client->xkbClientFlags & _XkbClientInitialized))
	return BadAccess;

    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
    CHK_MASK_MATCH(0x01, stuff->affectModLocks, stuff->modLocks);
    CHK_MASK_MATCH(0x01, stuff->affectModLatches, stuff->modLatches);

    status = Success;

    for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
        if ((dev == inputInfo.keyboard && tmpd->key && tmpd->coreEvents) ||
            tmpd == dev) {
            if (!tmpd->key->xkbInfo)
                continue;

            oldState = tmpd->key->xkbInfo->state;
            newState = &tmpd->key->xkbInfo->state;
            if (stuff->affectModLocks) {
                newState->locked_mods &= ~stuff->affectModLocks;
                newState->locked_mods |= (stuff->affectModLocks & stuff->modLocks);
            }
            if (status == Success && stuff->lockGroup)
                newState->locked_group = stuff->groupLock;
            if (status == Success && stuff->affectModLatches)
                status = XkbLatchModifiers(tmpd, stuff->affectModLatches,
                                           stuff->modLatches);
            if (status == Success && stuff->latchGroup)
                status = XkbLatchGroup(tmpd, stuff->groupLatch);

            if (status != Success)
                return status;

            XkbComputeDerivedState(tmpd->key->xkbInfo);
            tmpd->key->state = XkbStateFieldFromRec(newState);

            changed = XkbStateChangedFlags(&oldState, newState);
            if (changed) {
                sn.keycode = 0;
                sn.eventType = 0;
                sn.requestMajor = XkbReqCode;
                sn.requestMinor = X_kbLatchLockState;
                sn.changed = changed;
                XkbSendStateNotify(tmpd, &sn);
                changed = XkbIndicatorsToUpdate(tmpd, changed, False);
                if (changed) {
                    XkbSetCauseXkbReq(&cause, X_kbLatchLockState, client);
                    XkbUpdateIndicators(tmpd, changed, True, NULL, &cause);
	        }
            }
        }
    }

    return client->noClientException;
}


_XkbCheckAtoms(CARD32 *wire,int nAtoms,int swapped,Atom *pError)
{
register int i;

    for (i=0;i<nAtoms;i++,wire++) {
	if (swapped) {
	    register int n;
	    swapl(wire,n);
	}
	if ((((Atom)*wire)!=None)&&(!ValidAtom((Atom)*wire))) {
	    *pError= ((Atom)*wire);
	    return NULL;
	}
    }
    return wire;
}


ProcXkbGetKbdByName(ClientPtr client)
{
    DeviceIntPtr 		dev;
    DeviceIntPtr                tmpd;
    xkbGetKbdByNameReply 	rep;
    xkbGetMapReply		mrep;
    xkbGetCompatMapReply	crep;
    xkbGetIndicatorMapReply	irep;
    xkbGetNamesReply		nrep;
    xkbGetGeometryReply		grep;
    XkbComponentNamesRec	names;
    XkbDescPtr			xkb, new;
    unsigned char *		str;
    char 			mapFile[PATH_MAX];
    unsigned			len;
    unsigned			fwant,fneed,reported;
    int				status;
    Bool			geom_changed;
    XkbSrvLedInfoPtr            old_sli;
    XkbSrvLedInfoPtr            sli;
    Mask access_mode = DixGetAttrAccess | DixManageAccess;

    REQUEST(xkbGetKbdByNameReq);
    REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq);

    if (!(client->xkbClientFlags&_XkbClientInitialized))
	return BadAccess;

    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);

    xkb = dev->key->xkbInfo->desc;
    status= Success;
    str= (unsigned char *)&stuff[1];
    names.keymap= GetComponentSpec(&str,True,&status);
    names.keycodes= GetComponentSpec(&str,True,&status);
    names.types= GetComponentSpec(&str,True,&status);
    names.compat= GetComponentSpec(&str,True,&status);
    names.symbols= GetComponentSpec(&str,True,&status);
    names.geometry= GetComponentSpec(&str,True,&status);
    if (status!=Success)
	return status;
    len= str-((unsigned char *)stuff);
    if ((XkbPaddedSize(len)/4)!=stuff->length)
	return BadLength;

    CHK_MASK_LEGAL(0x01,stuff->want,XkbGBN_AllComponentsMask);
    CHK_MASK_LEGAL(0x02,stuff->need,XkbGBN_AllComponentsMask);

    if (stuff->load)
	 fwant= XkbGBN_AllComponentsMask;
    else fwant= stuff->want|stuff->need;
    if ((!names.compat)&&
        (fwant&(XkbGBN_CompatMapMask|XkbGBN_IndicatorMapMask))) {
        names.compat= _XkbDupString("%");
    }
    if ((!names.types)&&(fwant&(XkbGBN_TypesMask))) {
        names.types= _XkbDupString("%");
    }
    if ((!names.symbols)&&(fwant&XkbGBN_SymbolsMask)) {
        names.symbols= _XkbDupString("%");
    }
    geom_changed= ((names.geometry!=NULL)&&(strcmp(names.geometry,"%")!=0));
    if ((!names.geometry)&&(fwant&XkbGBN_GeometryMask)) {
        names.geometry= _XkbDupString("%");
        geom_changed= False;
    }

    bzero(mapFile,PATH_MAX);
    rep.type= X_Reply;
    rep.deviceID = dev->id;
    rep.sequenceNumber = client->sequence;
    rep.length = 0;
    rep.minKeyCode = xkb->min_key_code;
    rep.maxKeyCode = xkb->max_key_code;
    rep.loaded=	False;
    fwant= XkbConvertGetByNameComponents(True,stuff->want)|XkmVirtualModsMask;
    fneed= XkbConvertGetByNameComponents(True,stuff->need);
    rep.reported= XkbConvertGetByNameComponents(False,fwant|fneed);
    if (stuff->load) {
	fneed|= XkmKeymapRequired;
	fwant|= XkmKeymapLegal;
    }
    if ((fwant|fneed)&XkmSymbolsMask) {
	fneed|= XkmKeyNamesIndex|XkmTypesIndex;
	fwant|= XkmIndicatorsIndex;
    }

    /* We pass dev in here so we can get the old names out if needed. */
    rep.found = XkbDDXLoadKeymapByNames(dev,&names,fwant,fneed,&new,
                                        mapFile,PATH_MAX);
    rep.newKeyboard= False;
    rep.pad1= rep.pad2= rep.pad3= rep.pad4= 0;

    stuff->want|= stuff->need;
    if (new==NULL)
	rep.reported= 0;
    else {
	if (stuff->load)
	    rep.loaded= True;
	if (stuff->load ||
		((rep.reported&XkbGBN_SymbolsMask) && (new->compat))) {
	    XkbChangesRec changes;
	    bzero(&changes,sizeof(changes));
	    XkbUpdateDescActions(new,
			new->min_key_code,XkbNumKeys(new),
			&changes);
	}

	if (new->map==NULL)
	    rep.reported&= ~(XkbGBN_SymbolsMask|XkbGBN_TypesMask);
	else if (rep.reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask)) {
	    mrep.type= X_Reply;
	    mrep.deviceID = dev->id;
	    mrep.sequenceNumber= client->sequence;
	    mrep.length = ((SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2);
	    mrep.minKeyCode = new->min_key_code;
	    mrep.maxKeyCode = new->max_key_code;
	    mrep.present = 0;
	    mrep.totalSyms = mrep.totalActs =
		mrep.totalKeyBehaviors= mrep.totalKeyExplicit=
		mrep.totalModMapKeys= 0;
	    if (rep.reported&(XkbGBN_TypesMask|XkbGBN_ClientSymbolsMask)) {
		mrep.present|= XkbKeyTypesMask;
		mrep.firstType = 0;
		mrep.nTypes = mrep.totalTypes= new->map->num_types;
	    }
	    else {
		mrep.firstType = mrep.nTypes= 0;
		mrep.totalTypes= 0;
	    }
	    if (rep.reported&XkbGBN_ClientSymbolsMask) {
		mrep.present|= (XkbKeySymsMask|XkbModifierMapMask);
		mrep.firstKeySym = mrep.firstModMapKey= new->min_key_code;
		mrep.nKeySyms = mrep.nModMapKeys= XkbNumKeys(new);
	    }
	    else {
		mrep.firstKeySym= mrep.firstModMapKey= 0;
		mrep.nKeySyms= mrep.nModMapKeys= 0;
	    }
	    if (rep.reported&XkbGBN_ServerSymbolsMask) {
		mrep.present|= XkbAllServerInfoMask;
		mrep.virtualMods= ~0;
		mrep.firstKeyAct = mrep.firstKeyBehavior =
			mrep.firstKeyExplicit = new->min_key_code;
		mrep.nKeyActs = mrep.nKeyBehaviors =
			mrep.nKeyExplicit = XkbNumKeys(new);
	    }
	    else {
		mrep.virtualMods= 0;
		mrep.firstKeyAct= mrep.firstKeyBehavior=
			mrep.firstKeyExplicit = 0;
		mrep.nKeyActs= mrep.nKeyBehaviors= mrep.nKeyExplicit= 0;
	    }
	    XkbComputeGetMapReplySize(new,&mrep);
	    rep.length+= SIZEOF(xGenericReply)/4+mrep.length;
	}
	if (new->compat==NULL)
	    rep.reported&= ~XkbGBN_CompatMapMask;
	else if (rep.reported&XkbGBN_CompatMapMask) {
	    crep.type= X_Reply;
	    crep.deviceID= dev->id;
	    crep.sequenceNumber= client->sequence;
	    crep.length= 0;
	    crep.groups= XkbAllGroupsMask;
	    crep.firstSI= 0;
	    crep.nSI= crep.nTotalSI= new->compat->num_si;
	    XkbComputeGetCompatMapReplySize(new->compat,&crep);
	    rep.length+= SIZEOF(xGenericReply)/4+crep.length;
	}
	if (new->indicators==NULL)
	    rep.reported&= ~XkbGBN_IndicatorMapMask;
	else if (rep.reported&XkbGBN_IndicatorMapMask) {
	    irep.type= X_Reply;
	    irep.deviceID= dev->id;
	    irep.sequenceNumber= client->sequence;
	    irep.length= 0;
	    irep.which= XkbAllIndicatorsMask;
	    XkbComputeGetIndicatorMapReplySize(new->indicators,&irep);
	    rep.length+= SIZEOF(xGenericReply)/4+irep.length;
	}
	if (new->names==NULL)
	    rep.reported&= ~(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask);
	else if (rep.reported&(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask)) {
	    nrep.type= X_Reply;
	    nrep.deviceID= dev->id;
	    nrep.sequenceNumber= client->sequence;
	    nrep.length= 0;
	    nrep.minKeyCode= new->min_key_code;
	    nrep.maxKeyCode= new->max_key_code;
	    if (rep.reported&XkbGBN_OtherNamesMask) {
		nrep.which= XkbAllNamesMask;
		if (new->map!=NULL)
		     nrep.nTypes= new->map->num_types;
		else nrep.nTypes= 0;
		nrep.nKTLevels= 0;
		nrep.groupNames= XkbAllGroupsMask;
		nrep.virtualMods= XkbAllVirtualModsMask;
		nrep.indicators= XkbAllIndicatorsMask;
		nrep.nRadioGroups= new->names->num_rg;
	    }
	    else {
		nrep.which= 0;
		nrep.nTypes= 0;
		nrep.nKTLevels= 0;
		nrep.groupNames= 0;
		nrep.virtualMods= 0;
		nrep.indicators= 0;
		nrep.nRadioGroups= 0;
	    }
	    if (rep.reported&XkbGBN_KeyNamesMask) {
		nrep.which|= XkbKeyNamesMask;
		nrep.firstKey= new->min_key_code;
		nrep.nKeys= XkbNumKeys(new);
		nrep.nKeyAliases= new->names->num_key_aliases;
		if (nrep.nKeyAliases)
		    nrep.which|= XkbKeyAliasesMask;
	    }
	    else {
		nrep.which&= ~(XkbKeyNamesMask|XkbKeyAliasesMask);
		nrep.firstKey= nrep.nKeys= 0;
		nrep.nKeyAliases= 0;
	    }
	    XkbComputeGetNamesReplySize(new,&nrep);
	    rep.length+= SIZEOF(xGenericReply)/4+nrep.length;
	}
	if (new->geom==NULL)
	    rep.reported&= ~XkbGBN_GeometryMask;
	else if (rep.reported&XkbGBN_GeometryMask) {
	    grep.type= X_Reply;
	    grep.deviceID= dev->id;
	    grep.sequenceNumber= client->sequence;
	    grep.length= 0;
	    grep.found= True;
	    grep.pad= 0;
	    grep.widthMM= grep.heightMM= 0;
	    grep.nProperties= grep.nColors= grep.nShapes= 0;
	    grep.nSections= grep.nDoodads= 0;
	    grep.baseColorNdx= grep.labelColorNdx= 0;
	    XkbComputeGetGeometryReplySize(new->geom,&grep,None);
	    rep.length+= SIZEOF(xGenericReply)/4+grep.length;
	}
    }

    reported= rep.reported;
    if ( client->swapped ) {
	register int n;
	swaps(&rep.sequenceNumber,n);
	swapl(&rep.length,n);
	swaps(&rep.found,n);
	swaps(&rep.reported,n);
    }
    WriteToClient(client,SIZEOF(xkbGetKbdByNameReply), (char *)&rep);
    if (reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask))
	XkbSendMap(client,new,&mrep);
    if (reported&XkbGBN_CompatMapMask)
	XkbSendCompatMap(client,new->compat,&crep);
    if (reported&XkbGBN_IndicatorMapMask)
	XkbSendIndicatorMap(client,new->indicators,&irep);
    if (reported&(XkbGBN_KeyNamesMask|XkbGBN_OtherNamesMask))
	XkbSendNames(client,new,&nrep);
    if (reported&XkbGBN_GeometryMask)
	XkbSendGeometry(client,new->geom,&grep,False);
    if (rep.loaded) {
	XkbDescPtr		old_xkb;
	xkbNewKeyboardNotify 	nkn;
	int 			i,nG,nTG;
	old_xkb= xkb;
	xkb= new;
	dev->key->xkbInfo->desc= xkb;
	new= old_xkb; /* so it'll get freed automatically */

	*xkb->ctrls= *old_xkb->ctrls;
	for (nG=nTG=0,i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
	    nG= XkbKeyNumGroups(xkb,i);
	    if (nG>=XkbNumKbdGroups) {
		nTG= XkbNumKbdGroups;
		break;
	    }
	    if (nG>nTG) {
		nTG= nG;
	    }
	}
	xkb->ctrls->num_groups= nTG;

        for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
            if (tmpd == dev ||
                (dev->id == inputInfo.keyboard->id && tmpd->key &&
                 tmpd->coreEvents)) {

                memcpy(tmpd->key->modifierMap, xkb->map->modmap,
                       xkb->max_key_code + 1);
                if (tmpd != dev)
                    XkbCopyKeymap(dev->key->xkbInfo->desc,
                                  tmpd->key->xkbInfo->desc, True);
                XkbUpdateCoreDescription(tmpd, True);

                if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) {
                    old_sli = tmpd->kbdfeed->xkb_sli;
                    tmpd->kbdfeed->xkb_sli = NULL;
                    sli = XkbAllocSrvLedInfo(tmpd, tmpd->kbdfeed, NULL, 0);
                    if (sli) {
                        sli->explicitState = old_sli->explicitState;
                        sli->effectiveState = old_sli->effectiveState;
                    }
                    tmpd->kbdfeed->xkb_sli = sli;
                    XkbFreeSrvLedInfo(old_sli);
                }
            }
        }

        /* this should be either a MN or an NKN, depending on whether or not
         * the keycode range changed? */
	nkn.deviceID= nkn.oldDeviceID= dev->id;
	nkn.minKeyCode= new->min_key_code;
	nkn.maxKeyCode= new->max_key_code;
	nkn.oldMinKeyCode= xkb->min_key_code;
	nkn.oldMaxKeyCode= xkb->max_key_code;
	nkn.requestMajor= XkbReqCode;
	nkn.requestMinor= X_kbGetKbdByName;
	nkn.changed= XkbNKN_KeycodesMask;
	if (geom_changed)
	    nkn.changed|= XkbNKN_GeometryMask;
	XkbSendNewKeyboardNotify(dev,&nkn);
    }
    if ((new!=NULL)&&(new!=xkb)) {
	XkbFreeKeyboard(new,XkbAllComponentsMask,True);
	new= NULL;
    }
    if (names.keymap)	{ _XkbFree(names.keymap); names.keymap= NULL; }
    if (names.keycodes)	{ _XkbFree(names.keycodes); names.keycodes= NULL; }
    if (names.types)	{ _XkbFree(names.types); names.types= NULL; }
    if (names.compat)	{ _XkbFree(names.compat); names.compat= NULL; }
    if (names.symbols)	{ _XkbFree(names.symbols); names.symbols= NULL; }
    if (names.geometry)	{ _XkbFree(names.geometry); names.geometry= NULL; }
    return client->noClientException;
}


ProcXkbGetNamedIndicator(ClientPtr client)
{
    DeviceIntPtr 		dev;
    xkbGetNamedIndicatorReply 	rep;
    register int		i = 0;
    XkbSrvLedInfoPtr		sli;
    XkbIndicatorMapPtr		map = NULL;

    REQUEST(xkbGetNamedIndicatorReq);
    REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq);

    if (!(client->xkbClientFlags&_XkbClientInitialized))
	return BadAccess;

    CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
    CHK_ATOM_ONLY(stuff->indicator);

    sli= XkbFindSrvLedInfo(dev,stuff->ledClass,stuff->ledID,0);
    if (!sli)
	return BadAlloc;

    i= 0;
    map= NULL;
    if ((sli->names)&&(sli->maps)) {
        for (i=0;i<XkbNumIndicators;i++) {
            if (stuff->indicator==sli->names[i]) {
                map= &sli->maps[i];
                break;
            }
        }
    }

    rep.type= X_Reply;
    rep.length = 0;
    rep.sequenceNumber = client->sequence;
    rep.deviceID = dev->id;
    rep.indicator= stuff->indicator;
    if (map!=NULL) {
	rep.found= 		True;
	rep.on=			((sli->effectiveState&(1<<i))!=0);
	rep.realIndicator=	((sli->physIndicators&(1<<i))!=0);
	rep.ndx= 		i;
	rep.flags= 		map->flags;
	rep.whichGroups= 	map->which_groups;
	rep.groups= 		map->groups;
	rep.whichMods= 		map->which_mods;
	rep.mods= 		map->mods.mask;
	rep.realMods= 		map->mods.real_mods;
	rep.virtualMods= 	map->mods.vmods;
	rep.ctrls= 		map->ctrls;
	rep.supported= 		True;
    }
    else  {
	rep.found= 		False;
	rep.on= 		False;
	rep.realIndicator= 	False;
	rep.ndx= 		XkbNoIndicator;
	rep.flags= 		0;
	rep.whichGroups= 	0;
	rep.groups= 		0;
	rep.whichMods= 		0;
	rep.mods=		0;
	rep.realMods= 		0;
	rep.virtualMods= 	0;
	rep.ctrls= 		0;
	rep.supported= 		True;
    }
    if ( client->swapped ) {
	register int n;
	swapl(&rep.length,n);
	swaps(&rep.sequenceNumber,n);
	swapl(&rep.indicator,n);
	swaps(&rep.virtualMods,n);
	swapl(&rep.ctrls,n);
    }

    WriteToClient(client,SIZEOF(xkbGetNamedIndicatorReply), (char *)&rep);
    return client->noClientException;
}


_XkbSetNames(ClientPtr client, DeviceIntPtr dev, xkbSetNamesReq *stuff)
{
    XkbDescRec		*xkb;
    XkbNamesRec		*names;
    CARD32		*tmp;
    xkbNamesNotify	 nn;

    tmp = (CARD32 *)&stuff[1];
    xkb = dev->key->xkbInfo->desc;
    names = xkb->names;

    if (XkbAllocNames(xkb,stuff->which,stuff->nRadioGroups,
                stuff->nKeyAliases)!=Success) {
        return BadAlloc;
    }

    bzero(&nn,sizeof(xkbNamesNotify));
    nn.changed= stuff->which;
    tmp = (CARD32 *)&stuff[1];
    if (stuff->which&XkbKeycodesNameMask)
        names->keycodes= *tmp++;
    if (stuff->which&XkbGeometryNameMask)
        names->geometry= *tmp++;
    if (stuff->which&XkbSymbolsNameMask)
        names->symbols= *tmp++;
    if (stuff->which&XkbPhysSymbolsNameMask)
        names->phys_symbols= *tmp++;
    if (stuff->which&XkbTypesNameMask)
        names->types= *tmp++;
    if (stuff->which&XkbCompatNameMask)
        names->compat= *tmp++;
    if ((stuff->which&XkbKeyTypeNamesMask)&&(stuff->nTypes>0)) {
        register unsigned i;
        register XkbKeyTypePtr type;

        type= &xkb->map->types[stuff->firstType];
        for (i=0;i<stuff->nTypes;i++,type++) {
            type->name= *tmp++;
        }
        nn.firstType= stuff->firstType;
        nn.nTypes= stuff->nTypes;
    }
    if (stuff->which&XkbKTLevelNamesMask) {
        register XkbKeyTypePtr	type;
        register unsigned i;
        CARD8 *width;

        width = (CARD8 *)tmp;
        tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels));
        type= &xkb->map->types[stuff->firstKTLevel];
        for (i=0;i<stuff->nKTLevels;i++,type++) {
            if (width[i]>0) {
                if (type->level_names) {
                    register unsigned n;
                    for (n=0;n<width[i];n++) {
                        type->level_names[n]= tmp[n];
                    }
                }
                tmp+= width[i];
            }
        }
        nn.firstLevelName= 0;
        nn.nLevelNames= stuff->nTypes;
    }
    if (stuff->which&XkbIndicatorNamesMask) {
        tmp= _XkbCopyMaskedAtoms(tmp,names->indicators,XkbNumIndicators,
                stuff->indicators);
        nn.changedIndicators= stuff->indicators;
    }
    if (stuff->which&XkbVirtualModNamesMask) {
        tmp= _XkbCopyMaskedAtoms(tmp,names->vmods,XkbNumVirtualMods,
                stuff->virtualMods);
        nn.changedVirtualMods= stuff->virtualMods;
    }
    if (stuff->which&XkbGroupNamesMask) {
        tmp= _XkbCopyMaskedAtoms(tmp,names->groups,XkbNumKbdGroups,
                stuff->groupNames);
        nn.changedVirtualMods= stuff->groupNames;
    }
    if (stuff->which&XkbKeyNamesMask) {
        memcpy((char*)&names->keys[stuff->firstKey],(char *)tmp,
                stuff->nKeys*XkbKeyNameLength);
        tmp+= stuff->nKeys;
        nn.firstKey= stuff->firstKey;
        nn.nKeys= stuff->nKeys;
    }
    if (stuff->which&XkbKeyAliasesMask) {
        if (stuff->nKeyAliases>0) {
            register int na= stuff->nKeyAliases;
            if (XkbAllocNames(xkb,XkbKeyAliasesMask,0,na)!=Success)
                return BadAlloc;
            memcpy((char *)names->key_aliases,(char *)tmp,
                    stuff->nKeyAliases*sizeof(XkbKeyAliasRec));
            tmp+= stuff->nKeyAliases*2;
        }
        else if (names->key_aliases!=NULL) {
            _XkbFree(names->key_aliases);
            names->key_aliases= NULL;
            names->num_key_aliases= 0;
        }
        nn.nAliases= names->num_key_aliases;
    }
    if (stuff->which&XkbRGNamesMask) {
        if (stuff->nRadioGroups>0) {
            register unsigned i,nrg;
            nrg= stuff->nRadioGroups;
            if (XkbAllocNames(xkb,XkbRGNamesMask,nrg,0)!=Success)
                return BadAlloc;

            for (i=0;i<stuff->nRadioGroups;i++) {
                names->radio_groups[i]= tmp[i];
            }
            tmp+= stuff->nRadioGroups;
        }
        else if (names->radio_groups) {
            _XkbFree(names->radio_groups);
            names->radio_groups= NULL;
            names->num_rg= 0;
        }
        nn.nRadioGroups= names->num_rg;
    }
    if (nn.changed) {
        Bool needExtEvent;
        needExtEvent= (nn.changed&XkbIndicatorNamesMask)!=0;
        XkbSendNamesNotify(dev,&nn);
        if (needExtEvent) {
            XkbSrvLedInfoPtr		sli;
            xkbExtensionDeviceNotify	edev;
            register int		i;
            register unsigned		bit;

            sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,
                    XkbXI_IndicatorsMask);
            sli->namesPresent= 0;
            for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
                if (names->indicators[i]!=None)
                    sli->namesPresent|= bit;
            }
            bzero(&edev,sizeof(xkbExtensionDeviceNotify));
            edev.reason=	XkbXI_IndicatorNamesMask;
            edev.ledClass=	KbdFeedbackClass;
            edev.ledID=		dev->kbdfeed->ctrl.id;
            edev.ledsDefined= 	sli->namesPresent|sli->mapsPresent;
            edev.ledState=	sli->effectiveState;
            edev.firstBtn=	0;
            edev.nBtns=		0;
            edev.supported=	XkbXI_AllFeaturesMask;
            edev.unsupported=	0;
            XkbSendExtensionDeviceNotify(dev,client,&edev);
        }
    }
    return Success;
}


ProcXkbSetCompatMap(ClientPtr client)
{
    DeviceIntPtr        dev;
    char                *data;
    int                 rc;

    REQUEST(xkbSetCompatMapReq);
    REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq);

    if (!(client->xkbClientFlags&_XkbClientInitialized))
	return BadAccess;

    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);

    data = (char *)&stuff[1];

    /* check first using a dry-run */
    rc = _XkbSetCompatMap(client, dev, stuff, data, TRUE);
    if (rc != Success)
        return rc;
    if (stuff->deviceSpec == XkbUseCoreKbd)
    {
        DeviceIntPtr other;
        for (other = inputInfo.devices; other; other = other->next)
        {
            if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
            {
                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
                if (rc == Success)
                {
                    /* dry-run */
                    rc = _XkbSetCompatMap(client, other, stuff, data, TRUE);
                    if (rc != Success)
                        return rc;
                }
            }
        }
    }

    /* Yay, the dry-runs succeed. Let's apply */
    rc = _XkbSetCompatMap(client, dev, stuff, data, TRUE);
    if (rc != Success)
        return rc;
    if (stuff->deviceSpec == XkbUseCoreKbd)
    {
        DeviceIntPtr other;
        for (other = inputInfo.devices; other; other = other->next)
        {
            if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
            {
                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
                if (rc == Success)
                {
                    rc = _XkbSetCompatMap(client, other, stuff, data, TRUE);
                    if (rc != Success)
                        return rc;
                }
            }
        }
    }

    return client->noClientException;
}


XkbWriteKeySyms(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,ClientPtr client)
{
register KeySym *	pSym;
XkbSymMapPtr		symMap;
xkbSymMapWireDesc *	outMap;
register unsigned	i;

    symMap = &xkb->map->key_sym_map[rep->firstKeySym];
    for (i=0;i<rep->nKeySyms;i++,symMap++) {
	outMap = (xkbSymMapWireDesc *)buf;
	outMap->ktIndex[0] = symMap->kt_index[0];
	outMap->ktIndex[1] = symMap->kt_index[1];
	outMap->ktIndex[2] = symMap->kt_index[2];
	outMap->ktIndex[3] = symMap->kt_index[3];
	outMap->groupInfo = symMap->group_info;
	outMap->width= symMap->width;
	outMap->nSyms = symMap->width*XkbNumGroups(symMap->group_info);
	buf= (char *)&outMap[1];
	if (outMap->nSyms==0)
	    continue;

	pSym = &xkb->map->syms[symMap->offset];
	memcpy((char *)buf,(char *)pSym,outMap->nSyms*4);
	if (client->swapped) {
	    register int n,nSyms= outMap->nSyms;
	    swaps(&outMap->nSyms,n);
	    while (nSyms-->0) {
		swapl(buf,n);
		buf+= 4;
	    }
	}
	else buf+= outMap->nSyms*4;
    }
    return buf;
}


ProcXkbSetIndicatorMap(ClientPtr client)
{
    int                 i, bit;
    int                 nIndicators;
    DeviceIntPtr        dev;
    xkbIndicatorMapWireDesc     *from;
    int                 rc;

    REQUEST(xkbSetIndicatorMapReq);
    REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq);

    if (!(client->xkbClientFlags&_XkbClientInitialized))
	return BadAccess;

    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);

    if (stuff->which==0)
	return client->noClientException;

    for (nIndicators=i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
	if (stuff->which&bit)
	    nIndicators++;
    }
    if (stuff->length!=((SIZEOF(xkbSetIndicatorMapReq)+
			(nIndicators*SIZEOF(xkbIndicatorMapWireDesc)))/4)) {
	return BadLength;
    }

    from = (xkbIndicatorMapWireDesc *)&stuff[1];
    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
	if (stuff->which&bit) {
	    if (client->swapped) {
		int n;
		swaps(&from->virtualMods,n);
		swapl(&from->ctrls,n);
	    }
	    CHK_MASK_LEGAL(i,from->whichGroups,XkbIM_UseAnyGroup);
	    CHK_MASK_LEGAL(i,from->whichMods,XkbIM_UseAnyMods);
	    from++;
	}
    }

    from = (xkbIndicatorMapWireDesc *)&stuff[1];
    rc = _XkbSetIndicatorMap(client, dev, stuff->which, from);
    if (rc != Success)
        return rc;

    if (stuff->deviceSpec == XkbUseCoreKbd)
    {
        DeviceIntPtr other;
        for (other = inputInfo.devices; other; other = other->next)
        {
            if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
            {
                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess);
                if (rc == Success)
                    _XkbSetIndicatorMap(client, other, stuff->which, from);
            }
        }
    }

    return Success;
}


SendDeviceLedInfo(	XkbSrvLedInfoPtr	sli,
			ClientPtr		client)
{
xkbDeviceLedsWireDesc	wire;
int			length;

    length= 0;
    wire.ledClass= 		sli->class;
    wire.ledID= 		sli->id;
    wire.namesPresent= 		sli->namesPresent;
    wire.mapsPresent=   	sli->mapsPresent;
    wire.physIndicators= 	sli->physIndicators;
    wire.state=			sli->effectiveState;
    if (client->swapped) {
	register int n;
	swaps(&wire.ledClass,n);
	swaps(&wire.ledID,n);
	swapl(&wire.namesPresent,n);
	swapl(&wire.mapsPresent,n);
	swapl(&wire.physIndicators,n);
	swapl(&wire.state,n);
    }
    WriteToClient(client,SIZEOF(xkbDeviceLedsWireDesc),(char *)&wire);
    length+= SIZEOF(xkbDeviceLedsWireDesc);
    if (sli->namesPresent|sli->mapsPresent) {
	register unsigned i,bit;
	if (sli->namesPresent) {
	    CARD32	awire;
	    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
		if (sli->namesPresent&bit) {
		    awire= (CARD32)sli->names[i];
		    if (client->swapped) {
			register int n;
			swapl(&awire,n);
		    }
		    WriteToClient(client,4,(char *)&awire);
		    length+= 4;
		}
	    }
	}
	if (sli->mapsPresent) {
	    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
		xkbIndicatorMapWireDesc	iwire;
		if (sli->mapsPresent&bit) {
		    iwire.flags= 	sli->maps[i].flags;
		    iwire.whichGroups=	sli->maps[i].which_groups;
		    iwire.groups=	sli->maps[i].groups;
		    iwire.whichMods=	sli->maps[i].which_mods;
		    iwire.mods=		sli->maps[i].mods.mask;
		    iwire.realMods=	sli->maps[i].mods.real_mods;
		    iwire.virtualMods=	sli->maps[i].mods.vmods;
		    iwire.ctrls= 	sli->maps[i].ctrls;
		    if (client->swapped) {
			register int n;
			swaps(&iwire.virtualMods,n);
			swapl(&iwire.ctrls,n);
		    }
		    WriteToClient(client,SIZEOF(xkbIndicatorMapWireDesc),
								(char *)&iwire);
		    length+= SIZEOF(xkbIndicatorMapWireDesc);
		}
	    }
	}
    }
    return length;
}


SetVirtualModMap(	XkbSrvInfoPtr		xkbi,
			xkbSetMapReq *		req,
			xkbVModMapWireDesc *	wire,
			XkbChangesPtr 		changes)
{
register unsigned	i,first,last;
XkbServerMapPtr		srv = xkbi->desc->server;

    first= req->firstVModMapKey;
    last=  req->firstVModMapKey+req->nVModMapKeys-1;
    bzero(&srv->vmodmap[first],req->nVModMapKeys*sizeof(unsigned short));
    for (i=0;i<req->totalVModMapKeys;i++,wire++) {
	srv->vmodmap[wire->key]= wire->vmods;
    }
    if (first>0) {
	if (changes->map.changed&XkbVirtualModMapMask) {
	    int oldLast;
	    oldLast= changes->map.first_vmodmap_key+
					changes->map.num_vmodmap_keys-1;
	    if (changes->map.first_vmodmap_key<first)
		first= changes->map.first_vmodmap_key;
	    if (oldLast>last)
		last= oldLast;
	}
	changes->map.first_vmodmap_key= first;
	changes->map.num_vmodmap_keys= (last-first)+1;
    }
    return (char *)wire;
}


_XkbCheckMaskedAtoms(CARD32 *wire,int nAtoms,CARD32 present,int swapped,
								Atom *pError)
{
register unsigned i,bit;

    for (i=0,bit=1;(i<nAtoms)&&(present);i++,bit<<=1) {
	if ((present&bit)==0)
	    continue;
	if (swapped) {
	    register int n;
	    swapl(wire,n);
	}
	if ((((Atom)*wire)!=None)&&(!ValidAtom(((Atom)*wire)))) {
	    *pError= (Atom)*wire;
	    return NULL;
	}
	wire++;
    }
    return wire;
}


_XkbSetNamedIndicator(ClientPtr client, DeviceIntPtr dev,
                      xkbSetNamedIndicatorReq *stuff)
{
    unsigned int                extDevReason;
    unsigned int                statec, namec, mapc;
    XkbSrvLedInfoPtr            sli;
    int                         led = 0;
    XkbIndicatorMapPtr          map;
    DeviceIntPtr                kbd;
    XkbEventCauseRec            cause;
    xkbExtensionDeviceNotify    ed;
    XkbChangesRec               changes;
    int                         rc;

    rc = _XkbCreateIndicatorMap(dev, stuff->indicator, stuff->ledClass,
                                stuff->ledID, &map, &led, FALSE);
    if (rc != Success || !map) /* oh-oh */
        return rc;

    namec = mapc = statec = 0;
    extDevReason = 0;

    namec |= (1<<led);
    sli->namesPresent |= ((stuff->indicator != None) ? (1 << led) : 0);
    extDevReason |= XkbXI_IndicatorNamesMask;

    if (stuff->setMap) {
        map->flags = stuff->flags;
        map->which_groups = stuff->whichGroups;
        map->groups = stuff->groups;
        map->which_mods = stuff->whichMods;
        map->mods.mask = stuff->realMods;
        map->mods.real_mods = stuff->realMods;
        map->mods.vmods= stuff->virtualMods;
        map->ctrls = stuff->ctrls;
        mapc|= (1<<led);
    }

    if ((stuff->setState) && ((map->flags & XkbIM_NoExplicit) == 0))
    {
        if (stuff->on)	sli->explicitState |=  (1<<led);
        else		sli->explicitState &= ~(1<<led);
        statec |= ((sli->effectiveState ^ sli->explicitState) & (1 << led));
    }

    bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify));
    bzero((char *)&changes,sizeof(XkbChangesRec));
    XkbSetCauseXkbReq(&cause,X_kbSetNamedIndicator,client);
    if (namec)
        XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause);
    if (mapc)
        XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause);
    if (statec)
        XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause);

    kbd = dev;
    if ((sli->flags&XkbSLI_HasOwnState)==0)
        kbd = inputInfo.keyboard;
    XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause);

    return Success;
}


CheckDeviceLedFBs(	DeviceIntPtr			dev,
			int				class,
			int				id,
			xkbGetDeviceInfoReply *		rep,
			ClientPtr			client)
{
int			nFBs= 0;
int			length= 0;
Bool			classOk;

    if (class==XkbDfltXIClass) {
	if (dev->kbdfeed)	class= KbdFeedbackClass;
	else if (dev->leds)	class= LedFeedbackClass;
	else {
	    client->errorValue= _XkbErrCode2(XkbErr_BadClass,class);
	    return XkbKeyboardErrorCode;
	}
    }
    classOk= False;
    if ((dev->kbdfeed)&&((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) {
	KbdFeedbackPtr kf;
	classOk= True;
	for (kf= dev->kbdfeed;(kf);kf=kf->next) {
	    if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=kf->ctrl.id))
		continue;
	    nFBs++;
	    length+= SIZEOF(xkbDeviceLedsWireDesc);
	    if (!kf->xkb_sli)
		kf->xkb_sli= XkbAllocSrvLedInfo(dev,kf,NULL,0);
	    length+= ComputeDeviceLedInfoSize(dev,rep->present,kf->xkb_sli);
	    if (id!=XkbAllXIIds)
		break;
	}
    }
    if ((dev->leds)&&((class==LedFeedbackClass)||(class==XkbAllXIClasses))) {
	LedFeedbackPtr lf;
	classOk= True;
	for (lf= dev->leds;(lf);lf=lf->next) {
	    if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=lf->ctrl.id))
		continue;
	    nFBs++;
	    length+= SIZEOF(xkbDeviceLedsWireDesc);
	    if (!lf->xkb_sli)
		lf->xkb_sli= XkbAllocSrvLedInfo(dev,NULL,lf,0);
	    length+= ComputeDeviceLedInfoSize(dev,rep->present,lf->xkb_sli);
	    if (id!=XkbAllXIIds)
		break;
	}
    }
    if (nFBs>0) {
	if (rep->supported&XkbXI_IndicatorsMask) {
	    rep->nDeviceLedFBs= nFBs;
	    rep->length+= (length/4);
	}
	return Success;
    }
    if (classOk) client->errorValue= _XkbErrCode2(XkbErr_BadId,id);
    else	 client->errorValue= _XkbErrCode2(XkbErr_BadClass,class);
    return XkbKeyboardErrorCode;
}


XkbWriteCountedString(char *wire,char *str,Bool swap)
{
CARD16	len,*pLen;

    len= (str?strlen(str):0);
    pLen= (CARD16 *)wire;
    *pLen= len;
    if (swap) {
	register int n;
	swaps(pLen,n);
    }
    memcpy(&wire[2],str,len);
    wire+= ((2+len+3)/4)*4;
    return wire;
}


SetKeyBehaviors(	XkbSrvInfoPtr	 xkbi,
    			xkbSetMapReq	*req,
    			xkbBehaviorWireDesc	*wire,
    			XkbChangesPtr	 changes)
{
register unsigned i;
int maxRG = -1;
XkbDescPtr       xkb = xkbi->desc;
XkbServerMapPtr	 server = xkb->server;
unsigned	 first,last;

    first= req->firstKeyBehavior;
    last= req->firstKeyBehavior+req->nKeyBehaviors-1;
    bzero(&server->behaviors[first],req->nKeyBehaviors*sizeof(XkbBehavior));
    for (i=0;i<req->totalKeyBehaviors;i++) {
	if ((server->behaviors[wire->key].type&XkbKB_Permanent)==0) {
	    server->behaviors[wire->key].type= wire->type;
	    server->behaviors[wire->key].data= wire->data;
	    if ((wire->type==XkbKB_RadioGroup)&&(((int)wire->data)>maxRG))
		maxRG= wire->data + 1;
	}
	wire++;
    }

    if (maxRG>(int)xkbi->nRadioGroups) {
        int sz = maxRG*sizeof(XkbRadioGroupRec);
        if (xkbi->radioGroups)
             xkbi->radioGroups=(XkbRadioGroupPtr)_XkbRealloc(xkbi->radioGroups,sz);
        else xkbi->radioGroups= (XkbRadioGroupPtr)_XkbCalloc(1, sz);
        if (xkbi->radioGroups) {
             if (xkbi->nRadioGroups)
                bzero(&xkbi->radioGroups[xkbi->nRadioGroups],
                        (maxRG-xkbi->nRadioGroups)*sizeof(XkbRadioGroupRec));
             xkbi->nRadioGroups= maxRG;
        }
        else xkbi->nRadioGroups= 0;
        /* should compute members here */
    }
    if (changes->map.changed&XkbKeyBehaviorsMask) {
	unsigned oldLast;
	oldLast= changes->map.first_key_behavior+
					changes->map.num_key_behaviors-1;
        if (changes->map.first_key_behavior<req->firstKeyBehavior)
             first= changes->map.first_key_behavior;
        if (oldLast>last)
            last= oldLast;
    }
    changes->map.changed|= XkbKeyBehaviorsMask;
    changes->map.first_key_behavior = first;
    changes->map.num_key_behaviors = (last-first+1);
    return (char *)wire;
}


XkbWriteGeomDoodads(char *wire,int num_doodads,XkbDoodadPtr doodad,Bool swap)
{
register int		i;
xkbDoodadWireDesc *	doodadWire;

    for (i=0;i<num_doodads;i++,doodad++) {
	doodadWire= (xkbDoodadWireDesc *)wire;
	wire= (char *)&doodadWire[1];
	bzero(doodadWire,SIZEOF(xkbDoodadWireDesc));
	doodadWire->any.name= doodad->any.name;
	doodadWire->any.type= doodad->any.type;
	doodadWire->any.priority= doodad->any.priority;
	doodadWire->any.top= doodad->any.top;
	doodadWire->any.left= doodad->any.left;
	if (swap) {
	    register int n;
	    swapl(&doodadWire->any.name,n);
	    swaps(&doodadWire->any.top,n);
	    swaps(&doodadWire->any.left,n);
	}
	switch (doodad->any.type) {
	    case XkbOutlineDoodad:
	    case XkbSolidDoodad:
		doodadWire->shape.angle= doodad->shape.angle;
		doodadWire->shape.colorNdx= doodad->shape.color_ndx;
		doodadWire->shape.shapeNdx= doodad->shape.shape_ndx;
		if (swap) {
		    register int n;
		    swaps(&doodadWire->shape.angle,n);
		}
		break;
	    case XkbTextDoodad:
		doodadWire->text.angle= doodad->text.angle;
		doodadWire->text.width= doodad->text.width;
		doodadWire->text.height= doodad->text.height;
		doodadWire->text.colorNdx= doodad->text.color_ndx;
		if (swap) {
		    register int n;
		    swaps(&doodadWire->text.angle,n);
		    swaps(&doodadWire->text.width,n);
		    swaps(&doodadWire->text.height,n);
		}
		wire= XkbWriteCountedString(wire,doodad->text.text,swap);
		wire= XkbWriteCountedString(wire,doodad->text.font,swap);
		break;
	    case XkbIndicatorDoodad:
		doodadWire->indicator.shapeNdx= doodad->indicator.shape_ndx;
		doodadWire->indicator.onColorNdx=doodad->indicator.on_color_ndx;
		doodadWire->indicator.offColorNdx=
						doodad->indicator.off_color_ndx;
		break;
	    case XkbLogoDoodad:
		doodadWire->logo.angle= doodad->logo.angle;
		doodadWire->logo.colorNdx= doodad->logo.color_ndx;
		doodadWire->logo.shapeNdx= doodad->logo.shape_ndx;
		wire= XkbWriteCountedString(wire,doodad->logo.logo_name,swap);
		break;
	    default:
		ErrorF("[xkb] Unknown doodad type %d in XkbWriteGeomDoodads\n",
			doodad->any.type);
		ErrorF("[xkb] Ignored\n");
		break;
	}
    }
    return wire;
}


ProcXkbSetNamedIndicator(ClientPtr client)
{
    int                         rc;
    DeviceIntPtr                dev;
    int                         led = 0;
    XkbIndicatorMapPtr          map;

    REQUEST(xkbSetNamedIndicatorReq);
    REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq);

    if (!(client->xkbClientFlags&_XkbClientInitialized))
	return BadAccess;

    CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
    CHK_ATOM_ONLY(stuff->indicator);
    CHK_MASK_LEGAL(0x10,stuff->whichGroups,XkbIM_UseAnyGroup);
    CHK_MASK_LEGAL(0x11,stuff->whichMods,XkbIM_UseAnyMods);

    /* Dry-run for checks */
    rc = _XkbCreateIndicatorMap(dev, stuff->indicator,
                                stuff->ledClass, stuff->ledID,
                                &map, &led, TRUE);
    if (rc != Success || !map) /* couldn't be created or didn't exist */
        return rc;

    if (stuff->deviceSpec == XkbUseCoreKbd ||
        stuff->deviceSpec == XkbUseCorePtr)
    {
        DeviceIntPtr other;
        for (other = inputInfo.devices; other; other = other->next)
        {
            if ((other != dev) && !other->isMaster && (other->u.master == dev) &&
                (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) == Success))
            {
                rc = _XkbCreateIndicatorMap(other, stuff->indicator,
                                            stuff->ledClass, stuff->ledID,
                                            &map, &led, TRUE);
                if (rc != Success || !map)
                    return rc;
            }
        }
    }

    /* All checks passed, let's do it */
    rc = _XkbSetNamedIndicator(client, dev, stuff);
    if (rc != Success)
        return rc;

    if (stuff->deviceSpec == XkbUseCoreKbd ||
        stuff->deviceSpec == XkbUseCorePtr)
    {
        DeviceIntPtr other;
        for (other = inputInfo.devices; other; other = other->next)
        {
            if ((other != dev) && !other->isMaster && (other->u.master == dev) &&
                (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) == Success))
            {
                _XkbSetNamedIndicator(client, other, stuff);
            }
        }
    }

    return client->noClientException;
}


ProcXkbSetDebuggingFlags(ClientPtr client)
{
CARD32 				newFlags,newCtrls,extraLength;
xkbSetDebuggingFlagsReply 	rep;
int rc;

    REQUEST(xkbSetDebuggingFlagsReq);
    REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq);

    rc = XaceHook(XACE_SERVER_ACCESS, client, DixDebugAccess);
    if (rc != Success)
	return rc;

    newFlags=  xkbDebugFlags&(~stuff->affectFlags);
    newFlags|= (stuff->flags&stuff->affectFlags);
    newCtrls=  xkbDebugCtrls&(~stuff->affectCtrls);
    newCtrls|= (stuff->ctrls&stuff->affectCtrls);
    if (xkbDebugFlags || newFlags || stuff->msgLength) {
	ErrorF("[xkb] XkbDebug: Setting debug flags to 0x%lx\n",(long)newFlags);
	if (newCtrls!=xkbDebugCtrls)
	    ErrorF("[xkb] XkbDebug: Setting debug controls to 0x%lx\n",(long)newCtrls);
    }
    extraLength= (stuff->length<<2)-sz_xkbSetDebuggingFlagsReq;
    if (stuff->msgLength>0) {
	char *msg;
	if (extraLength<XkbPaddedSize(stuff->msgLength)) {
	    ErrorF("[xkb] XkbDebug: msgLength= %d, length= %ld (should be %d)\n",
			stuff->msgLength,(long)extraLength,
			XkbPaddedSize(stuff->msgLength));
	    return BadLength;
	}
	msg= (char *)&stuff[1];
	if (msg[stuff->msgLength-1]!='\0') {
	    ErrorF("[xkb] XkbDebug: message not null-terminated\n");
	    return BadValue;
	}
	ErrorF("[xkb] XkbDebug: %s\n",msg);
    }
    xkbDebugFlags = newFlags;
    xkbDebugCtrls = newCtrls;

    XkbDisableLockActions= (xkbDebugCtrls&XkbDF_DisableLocks);

    rep.type= X_Reply;
    rep.length = 0;
    rep.sequenceNumber = client->sequence;
    rep.currentFlags = newFlags;
    rep.currentCtrls = newCtrls;
    rep.supportedFlags = ~0;
    rep.supportedCtrls = ~0;
    if ( client->swapped ) {
	register int n;
	swaps(&rep.sequenceNumber, n);
	swapl(&rep.currentFlags, n);
	swapl(&rep.currentCtrls, n);
	swapl(&rep.supportedFlags, n);
	swapl(&rep.supportedCtrls, n);
    }
    WriteToClient(client,SIZEOF(xkbSetDebuggingFlagsReply), (char *)&rep);
    return client->noClientException;
}


_CheckSetShapes( 	XkbGeometryPtr		geom,
			xkbSetGeometryReq *	req,
			char **			wire_inout,
			ClientPtr		client)
{
register int	i;
char *		wire;

    wire= *wire_inout;
    if (req->nShapes<1) {
	client->errorValue= _XkbErrCode2(0x06,req->nShapes);
	return BadValue;
    }
    else {
	xkbShapeWireDesc *	shapeWire;
	XkbShapePtr		shape;
	register int		o;
	shapeWire= (xkbShapeWireDesc *)wire;
	for (i=0;i<req->nShapes;i++) {
	    xkbOutlineWireDesc *	olWire;
	    XkbOutlinePtr		ol;
	    shape= XkbAddGeomShape(geom,shapeWire->name,shapeWire->nOutlines);
	    if (!shape)
		return BadAlloc;
	    olWire= (xkbOutlineWireDesc *)(&shapeWire[1]);
	    for (o=0;o<shapeWire->nOutlines;o++) {
		register int		p;
		XkbPointPtr		pt;
		xkbPointWireDesc *	ptWire;

		ol= XkbAddGeomOutline(shape,olWire->nPoints);
		if (!ol)
		    return BadAlloc;
		ol->corner_radius=	olWire->cornerRadius;
		ptWire= (xkbPointWireDesc *)&olWire[1];
		for (p=0,pt=ol->points;p<olWire->nPoints;p++,pt++) {
		    pt->x= ptWire[p].x;
		    pt->y= ptWire[p].y;
		    if (client->swapped) {
			register int n;
			swaps(&pt->x,n);
			swaps(&pt->y,n);
		    }
		}
		ol->num_points= olWire->nPoints;
		olWire= (xkbOutlineWireDesc *)(&ptWire[olWire->nPoints]);
	    }
	    if (shapeWire->primaryNdx!=XkbNoShape)
		shape->primary= &shape->outlines[shapeWire->primaryNdx];
	    if (shapeWire->approxNdx!=XkbNoShape)
		shape->approx= &shape->outlines[shapeWire->approxNdx];
	    shapeWire= (xkbShapeWireDesc *)olWire;
	}
	wire= (char *)shapeWire;
    }
    if (geom->num_shapes!=req->nShapes) {
	client->errorValue= _XkbErrCode3(0x07,geom->num_shapes,req->nShapes);
	return BadMatch;
    }

    *wire_inout= wire;
    return Success;
}


_XkbBell(ClientPtr client, DeviceIntPtr dev, WindowPtr pWin,
         int bellClass, int bellID, int pitch, int duration,
         int percent, int forceSound, int eventOnly, Atom name)
{
    int         base;
    pointer     ctrl;
    int         oldPitch, oldDuration;
    int         newPercent;

    if (bellClass == KbdFeedbackClass) {
        KbdFeedbackPtr	k;
        if (bellID==XkbDfltXIId)
            k= dev->kbdfeed;
        else {
            for (k=dev->kbdfeed; k; k=k->next) {
                if (k->ctrl.id == bellID)
                    break;
            }
        }
        if (!k) {
            client->errorValue = _XkbErrCode2(0x5,bellID);
            return BadValue;
        }
        base = k->ctrl.bell;
        ctrl = (pointer) &(k->ctrl);
        oldPitch= k->ctrl.bell_pitch;
        oldDuration= k->ctrl.bell_duration;
        if (pitch!=0) {
            if (pitch==-1)
                k->ctrl.bell_pitch= defaultKeyboardControl.bell_pitch;
            else k->ctrl.bell_pitch= pitch;
        }
        if (duration!=0) {
            if (duration==-1)
                k->ctrl.bell_duration= defaultKeyboardControl.bell_duration;
            else k->ctrl.bell_duration= duration;
        }
    }
    else if (bellClass == BellFeedbackClass) {
        BellFeedbackPtr	b;
        if (bellID==XkbDfltXIId)
            b= dev->bell;
        else {
            for (b=dev->bell; b; b=b->next) {
                if (b->ctrl.id == bellID)
                    break;
            }
        }
        if (!b) {
            client->errorValue = _XkbErrCode2(0x6,bellID);
            return BadValue;
        }
        base = b->ctrl.percent;
        ctrl = (pointer) &(b->ctrl);
        oldPitch= b->ctrl.pitch;
        oldDuration= b->ctrl.duration;
        if (pitch!=0) {
            if (pitch==-1)
                b->ctrl.pitch= defaultKeyboardControl.bell_pitch;
            else b->ctrl.pitch= pitch;
        }
        if (duration!=0) {
            if (duration==-1)
                b->ctrl.duration= defaultKeyboardControl.bell_duration;
            else b->ctrl.duration= duration;
        }
    }
    else {
        client->errorValue = _XkbErrCode2(0x7, bellClass);;
        return BadValue;
    }

    newPercent = (base * percent)/100;
    if (percent < 0)
         newPercent = base + newPercent;
    else newPercent = base - newPercent + percent;

    XkbHandleBell(forceSound, eventOnly,
                  dev, newPercent, ctrl, bellClass,
                  name, pWin, client);
    if ((pitch!=0)||(duration!=0)) {
        if (bellClass == KbdFeedbackClass) {
            KbdFeedbackPtr      k;
            k= (KbdFeedbackPtr)ctrl;
            if (pitch!=0)
                k->ctrl.bell_pitch= oldPitch;
            if (duration!=0)
                k->ctrl.bell_duration= oldDuration;
        }
        else {
            BellFeedbackPtr     b;
            b= (BellFeedbackPtr)ctrl;
            if (pitch!=0)
                b->ctrl.pitch= oldPitch;
            if (duration!=0)
                b->ctrl.duration= oldDuration;
        }
    }

    return Success;
}


XkbSendMap(ClientPtr client,XkbDescPtr xkb,xkbGetMapReply *rep)
{
unsigned	i,len;
char		*desc,*start;

    len= (rep->length*4)-(SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply));
    start= desc= (char *)xalloc(len);
    if (!start)
	return BadAlloc;
    if ( rep->nTypes>0 )
	desc = XkbWriteKeyTypes(xkb,rep,desc,client);
    if ( rep->nKeySyms>0 )
	desc = XkbWriteKeySyms(xkb,rep,desc,client);
    if ( rep->nKeyActs>0 )
	desc = XkbWriteKeyActions(xkb,rep,desc,client);
    if ( rep->totalKeyBehaviors>0 )
	desc = XkbWriteKeyBehaviors(xkb,rep,desc,client);
    if ( rep->virtualMods ) {
	register int sz,bit;
	for (i=sz=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
	    if (rep->virtualMods&bit) {
		desc[sz++]= xkb->server->vmods[i];
	    }
	}
	desc+= XkbPaddedSize(sz);
    }
    if ( rep->totalKeyExplicit>0 )
	desc= XkbWriteExplicit(xkb,rep,desc,client);
    if ( rep->totalModMapKeys>0 )
	desc= XkbWriteModifierMap(xkb,rep,desc,client);
    if ( rep->totalVModMapKeys>0 )
	desc= XkbWriteVirtualModMap(xkb,rep,desc,client);
    if ((desc-start)!=(len)) {
	ErrorF("[xkb] BOGUS LENGTH in write keyboard desc, expected %d, got %ld\n",
					len, (unsigned long)(desc-start));
    }
    if (client->swapped) {
	register int n;
	swaps(&rep->sequenceNumber,n);
	swapl(&rep->length,n);
	swaps(&rep->present,n);
	swaps(&rep->totalSyms,n);
	swaps(&rep->totalActs,n);
    }
    WriteToClient(client, (i=SIZEOF(xkbGetMapReply)), (char *)rep);
    WriteToClient(client, len, start);
    xfree((char *)start);
    return client->noClientException;
}


SetModifierMap(	XkbSrvInfoPtr	xkbi,
		xkbSetMapReq *	req,
		CARD8 *		wire,
		XkbChangesPtr	changes)
{
register unsigned	i,first,last;
XkbClientMapPtr		xkb = xkbi->desc->map;
CARD8 *			start;

    start= wire;
    first= req->firstModMapKey;
    last=  req->firstModMapKey+req->nModMapKeys-1;
    bzero(&xkb->modmap[first],req->nModMapKeys);
    for (i=0;i<req->totalModMapKeys;i++,wire+= 2) {
	xkb->modmap[wire[0]]= wire[1];
    }
    if (first>0) {
	if (changes->map.changed&XkbModifierMapMask) {
	    int oldLast;
	    oldLast= changes->map.first_modmap_key+
						changes->map.num_modmap_keys-1;
	    if (changes->map.first_modmap_key<first)
		first= changes->map.first_modmap_key;
	    if (oldLast>last)
		last= oldLast;
	}
	changes->map.first_modmap_key= first;
	changes->map.num_modmap_keys= (last-first)+1;
    }
    wire+= XkbPaddedSize(wire-start)-(wire-start);
    return (char *)wire;
}


_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev,
                  xkbSetDeviceInfoReq *stuff)
{
    unsigned                    change;
    char                       *wire;

    change = stuff->change;

    wire= (char *)&stuff[1];
    if (change&XkbXI_ButtonActionsMask) {
	if (!dev->button) {
	    client->errorValue = _XkbErrCode2(XkbErr_BadClass,ButtonClass);
	    return XkbKeyboardErrorCode;
	}
	if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) {
	    client->errorValue= _XkbErrCode4(0x02,stuff->firstBtn,stuff->nBtns,
						dev->button->numButtons);
	    return BadMatch;
	}
	wire+= (stuff->nBtns*SIZEOF(xkbActionWireDesc));
    }
    if (stuff->change&XkbXI_IndicatorsMask) {
	int status= Success;
	wire= CheckSetDeviceIndicators(wire,dev,stuff->nDeviceLedFBs,
							&status,client);
	if (status!=Success)
	    return status;
    }
    if (((wire-((char *)stuff))/4)!=stuff->length)
	return BadLength;

    return Success;
}


XkbWriteVirtualModMap(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
							ClientPtr client)
{
unsigned		i;
xkbVModMapWireDesc *	wire;
unsigned short *	pMap;

    wire= (xkbVModMapWireDesc *)buf;
    pMap= &xkb->server->vmodmap[rep->firstVModMapKey];
    for (i=0;i<rep->nVModMapKeys-1;i++,pMap++) {
	if (*pMap!=0) {
	    wire->key= i+rep->firstVModMapKey;
	    wire->vmods= *pMap;
	    wire++;
	}
    }
    return (char *)wire;
}


XkbSendCompatMap(	ClientPtr 		client,
			XkbCompatMapPtr 	compat,
			xkbGetCompatMapReply *	rep)
{
char	*	data;
int		size;

    size= rep->length*4;
    if (size>0) {
	data = (char *)xalloc(size);
	if (data) {
	    register unsigned i,bit;
	    xkbModsWireDesc *	grp;
	    XkbSymInterpretPtr	sym= &compat->sym_interpret[rep->firstSI];
	    xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data;
	    for (i=0;i<rep->nSI;i++,sym++,wire++) {
		wire->sym= sym->sym;
		wire->mods= sym->mods;
		wire->match= sym->match;
		wire->virtualMod= sym->virtual_mod;
		wire->flags= sym->flags;
		memcpy((char*)&wire->act,(char*)&sym->act,sz_xkbActionWireDesc);
		if (client->swapped) {
		    register int n;
		    swapl(&wire->sym,n);
		}
	    }
	    if (rep->groups) {
		grp = (xkbModsWireDesc *)wire;
		for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
		    if (rep->groups&bit) {
			grp->mask= compat->groups[i].mask;
			grp->realMods= compat->groups[i].real_mods;
			grp->virtualMods= compat->groups[i].vmods;
			if (client->swapped) {
			    register int n;
			    swaps(&grp->virtualMods,n);
			}
			grp++;
		    }
		}
		wire= (xkbSymInterpretWireDesc*)grp;
	    }
	}
	else return BadAlloc;
    }
    else data= NULL;

    if (client->swapped) {
	register int n;
	swaps(&rep->sequenceNumber,n);
	swapl(&rep->length,n);
	swaps(&rep->firstSI,n);
	swaps(&rep->nSI,n);
	swaps(&rep->nTotalSI,n);
    }

    WriteToClient(client, SIZEOF(xkbGetCompatMapReply), (char *)rep);
    if (data) {
	WriteToClient(client, size, data);
	xfree((char *)data);
    }
    return client->noClientException;
}


ProcXkbGetNames(ClientPtr client)
{
    DeviceIntPtr	dev;
    XkbDescPtr		xkb;
    xkbGetNamesReply 	rep;

    REQUEST(xkbGetNamesReq);
    REQUEST_SIZE_MATCH(xkbGetNamesReq);

    if (!(client->xkbClientFlags&_XkbClientInitialized))
	return BadAccess;

    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
    CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask);

    xkb = dev->key->xkbInfo->desc;
    rep.type= X_Reply;
    rep.sequenceNumber= client->sequence;
    rep.length = 0;
    rep.deviceID = dev->id;
    rep.which = stuff->which;
    rep.nTypes = xkb->map->num_types;
    rep.firstKey = xkb->min_key_code;
    rep.nKeys = XkbNumKeys(xkb);
    if (xkb->names!=NULL) {
	rep.nKeyAliases= xkb->names->num_key_aliases;
	rep.nRadioGroups = xkb->names->num_rg;
    }
    else {
	rep.nKeyAliases= rep.nRadioGroups= 0;
    }
    XkbComputeGetNamesReplySize(xkb,&rep);
    return XkbSendNames(client,xkb,&rep);
}


XkbSendIndicatorMap(	ClientPtr			client,
			XkbIndicatorPtr			indicators,
			xkbGetIndicatorMapReply *	rep)
{
int 			length;
CARD8 *			map;
register int		i;
register unsigned	bit;

    length = rep->length*4;
    if (length>0) {
	CARD8 *to;
	to= map= (CARD8 *)xalloc(length);
	if (map) {
	    xkbIndicatorMapWireDesc  *wire = (xkbIndicatorMapWireDesc *)to;
	    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
		if (rep->which&bit) {
		    wire->flags= indicators->maps[i].flags;
		    wire->whichGroups= indicators->maps[i].which_groups;
		    wire->groups= indicators->maps[i].groups;
		    wire->whichMods= indicators->maps[i].which_mods;
		    wire->mods= indicators->maps[i].mods.mask;
		    wire->realMods= indicators->maps[i].mods.real_mods;
		    wire->virtualMods= indicators->maps[i].mods.vmods;
		    wire->ctrls= indicators->maps[i].ctrls;
		    if (client->swapped) {
			register int n;
			swaps(&wire->virtualMods,n);
			swapl(&wire->ctrls,n);
		    }
		    wire++;
		}
	    }
	    to = (CARD8 *)wire;
	    if ((to-map)!=length) {
		client->errorValue = _XkbErrCode2(0xff,length);
		return BadLength;
	    }
	}
	else return BadAlloc;
    }
    else map = NULL;
    if (client->swapped) {
	swaps(&rep->sequenceNumber,i);
	swapl(&rep->length,i);
	swapl(&rep->which,i);
	swapl(&rep->realIndicators,i);
    }
    WriteToClient(client, SIZEOF(xkbGetIndicatorMapReply), (char *)rep);
    if (map) {
	WriteToClient(client, length, (char *)map);
	xfree((char *)map);
    }
    return client->noClientException;
}