xkb.c revision 05b261ec
1/************************************************************
2Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3
4Permission to use, copy, modify, and distribute this
5software and its documentation for any purpose and without
6fee is hereby granted, provided that the above copyright
7notice appear in all copies and that both that copyright
8notice and this permission notice appear in supporting
9documentation, and that the name of Silicon Graphics not be
10used in advertising or publicity pertaining to distribution
11of the software without specific prior written permission.
12Silicon Graphics makes no representation about the suitability
13of this software for any purpose. It is provided "as is"
14without any express or implied warranty.
15
16SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25********************************************************/
26
27#ifdef HAVE_DIX_CONFIG_H
28#include <dix-config.h>
29#endif
30
31#include <stdio.h>
32#include <X11/X.h>
33#define	NEED_EVENTS
34#define	NEED_REPLIES
35#include <X11/Xproto.h>
36#include "misc.h"
37#include "inputstr.h"
38#define	XKBSRV_NEED_FILE_FUNCS
39#include <xkbsrv.h>
40#include "extnsionst.h"
41#include "xkb.h"
42
43#include <X11/extensions/XI.h>
44
45	int	XkbEventBase;
46static	int	XkbErrorBase;
47	int	XkbReqCode;
48static  int	XkbKeyboardErrorCode;
49CARD32	xkbDebugFlags = 0;
50static CARD32	xkbDebugCtrls = 0;
51
52static RESTYPE	RT_XKBCLIENT;
53
54/***====================================================================***/
55
56#define	CHK_DEVICE(d,sp,lf) {\
57    int why;\
58    d = (DeviceIntPtr)lf((sp),&why);\
59    if  (!dev) {\
60	client->errorValue = _XkbErrCode2(why,(sp));\
61	return XkbKeyboardErrorCode;\
62    }\
63}
64
65#define	CHK_KBD_DEVICE(d,sp) 	CHK_DEVICE(d,sp,_XkbLookupKeyboard)
66#define	CHK_LED_DEVICE(d,sp) 	CHK_DEVICE(d,sp,_XkbLookupLedDevice)
67#define	CHK_BELL_DEVICE(d,sp) 	CHK_DEVICE(d,sp,_XkbLookupBellDevice)
68#define	CHK_ANY_DEVICE(d,sp) 	CHK_DEVICE(d,sp,_XkbLookupAnyDevice)
69
70#define	CHK_ATOM_ONLY2(a,ev,er) {\
71	if (((a)==None)||(!ValidAtom((a)))) {\
72	    (ev)= (XID)(a);\
73	    return er;\
74	}\
75}
76#define	CHK_ATOM_ONLY(a) \
77	CHK_ATOM_ONLY2(a,client->errorValue,BadAtom)
78
79#define	CHK_ATOM_OR_NONE3(a,ev,er,ret) {\
80	if (((a)!=None)&&(!ValidAtom((a)))) {\
81	    (ev)= (XID)(a);\
82	    (er)= BadAtom;\
83	    return ret;\
84	}\
85}
86#define	CHK_ATOM_OR_NONE2(a,ev,er) {\
87	if (((a)!=None)&&(!ValidAtom((a)))) {\
88	    (ev)= (XID)(a);\
89	    return er;\
90	}\
91}
92#define	CHK_ATOM_OR_NONE(a) \
93	CHK_ATOM_OR_NONE2(a,client->errorValue,BadAtom)
94
95#define	CHK_MASK_LEGAL3(err,mask,legal,ev,er,ret)	{\
96	if ((mask)&(~(legal))) { \
97	    (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\
98	    (er)= BadValue;\
99	    return ret;\
100	}\
101}
102#define	CHK_MASK_LEGAL2(err,mask,legal,ev,er)	{\
103	if ((mask)&(~(legal))) { \
104	    (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\
105	    return er;\
106	}\
107}
108#define	CHK_MASK_LEGAL(err,mask,legal) \
109	CHK_MASK_LEGAL2(err,mask,legal,client->errorValue,BadValue)
110
111#define	CHK_MASK_MATCH(err,affect,value) {\
112	if ((value)&(~(affect))) { \
113	    client->errorValue= _XkbErrCode2((err),((value)&(~(affect))));\
114	    return BadMatch;\
115	}\
116}
117#define	CHK_MASK_OVERLAP(err,m1,m2) {\
118	if ((m1)&(m2)) { \
119	    client->errorValue= _XkbErrCode2((err),((m1)&(m2)));\
120	    return BadMatch;\
121	}\
122}
123#define	CHK_KEY_RANGE2(err,first,num,x,ev,er) {\
124	if (((unsigned)(first)+(num)-1)>(x)->max_key_code) {\
125	    (ev)=_XkbErrCode4(err,(first),(num),(x)->max_key_code);\
126	    return er;\
127	}\
128	else if ( (first)<(x)->min_key_code ) {\
129	    (ev)=_XkbErrCode3(err+1,(first),xkb->min_key_code);\
130	    return er;\
131	}\
132}
133#define	CHK_KEY_RANGE(err,first,num,x)  \
134	CHK_KEY_RANGE2(err,first,num,x,client->errorValue,BadValue)
135
136#define	CHK_REQ_KEY_RANGE2(err,first,num,r,ev,er) {\
137	if (((unsigned)(first)+(num)-1)>(r)->maxKeyCode) {\
138	    (ev)=_XkbErrCode4(err,(first),(num),(r)->maxKeyCode);\
139	    return er;\
140	}\
141	else if ( (first)<(r)->minKeyCode ) {\
142	    (ev)=_XkbErrCode3(err+1,(first),(r)->minKeyCode);\
143	    return er;\
144	}\
145}
146#define	CHK_REQ_KEY_RANGE(err,first,num,r)  \
147	CHK_REQ_KEY_RANGE2(err,first,num,r,client->errorValue,BadValue)
148
149/***====================================================================***/
150
151int
152ProcXkbUseExtension(ClientPtr client)
153{
154    REQUEST(xkbUseExtensionReq);
155    xkbUseExtensionReply	rep;
156    register int n;
157    int	supported;
158
159    REQUEST_SIZE_MATCH(xkbUseExtensionReq);
160    if (stuff->wantedMajor != XkbMajorVersion) {
161	/* pre-release version 0.65 is compatible with 1.00 */
162	supported= ((XkbMajorVersion==1)&&
163		    (stuff->wantedMajor==0)&&(stuff->wantedMinor==65));
164    }
165    else supported = 1;
166
167    if ((supported) && (!(client->xkbClientFlags&_XkbClientInitialized))) {
168	client->xkbClientFlags= _XkbClientInitialized;
169	client->vMajor= stuff->wantedMajor;
170	client->vMinor= stuff->wantedMinor;
171    }
172    else if (xkbDebugFlags&0x1) {
173	ErrorF("Rejecting client %d (0x%lx) (wants %d.%02d, have %d.%02d)\n",
174					client->index,
175					(long)client->clientAsMask,
176					stuff->wantedMajor,stuff->wantedMinor,
177					XkbMajorVersion,XkbMinorVersion);
178    }
179    rep.type = X_Reply;
180    rep.supported = supported;
181    rep.length = 0;
182    rep.sequenceNumber = client->sequence;
183    rep.serverMajor = XkbMajorVersion;
184    rep.serverMinor = XkbMinorVersion;
185    if ( client->swapped ) {
186	swaps(&rep.sequenceNumber, n);
187	swaps(&rep.serverMajor, n);
188	swaps(&rep.serverMinor, n);
189    }
190    WriteToClient(client,SIZEOF(xkbUseExtensionReply), (char *)&rep);
191    return client->noClientException;
192}
193
194/***====================================================================***/
195
196int
197ProcXkbSelectEvents(ClientPtr client)
198{
199    unsigned		legal;
200    DeviceIntPtr 	dev;
201    XkbInterestPtr	masks;
202    REQUEST(xkbSelectEventsReq);
203
204    REQUEST_AT_LEAST_SIZE(xkbSelectEventsReq);
205
206    if (!(client->xkbClientFlags&_XkbClientInitialized))
207	return BadAccess;
208
209    CHK_ANY_DEVICE(dev,stuff->deviceSpec);
210
211    if (((stuff->affectWhich&XkbMapNotifyMask)!=0)&&(stuff->affectMap)) {
212	client->mapNotifyMask&= ~stuff->affectMap;
213	client->mapNotifyMask|= (stuff->affectMap&stuff->map);
214    }
215    if ((stuff->affectWhich&(~XkbMapNotifyMask))==0)
216	return client->noClientException;
217
218    masks = XkbFindClientResource((DevicePtr)dev,client);
219    if (!masks){
220	XID id = FakeClientID(client->index);
221	AddResource(id,RT_XKBCLIENT,dev);
222	masks= XkbAddClientResource((DevicePtr)dev,client,id);
223    }
224    if (masks) {
225	union {
226	    CARD8	*c8;
227	    CARD16	*c16;
228	    CARD32	*c32;
229	} from,to;
230	register unsigned bit,ndx,maskLeft,dataLeft,size;
231
232	from.c8= (CARD8 *)&stuff[1];
233	dataLeft= (stuff->length*4)-SIZEOF(xkbSelectEventsReq);
234	maskLeft= (stuff->affectWhich&(~XkbMapNotifyMask));
235	for (ndx=0,bit=1; (maskLeft!=0); ndx++, bit<<=1) {
236	    if ((bit&maskLeft)==0)
237		continue;
238	    maskLeft&= ~bit;
239	    switch (ndx) {
240		case XkbNewKeyboardNotify:
241		    to.c16= &client->newKeyboardNotifyMask;
242		    legal= XkbAllNewKeyboardEventsMask;
243		    size= 2;
244		    break;
245		case XkbStateNotify:
246		    to.c16= &masks->stateNotifyMask;
247		    legal= XkbAllStateEventsMask;
248		    size= 2;
249		    break;
250		case XkbControlsNotify:
251		    to.c32= &masks->ctrlsNotifyMask;
252		    legal= XkbAllControlEventsMask;
253		    size= 4;
254		    break;
255		case XkbIndicatorStateNotify:
256		    to.c32= &masks->iStateNotifyMask;
257		    legal= XkbAllIndicatorEventsMask;
258		    size= 4;
259		    break;
260		case XkbIndicatorMapNotify:
261		    to.c32= &masks->iMapNotifyMask;
262		    legal= XkbAllIndicatorEventsMask;
263		    size= 4;
264		    break;
265		case XkbNamesNotify:
266		    to.c16= &masks->namesNotifyMask;
267		    legal= XkbAllNameEventsMask;
268		    size= 2;
269		    break;
270		case XkbCompatMapNotify:
271		    to.c8= &masks->compatNotifyMask;
272		    legal= XkbAllCompatMapEventsMask;
273		    size= 1;
274		    break;
275		case XkbBellNotify:
276		    to.c8= &masks->bellNotifyMask;
277		    legal= XkbAllBellEventsMask;
278		    size= 1;
279		    break;
280		case XkbActionMessage:
281		    to.c8= &masks->actionMessageMask;
282		    legal= XkbAllActionMessagesMask;
283		    size= 1;
284		    break;
285		case XkbAccessXNotify:
286		    to.c16= &masks->accessXNotifyMask;
287		    legal= XkbAllAccessXEventsMask;
288		    size= 2;
289		    break;
290		case XkbExtensionDeviceNotify:
291		    to.c16= &masks->extDevNotifyMask;
292		    legal= XkbAllExtensionDeviceEventsMask;
293		    size= 2;
294		    break;
295		default:
296		    client->errorValue = _XkbErrCode2(33,bit);
297		    return BadValue;
298	    }
299
300	    if (stuff->clear&bit) {
301		if (size==2)		to.c16[0]= 0;
302		else if (size==4)	to.c32[0]= 0;
303		else			to.c8[0]=  0;
304	    }
305	    else if (stuff->selectAll&bit) {
306		if (size==2)		to.c16[0]= ~0;
307		else if (size==4)	to.c32[0]= ~0;
308		else			to.c8[0]=  ~0;
309	    }
310	    else {
311		if (dataLeft<(size*2))
312		    return BadLength;
313		if (size==2) {
314		    CHK_MASK_MATCH(ndx,from.c16[0],from.c16[1]);
315		    CHK_MASK_LEGAL(ndx,from.c16[0],legal);
316		    to.c16[0]&= ~from.c16[0];
317		    to.c16[0]|= (from.c16[0]&from.c16[1]);
318		}
319		else if (size==4) {
320		    CHK_MASK_MATCH(ndx,from.c32[0],from.c32[1]);
321		    CHK_MASK_LEGAL(ndx,from.c32[0],legal);
322		    to.c32[0]&= ~from.c32[0];
323		    to.c32[0]|= (from.c32[0]&from.c32[1]);
324		}
325		else  {
326		    CHK_MASK_MATCH(ndx,from.c8[0],from.c8[1]);
327		    CHK_MASK_LEGAL(ndx,from.c8[0],legal);
328		    to.c8[0]&= ~from.c8[0];
329		    to.c8[0]|= (from.c8[0]&from.c8[1]);
330		    size= 2;
331		}
332		from.c8+= (size*2);
333		dataLeft-= (size*2);
334	    }
335	}
336	if (dataLeft>2) {
337	    ErrorF("Extra data (%d bytes) after SelectEvents\n",dataLeft);
338	    return BadLength;
339	}
340	return client->noClientException;
341    }
342    return BadAlloc;
343}
344
345/***====================================================================***/
346
347/* FIXME: Needs to ding on all core-sending devices. */
348int
349ProcXkbBell(ClientPtr client)
350{
351    REQUEST(xkbBellReq);
352    DeviceIntPtr dev;
353    WindowPtr	 pWin;
354    int base;
355    int newPercent,oldPitch,oldDuration;
356    pointer ctrl;
357
358    REQUEST_SIZE_MATCH(xkbBellReq);
359
360    if (!(client->xkbClientFlags&_XkbClientInitialized))
361	return BadAccess;
362
363    CHK_BELL_DEVICE(dev,stuff->deviceSpec);
364    CHK_ATOM_OR_NONE(stuff->name);
365
366    if ((stuff->forceSound)&&(stuff->eventOnly)) {
367	client->errorValue=_XkbErrCode3(0x1,stuff->forceSound,stuff->eventOnly);
368	return BadMatch;
369    }
370    if (stuff->percent < -100 || stuff->percent > 100) {
371	client->errorValue = _XkbErrCode2(0x2,stuff->percent);
372	return BadValue;
373    }
374    if (stuff->duration<-1) {
375	client->errorValue = _XkbErrCode2(0x3,stuff->duration);
376	return BadValue;
377    }
378    if (stuff->pitch<-1) {
379	client->errorValue = _XkbErrCode2(0x4,stuff->pitch);
380	return BadValue;
381    }
382
383    if (stuff->bellClass == XkbDfltXIClass) {
384	if (dev->kbdfeed!=NULL)
385	     stuff->bellClass= KbdFeedbackClass;
386	else stuff->bellClass= BellFeedbackClass;
387    }
388    if (stuff->bellClass == KbdFeedbackClass) {
389	KbdFeedbackPtr	k;
390	if (stuff->bellID==XkbDfltXIId)
391	    k= dev->kbdfeed;
392	else {
393	    for (k=dev->kbdfeed; k; k=k->next) {
394		if (k->ctrl.id == stuff->bellID)
395		    break;
396	    }
397	}
398	if (!k) {
399	    client->errorValue= _XkbErrCode2(0x5,stuff->bellID);
400	    return BadValue;
401	}
402	base = k->ctrl.bell;
403	ctrl = (pointer) &(k->ctrl);
404	oldPitch= k->ctrl.bell_pitch;
405	oldDuration= k->ctrl.bell_duration;
406	if (stuff->pitch!=0) {
407	    if (stuff->pitch==-1)
408		 k->ctrl.bell_pitch= defaultKeyboardControl.bell_pitch;
409	    else k->ctrl.bell_pitch= stuff->pitch;
410	}
411	if (stuff->duration!=0) {
412	    if (stuff->duration==-1)
413		 k->ctrl.bell_duration= defaultKeyboardControl.bell_duration;
414	    else k->ctrl.bell_duration= stuff->duration;
415	}
416    }
417    else if (stuff->bellClass == BellFeedbackClass) {
418	BellFeedbackPtr	b;
419	if (stuff->bellID==XkbDfltXIId)
420	    b= dev->bell;
421	else {
422	    for (b=dev->bell; b; b=b->next) {
423		if (b->ctrl.id == stuff->bellID)
424		    break;
425	    }
426	}
427	if (!b) {
428	    client->errorValue = _XkbErrCode2(0x6,stuff->bellID);
429	    return BadValue;
430	}
431	base = b->ctrl.percent;
432	ctrl = (pointer) &(b->ctrl);
433	oldPitch= b->ctrl.pitch;
434	oldDuration= b->ctrl.duration;
435	if (stuff->pitch!=0) {
436	    if (stuff->pitch==-1)
437		 b->ctrl.pitch= defaultKeyboardControl.bell_pitch;
438	    else b->ctrl.pitch= stuff->pitch;
439	}
440	if (stuff->duration!=0) {
441	    if (stuff->duration==-1)
442		 b->ctrl.duration= defaultKeyboardControl.bell_duration;
443	    else b->ctrl.duration= stuff->duration;
444	}
445    }
446    else {
447	client->errorValue = _XkbErrCode2(0x7,stuff->bellClass);;
448	return BadValue;
449    }
450    if (stuff->window!=None) {
451	pWin= (WindowPtr)LookupIDByType(stuff->window,RT_WINDOW);
452	if (pWin==NULL) {
453	    client->errorValue= stuff->window;
454	    return BadValue;
455	}
456    }
457    else pWin= NULL;
458
459    newPercent= (base*stuff->percent)/100;
460    if (stuff->percent < 0)
461         newPercent= base+newPercent;
462    else newPercent= base-newPercent+stuff->percent;
463    XkbHandleBell(stuff->forceSound, stuff->eventOnly,
464				dev, newPercent, ctrl, stuff->bellClass,
465				stuff->name, pWin, client);
466    if ((stuff->pitch!=0)||(stuff->duration!=0)) {
467	if (stuff->bellClass == KbdFeedbackClass) {
468	    KbdFeedbackPtr	k;
469	    k= (KbdFeedbackPtr)ctrl;
470	    if (stuff->pitch!=0)
471		k->ctrl.bell_pitch= oldPitch;
472	    if (stuff->duration!=0)
473		k->ctrl.bell_duration= oldDuration;
474	}
475	else {
476	    BellFeedbackPtr	b;
477	    b= (BellFeedbackPtr)ctrl;
478	    if (stuff->pitch!=0)
479		b->ctrl.pitch= oldPitch;
480	    if (stuff->duration!=0)
481		b->ctrl.duration= oldDuration;
482	}
483    }
484    return Success;
485}
486
487/***====================================================================***/
488
489int
490ProcXkbGetState(ClientPtr client)
491{
492    REQUEST(xkbGetStateReq);
493    DeviceIntPtr	dev;
494    xkbGetStateReply	 rep;
495    XkbStateRec		*xkb;
496
497    REQUEST_SIZE_MATCH(xkbGetStateReq);
498
499    if (!(client->xkbClientFlags&_XkbClientInitialized))
500	return BadAccess;
501
502    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
503
504    xkb= &dev->key->xkbInfo->state;
505    bzero(&rep,sizeof(xkbGetStateReply));
506    rep.type= X_Reply;
507    rep.sequenceNumber= client->sequence;
508    rep.length = 0;
509    rep.deviceID = dev->id;
510    rep.mods = dev->key->state&0xff;
511    rep.baseMods = xkb->base_mods;
512    rep.lockedMods = xkb->locked_mods;
513    rep.latchedMods = xkb->latched_mods;
514    rep.group = xkb->group;
515    rep.baseGroup = xkb->base_group;
516    rep.latchedGroup = xkb->latched_group;
517    rep.lockedGroup = xkb->locked_group;
518    rep.compatState = xkb->compat_state;
519    rep.ptrBtnState = xkb->ptr_buttons;
520    if (client->swapped) {
521	register int n;
522	swaps(&rep.sequenceNumber,n);
523	swaps(&rep.ptrBtnState,n);
524    }
525    WriteToClient(client, SIZEOF(xkbGetStateReply), (char *)&rep);
526    return client->noClientException;
527}
528
529/***====================================================================***/
530
531int
532ProcXkbLatchLockState(ClientPtr client)
533{
534    int status;
535    DeviceIntPtr dev, tmpd;
536    XkbStateRec	oldState,*newState;
537    CARD16 changed;
538    xkbStateNotify sn;
539    XkbEventCauseRec cause;
540
541    REQUEST(xkbLatchLockStateReq);
542    REQUEST_SIZE_MATCH(xkbLatchLockStateReq);
543
544    if (!(client->xkbClientFlags & _XkbClientInitialized))
545	return BadAccess;
546
547    CHK_KBD_DEVICE(dev, stuff->deviceSpec);
548    CHK_MASK_MATCH(0x01, stuff->affectModLocks, stuff->modLocks);
549    CHK_MASK_MATCH(0x01, stuff->affectModLatches, stuff->modLatches);
550
551    status = Success;
552
553    for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
554        if ((dev == inputInfo.keyboard && tmpd->key && tmpd->coreEvents) ||
555            tmpd == dev) {
556            if (!tmpd->key->xkbInfo)
557                continue;
558
559            oldState = tmpd->key->xkbInfo->state;
560            newState = &tmpd->key->xkbInfo->state;
561            if (stuff->affectModLocks) {
562                newState->locked_mods &= ~stuff->affectModLocks;
563                newState->locked_mods |= (stuff->affectModLocks & stuff->modLocks);
564            }
565            if (status == Success && stuff->lockGroup)
566                newState->locked_group = stuff->groupLock;
567            if (status == Success && stuff->affectModLatches)
568                status = XkbLatchModifiers(tmpd, stuff->affectModLatches,
569                                           stuff->modLatches);
570            if (status == Success && stuff->latchGroup)
571                status = XkbLatchGroup(tmpd, stuff->groupLatch);
572
573            if (status != Success)
574                return status;
575
576            XkbComputeDerivedState(tmpd->key->xkbInfo);
577            tmpd->key->state = XkbStateFieldFromRec(newState);
578
579            changed = XkbStateChangedFlags(&oldState, newState);
580            if (changed) {
581                sn.keycode = 0;
582                sn.eventType = 0;
583                sn.requestMajor = XkbReqCode;
584                sn.requestMinor = X_kbLatchLockState;
585                sn.changed = changed;
586                XkbSendStateNotify(tmpd, &sn);
587                changed = XkbIndicatorsToUpdate(tmpd, changed, False);
588                if (changed) {
589                    XkbSetCauseXkbReq(&cause, X_kbLatchLockState, client);
590                    XkbUpdateIndicators(tmpd, changed, True, NULL, &cause);
591	        }
592            }
593        }
594    }
595
596    return client->noClientException;
597}
598
599/***====================================================================***/
600
601int
602ProcXkbGetControls(ClientPtr client)
603{
604    xkbGetControlsReply rep;
605    XkbControlsPtr	xkb;
606    DeviceIntPtr 	dev;
607    register int 	n;
608
609    REQUEST(xkbGetControlsReq);
610    REQUEST_SIZE_MATCH(xkbGetControlsReq);
611
612    if (!(client->xkbClientFlags&_XkbClientInitialized))
613	return BadAccess;
614
615    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
616
617    xkb = dev->key->xkbInfo->desc->ctrls;
618    rep.type = X_Reply;
619    rep.length = (SIZEOF(xkbGetControlsReply)-
620		  SIZEOF(xGenericReply)) >> 2;
621    rep.sequenceNumber = client->sequence;
622    rep.deviceID = ((DeviceIntPtr)dev)->id;
623    rep.numGroups = xkb->num_groups;
624    rep.groupsWrap = xkb->groups_wrap;
625    rep.internalMods = xkb->internal.mask;
626    rep.ignoreLockMods = xkb->ignore_lock.mask;
627    rep.internalRealMods = xkb->internal.real_mods;
628    rep.ignoreLockRealMods = xkb->ignore_lock.real_mods;
629    rep.internalVMods = xkb->internal.vmods;
630    rep.ignoreLockVMods = xkb->ignore_lock.vmods;
631    rep.enabledCtrls = xkb->enabled_ctrls;
632    rep.repeatDelay = xkb->repeat_delay;
633    rep.repeatInterval = xkb->repeat_interval;
634    rep.slowKeysDelay = xkb->slow_keys_delay;
635    rep.debounceDelay = xkb->debounce_delay;
636    rep.mkDelay = xkb->mk_delay;
637    rep.mkInterval = xkb->mk_interval;
638    rep.mkTimeToMax = xkb->mk_time_to_max;
639    rep.mkMaxSpeed = xkb->mk_max_speed;
640    rep.mkCurve = xkb->mk_curve;
641    rep.mkDfltBtn = xkb->mk_dflt_btn;
642    rep.axTimeout = xkb->ax_timeout;
643    rep.axtCtrlsMask = xkb->axt_ctrls_mask;
644    rep.axtCtrlsValues = xkb->axt_ctrls_values;
645    rep.axtOptsMask = xkb->axt_opts_mask;
646    rep.axtOptsValues = xkb->axt_opts_values;
647    rep.axOptions = xkb->ax_options;
648    memcpy(rep.perKeyRepeat,xkb->per_key_repeat,XkbPerKeyBitArraySize);
649    if (client->swapped) {
650    	swaps(&rep.sequenceNumber, n);
651	swapl(&rep.length,n);
652	swaps(&rep.internalVMods, n);
653	swaps(&rep.ignoreLockVMods, n);
654	swapl(&rep.enabledCtrls, n);
655	swaps(&rep.repeatDelay, n);
656	swaps(&rep.repeatInterval, n);
657	swaps(&rep.slowKeysDelay, n);
658	swaps(&rep.debounceDelay, n);
659	swaps(&rep.mkDelay, n);
660	swaps(&rep.mkInterval, n);
661	swaps(&rep.mkTimeToMax, n);
662	swaps(&rep.mkMaxSpeed, n);
663	swaps(&rep.mkCurve, n);
664	swaps(&rep.axTimeout, n);
665	swapl(&rep.axtCtrlsMask, n);
666	swapl(&rep.axtCtrlsValues, n);
667	swaps(&rep.axtOptsMask, n);
668	swaps(&rep.axtOptsValues, n);
669	swaps(&rep.axOptions, n);
670    }
671    WriteToClient(client, SIZEOF(xkbGetControlsReply), (char *)&rep);
672    return(client->noClientException);
673}
674
675int
676ProcXkbSetControls(ClientPtr client)
677{
678    DeviceIntPtr 	dev, tmpd;
679    XkbSrvInfoPtr	xkbi;
680    XkbControlsPtr	ctrl;
681    XkbControlsRec	new,old;
682    xkbControlsNotify	cn;
683    XkbEventCauseRec	cause;
684    XkbSrvLedInfoPtr	sli;
685
686    REQUEST(xkbSetControlsReq);
687    REQUEST_SIZE_MATCH(xkbSetControlsReq);
688
689    if (!(client->xkbClientFlags & _XkbClientInitialized))
690	return BadAccess;
691
692    CHK_KBD_DEVICE(dev, stuff->deviceSpec);
693    CHK_MASK_LEGAL(0x01, stuff->changeCtrls, XkbAllControlsMask);
694
695    for (tmpd = inputInfo.keyboard; tmpd; tmpd = tmpd->next) {
696        if ((dev == inputInfo.keyboard && tmpd->key && tmpd->coreEvents) ||
697            tmpd == dev) {
698
699            xkbi = tmpd->key->xkbInfo;
700            ctrl = xkbi->desc->ctrls;
701            new = *ctrl;
702            XkbSetCauseXkbReq(&cause, X_kbSetControls, client);
703
704            if (stuff->changeCtrls & XkbInternalModsMask) {
705                CHK_MASK_MATCH(0x02, stuff->affectInternalMods,
706                               stuff->internalMods);
707                CHK_MASK_MATCH(0x03, stuff->affectInternalVMods,
708                               stuff->internalVMods);
709
710                new.internal.real_mods &= ~(stuff->affectInternalMods);
711                new.internal.real_mods |= (stuff->affectInternalMods &
712                                           stuff->internalMods);
713                new.internal.vmods &= ~(stuff->affectInternalVMods);
714                new.internal.vmods |= (stuff->affectInternalVMods &
715                                       stuff->internalVMods);
716                new.internal.mask = new.internal.real_mods |
717                                    XkbMaskForVMask(xkbi->desc,
718                                                    new.internal.vmods);
719            }
720
721            if (stuff->changeCtrls & XkbIgnoreLockModsMask) {
722                CHK_MASK_MATCH(0x4, stuff->affectIgnoreLockMods,
723                               stuff->ignoreLockMods);
724                CHK_MASK_MATCH(0x5, stuff->affectIgnoreLockVMods,
725                               stuff->ignoreLockVMods);
726
727                new.ignore_lock.real_mods &= ~(stuff->affectIgnoreLockMods);
728                new.ignore_lock.real_mods |= (stuff->affectIgnoreLockMods &
729                                              stuff->ignoreLockMods);
730                new.ignore_lock.vmods &= ~(stuff->affectIgnoreLockVMods);
731                new.ignore_lock.vmods |= (stuff->affectIgnoreLockVMods &
732                                          stuff->ignoreLockVMods);
733                new.ignore_lock.mask = new.ignore_lock.real_mods |
734                                       XkbMaskForVMask(xkbi->desc,
735                                                       new.ignore_lock.vmods);
736            }
737
738            CHK_MASK_MATCH(0x06, stuff->affectEnabledCtrls,
739                           stuff->enabledCtrls);
740            if (stuff->affectEnabledCtrls) {
741                CHK_MASK_LEGAL(0x07, stuff->affectEnabledCtrls,
742                               XkbAllBooleanCtrlsMask);
743
744                new.enabled_ctrls &= ~(stuff->affectEnabledCtrls);
745                new.enabled_ctrls |= (stuff->affectEnabledCtrls &
746                                      stuff->enabledCtrls);
747            }
748
749            if (stuff->changeCtrls & XkbRepeatKeysMask) {
750                if (stuff->repeatDelay < 1 || stuff->repeatInterval < 1) {
751                    client->errorValue = _XkbErrCode3(0x08, stuff->repeatDelay,
752                                                      stuff->repeatInterval);
753                    return BadValue;
754                }
755
756                new.repeat_delay = stuff->repeatDelay;
757                new.repeat_interval = stuff->repeatInterval;
758            }
759
760            if (stuff->changeCtrls & XkbSlowKeysMask) {
761                if (stuff->slowKeysDelay < 1) {
762                    client->errorValue = _XkbErrCode2(0x09,
763                                                      stuff->slowKeysDelay);
764                    return BadValue;
765                }
766
767                new.slow_keys_delay = stuff->slowKeysDelay;
768            }
769
770            if (stuff->changeCtrls & XkbBounceKeysMask) {
771                if (stuff->debounceDelay < 1) {
772                    client->errorValue = _XkbErrCode2(0x0A,
773                                                      stuff->debounceDelay);
774                    return BadValue;
775                }
776
777                new.debounce_delay = stuff->debounceDelay;
778            }
779
780            if (stuff->changeCtrls & XkbMouseKeysMask) {
781                if (stuff->mkDfltBtn > XkbMaxMouseKeysBtn) {
782                    client->errorValue = _XkbErrCode2(0x0B, stuff->mkDfltBtn);
783                    return BadValue;
784                }
785
786                new.mk_dflt_btn = stuff->mkDfltBtn;
787            }
788
789            if (stuff->changeCtrls & XkbMouseKeysAccelMask) {
790                if (stuff->mkDelay < 1 || stuff->mkInterval < 1 ||
791                    stuff->mkTimeToMax < 1 || stuff->mkMaxSpeed < 1 ||
792                    stuff->mkCurve < -1000) {
793                    client->errorValue = _XkbErrCode2(0x0C,0);
794                    return BadValue;
795                }
796
797                new.mk_delay = stuff->mkDelay;
798                new.mk_interval = stuff->mkInterval;
799                new.mk_time_to_max = stuff->mkTimeToMax;
800                new.mk_max_speed = stuff->mkMaxSpeed;
801                new.mk_curve = stuff->mkCurve;
802                AccessXComputeCurveFactor(xkbi, &new);
803            }
804
805            if (stuff->changeCtrls & XkbGroupsWrapMask) {
806                unsigned act, num;
807
808                act = XkbOutOfRangeGroupAction(stuff->groupsWrap);
809                switch (act) {
810                case XkbRedirectIntoRange:
811                    num = XkbOutOfRangeGroupNumber(stuff->groupsWrap);
812                    if (num >= new.num_groups) {
813                        client->errorValue = _XkbErrCode3(0x0D, new.num_groups,
814                                                          num);
815                        return BadValue;
816                    }
817                case XkbWrapIntoRange:
818                case XkbClampIntoRange:
819                    break;
820                default:
821                    client->errorValue = _XkbErrCode2(0x0E, act);
822                    return BadValue;
823                }
824
825                new.groups_wrap= stuff->groupsWrap;
826            }
827
828            CHK_MASK_LEGAL(0x0F, stuff->axOptions, XkbAX_AllOptionsMask);
829            if (stuff->changeCtrls & XkbAccessXKeysMask) {
830                new.ax_options = stuff->axOptions & XkbAX_AllOptionsMask;
831            }
832            else {
833                if (stuff->changeCtrls & XkbStickyKeysMask) {
834                    new.ax_options &= ~(XkbAX_SKOptionsMask);
835                    new.ax_options |= (stuff->axOptions & XkbAX_SKOptionsMask);
836                }
837
838                if (stuff->changeCtrls & XkbAccessXFeedbackMask) {
839                    new.ax_options &= ~(XkbAX_FBOptionsMask);
840                    new.ax_options |= (stuff->axOptions & XkbAX_FBOptionsMask);
841                }
842            }
843
844            if (stuff->changeCtrls & XkbAccessXTimeoutMask) {
845                if (stuff->axTimeout < 1) {
846                    client->errorValue = _XkbErrCode2(0x10, stuff->axTimeout);
847                    return BadValue;
848                }
849                CHK_MASK_MATCH(0x11, stuff->axtCtrlsMask,
850                               stuff->axtCtrlsValues);
851                CHK_MASK_LEGAL(0x12, stuff->axtCtrlsMask,
852                               XkbAllBooleanCtrlsMask);
853                CHK_MASK_MATCH(0x13, stuff->axtOptsMask, stuff->axtOptsValues);
854                CHK_MASK_LEGAL(0x14, stuff->axtOptsMask, XkbAX_AllOptionsMask);
855                new.ax_timeout = stuff->axTimeout;
856                new.axt_ctrls_mask = stuff->axtCtrlsMask;
857                new.axt_ctrls_values = (stuff->axtCtrlsValues &
858                                        stuff->axtCtrlsMask);
859                new.axt_opts_mask = stuff->axtOptsMask;
860                new.axt_opts_values = (stuff->axtOptsValues &
861                                       stuff->axtOptsMask);
862            }
863
864            if (stuff->changeCtrls & XkbPerKeyRepeatMask)
865                memcpy(new.per_key_repeat, stuff->perKeyRepeat,
866                       XkbPerKeyBitArraySize);
867
868            old= *ctrl;
869            *ctrl= new;
870            XkbDDXChangeControls(tmpd, &old, ctrl);
871
872            if (XkbComputeControlsNotify(tmpd, &old, ctrl, &cn, False)) {
873                cn.keycode = 0;
874                cn.eventType = 0;
875                cn.requestMajor = XkbReqCode;
876                cn.requestMinor = X_kbSetControls;
877                XkbSendControlsNotify(tmpd, &cn);
878            }
879
880            sli = XkbFindSrvLedInfo(tmpd, XkbDfltXIClass, XkbDfltXIId, 0);
881            if (sli)
882                XkbUpdateIndicators(tmpd, sli->usesControls, True, NULL,
883                                    &cause);
884
885            /* If sticky keys were disabled, clear all locks and latches */
886            if ((old.enabled_ctrls & XkbStickyKeysMask) &&
887                !(ctrl->enabled_ctrls & XkbStickyKeysMask))
888                XkbClearAllLatchesAndLocks(tmpd, xkbi, True, &cause);
889        }
890    }
891
892    return client->noClientException;
893}
894
895/***====================================================================***/
896
897static int
898XkbSizeKeyTypes(XkbDescPtr xkb,xkbGetMapReply *rep)
899{
900    XkbKeyTypeRec 	*type;
901    unsigned		i,len;
902
903    len= 0;
904    if (((rep->present&XkbKeyTypesMask)==0)||(rep->nTypes<1)||
905	(!xkb)||(!xkb->map)||(!xkb->map->types)) {
906	rep->present&= ~XkbKeyTypesMask;
907	rep->firstType= rep->nTypes= 0;
908	return 0;
909    }
910    type= &xkb->map->types[rep->firstType];
911    for (i=0;i<rep->nTypes;i++,type++){
912	len+= SIZEOF(xkbKeyTypeWireDesc);
913	if (type->map_count>0) {
914	    len+= (type->map_count*SIZEOF(xkbKTMapEntryWireDesc));
915	    if (type->preserve)
916		len+= (type->map_count*SIZEOF(xkbModsWireDesc));
917	}
918    }
919    return len;
920}
921
922static char *
923XkbWriteKeyTypes(	XkbDescPtr		xkb,
924			xkbGetMapReply *	rep,
925			char *			buf,
926			ClientPtr 		client)
927{
928    XkbKeyTypePtr	type;
929    unsigned		i;
930    xkbKeyTypeWireDesc *wire;
931
932    type= &xkb->map->types[rep->firstType];
933    for (i=0;i<rep->nTypes;i++,type++) {
934	register unsigned n;
935	wire= (xkbKeyTypeWireDesc *)buf;
936	wire->mask = type->mods.mask;
937	wire->realMods = type->mods.real_mods;
938	wire->virtualMods = type->mods.vmods;
939	wire->numLevels = type->num_levels;
940	wire->nMapEntries = type->map_count;
941	wire->preserve = (type->preserve!=NULL);
942	if (client->swapped) {
943	    register int n;
944	    swaps(&wire->virtualMods,n);
945	}
946
947	buf= (char *)&wire[1];
948	if (wire->nMapEntries>0) {
949	    xkbKTMapEntryWireDesc *	wire;
950	    XkbKTMapEntryPtr		entry;
951	    wire= (xkbKTMapEntryWireDesc *)buf;
952	    entry= type->map;
953	    for (n=0;n<type->map_count;n++,wire++,entry++) {
954		wire->active= entry->active;
955		wire->mask= entry->mods.mask;
956		wire->level= entry->level;
957		wire->realMods= entry->mods.real_mods;
958		wire->virtualMods= entry->mods.vmods;
959		if (client->swapped) {
960		    register int n;
961		    swaps(&wire->virtualMods,n);
962		}
963	    }
964	    buf= (char *)wire;
965	    if (type->preserve!=NULL) {
966		xkbModsWireDesc *	pwire;
967		XkbModsPtr		preserve;
968		pwire= (xkbModsWireDesc *)buf;
969		preserve= type->preserve;
970		for (n=0;n<type->map_count;n++,pwire++,preserve++) {
971		    pwire->mask= preserve->mask;
972		    pwire->realMods= preserve->real_mods;
973		    pwire->virtualMods= preserve->vmods;
974		    if (client->swapped) {
975			register int n;
976			swaps(&pwire->virtualMods,n);
977		    }
978		}
979		buf= (char *)pwire;
980	    }
981	}
982    }
983    return buf;
984}
985
986static int
987XkbSizeKeySyms(XkbDescPtr xkb,xkbGetMapReply *rep)
988{
989    XkbSymMapPtr	symMap;
990    unsigned		i,len;
991    unsigned		nSyms,nSymsThisKey;
992
993    if (((rep->present&XkbKeySymsMask)==0)||(rep->nKeySyms<1)||
994	(!xkb)||(!xkb->map)||(!xkb->map->key_sym_map)) {
995	rep->present&= ~XkbKeySymsMask;
996	rep->firstKeySym= rep->nKeySyms= 0;
997	rep->totalSyms= 0;
998	return 0;
999    }
1000    len= rep->nKeySyms*SIZEOF(xkbSymMapWireDesc);
1001    symMap = &xkb->map->key_sym_map[rep->firstKeySym];
1002    for (i=nSyms=0;i<rep->nKeySyms;i++,symMap++) {
1003	if (symMap->offset!=0) {
1004	    nSymsThisKey= XkbNumGroups(symMap->group_info)*symMap->width;
1005	    nSyms+= nSymsThisKey;
1006	}
1007    }
1008    len+= nSyms*4;
1009    rep->totalSyms= nSyms;
1010    return len;
1011}
1012
1013static int
1014XkbSizeVirtualMods(XkbDescPtr xkb,xkbGetMapReply *rep)
1015{
1016register unsigned i,nMods,bit;
1017
1018    if (((rep->present&XkbVirtualModsMask)==0)||(rep->virtualMods==0)||
1019	(!xkb)||(!xkb->server)) {
1020	rep->present&= ~XkbVirtualModsMask;
1021	rep->virtualMods= 0;
1022	return 0;
1023    }
1024    for (i=nMods=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
1025        if (rep->virtualMods&bit)
1026	    nMods++;
1027    }
1028    return XkbPaddedSize(nMods);
1029}
1030
1031static char *
1032XkbWriteKeySyms(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,ClientPtr client)
1033{
1034register KeySym *	pSym;
1035XkbSymMapPtr		symMap;
1036xkbSymMapWireDesc *	outMap;
1037register unsigned	i;
1038
1039    symMap = &xkb->map->key_sym_map[rep->firstKeySym];
1040    for (i=0;i<rep->nKeySyms;i++,symMap++) {
1041	outMap = (xkbSymMapWireDesc *)buf;
1042	outMap->ktIndex[0] = symMap->kt_index[0];
1043	outMap->ktIndex[1] = symMap->kt_index[1];
1044	outMap->ktIndex[2] = symMap->kt_index[2];
1045	outMap->ktIndex[3] = symMap->kt_index[3];
1046	outMap->groupInfo = symMap->group_info;
1047	outMap->width= symMap->width;
1048	outMap->nSyms = symMap->width*XkbNumGroups(symMap->group_info);
1049	buf= (char *)&outMap[1];
1050	if (outMap->nSyms==0)
1051	    continue;
1052
1053	pSym = &xkb->map->syms[symMap->offset];
1054	memcpy((char *)buf,(char *)pSym,outMap->nSyms*4);
1055	if (client->swapped) {
1056	    register int n,nSyms= outMap->nSyms;
1057	    swaps(&outMap->nSyms,n);
1058	    while (nSyms-->0) {
1059		swapl(buf,n);
1060		buf+= 4;
1061	    }
1062	}
1063	else buf+= outMap->nSyms*4;
1064    }
1065    return buf;
1066}
1067
1068static int
1069XkbSizeKeyActions(XkbDescPtr xkb,xkbGetMapReply *rep)
1070{
1071    unsigned		i,len,nActs;
1072    register KeyCode	firstKey;
1073
1074    if (((rep->present&XkbKeyActionsMask)==0)||(rep->nKeyActs<1)||
1075	(!xkb)||(!xkb->server)||(!xkb->server->key_acts)) {
1076	rep->present&= ~XkbKeyActionsMask;
1077	rep->firstKeyAct= rep->nKeyActs= 0;
1078	rep->totalActs= 0;
1079	return 0;
1080    }
1081    firstKey= rep->firstKeyAct;
1082    for (nActs=i=0;i<rep->nKeyActs;i++) {
1083	if (xkb->server->key_acts[i+firstKey]!=0)
1084	    nActs+= XkbKeyNumActions(xkb,i+firstKey);
1085    }
1086    len= XkbPaddedSize(rep->nKeyActs)+(nActs*SIZEOF(xkbActionWireDesc));
1087    rep->totalActs= nActs;
1088    return len;
1089}
1090
1091static char *
1092XkbWriteKeyActions(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
1093							ClientPtr client)
1094{
1095    unsigned		i;
1096    CARD8 *		numDesc;
1097    XkbAnyAction *	actDesc;
1098
1099    numDesc = (CARD8 *)buf;
1100    for (i=0;i<rep->nKeyActs;i++) {
1101	if (xkb->server->key_acts[i+rep->firstKeyAct]==0)
1102	     numDesc[i] = 0;
1103	else numDesc[i] = XkbKeyNumActions(xkb,(i+rep->firstKeyAct));
1104    }
1105    buf+= XkbPaddedSize(rep->nKeyActs);
1106
1107    actDesc = (XkbAnyAction *)buf;
1108    for (i=0;i<rep->nKeyActs;i++) {
1109	if (xkb->server->key_acts[i+rep->firstKeyAct]!=0) {
1110	    unsigned int num;
1111	    num = XkbKeyNumActions(xkb,(i+rep->firstKeyAct));
1112	    memcpy((char *)actDesc,
1113		   (char*)XkbKeyActionsPtr(xkb,(i+rep->firstKeyAct)),
1114		   num*SIZEOF(xkbActionWireDesc));
1115	    actDesc+= num;
1116	}
1117    }
1118    buf = (char *)actDesc;
1119    return buf;
1120}
1121
1122static int
1123XkbSizeKeyBehaviors(XkbDescPtr xkb,xkbGetMapReply *rep)
1124{
1125    unsigned		i,len,nBhvr;
1126    XkbBehavior *	bhv;
1127
1128    if (((rep->present&XkbKeyBehaviorsMask)==0)||(rep->nKeyBehaviors<1)||
1129	(!xkb)||(!xkb->server)||(!xkb->server->behaviors)) {
1130	rep->present&= ~XkbKeyBehaviorsMask;
1131	rep->firstKeyBehavior= rep->nKeyBehaviors= 0;
1132	rep->totalKeyBehaviors= 0;
1133	return 0;
1134    }
1135    bhv= &xkb->server->behaviors[rep->firstKeyBehavior];
1136    for (nBhvr=i=0;i<rep->nKeyBehaviors;i++,bhv++) {
1137	if (bhv->type!=XkbKB_Default)
1138	    nBhvr++;
1139    }
1140    len= nBhvr*SIZEOF(xkbBehaviorWireDesc);
1141    rep->totalKeyBehaviors= nBhvr;
1142    return len;
1143}
1144
1145static char *
1146XkbWriteKeyBehaviors(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
1147							ClientPtr client)
1148{
1149    unsigned		i;
1150    xkbBehaviorWireDesc	*wire;
1151    XkbBehavior		*pBhvr;
1152
1153    wire = (xkbBehaviorWireDesc *)buf;
1154    pBhvr= &xkb->server->behaviors[rep->firstKeyBehavior];
1155    for (i=0;i<rep->nKeyBehaviors;i++,pBhvr++) {
1156	if (pBhvr->type!=XkbKB_Default) {
1157	    wire->key=  i+rep->firstKeyBehavior;
1158	    wire->type= pBhvr->type;
1159	    wire->data= pBhvr->data;
1160	    wire++;
1161	}
1162    }
1163    buf = (char *)wire;
1164    return buf;
1165}
1166
1167static int
1168XkbSizeExplicit(XkbDescPtr xkb,xkbGetMapReply *rep)
1169{
1170    unsigned	i,len,nRtrn;
1171
1172    if (((rep->present&XkbExplicitComponentsMask)==0)||(rep->nKeyExplicit<1)||
1173	(!xkb)||(!xkb->server)||(!xkb->server->explicit)) {
1174	rep->present&= ~XkbExplicitComponentsMask;
1175	rep->firstKeyExplicit= rep->nKeyExplicit= 0;
1176	rep->totalKeyExplicit= 0;
1177	return 0;
1178    }
1179    for (nRtrn=i=0;i<rep->nKeyExplicit;i++) {
1180	if (xkb->server->explicit[i+rep->firstKeyExplicit]!=0)
1181	    nRtrn++;
1182    }
1183    rep->totalKeyExplicit= nRtrn;
1184    len= XkbPaddedSize(nRtrn*2); /* two bytes per non-zero explicit component */
1185    return len;
1186}
1187
1188static char *
1189XkbWriteExplicit(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,ClientPtr client)
1190{
1191unsigned	i;
1192char *		start;
1193unsigned char *	pExp;
1194
1195    start= buf;
1196    pExp= &xkb->server->explicit[rep->firstKeyExplicit];
1197    for (i=0;i<rep->nKeyExplicit;i++,pExp++) {
1198	if (*pExp!=0) {
1199	    *buf++= i+rep->firstKeyExplicit;
1200	    *buf++= *pExp;
1201	}
1202    }
1203    i= XkbPaddedSize(buf-start)-(buf-start); /* pad to word boundary */
1204    return buf+i;
1205}
1206
1207static int
1208XkbSizeModifierMap(XkbDescPtr xkb,xkbGetMapReply *rep)
1209{
1210    unsigned	i,len,nRtrn;
1211
1212    if (((rep->present&XkbModifierMapMask)==0)||(rep->nModMapKeys<1)||
1213	(!xkb)||(!xkb->map)||(!xkb->map->modmap)) {
1214	rep->present&= ~XkbModifierMapMask;
1215	rep->firstModMapKey= rep->nModMapKeys= 0;
1216	rep->totalModMapKeys= 0;
1217	return 0;
1218    }
1219    for (nRtrn=i=0;i<rep->nModMapKeys;i++) {
1220	if (xkb->map->modmap[i+rep->firstModMapKey]!=0)
1221	    nRtrn++;
1222    }
1223    rep->totalModMapKeys= nRtrn;
1224    len= XkbPaddedSize(nRtrn*2); /* two bytes per non-zero modmap component */
1225    return len;
1226}
1227
1228static char *
1229XkbWriteModifierMap(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
1230							ClientPtr client)
1231{
1232unsigned	i;
1233char *		start;
1234unsigned char *	pMap;
1235
1236    start= buf;
1237    pMap= &xkb->map->modmap[rep->firstModMapKey];
1238    for (i=0;i<rep->nModMapKeys;i++,pMap++) {
1239	if (*pMap!=0) {
1240	    *buf++= i+rep->firstModMapKey;
1241	    *buf++= *pMap;
1242	}
1243    }
1244    i= XkbPaddedSize(buf-start)-(buf-start); /* pad to word boundary */
1245    return buf+i;
1246}
1247
1248static int
1249XkbSizeVirtualModMap(XkbDescPtr xkb,xkbGetMapReply *rep)
1250{
1251    unsigned	i,len,nRtrn;
1252
1253    if (((rep->present&XkbVirtualModMapMask)==0)||(rep->nVModMapKeys<1)||
1254	(!xkb)||(!xkb->server)||(!xkb->server->vmodmap)) {
1255	rep->present&= ~XkbVirtualModMapMask;
1256	rep->firstVModMapKey= rep->nVModMapKeys= 0;
1257	rep->totalVModMapKeys= 0;
1258	return 0;
1259    }
1260    for (nRtrn=i=0;i<rep->nVModMapKeys-1;i++) {
1261	if (xkb->server->vmodmap[i+rep->firstVModMapKey]!=0)
1262	    nRtrn++;
1263    }
1264    rep->totalVModMapKeys= nRtrn;
1265    len= nRtrn*SIZEOF(xkbVModMapWireDesc);
1266    return len;
1267}
1268
1269static char *
1270XkbWriteVirtualModMap(XkbDescPtr xkb,xkbGetMapReply *rep,char *buf,
1271							ClientPtr client)
1272{
1273unsigned		i;
1274xkbVModMapWireDesc *	wire;
1275unsigned short *	pMap;
1276
1277    wire= (xkbVModMapWireDesc *)buf;
1278    pMap= &xkb->server->vmodmap[rep->firstVModMapKey];
1279    for (i=0;i<rep->nVModMapKeys-1;i++,pMap++) {
1280	if (*pMap!=0) {
1281	    wire->key= i+rep->firstVModMapKey;
1282	    wire->vmods= *pMap;
1283	    wire++;
1284	}
1285    }
1286    return (char *)wire;
1287}
1288
1289static Status
1290XkbComputeGetMapReplySize(XkbDescPtr xkb,xkbGetMapReply *rep)
1291{
1292int	len;
1293
1294    rep->minKeyCode= xkb->min_key_code;
1295    rep->maxKeyCode= xkb->max_key_code;
1296    len= XkbSizeKeyTypes(xkb,rep);
1297    len+= XkbSizeKeySyms(xkb,rep);
1298    len+= XkbSizeKeyActions(xkb,rep);
1299    len+= XkbSizeKeyBehaviors(xkb,rep);
1300    len+= XkbSizeVirtualMods(xkb,rep);
1301    len+= XkbSizeExplicit(xkb,rep);
1302    len+= XkbSizeModifierMap(xkb,rep);
1303    len+= XkbSizeVirtualModMap(xkb,rep);
1304    rep->length+= (len/4);
1305    return Success;
1306}
1307
1308static int
1309XkbSendMap(ClientPtr client,XkbDescPtr xkb,xkbGetMapReply *rep)
1310{
1311unsigned	i,len;
1312char		*desc,*start;
1313
1314    len= (rep->length*4)-(SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply));
1315    start= desc= (char *)ALLOCATE_LOCAL(len);
1316    if (!start)
1317	return BadAlloc;
1318    if ( rep->nTypes>0 )
1319	desc = XkbWriteKeyTypes(xkb,rep,desc,client);
1320    if ( rep->nKeySyms>0 )
1321	desc = XkbWriteKeySyms(xkb,rep,desc,client);
1322    if ( rep->nKeyActs>0 )
1323	desc = XkbWriteKeyActions(xkb,rep,desc,client);
1324    if ( rep->totalKeyBehaviors>0 )
1325	desc = XkbWriteKeyBehaviors(xkb,rep,desc,client);
1326    if ( rep->virtualMods ) {
1327	register int sz,bit;
1328	for (i=sz=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
1329	    if (rep->virtualMods&bit) {
1330		desc[sz++]= xkb->server->vmods[i];
1331	    }
1332	}
1333	desc+= XkbPaddedSize(sz);
1334    }
1335    if ( rep->totalKeyExplicit>0 )
1336	desc= XkbWriteExplicit(xkb,rep,desc,client);
1337    if ( rep->totalModMapKeys>0 )
1338	desc= XkbWriteModifierMap(xkb,rep,desc,client);
1339    if ( rep->totalVModMapKeys>0 )
1340	desc= XkbWriteVirtualModMap(xkb,rep,desc,client);
1341    if ((desc-start)!=(len)) {
1342	ErrorF("BOGUS LENGTH in write keyboard desc, expected %d, got %ld\n",
1343					len, (unsigned long)(desc-start));
1344    }
1345    if (client->swapped) {
1346	register int n;
1347	swaps(&rep->sequenceNumber,n);
1348	swapl(&rep->length,n);
1349	swaps(&rep->present,n);
1350	swaps(&rep->totalSyms,n);
1351	swaps(&rep->totalActs,n);
1352    }
1353    WriteToClient(client, (i=SIZEOF(xkbGetMapReply)), (char *)rep);
1354    WriteToClient(client, len, start);
1355    DEALLOCATE_LOCAL((char *)start);
1356    return client->noClientException;
1357}
1358
1359int
1360ProcXkbGetMap(ClientPtr client)
1361{
1362    DeviceIntPtr	 dev;
1363    xkbGetMapReply	 rep;
1364    XkbDescRec		*xkb;
1365    int			 n,status;
1366
1367    REQUEST(xkbGetMapReq);
1368    REQUEST_SIZE_MATCH(xkbGetMapReq);
1369
1370    if (!(client->xkbClientFlags&_XkbClientInitialized))
1371	return BadAccess;
1372
1373    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
1374    CHK_MASK_OVERLAP(0x01,stuff->full,stuff->partial);
1375    CHK_MASK_LEGAL(0x02,stuff->full,XkbAllMapComponentsMask);
1376    CHK_MASK_LEGAL(0x03,stuff->partial,XkbAllMapComponentsMask);
1377
1378    xkb= dev->key->xkbInfo->desc;
1379    bzero(&rep,sizeof(xkbGetMapReply));
1380    rep.type= X_Reply;
1381    rep.sequenceNumber= client->sequence;
1382    rep.length = (SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2;
1383    rep.deviceID = dev->id;
1384    rep.present = stuff->partial|stuff->full;
1385    rep.minKeyCode = xkb->min_key_code;
1386    rep.maxKeyCode = xkb->max_key_code;
1387    if ( stuff->full&XkbKeyTypesMask ) {
1388	rep.firstType = 0;
1389	rep.nTypes = xkb->map->num_types;
1390    }
1391    else if (stuff->partial&XkbKeyTypesMask) {
1392	if (((unsigned)stuff->firstType+stuff->nTypes)>xkb->map->num_types) {
1393	    client->errorValue = _XkbErrCode4(0x04,xkb->map->num_types,
1394					stuff->firstType,stuff->nTypes);
1395	    return BadValue;
1396	}
1397	rep.firstType = stuff->firstType;
1398	rep.nTypes = stuff->nTypes;
1399    }
1400    else rep.nTypes = 0;
1401    rep.totalTypes = xkb->map->num_types;
1402
1403    n= XkbNumKeys(xkb);
1404    if ( stuff->full&XkbKeySymsMask ) {
1405	rep.firstKeySym = xkb->min_key_code;
1406	rep.nKeySyms = n;
1407    }
1408    else if (stuff->partial&XkbKeySymsMask) {
1409	CHK_KEY_RANGE(0x05,stuff->firstKeySym,stuff->nKeySyms,xkb);
1410	rep.firstKeySym = stuff->firstKeySym;
1411	rep.nKeySyms = stuff->nKeySyms;
1412    }
1413    else rep.nKeySyms = 0;
1414    rep.totalSyms= 0;
1415
1416    if ( stuff->full&XkbKeyActionsMask ) {
1417	rep.firstKeyAct= xkb->min_key_code;
1418	rep.nKeyActs= n;
1419    }
1420    else if (stuff->partial&XkbKeyActionsMask) {
1421	CHK_KEY_RANGE(0x07,stuff->firstKeyAct,stuff->nKeyActs,xkb);
1422	rep.firstKeyAct= stuff->firstKeyAct;
1423	rep.nKeyActs= stuff->nKeyActs;
1424    }
1425    else rep.nKeyActs= 0;
1426    rep.totalActs= 0;
1427
1428    if ( stuff->full&XkbKeyBehaviorsMask ) {
1429	rep.firstKeyBehavior = xkb->min_key_code;
1430	rep.nKeyBehaviors = n;
1431    }
1432    else if (stuff->partial&XkbKeyBehaviorsMask) {
1433	CHK_KEY_RANGE(0x09,stuff->firstKeyBehavior,stuff->nKeyBehaviors,xkb);
1434	rep.firstKeyBehavior= stuff->firstKeyBehavior;
1435	rep.nKeyBehaviors= stuff->nKeyBehaviors;
1436    }
1437    else rep.nKeyBehaviors = 0;
1438    rep.totalKeyBehaviors= 0;
1439
1440    if (stuff->full&XkbVirtualModsMask)
1441	rep.virtualMods= ~0;
1442    else if (stuff->partial&XkbVirtualModsMask)
1443	rep.virtualMods= stuff->virtualMods;
1444
1445    if (stuff->full&XkbExplicitComponentsMask) {
1446	rep.firstKeyExplicit= xkb->min_key_code;
1447	rep.nKeyExplicit= n;
1448    }
1449    else if (stuff->partial&XkbExplicitComponentsMask) {
1450	CHK_KEY_RANGE(0x0B,stuff->firstKeyExplicit,stuff->nKeyExplicit,xkb);
1451	rep.firstKeyExplicit= stuff->firstKeyExplicit;
1452	rep.nKeyExplicit= stuff->nKeyExplicit;
1453    }
1454    else rep.nKeyExplicit = 0;
1455    rep.totalKeyExplicit=  0;
1456
1457    if (stuff->full&XkbModifierMapMask) {
1458	rep.firstModMapKey= xkb->min_key_code;
1459	rep.nModMapKeys= n;
1460    }
1461    else if (stuff->partial&XkbModifierMapMask) {
1462	CHK_KEY_RANGE(0x0D,stuff->firstModMapKey,stuff->nModMapKeys,xkb);
1463	rep.firstModMapKey= stuff->firstModMapKey;
1464	rep.nModMapKeys= stuff->nModMapKeys;
1465    }
1466    else rep.nModMapKeys = 0;
1467    rep.totalModMapKeys= 0;
1468
1469    if (stuff->full&XkbVirtualModMapMask) {
1470	rep.firstVModMapKey= xkb->min_key_code;
1471	rep.nVModMapKeys= n;
1472    }
1473    else if (stuff->partial&XkbVirtualModMapMask) {
1474	CHK_KEY_RANGE(0x0F,stuff->firstVModMapKey,stuff->nVModMapKeys,xkb);
1475	rep.firstVModMapKey= stuff->firstVModMapKey;
1476	rep.nVModMapKeys= stuff->nVModMapKeys;
1477    }
1478    else rep.nVModMapKeys = 0;
1479    rep.totalVModMapKeys= 0;
1480
1481    if ((status=XkbComputeGetMapReplySize(xkb,&rep))!=Success)
1482	return status;
1483    return XkbSendMap(client,xkb,&rep);
1484}
1485
1486/***====================================================================***/
1487
1488static int
1489CheckKeyTypes(	ClientPtr	client,
1490		XkbDescPtr	xkb,
1491		xkbSetMapReq *	req,
1492		xkbKeyTypeWireDesc **wireRtrn,
1493		int	 *	nMapsRtrn,
1494		CARD8 *		mapWidthRtrn)
1495{
1496unsigned		nMaps;
1497register unsigned	i,n;
1498register CARD8 *	map;
1499register xkbKeyTypeWireDesc	*wire = *wireRtrn;
1500
1501    if (req->firstType>((unsigned)xkb->map->num_types)) {
1502	*nMapsRtrn = _XkbErrCode3(0x01,req->firstType,xkb->map->num_types);
1503	return 0;
1504    }
1505    if (req->flags&XkbSetMapResizeTypes) {
1506	nMaps = req->firstType+req->nTypes;
1507	if (nMaps<XkbNumRequiredTypes) {  /* canonical types must be there */
1508	    *nMapsRtrn= _XkbErrCode4(0x02,req->firstType,req->nTypes,4);
1509	    return 0;
1510	}
1511    }
1512    else if (req->present&XkbKeyTypesMask) {
1513	nMaps = xkb->map->num_types;
1514	if ((req->firstType+req->nTypes)>nMaps) {
1515	    *nMapsRtrn = req->firstType+req->nTypes;
1516	    return 0;
1517	}
1518    }
1519    else {
1520	*nMapsRtrn = xkb->map->num_types;
1521	for (i=0;i<xkb->map->num_types;i++) {
1522	    mapWidthRtrn[i] = xkb->map->types[i].num_levels;
1523	}
1524	return 1;
1525    }
1526
1527    for (i=0;i<req->firstType;i++) {
1528	mapWidthRtrn[i] = xkb->map->types[i].num_levels;
1529    }
1530    for (i=0;i<req->nTypes;i++) {
1531	unsigned	width;
1532	if (client->swapped) {
1533	    register int s;
1534	    swaps(&wire->virtualMods,s);
1535	}
1536	n= i+req->firstType;
1537	width= wire->numLevels;
1538	if (width<1) {
1539	    *nMapsRtrn= _XkbErrCode3(0x04,n,width);
1540	    return 0;
1541	}
1542	else if ((n==XkbOneLevelIndex)&&(width!=1)) { /* must be width 1 */
1543	    *nMapsRtrn= _XkbErrCode3(0x05,n,width);
1544	    return 0;
1545	}
1546	else if ((width!=2)&&
1547		 ((n==XkbTwoLevelIndex)||(n==XkbKeypadIndex)||
1548		  (n==XkbAlphabeticIndex))) {
1549	    /* TWO_LEVEL, ALPHABETIC and KEYPAD must be width 2 */
1550	    *nMapsRtrn= _XkbErrCode3(0x05,n,width);
1551	    return 0;
1552	}
1553	if (wire->nMapEntries>0) {
1554	    xkbKTSetMapEntryWireDesc *	mapWire;
1555	    xkbModsWireDesc *		preWire;
1556	    mapWire= (xkbKTSetMapEntryWireDesc *)&wire[1];
1557	    preWire= (xkbModsWireDesc *)&mapWire[wire->nMapEntries];
1558	    for (n=0;n<wire->nMapEntries;n++) {
1559		if (client->swapped) {
1560		    register int s;
1561		    swaps(&mapWire[n].virtualMods,s);
1562		}
1563		if (mapWire[n].realMods&(~wire->realMods)) {
1564		    *nMapsRtrn= _XkbErrCode4(0x06,n,mapWire[n].realMods,
1565						 wire->realMods);
1566		    return 0;
1567		}
1568		if (mapWire[n].virtualMods&(~wire->virtualMods)) {
1569		    *nMapsRtrn= _XkbErrCode3(0x07,n,mapWire[n].virtualMods);
1570		    return 0;
1571		}
1572		if (mapWire[n].level>=wire->numLevels) {
1573		    *nMapsRtrn= _XkbErrCode4(0x08,n,wire->numLevels,
1574						 mapWire[n].level);
1575		    return 0;
1576		}
1577		if (wire->preserve) {
1578		    if (client->swapped) {
1579			register int s;
1580			swaps(&preWire[n].virtualMods,s);
1581		    }
1582		    if (preWire[n].realMods&(~mapWire[n].realMods)) {
1583			*nMapsRtrn= _XkbErrCode4(0x09,n,preWire[n].realMods,
1584							mapWire[n].realMods);
1585			return 0;
1586		    }
1587		    if (preWire[n].virtualMods&(~mapWire[n].virtualMods)) {
1588			*nMapsRtrn=_XkbErrCode3(0x0a,n,preWire[n].virtualMods);
1589			return 0;
1590		    }
1591		}
1592	    }
1593	    if (wire->preserve)
1594		 map= (CARD8 *)&preWire[wire->nMapEntries];
1595	    else map= (CARD8 *)&mapWire[wire->nMapEntries];
1596	}
1597	else map= (CARD8 *)&wire[1];
1598	mapWidthRtrn[i+req->firstType] = wire->numLevels;
1599	wire= (xkbKeyTypeWireDesc *)map;
1600    }
1601    for (i=req->firstType+req->nTypes;i<nMaps;i++) {
1602	mapWidthRtrn[i] = xkb->map->types[i].num_levels;
1603    }
1604    *nMapsRtrn = nMaps;
1605    *wireRtrn = wire;
1606    return 1;
1607}
1608
1609static int
1610CheckKeySyms(	ClientPtr		client,
1611		XkbDescPtr		xkb,
1612		xkbSetMapReq *		req,
1613		int			nTypes,
1614		CARD8 *	 		mapWidths,
1615		CARD16 *	 	symsPerKey,
1616		xkbSymMapWireDesc **	wireRtrn,
1617		int *			errorRtrn)
1618{
1619register unsigned	i;
1620XkbSymMapPtr		map;
1621xkbSymMapWireDesc*	wire = *wireRtrn;
1622
1623    if (!(XkbKeySymsMask&req->present))
1624	return 1;
1625    CHK_REQ_KEY_RANGE2(0x11,req->firstKeySym,req->nKeySyms,req,(*errorRtrn),0);
1626    map = &xkb->map->key_sym_map[xkb->min_key_code];
1627    for (i=xkb->min_key_code;i<(unsigned)req->firstKeySym;i++,map++) {
1628	register int g,ng,w;
1629	ng= XkbNumGroups(map->group_info);
1630	for (w=g=0;g<ng;g++) {
1631	    if (map->kt_index[g]>=(unsigned)nTypes) {
1632		*errorRtrn = _XkbErrCode4(0x13,i,g,map->kt_index[g]);
1633		return 0;
1634	    }
1635	    if (mapWidths[map->kt_index[g]]>w)
1636		w= mapWidths[map->kt_index[g]];
1637	}
1638	symsPerKey[i] = w*ng;
1639    }
1640    for (i=0;i<req->nKeySyms;i++) {
1641	KeySym *pSyms;
1642	register unsigned nG;
1643	if (client->swapped) {
1644	    swaps(&wire->nSyms,nG);
1645	}
1646	nG = XkbNumGroups(wire->groupInfo);
1647	if (nG>XkbNumKbdGroups) {
1648	    *errorRtrn = _XkbErrCode3(0x14,i+req->firstKeySym,nG);
1649	    return 0;
1650	}
1651	if (nG>0) {
1652	    register int g,w;
1653	    for (g=w=0;g<nG;g++) {
1654		if (wire->ktIndex[g]>=(unsigned)nTypes) {
1655		    *errorRtrn= _XkbErrCode4(0x15,i+req->firstKeySym,g,
1656		    					   wire->ktIndex[g]);
1657		    return 0;
1658		}
1659		if (mapWidths[wire->ktIndex[g]]>w)
1660		    w= mapWidths[wire->ktIndex[g]];
1661	    }
1662	    if (wire->width!=w) {
1663		*errorRtrn= _XkbErrCode3(0x16,i+req->firstKeySym,wire->width);
1664		return 0;
1665	    }
1666	    w*= nG;
1667	    symsPerKey[i+req->firstKeySym] = w;
1668	    if (w!=wire->nSyms) {
1669		*errorRtrn=_XkbErrCode4(0x16,i+req->firstKeySym,wire->nSyms,w);
1670		return 0;
1671	    }
1672	}
1673	else if (wire->nSyms!=0) {
1674	    *errorRtrn = _XkbErrCode3(0x17,i+req->firstKeySym,wire->nSyms);
1675	    return 0;
1676	}
1677	pSyms = (KeySym *)&wire[1];
1678	wire = (xkbSymMapWireDesc *)&pSyms[wire->nSyms];
1679    }
1680
1681    map = &xkb->map->key_sym_map[i];
1682    for (;i<=(unsigned)xkb->max_key_code;i++,map++) {
1683	register int g,nG,w;
1684	nG= XkbKeyNumGroups(xkb,i);
1685	for (w=g=0;g<nG;g++)  {
1686	    if (map->kt_index[g]>=(unsigned)nTypes) {
1687		*errorRtrn = _XkbErrCode4(0x18,i,g,map->kt_index[g]);
1688		return 0;
1689	    }
1690	    if (mapWidths[map->kt_index[g]]>w)
1691		    w= mapWidths[map->kt_index[g]];
1692	}
1693	symsPerKey[i] = w*nG;
1694    }
1695    *wireRtrn = wire;
1696    return 1;
1697}
1698
1699static int
1700CheckKeyActions(	XkbDescPtr	xkb,
1701			xkbSetMapReq *	req,
1702			int		nTypes,
1703			CARD8 *		mapWidths,
1704			CARD16 *	symsPerKey,
1705			CARD8 **	wireRtrn,
1706			int *		nActsRtrn)
1707{
1708int			 nActs;
1709CARD8 *			 wire = *wireRtrn;
1710register unsigned	 i;
1711
1712    if (!(XkbKeyActionsMask&req->present))
1713	return 1;
1714    CHK_REQ_KEY_RANGE2(0x21,req->firstKeyAct,req->nKeyActs,req,(*nActsRtrn),0);
1715    for (nActs=i=0;i<req->nKeyActs;i++) {
1716	if (wire[0]!=0) {
1717	    if (wire[0]==symsPerKey[i+req->firstKeyAct])
1718		nActs+= wire[0];
1719	    else {
1720		*nActsRtrn= _XkbErrCode3(0x23,i+req->firstKeyAct,wire[0]);
1721		return 0;
1722	    }
1723	}
1724	wire++;
1725    }
1726    if (req->nKeyActs%4)
1727	wire+= 4-(req->nKeyActs%4);
1728    *wireRtrn = (CARD8 *)(((XkbAnyAction *)wire)+nActs);
1729    *nActsRtrn = nActs;
1730    return 1;
1731}
1732
1733static int
1734CheckKeyBehaviors(	XkbDescPtr 		xkb,
1735			xkbSetMapReq *		req,
1736			xkbBehaviorWireDesc **	wireRtrn,
1737			int *			errorRtrn)
1738{
1739register xkbBehaviorWireDesc *	wire = *wireRtrn;
1740register XkbServerMapPtr	server = xkb->server;
1741register unsigned	 	i;
1742unsigned			first,last;
1743
1744    if (((req->present&XkbKeyBehaviorsMask)==0)||(req->nKeyBehaviors<1)) {
1745	req->present&= ~XkbKeyBehaviorsMask;
1746	req->nKeyBehaviors= 0;
1747	return 1;
1748    }
1749    first= req->firstKeyBehavior;
1750    last=  req->firstKeyBehavior+req->nKeyBehaviors-1;
1751    if (first<req->minKeyCode) {
1752	*errorRtrn = _XkbErrCode3(0x31,first,req->minKeyCode);
1753	return 0;
1754    }
1755    if (last>req->maxKeyCode) {
1756	*errorRtrn = _XkbErrCode3(0x32,last,req->maxKeyCode);
1757	return 0;
1758    }
1759
1760    for (i=0;i<req->totalKeyBehaviors;i++,wire++) {
1761	if ((wire->key<first)||(wire->key>last)) {
1762	    *errorRtrn = _XkbErrCode4(0x33,first,last,wire->key);
1763	    return 0;
1764	}
1765	if ((wire->type&XkbKB_Permanent)&&
1766	    ((server->behaviors[wire->key].type!=wire->type)||
1767	     (server->behaviors[wire->key].data!=wire->data))) {
1768	    *errorRtrn = _XkbErrCode3(0x33,wire->key,wire->type);
1769	    return 0;
1770	}
1771	if ((wire->type==XkbKB_RadioGroup)&&
1772		((wire->data&(~XkbKB_RGAllowNone))>XkbMaxRadioGroups)) {
1773	    *errorRtrn= _XkbErrCode4(0x34,wire->key,wire->data,
1774							XkbMaxRadioGroups);
1775	    return 0;
1776	}
1777	if ((wire->type==XkbKB_Overlay1)||(wire->type==XkbKB_Overlay2)) {
1778	    CHK_KEY_RANGE2(0x35,wire->key,1,xkb,*errorRtrn,0);
1779	}
1780    }
1781    *wireRtrn = wire;
1782    return 1;
1783}
1784
1785static int
1786CheckVirtualMods(	XkbDescRec *	xkb,
1787			xkbSetMapReq *	req,
1788			CARD8 **	wireRtrn,
1789			int *		errorRtrn)
1790{
1791register CARD8		*wire = *wireRtrn;
1792register unsigned 	 i,nMods,bit;
1793
1794    if (((req->present&XkbVirtualModsMask)==0)||(req->virtualMods==0))
1795	return 1;
1796    for (i=nMods=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
1797	if (req->virtualMods&bit)
1798	    nMods++;
1799    }
1800    *wireRtrn= (wire+XkbPaddedSize(nMods));
1801    return 1;
1802}
1803
1804static int
1805CheckKeyExplicit(	XkbDescPtr	xkb,
1806			xkbSetMapReq *	req,
1807			CARD8 **	wireRtrn,
1808			int	*	errorRtrn)
1809{
1810register CARD8 *	wire = *wireRtrn;
1811CARD8	*		start;
1812register unsigned 	i;
1813int			first,last;
1814
1815    if (((req->present&XkbExplicitComponentsMask)==0)||(req->nKeyExplicit<1)) {
1816	req->present&= ~XkbExplicitComponentsMask;
1817	req->nKeyExplicit= 0;
1818	return 1;
1819    }
1820    first= req->firstKeyExplicit;
1821    last=  first+req->nKeyExplicit-1;
1822    if (first<req->minKeyCode) {
1823	*errorRtrn = _XkbErrCode3(0x51,first,req->minKeyCode);
1824	return 0;
1825    }
1826    if (last>req->maxKeyCode) {
1827	*errorRtrn = _XkbErrCode3(0x52,last,req->maxKeyCode);
1828	return 0;
1829    }
1830    start= wire;
1831    for (i=0;i<req->totalKeyExplicit;i++,wire+=2) {
1832	if ((wire[0]<first)||(wire[0]>last)) {
1833	    *errorRtrn = _XkbErrCode4(0x53,first,last,wire[0]);
1834	    return 0;
1835	}
1836	if (wire[1]&(~XkbAllExplicitMask)) {
1837	     *errorRtrn= _XkbErrCode3(0x52,~XkbAllExplicitMask,wire[1]);
1838	     return 0;
1839	}
1840    }
1841    wire+= XkbPaddedSize(wire-start)-(wire-start);
1842    *wireRtrn= wire;
1843    return 1;
1844}
1845
1846static int
1847CheckModifierMap(XkbDescPtr xkb,xkbSetMapReq *req,CARD8 **wireRtrn,int *errRtrn)
1848{
1849register CARD8 *	wire = *wireRtrn;
1850CARD8	*		start;
1851register unsigned 	i;
1852int			first,last;
1853
1854    if (((req->present&XkbModifierMapMask)==0)||(req->nModMapKeys<1)) {
1855	req->present&= ~XkbModifierMapMask;
1856	req->nModMapKeys= 0;
1857	return 1;
1858    }
1859    first= req->firstModMapKey;
1860    last=  first+req->nModMapKeys-1;
1861    if (first<req->minKeyCode) {
1862	*errRtrn = _XkbErrCode3(0x61,first,req->minKeyCode);
1863	return 0;
1864    }
1865    if (last>req->maxKeyCode) {
1866	*errRtrn = _XkbErrCode3(0x62,last,req->maxKeyCode);
1867	return 0;
1868    }
1869    start= wire;
1870    for (i=0;i<req->totalModMapKeys;i++,wire+=2) {
1871	if ((wire[0]<first)||(wire[0]>last)) {
1872	    *errRtrn = _XkbErrCode4(0x63,first,last,wire[0]);
1873	    return 0;
1874	}
1875    }
1876    wire+= XkbPaddedSize(wire-start)-(wire-start);
1877    *wireRtrn= wire;
1878    return 1;
1879}
1880
1881static int
1882CheckVirtualModMap(	XkbDescPtr xkb,
1883			xkbSetMapReq *req,
1884			xkbVModMapWireDesc **wireRtrn,
1885			int *errRtrn)
1886{
1887register xkbVModMapWireDesc *	wire = *wireRtrn;
1888register unsigned 		i;
1889int				first,last;
1890
1891    if (((req->present&XkbVirtualModMapMask)==0)||(req->nVModMapKeys<1)) {
1892	req->present&= ~XkbVirtualModMapMask;
1893	req->nVModMapKeys= 0;
1894	return 1;
1895    }
1896    first= req->firstVModMapKey;
1897    last=  first+req->nVModMapKeys-1;
1898    if (first<req->minKeyCode) {
1899	*errRtrn = _XkbErrCode3(0x71,first,req->minKeyCode);
1900	return 0;
1901    }
1902    if (last>req->maxKeyCode) {
1903	*errRtrn = _XkbErrCode3(0x72,last,req->maxKeyCode);
1904	return 0;
1905    }
1906    for (i=0;i<req->totalVModMapKeys;i++,wire++) {
1907	if ((wire->key<first)||(wire->key>last)) {
1908	    *errRtrn = _XkbErrCode4(0x73,first,last,wire->key);
1909	    return 0;
1910	}
1911    }
1912    *wireRtrn= wire;
1913    return 1;
1914}
1915
1916static char *
1917SetKeyTypes(	XkbDescPtr		xkb,
1918		xkbSetMapReq *		req,
1919		xkbKeyTypeWireDesc *	wire,
1920		XkbChangesPtr		changes)
1921{
1922register unsigned	i;
1923unsigned		first,last;
1924CARD8			*map;
1925
1926    if ((unsigned)(req->firstType+req->nTypes)>xkb->map->size_types) {
1927	i= req->firstType+req->nTypes;
1928	if (XkbAllocClientMap(xkb,XkbKeyTypesMask,i)!=Success) {
1929	    return NULL;
1930	}
1931    }
1932    if ((unsigned)(req->firstType+req->nTypes)>xkb->map->num_types)
1933	xkb->map->num_types= req->firstType+req->nTypes;
1934
1935    for (i=0;i<req->nTypes;i++) {
1936	XkbKeyTypePtr		pOld;
1937	register unsigned 	n;
1938
1939	if (XkbResizeKeyType(xkb,i+req->firstType,wire->nMapEntries,
1940				wire->preserve,wire->numLevels)!=Success) {
1941	    return NULL;
1942	}
1943	pOld = &xkb->map->types[i+req->firstType];
1944	map = (CARD8 *)&wire[1];
1945
1946	pOld->mods.real_mods = wire->realMods;
1947	pOld->mods.vmods= wire->virtualMods;
1948	pOld->num_levels = wire->numLevels;
1949	pOld->map_count= wire->nMapEntries;
1950
1951	pOld->mods.mask= pOld->mods.real_mods|
1952					XkbMaskForVMask(xkb,pOld->mods.vmods);
1953
1954	if (wire->nMapEntries) {
1955	    xkbKTSetMapEntryWireDesc *mapWire;
1956	    xkbModsWireDesc *preWire;
1957	    unsigned tmp;
1958	    mapWire= (xkbKTSetMapEntryWireDesc *)map;
1959	    preWire= (xkbModsWireDesc *)&mapWire[wire->nMapEntries];
1960	    for (n=0;n<wire->nMapEntries;n++) {
1961		pOld->map[n].active= 1;
1962		pOld->map[n].mods.mask= mapWire[n].realMods;
1963		pOld->map[n].mods.real_mods= mapWire[n].realMods;
1964		pOld->map[n].mods.vmods= mapWire[n].virtualMods;
1965		pOld->map[n].level= mapWire[n].level;
1966		if (mapWire[n].virtualMods!=0) {
1967		    tmp= XkbMaskForVMask(xkb,mapWire[n].virtualMods);
1968		    pOld->map[n].active= (tmp!=0);
1969		    pOld->map[n].mods.mask|= tmp;
1970		}
1971		if (wire->preserve) {
1972		    pOld->preserve[n].real_mods= preWire[n].realMods;
1973		    pOld->preserve[n].vmods= preWire[n].virtualMods;
1974		    tmp= XkbMaskForVMask(xkb,preWire[n].virtualMods);
1975		    pOld->preserve[n].mask= preWire[n].realMods|tmp;
1976		}
1977	    }
1978	    if (wire->preserve)
1979		 map= (CARD8 *)&preWire[wire->nMapEntries];
1980	    else map= (CARD8 *)&mapWire[wire->nMapEntries];
1981	}
1982	else map= (CARD8 *)&wire[1];
1983	wire = (xkbKeyTypeWireDesc *)map;
1984    }
1985    first= req->firstType;
1986    last= first+req->nTypes-1; /* last changed type */
1987    if (changes->map.changed&XkbKeyTypesMask) {
1988	int oldLast;
1989	oldLast= changes->map.first_type+changes->map.num_types-1;
1990	if (changes->map.first_type<first)
1991	    first= changes->map.first_type;
1992	if (oldLast>last)
1993	    last= oldLast;
1994    }
1995    changes->map.changed|= XkbKeyTypesMask;
1996    changes->map.first_type = first;
1997    changes->map.num_types = (last-first)+1;
1998    return (char *)wire;
1999}
2000
2001static char *
2002SetKeySyms(	ClientPtr		client,
2003		XkbDescPtr		xkb,
2004		xkbSetMapReq *		req,
2005		xkbSymMapWireDesc *	wire,
2006		XkbChangesPtr 		changes,
2007		DeviceIntPtr		dev)
2008{
2009register unsigned 	i,s;
2010XkbSymMapPtr		oldMap;
2011KeySym *		newSyms;
2012KeySym *		pSyms;
2013unsigned		first,last;
2014
2015    oldMap = &xkb->map->key_sym_map[req->firstKeySym];
2016    for (i=0;i<req->nKeySyms;i++,oldMap++) {
2017	pSyms = (KeySym *)&wire[1];
2018	if (wire->nSyms>0) {
2019	    newSyms = XkbResizeKeySyms(xkb,i+req->firstKeySym,wire->nSyms);
2020	    for (s=0;s<wire->nSyms;s++) {
2021		newSyms[s]= pSyms[s];
2022	    }
2023	    if (client->swapped) {
2024		int n;
2025		for (s=0;s<wire->nSyms;s++) {
2026		    swapl(&newSyms[s],n);
2027		}
2028	    }
2029	}
2030	oldMap->kt_index[0] = wire->ktIndex[0];
2031	oldMap->kt_index[1] = wire->ktIndex[1];
2032	oldMap->kt_index[2] = wire->ktIndex[2];
2033	oldMap->kt_index[3] = wire->ktIndex[3];
2034	oldMap->group_info = wire->groupInfo;
2035	oldMap->width = wire->width;
2036	wire= (xkbSymMapWireDesc *)&pSyms[wire->nSyms];
2037    }
2038    first= req->firstKeySym;
2039    last= first+req->nKeySyms-1;
2040    if (changes->map.changed&XkbKeySymsMask) {
2041	int oldLast= (changes->map.first_key_sym+changes->map.num_key_syms-1);
2042	if (changes->map.first_key_sym<first)
2043	    first= changes->map.first_key_sym;
2044	if (oldLast>last)
2045	    last= oldLast;
2046    }
2047    changes->map.changed|= XkbKeySymsMask;
2048    changes->map.first_key_sym = first;
2049    changes->map.num_key_syms = (last-first+1);
2050
2051    s= 0;
2052    for (i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
2053	if (XkbKeyNumGroups(xkb,i)>s)
2054	    s= XkbKeyNumGroups(xkb,i);
2055    }
2056    if (s!=xkb->ctrls->num_groups) {
2057	xkbControlsNotify	cn;
2058	XkbControlsRec		old;
2059	cn.keycode= 0;
2060	cn.eventType= 0;
2061	cn.requestMajor= XkbReqCode;
2062	cn.requestMinor= X_kbSetMap;
2063	old= *xkb->ctrls;
2064	xkb->ctrls->num_groups= s;
2065	if (XkbComputeControlsNotify(dev,&old,xkb->ctrls,&cn,False))
2066	    XkbSendControlsNotify(dev,&cn);
2067    }
2068    return (char *)wire;
2069}
2070
2071static char *
2072SetKeyActions(	XkbDescPtr	xkb,
2073		xkbSetMapReq *	req,
2074		CARD8 *		wire,
2075		XkbChangesPtr	changes)
2076{
2077register unsigned	i,first,last;
2078CARD8 *			nActs = wire;
2079XkbAction *		newActs;
2080
2081    wire+= XkbPaddedSize(req->nKeyActs);
2082    for (i=0;i<req->nKeyActs;i++) {
2083	if (nActs[i]==0)
2084	    xkb->server->key_acts[i+req->firstKeyAct]= 0;
2085	else {
2086	    newActs= XkbResizeKeyActions(xkb,i+req->firstKeyAct,nActs[i]);
2087	    memcpy((char *)newActs,(char *)wire,
2088					nActs[i]*SIZEOF(xkbActionWireDesc));
2089	    wire+= nActs[i]*SIZEOF(xkbActionWireDesc);
2090	}
2091    }
2092    first= req->firstKeyAct;
2093    last= (first+req->nKeyActs-1);
2094    if (changes->map.changed&XkbKeyActionsMask) {
2095	int oldLast;
2096	oldLast= changes->map.first_key_act+changes->map.num_key_acts-1;
2097	if (changes->map.first_key_act<first)
2098	    first= changes->map.first_key_act;
2099	if (oldLast>last)
2100	    last= oldLast;
2101    }
2102    changes->map.changed|= XkbKeyActionsMask;
2103    changes->map.first_key_act= first;
2104    changes->map.num_key_acts= (last-first+1);
2105    return (char *)wire;
2106}
2107
2108static char *
2109SetKeyBehaviors(	XkbSrvInfoPtr	 xkbi,
2110    			xkbSetMapReq	*req,
2111    			xkbBehaviorWireDesc	*wire,
2112    			XkbChangesPtr	 changes)
2113{
2114register unsigned i;
2115int maxRG = -1;
2116XkbDescPtr       xkb = xkbi->desc;
2117XkbServerMapPtr	 server = xkb->server;
2118unsigned	 first,last;
2119
2120    first= req->firstKeyBehavior;
2121    last= req->firstKeyBehavior+req->nKeyBehaviors-1;
2122    bzero(&server->behaviors[first],req->nKeyBehaviors*sizeof(XkbBehavior));
2123    for (i=0;i<req->totalKeyBehaviors;i++) {
2124	if ((server->behaviors[wire->key].type&XkbKB_Permanent)==0) {
2125	    server->behaviors[wire->key].type= wire->type;
2126	    server->behaviors[wire->key].data= wire->data;
2127	    if ((wire->type==XkbKB_RadioGroup)&&(((int)wire->data)>maxRG))
2128		maxRG= wire->data + 1;
2129	}
2130	wire++;
2131    }
2132
2133    if (maxRG>(int)xkbi->nRadioGroups) {
2134        int sz = maxRG*sizeof(XkbRadioGroupRec);
2135        if (xkbi->radioGroups)
2136             xkbi->radioGroups=(XkbRadioGroupPtr)_XkbRealloc(xkbi->radioGroups,sz);
2137        else xkbi->radioGroups= (XkbRadioGroupPtr)_XkbCalloc(1, sz);
2138        if (xkbi->radioGroups) {
2139             if (xkbi->nRadioGroups)
2140                bzero(&xkbi->radioGroups[xkbi->nRadioGroups],
2141                        (maxRG-xkbi->nRadioGroups)*sizeof(XkbRadioGroupRec));
2142             xkbi->nRadioGroups= maxRG;
2143        }
2144        else xkbi->nRadioGroups= 0;
2145        /* should compute members here */
2146    }
2147    if (changes->map.changed&XkbKeyBehaviorsMask) {
2148	unsigned oldLast;
2149	oldLast= changes->map.first_key_behavior+
2150					changes->map.num_key_behaviors-1;
2151        if (changes->map.first_key_behavior<req->firstKeyBehavior)
2152             first= changes->map.first_key_behavior;
2153        if (oldLast>last)
2154            last= oldLast;
2155    }
2156    changes->map.changed|= XkbKeyBehaviorsMask;
2157    changes->map.first_key_behavior = first;
2158    changes->map.num_key_behaviors = (last-first+1);
2159    return (char *)wire;
2160}
2161
2162static char *
2163SetVirtualMods(XkbSrvInfoPtr xkbi,xkbSetMapReq *req,CARD8 *wire,
2164						XkbChangesPtr changes)
2165{
2166register int 		i,bit,nMods;
2167XkbServerMapPtr		srv = xkbi->desc->server;
2168
2169    if (((req->present&XkbVirtualModsMask)==0)||(req->virtualMods==0))
2170	return (char *)wire;
2171    for (i=nMods=0,bit=1;i<XkbNumVirtualMods;i++,bit<<=1) {
2172	if (req->virtualMods&bit) {
2173	    if (srv->vmods[i]!=wire[nMods]) {
2174		changes->map.changed|= XkbVirtualModsMask;
2175		changes->map.vmods|= bit;
2176		srv->vmods[i]= wire[nMods];
2177	    }
2178	    nMods++;
2179	}
2180    }
2181    return (char *)(wire+XkbPaddedSize(nMods));
2182}
2183
2184static char *
2185SetKeyExplicit(XkbSrvInfoPtr xkbi,xkbSetMapReq *req,CARD8 *wire,
2186							XkbChangesPtr changes)
2187{
2188register unsigned	i,first,last;
2189XkbServerMapPtr		xkb = xkbi->desc->server;
2190CARD8 *			start;
2191
2192    start= wire;
2193    first= req->firstKeyExplicit;
2194    last=  req->firstKeyExplicit+req->nKeyExplicit-1;
2195    bzero(&xkb->explicit[first],req->nKeyExplicit);
2196    for (i=0;i<req->totalKeyExplicit;i++,wire+= 2) {
2197	xkb->explicit[wire[0]]= wire[1];
2198    }
2199    if (first>0) {
2200	if (changes->map.changed&XkbExplicitComponentsMask) {
2201	    int oldLast;
2202	    oldLast= changes->map.first_key_explicit+
2203					changes->map.num_key_explicit-1;
2204	    if (changes->map.first_key_explicit<first)
2205		first= changes->map.first_key_explicit;
2206	    if (oldLast>last)
2207		last= oldLast;
2208	}
2209	changes->map.first_key_explicit= first;
2210	changes->map.num_key_explicit= (last-first)+1;
2211    }
2212    wire+= XkbPaddedSize(wire-start)-(wire-start);
2213    return (char *)wire;
2214}
2215
2216static char *
2217SetModifierMap(	XkbSrvInfoPtr	xkbi,
2218		xkbSetMapReq *	req,
2219		CARD8 *		wire,
2220		XkbChangesPtr	changes)
2221{
2222register unsigned	i,first,last;
2223XkbClientMapPtr		xkb = xkbi->desc->map;
2224CARD8 *			start;
2225
2226    start= wire;
2227    first= req->firstModMapKey;
2228    last=  req->firstModMapKey+req->nModMapKeys-1;
2229    bzero(&xkb->modmap[first],req->nModMapKeys);
2230    for (i=0;i<req->totalModMapKeys;i++,wire+= 2) {
2231	xkb->modmap[wire[0]]= wire[1];
2232    }
2233    if (first>0) {
2234	if (changes->map.changed&XkbModifierMapMask) {
2235	    int oldLast;
2236	    oldLast= changes->map.first_modmap_key+
2237						changes->map.num_modmap_keys-1;
2238	    if (changes->map.first_modmap_key<first)
2239		first= changes->map.first_modmap_key;
2240	    if (oldLast>last)
2241		last= oldLast;
2242	}
2243	changes->map.first_modmap_key= first;
2244	changes->map.num_modmap_keys= (last-first)+1;
2245    }
2246    wire+= XkbPaddedSize(wire-start)-(wire-start);
2247    return (char *)wire;
2248}
2249
2250static char *
2251SetVirtualModMap(	XkbSrvInfoPtr		xkbi,
2252			xkbSetMapReq *		req,
2253			xkbVModMapWireDesc *	wire,
2254			XkbChangesPtr 		changes)
2255{
2256register unsigned	i,first,last;
2257XkbServerMapPtr		srv = xkbi->desc->server;
2258
2259    first= req->firstVModMapKey;
2260    last=  req->firstVModMapKey+req->nVModMapKeys-1;
2261    bzero(&srv->vmodmap[first],req->nVModMapKeys*sizeof(unsigned short));
2262    for (i=0;i<req->totalVModMapKeys;i++,wire++) {
2263	srv->vmodmap[wire->key]= wire->vmods;
2264    }
2265    if (first>0) {
2266	if (changes->map.changed&XkbVirtualModMapMask) {
2267	    int oldLast;
2268	    oldLast= changes->map.first_vmodmap_key+
2269					changes->map.num_vmodmap_keys-1;
2270	    if (changes->map.first_vmodmap_key<first)
2271		first= changes->map.first_vmodmap_key;
2272	    if (oldLast>last)
2273		last= oldLast;
2274	}
2275	changes->map.first_vmodmap_key= first;
2276	changes->map.num_vmodmap_keys= (last-first)+1;
2277    }
2278    return (char *)wire;
2279}
2280
2281/* FIXME: Needs to set map on all core-sending devices. */
2282int
2283ProcXkbSetMap(ClientPtr client)
2284{
2285    DeviceIntPtr	dev;
2286    XkbSrvInfoPtr	xkbi;
2287    XkbDescPtr		xkb;
2288    XkbChangesRec	change;
2289    XkbEventCauseRec	cause;
2290    int			nTypes = 0,nActions,error;
2291    char *		tmp;
2292    CARD8	 	mapWidths[XkbMaxLegalKeyCode+1];
2293    CARD16	 	symsPerKey[XkbMaxLegalKeyCode+1];
2294    Bool		sentNKN;
2295
2296    REQUEST(xkbSetMapReq);
2297    REQUEST_AT_LEAST_SIZE(xkbSetMapReq);
2298
2299    if (!(client->xkbClientFlags&_XkbClientInitialized))
2300	return BadAccess;
2301
2302    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
2303    CHK_MASK_LEGAL(0x01,stuff->present,XkbAllMapComponentsMask);
2304
2305    XkbSetCauseXkbReq(&cause,X_kbSetMap,client);
2306    xkbi= dev->key->xkbInfo;
2307    xkb = xkbi->desc;
2308
2309    if ((xkb->min_key_code!=stuff->minKeyCode)||
2310    				(xkb->max_key_code!=stuff->maxKeyCode)) {
2311	if (client->vMajor!=1) { /* pre 1.0 versions of Xlib have a bug */
2312	    stuff->minKeyCode= xkb->min_key_code;
2313	    stuff->maxKeyCode= xkb->max_key_code;
2314	}
2315	else {
2316	    if (!XkbIsLegalKeycode(stuff->minKeyCode)) {
2317		client->errorValue= _XkbErrCode3(2,stuff->minKeyCode,
2318							stuff->maxKeyCode);
2319		return BadValue;
2320	    }
2321	    if (stuff->minKeyCode>stuff->maxKeyCode) {
2322		client->errorValue= _XkbErrCode3(3,stuff->minKeyCode,
2323							stuff->maxKeyCode);
2324		return BadMatch;
2325	    }
2326	}
2327    }
2328
2329    tmp = (char *)&stuff[1];
2330    if ((stuff->present&XkbKeyTypesMask)&&
2331	(!CheckKeyTypes(client,xkb,stuff,(xkbKeyTypeWireDesc **)&tmp,
2332						&nTypes,mapWidths))) {
2333	client->errorValue = nTypes;
2334	return BadValue;
2335    }
2336    if ((stuff->present&XkbKeySymsMask)&&
2337	(!CheckKeySyms(client,xkb,stuff,nTypes,mapWidths,symsPerKey,
2338					(xkbSymMapWireDesc **)&tmp,&error))) {
2339	client->errorValue = error;
2340	return BadValue;
2341    }
2342
2343    if ((stuff->present&XkbKeyActionsMask)&&
2344	(!CheckKeyActions(xkb,stuff,nTypes,mapWidths,symsPerKey,
2345						(CARD8 **)&tmp,&nActions))) {
2346	client->errorValue = nActions;
2347	return BadValue;
2348    }
2349
2350    if ((stuff->present&XkbKeyBehaviorsMask)&&
2351	(!CheckKeyBehaviors(xkb,stuff,(xkbBehaviorWireDesc**)&tmp,&error))) {
2352	client->errorValue = error;
2353	return BadValue;
2354    }
2355
2356    if ((stuff->present&XkbVirtualModsMask)&&
2357	(!CheckVirtualMods(xkb,stuff,(CARD8 **)&tmp,&error))) {
2358	client->errorValue= error;
2359	return BadValue;
2360    }
2361    if ((stuff->present&XkbExplicitComponentsMask)&&
2362	(!CheckKeyExplicit(xkb,stuff,(CARD8 **)&tmp,&error))) {
2363	client->errorValue= error;
2364	return BadValue;
2365    }
2366    if ((stuff->present&XkbModifierMapMask)&&
2367	(!CheckModifierMap(xkb,stuff,(CARD8 **)&tmp,&error))) {
2368	client->errorValue= error;
2369	return BadValue;
2370    }
2371    if ((stuff->present&XkbVirtualModMapMask)&&
2372	(!CheckVirtualModMap(xkb,stuff,(xkbVModMapWireDesc **)&tmp,&error))) {
2373	client->errorValue= error;
2374	return BadValue;
2375    }
2376    if (((tmp-((char *)stuff))/4)!=stuff->length) {
2377	ErrorF("Internal error! Bad length in XkbSetMap (after check)\n");
2378	client->errorValue = tmp-((char *)&stuff[1]);
2379	return BadLength;
2380    }
2381    bzero(&change,sizeof(change));
2382    sentNKN= False;
2383    if ((xkb->min_key_code!=stuff->minKeyCode)||
2384    				(xkb->max_key_code!=stuff->maxKeyCode)) {
2385	Status			status;
2386	xkbNewKeyboardNotify	nkn;
2387	nkn.deviceID= nkn.oldDeviceID= dev->id;
2388	nkn.oldMinKeyCode= xkb->min_key_code;
2389	nkn.oldMaxKeyCode= xkb->max_key_code;
2390	status= XkbChangeKeycodeRange(xkb,stuff->minKeyCode,stuff->maxKeyCode,
2391								&change);
2392	if (status!=Success)
2393	    return status;
2394	nkn.minKeyCode= xkb->min_key_code;
2395	nkn.maxKeyCode= xkb->max_key_code;
2396	nkn.requestMajor= XkbReqCode;
2397	nkn.requestMinor= X_kbSetMap;
2398	nkn.changed= XkbNKN_KeycodesMask;
2399	XkbSendNewKeyboardNotify(dev,&nkn);
2400	sentNKN= True;
2401    }
2402    tmp = (char *)&stuff[1];
2403    if (stuff->present&XkbKeyTypesMask) {
2404	tmp = SetKeyTypes(xkb,stuff,(xkbKeyTypeWireDesc *)tmp,&change);
2405	if (!tmp)	goto allocFailure;
2406    }
2407    if (stuff->present&XkbKeySymsMask) {
2408	tmp = SetKeySyms(client,xkb,stuff,(xkbSymMapWireDesc *)tmp,&change,dev);
2409	if (!tmp)	goto allocFailure;
2410    }
2411    if (stuff->present&XkbKeyActionsMask) {
2412	tmp = SetKeyActions(xkb,stuff,(CARD8 *)tmp,&change);
2413	if (!tmp)	goto allocFailure;
2414    }
2415    if (stuff->present&XkbKeyBehaviorsMask) {
2416	tmp= SetKeyBehaviors(xkbi,stuff,(xkbBehaviorWireDesc *)tmp,&change);
2417	if (!tmp)	goto allocFailure;
2418    }
2419    if (stuff->present&XkbVirtualModsMask)
2420	tmp= SetVirtualMods(xkbi,stuff,(CARD8 *)tmp,&change);
2421    if (stuff->present&XkbExplicitComponentsMask)
2422	tmp= SetKeyExplicit(xkbi,stuff,(CARD8 *)tmp,&change);
2423    if (stuff->present&XkbModifierMapMask)
2424	tmp= SetModifierMap(xkbi,stuff,(CARD8 *)tmp,&change);
2425    if (stuff->present&XkbVirtualModMapMask)
2426	tmp= SetVirtualModMap(xkbi,stuff,(xkbVModMapWireDesc *)tmp,&change);
2427    if (((tmp-((char *)stuff))/4)!=stuff->length) {
2428	ErrorF("Internal error! Bad length in XkbSetMap (after set)\n");
2429	client->errorValue = tmp-((char *)&stuff[1]);
2430	return BadLength;
2431    }
2432    if (stuff->flags&XkbSetMapRecomputeActions) {
2433	KeyCode		first,last,firstMM,lastMM;
2434	if (change.map.num_key_syms>0) {
2435	    first= change.map.first_key_sym;
2436	    last= first+change.map.num_key_syms-1;
2437	}
2438	else first= last= 0;
2439	if (change.map.num_modmap_keys>0) {
2440	    firstMM= change.map.first_modmap_key;
2441	    lastMM= first+change.map.num_modmap_keys-1;
2442	}
2443	else firstMM= lastMM= 0;
2444	if ((last>0) && (lastMM>0)) {
2445	    if (firstMM<first)
2446		first= firstMM;
2447	    if (lastMM>last)
2448		last= lastMM;
2449	}
2450	else if (lastMM>0) {
2451	    first= firstMM;
2452	    last= lastMM;
2453	}
2454	if (last>0) {
2455	    unsigned check= 0;
2456	    XkbUpdateActions(dev,first,(last-first+1),&change,&check,&cause);
2457	    if (check)
2458		XkbCheckSecondaryEffects(xkbi,check,&change,&cause);
2459	}
2460    }
2461    if (!sentNKN)
2462	XkbSendNotification(dev,&change,&cause);
2463
2464    XkbUpdateCoreDescription(dev,False);
2465    return client->noClientException;
2466allocFailure:
2467    return BadAlloc;
2468}
2469
2470/***====================================================================***/
2471
2472static Status
2473XkbComputeGetCompatMapReplySize(	XkbCompatMapPtr 	compat,
2474					xkbGetCompatMapReply *	rep)
2475{
2476unsigned	 size,nGroups;
2477
2478    nGroups= 0;
2479    if (rep->groups!=0) {
2480	register int i,bit;
2481	for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
2482	    if (rep->groups&bit)
2483		nGroups++;
2484	}
2485    }
2486    size= nGroups*SIZEOF(xkbModsWireDesc);
2487    size+= (rep->nSI*SIZEOF(xkbSymInterpretWireDesc));
2488    rep->length= size/4;
2489    return Success;
2490}
2491
2492static int
2493XkbSendCompatMap(	ClientPtr 		client,
2494			XkbCompatMapPtr 	compat,
2495			xkbGetCompatMapReply *	rep)
2496{
2497char	*	data;
2498int		size;
2499
2500    size= rep->length*4;
2501    if (size>0) {
2502	data = (char *)ALLOCATE_LOCAL(size);
2503	if (data) {
2504	    register unsigned i,bit;
2505	    xkbModsWireDesc *	grp;
2506	    XkbSymInterpretPtr	sym= &compat->sym_interpret[rep->firstSI];
2507	    xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data;
2508	    for (i=0;i<rep->nSI;i++,sym++,wire++) {
2509		wire->sym= sym->sym;
2510		wire->mods= sym->mods;
2511		wire->match= sym->match;
2512		wire->virtualMod= sym->virtual_mod;
2513		wire->flags= sym->flags;
2514		memcpy((char*)&wire->act,(char*)&sym->act,sz_xkbActionWireDesc);
2515		if (client->swapped) {
2516		    register int n;
2517		    swapl(&wire->sym,n);
2518		}
2519	    }
2520	    if (rep->groups) {
2521		grp = (xkbModsWireDesc *)wire;
2522		for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
2523		    if (rep->groups&bit) {
2524			grp->mask= compat->groups[i].mask;
2525			grp->realMods= compat->groups[i].real_mods;
2526			grp->virtualMods= compat->groups[i].vmods;
2527			if (client->swapped) {
2528			    register int n;
2529			    swaps(&grp->virtualMods,n);
2530			}
2531			grp++;
2532		    }
2533		}
2534		wire= (xkbSymInterpretWireDesc*)grp;
2535	    }
2536	}
2537	else return BadAlloc;
2538    }
2539    else data= NULL;
2540
2541    if (client->swapped) {
2542	register int n;
2543	swaps(&rep->sequenceNumber,n);
2544	swapl(&rep->length,n);
2545	swaps(&rep->firstSI,n);
2546	swaps(&rep->nSI,n);
2547	swaps(&rep->nTotalSI,n);
2548    }
2549
2550    WriteToClient(client, SIZEOF(xkbGetCompatMapReply), (char *)rep);
2551    if (data) {
2552	WriteToClient(client, size, data);
2553	DEALLOCATE_LOCAL((char *)data);
2554    }
2555    return client->noClientException;
2556}
2557
2558int
2559ProcXkbGetCompatMap(ClientPtr client)
2560{
2561    xkbGetCompatMapReply 	rep;
2562    DeviceIntPtr 		dev;
2563    XkbDescPtr			xkb;
2564    XkbCompatMapPtr		compat;
2565
2566    REQUEST(xkbGetCompatMapReq);
2567    REQUEST_SIZE_MATCH(xkbGetCompatMapReq);
2568
2569    if (!(client->xkbClientFlags&_XkbClientInitialized))
2570	return BadAccess;
2571
2572    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
2573
2574    xkb = dev->key->xkbInfo->desc;
2575    compat= xkb->compat;
2576
2577    rep.type = X_Reply;
2578    rep.deviceID = dev->id;
2579    rep.sequenceNumber = client->sequence;
2580    rep.length = 0;
2581    rep.firstSI = stuff->firstSI;
2582    rep.nSI = stuff->nSI;
2583    if (stuff->getAllSI) {
2584	rep.firstSI = 0;
2585	rep.nSI = compat->num_si;
2586    }
2587    else if ((((unsigned)stuff->nSI)>0)&&
2588		((unsigned)(stuff->firstSI+stuff->nSI-1)>=compat->num_si)) {
2589	client->errorValue = _XkbErrCode2(0x05,compat->num_si);
2590	return BadValue;
2591    }
2592    rep.nTotalSI = compat->num_si;
2593    rep.groups= stuff->groups;
2594    XkbComputeGetCompatMapReplySize(compat,&rep);
2595    return XkbSendCompatMap(client,compat,&rep);
2596}
2597
2598/* FIXME: Needs to set compat map on all core-sending devices. */
2599int
2600ProcXkbSetCompatMap(ClientPtr client)
2601{
2602    DeviceIntPtr 	dev;
2603    XkbSrvInfoPtr 	xkbi;
2604    XkbDescPtr		xkb;
2605    XkbCompatMapPtr 	compat;
2606    char	*	data;
2607    int		 	nGroups;
2608    register unsigned	i,bit;
2609
2610    REQUEST(xkbSetCompatMapReq);
2611    REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq);
2612
2613    if (!(client->xkbClientFlags&_XkbClientInitialized))
2614	return BadAccess;
2615
2616    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
2617
2618    data = (char *)&stuff[1];
2619    xkbi = dev->key->xkbInfo;
2620    xkb= xkbi->desc;
2621    compat= xkb->compat;
2622    if ((stuff->nSI>0)||(stuff->truncateSI)) {
2623	xkbSymInterpretWireDesc *wire;
2624	if (stuff->firstSI>compat->num_si) {
2625	    client->errorValue = _XkbErrCode2(0x02,compat->num_si);
2626	    return BadValue;
2627	}
2628	wire= (xkbSymInterpretWireDesc *)data;
2629	wire+= stuff->nSI;
2630	data = (char *)wire;
2631    }
2632    nGroups= 0;
2633    if (stuff->groups!=0) {
2634	for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
2635	    if ( stuff->groups&bit )
2636		nGroups++;
2637	}
2638    }
2639    data+= nGroups*SIZEOF(xkbModsWireDesc);
2640    if (((data-((char *)stuff))/4)!=stuff->length) {
2641	return BadLength;
2642    }
2643    data = (char *)&stuff[1];
2644    if (stuff->nSI>0) {
2645	xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *)data;
2646	XkbSymInterpretPtr	sym;
2647	if ((unsigned)(stuff->firstSI+stuff->nSI)>compat->num_si) {
2648	    compat->num_si= stuff->firstSI+stuff->nSI;
2649	    compat->sym_interpret= _XkbTypedRealloc(compat->sym_interpret,
2650						   compat->num_si,
2651						   XkbSymInterpretRec);
2652	    if (!compat->sym_interpret) {
2653		compat->num_si= 0;
2654		return BadAlloc;
2655	    }
2656	}
2657	else if (stuff->truncateSI) {
2658	    compat->num_si = stuff->firstSI+stuff->nSI;
2659	}
2660	sym = &compat->sym_interpret[stuff->firstSI];
2661	for (i=0;i<stuff->nSI;i++,wire++,sym++) {
2662	    if (client->swapped) {
2663		register int n;
2664		swapl(&wire->sym,n);
2665	    }
2666	    sym->sym= wire->sym;
2667	    sym->mods= wire->mods;
2668	    sym->match= wire->match;
2669	    sym->flags= wire->flags;
2670	    sym->virtual_mod= wire->virtualMod;
2671	    memcpy((char *)&sym->act,(char *)&wire->act,
2672	    					SIZEOF(xkbActionWireDesc));
2673	}
2674	data = (char *)wire;
2675    }
2676    else if (stuff->truncateSI) {
2677	compat->num_si = stuff->firstSI;
2678    }
2679
2680    if (stuff->groups!=0) {
2681	register unsigned i,bit;
2682	xkbModsWireDesc *wire = (xkbModsWireDesc *)data;
2683	for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
2684	    if (stuff->groups&bit) {
2685		if (client->swapped) {
2686		    register int n;
2687		    swaps(&wire->virtualMods,n);
2688		}
2689		compat->groups[i].mask= wire->realMods;
2690		compat->groups[i].real_mods= wire->realMods;
2691		compat->groups[i].vmods= wire->virtualMods;
2692		if (wire->virtualMods!=0) {
2693		    unsigned tmp;
2694		    tmp= XkbMaskForVMask(xkb,wire->virtualMods);
2695		    compat->groups[i].mask|= tmp;
2696		}
2697		data+= SIZEOF(xkbModsWireDesc);
2698		wire= (xkbModsWireDesc *)data;
2699	    }
2700	}
2701    }
2702    i= XkbPaddedSize((data-((char *)stuff)));
2703    if ((i/4)!=stuff->length) {
2704	ErrorF("Internal length error on read in ProcXkbSetCompatMap\n");
2705	return BadLength;
2706    }
2707
2708    if (dev->xkb_interest) {
2709	xkbCompatMapNotify ev;
2710	ev.deviceID = dev->id;
2711	ev.changedGroups = stuff->groups;
2712	ev.firstSI = stuff->firstSI;
2713	ev.nSI = stuff->nSI;
2714	ev.nTotalSI = compat->num_si;
2715	XkbSendCompatMapNotify(dev,&ev);
2716    }
2717
2718    if (stuff->recomputeActions) {
2719	XkbChangesRec		change;
2720	unsigned		check;
2721	XkbEventCauseRec	cause;
2722
2723	XkbSetCauseXkbReq(&cause,X_kbSetCompatMap,client);
2724	bzero(&change,sizeof(XkbChangesRec));
2725	XkbUpdateActions(dev,xkb->min_key_code,XkbNumKeys(xkb),&change,&check,
2726									&cause);
2727	if (check)
2728	    XkbCheckSecondaryEffects(xkbi,check,&change,&cause);
2729	XkbUpdateCoreDescription(dev,False);
2730	XkbSendNotification(dev,&change,&cause);
2731    }
2732    return client->noClientException;
2733}
2734
2735/***====================================================================***/
2736
2737int
2738ProcXkbGetIndicatorState(ClientPtr client)
2739{
2740    xkbGetIndicatorStateReply 	rep;
2741    XkbSrvLedInfoPtr		sli;
2742    DeviceIntPtr 		dev;
2743    register int 		i;
2744
2745    REQUEST(xkbGetIndicatorStateReq);
2746    REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq);
2747
2748    if (!(client->xkbClientFlags&_XkbClientInitialized))
2749	return BadAccess;
2750
2751    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
2752
2753    sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,
2754						XkbXI_IndicatorStateMask);
2755    if (!sli)
2756	return BadAlloc;
2757
2758    rep.type = X_Reply;
2759    rep.sequenceNumber = client->sequence;
2760    rep.length = 0;
2761    rep.deviceID = dev->id;
2762    rep.state = sli->effectiveState;
2763
2764    if (client->swapped) {
2765	swaps(&rep.sequenceNumber,i);
2766	swapl(&rep.state,i);
2767    }
2768    WriteToClient(client, SIZEOF(xkbGetIndicatorStateReply), (char *)&rep);
2769    return client->noClientException;
2770}
2771
2772/***====================================================================***/
2773
2774static Status
2775XkbComputeGetIndicatorMapReplySize(
2776    XkbIndicatorPtr		indicators,
2777    xkbGetIndicatorMapReply	*rep)
2778{
2779register int 	i,bit;
2780int		nIndicators;
2781
2782    rep->realIndicators = indicators->phys_indicators;
2783    for (i=nIndicators=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
2784	if (rep->which&bit)
2785	    nIndicators++;
2786    }
2787    rep->length = (nIndicators*SIZEOF(xkbIndicatorMapWireDesc))/4;
2788    return Success;
2789}
2790
2791static int
2792XkbSendIndicatorMap(	ClientPtr			client,
2793			XkbIndicatorPtr			indicators,
2794			xkbGetIndicatorMapReply *	rep)
2795{
2796int 			length;
2797CARD8 *			map;
2798register int		i;
2799register unsigned	bit;
2800
2801    length = rep->length*4;
2802    if (length>0) {
2803	CARD8 *to;
2804	to= map= (CARD8 *)ALLOCATE_LOCAL(length);
2805	if (map) {
2806	    xkbIndicatorMapWireDesc  *wire = (xkbIndicatorMapWireDesc *)to;
2807	    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
2808		if (rep->which&bit) {
2809		    wire->flags= indicators->maps[i].flags;
2810		    wire->whichGroups= indicators->maps[i].which_groups;
2811		    wire->groups= indicators->maps[i].groups;
2812		    wire->whichMods= indicators->maps[i].which_mods;
2813		    wire->mods= indicators->maps[i].mods.mask;
2814		    wire->realMods= indicators->maps[i].mods.real_mods;
2815		    wire->virtualMods= indicators->maps[i].mods.vmods;
2816		    wire->ctrls= indicators->maps[i].ctrls;
2817		    if (client->swapped) {
2818			register int n;
2819			swaps(&wire->virtualMods,n);
2820			swapl(&wire->ctrls,n);
2821		    }
2822		    wire++;
2823		}
2824	    }
2825	    to = (CARD8 *)wire;
2826	    if ((to-map)!=length) {
2827		client->errorValue = _XkbErrCode2(0xff,length);
2828		return BadLength;
2829	    }
2830	}
2831	else return BadAlloc;
2832    }
2833    else map = NULL;
2834    if (client->swapped) {
2835	swaps(&rep->sequenceNumber,i);
2836	swapl(&rep->length,i);
2837	swapl(&rep->which,i);
2838	swapl(&rep->realIndicators,i);
2839    }
2840    WriteToClient(client, SIZEOF(xkbGetIndicatorMapReply), (char *)rep);
2841    if (map) {
2842	WriteToClient(client, length, (char *)map);
2843	DEALLOCATE_LOCAL((char *)map);
2844    }
2845    return client->noClientException;
2846}
2847
2848int
2849ProcXkbGetIndicatorMap(ClientPtr client)
2850{
2851xkbGetIndicatorMapReply rep;
2852DeviceIntPtr		dev;
2853XkbDescPtr		xkb;
2854XkbIndicatorPtr		leds;
2855
2856    REQUEST(xkbGetIndicatorMapReq);
2857    REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq);
2858
2859    if (!(client->xkbClientFlags&_XkbClientInitialized))
2860	return BadAccess;
2861
2862    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
2863
2864    xkb= dev->key->xkbInfo->desc;
2865    leds= xkb->indicators;
2866
2867    rep.type = X_Reply;
2868    rep.sequenceNumber = client->sequence;
2869    rep.length = 0;
2870    rep.deviceID = dev->id;
2871    rep.which = stuff->which;
2872    XkbComputeGetIndicatorMapReplySize(leds,&rep);
2873    return XkbSendIndicatorMap(client,leds,&rep);
2874}
2875
2876/* FIXME: Needs to set indicator map on all core-sending devices. */
2877int
2878ProcXkbSetIndicatorMap(ClientPtr client)
2879{
2880    register int 	i,bit;
2881    int			nIndicators,why;
2882    DeviceIntPtr 	dev;
2883    XkbSrvInfoPtr	xkbi;
2884    xkbIndicatorMapWireDesc *from;
2885    XkbSrvLedInfoPtr	sli;
2886    XkbEventCauseRec	cause;
2887
2888    REQUEST(xkbSetIndicatorMapReq);
2889    REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq);
2890
2891    if (!(client->xkbClientFlags&_XkbClientInitialized))
2892	return BadAccess;
2893
2894    dev = _XkbLookupKeyboard(stuff->deviceSpec,&why);
2895    if (!dev) {
2896	client->errorValue = _XkbErrCode2(why,stuff->deviceSpec);
2897	return XkbKeyboardErrorCode;
2898    }
2899    xkbi= dev->key->xkbInfo;
2900
2901    if (stuff->which==0)
2902	return client->noClientException;
2903
2904    for (nIndicators=i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
2905	if (stuff->which&bit)
2906	    nIndicators++;
2907    }
2908    if (stuff->length!=((SIZEOF(xkbSetIndicatorMapReq)+
2909			(nIndicators*SIZEOF(xkbIndicatorMapWireDesc)))/4)) {
2910	return BadLength;
2911    }
2912
2913    sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,
2914						XkbXI_IndicatorMapsMask);
2915    if (!sli)
2916	return BadAlloc;
2917
2918    from = (xkbIndicatorMapWireDesc *)&stuff[1];
2919    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
2920	if (stuff->which&bit) {
2921	    if (client->swapped) {
2922		register int n;
2923		swaps(&from->virtualMods,n);
2924		swapl(&from->ctrls,n);
2925	    }
2926	    CHK_MASK_LEGAL(i,from->whichGroups,XkbIM_UseAnyGroup);
2927	    CHK_MASK_LEGAL(i,from->whichMods,XkbIM_UseAnyMods);
2928	    from++;
2929	}
2930    }
2931
2932    from = (xkbIndicatorMapWireDesc *)&stuff[1];
2933    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
2934	if (stuff->which&bit) {
2935	    sli->maps[i].flags = from->flags;
2936	    sli->maps[i].which_groups = from->whichGroups;
2937	    sli->maps[i].groups = from->groups;
2938	    sli->maps[i].which_mods = from->whichMods;
2939	    sli->maps[i].mods.mask = from->mods;
2940	    sli->maps[i].mods.real_mods = from->mods;
2941	    sli->maps[i].mods.vmods= from->virtualMods;
2942	    sli->maps[i].ctrls = from->ctrls;
2943	    if (from->virtualMods!=0) {
2944		unsigned tmp;
2945		tmp= XkbMaskForVMask(xkbi->desc,from->virtualMods);
2946		sli->maps[i].mods.mask= from->mods|tmp;
2947	    }
2948	    from++;
2949	}
2950    }
2951
2952    XkbSetCauseXkbReq(&cause,X_kbSetIndicatorMap,client);
2953    XkbApplyLedMapChanges(dev,sli,stuff->which,NULL,NULL,&cause);
2954    return client->noClientException;
2955}
2956
2957/***====================================================================***/
2958
2959int
2960ProcXkbGetNamedIndicator(ClientPtr client)
2961{
2962    DeviceIntPtr 		dev;
2963    xkbGetNamedIndicatorReply 	rep;
2964    register int		i = 0;
2965    XkbSrvLedInfoPtr		sli;
2966    XkbIndicatorMapPtr		map = NULL;
2967
2968    REQUEST(xkbGetNamedIndicatorReq);
2969    REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq);
2970
2971    if (!(client->xkbClientFlags&_XkbClientInitialized))
2972	return BadAccess;
2973
2974    CHK_LED_DEVICE(dev,stuff->deviceSpec);
2975    CHK_ATOM_ONLY(stuff->indicator);
2976
2977    sli= XkbFindSrvLedInfo(dev,stuff->ledClass,stuff->ledID,0);
2978    if (!sli)
2979	return BadAlloc;
2980
2981    i= 0;
2982    map= NULL;
2983    if ((sli->names)&&(sli->maps)) {
2984        for (i=0;i<XkbNumIndicators;i++) {
2985            if (stuff->indicator==sli->names[i]) {
2986                map= &sli->maps[i];
2987                break;
2988            }
2989        }
2990    }
2991
2992    rep.type= X_Reply;
2993    rep.length = 0;
2994    rep.sequenceNumber = client->sequence;
2995    rep.deviceID = dev->id;
2996    rep.indicator= stuff->indicator;
2997    if (map!=NULL) {
2998	rep.found= 		True;
2999	rep.on=			((sli->effectiveState&(1<<i))!=0);
3000	rep.realIndicator=	((sli->physIndicators&(1<<i))!=0);
3001	rep.ndx= 		i;
3002	rep.flags= 		map->flags;
3003	rep.whichGroups= 	map->which_groups;
3004	rep.groups= 		map->groups;
3005	rep.whichMods= 		map->which_mods;
3006	rep.mods= 		map->mods.mask;
3007	rep.realMods= 		map->mods.real_mods;
3008	rep.virtualMods= 	map->mods.vmods;
3009	rep.ctrls= 		map->ctrls;
3010	rep.supported= 		True;
3011    }
3012    else  {
3013	rep.found= 		False;
3014	rep.on= 		False;
3015	rep.realIndicator= 	False;
3016	rep.ndx= 		XkbNoIndicator;
3017	rep.flags= 		0;
3018	rep.whichGroups= 	0;
3019	rep.groups= 		0;
3020	rep.whichMods= 		0;
3021	rep.mods=		0;
3022	rep.realMods= 		0;
3023	rep.virtualMods= 	0;
3024	rep.ctrls= 		0;
3025	rep.supported= 		True;
3026    }
3027    if ( client->swapped ) {
3028	register int n;
3029	swapl(&rep.length,n);
3030	swaps(&rep.sequenceNumber,n);
3031	swapl(&rep.indicator,n);
3032	swaps(&rep.virtualMods,n);
3033	swapl(&rep.ctrls,n);
3034    }
3035
3036    WriteToClient(client,SIZEOF(xkbGetNamedIndicatorReply), (char *)&rep);
3037    return client->noClientException;
3038}
3039
3040/* FIXME: Needs to set indicator on all core-sending devices. */
3041int
3042ProcXkbSetNamedIndicator(ClientPtr client)
3043{
3044    DeviceIntPtr 		dev,kbd;
3045    XkbIndicatorMapPtr		map;
3046    XkbSrvLedInfoPtr 		sli;
3047    register int		led = 0;
3048    unsigned			extDevReason;
3049    unsigned			statec,namec,mapc;
3050    XkbEventCauseRec		cause;
3051    xkbExtensionDeviceNotify	ed;
3052    XkbChangesRec		changes;
3053
3054    REQUEST(xkbSetNamedIndicatorReq);
3055    REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq);
3056
3057    if (!(client->xkbClientFlags&_XkbClientInitialized))
3058	return BadAccess;
3059
3060    CHK_LED_DEVICE(dev,stuff->deviceSpec);
3061    CHK_ATOM_ONLY(stuff->indicator);
3062    CHK_MASK_LEGAL(0x10,stuff->whichGroups,XkbIM_UseAnyGroup);
3063    CHK_MASK_LEGAL(0x11,stuff->whichMods,XkbIM_UseAnyMods);
3064
3065    extDevReason= 0;
3066
3067    sli= XkbFindSrvLedInfo(dev,stuff->ledClass,stuff->ledID,
3068							XkbXI_IndicatorsMask);
3069    if (!sli)
3070	return BadAlloc;
3071
3072    statec= mapc= namec= 0;
3073    map= NULL;
3074    if (sli->names && sli->maps) {
3075	for (led=0;(led<XkbNumIndicators)&&(map==NULL);led++) {
3076	    if (sli->names[led]==stuff->indicator) {
3077		map= &sli->maps[led];
3078		break;
3079	    }
3080	}
3081    }
3082    if (map==NULL) {
3083	if (!stuff->createMap)
3084	    return client->noClientException;
3085	for (led=0,map=NULL;(led<XkbNumIndicators)&&(map==NULL);led++) {
3086	    if ((sli->names)&&(sli->maps)&&(sli->names[led]==None)&&
3087                (!XkbIM_InUse(&sli->maps[led]))) {
3088		map= &sli->maps[led];
3089		sli->names[led]= stuff->indicator;
3090		break;
3091	    }
3092	}
3093	if (map==NULL)
3094	    return client->noClientException;
3095	namec|= (1<<led);
3096	sli->namesPresent|= ((stuff->indicator!=None)?(1<<led):0);
3097	extDevReason|= XkbXI_IndicatorNamesMask;
3098    }
3099
3100    if (stuff->setMap) {
3101	map->flags = stuff->flags;
3102	map->which_groups = stuff->whichGroups;
3103	map->groups = stuff->groups;
3104	map->which_mods = stuff->whichMods;
3105	map->mods.mask = stuff->realMods;
3106	map->mods.real_mods = stuff->realMods;
3107	map->mods.vmods= stuff->virtualMods;
3108	map->ctrls = stuff->ctrls;
3109	mapc|= (1<<led);
3110    }
3111    if ((stuff->setState)&&((map->flags&XkbIM_NoExplicit)==0)) {
3112	if (stuff->on)	sli->explicitState|=  (1<<led);
3113	else		sli->explicitState&= ~(1<<led);
3114	statec|= ((sli->effectiveState^sli->explicitState)&(1<<led));
3115    }
3116    bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify));
3117    bzero((char *)&changes,sizeof(XkbChangesRec));
3118    XkbSetCauseXkbReq(&cause,X_kbSetNamedIndicator,client);
3119    if (namec)
3120	XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause);
3121    if (mapc)
3122	XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause);
3123    if (statec)
3124	XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause);
3125
3126    kbd= dev;
3127    if ((sli->flags&XkbSLI_HasOwnState)==0)
3128	kbd= (DeviceIntPtr)LookupKeyboardDevice();
3129    XkbFlushLedEvents(dev,kbd,sli,&ed,&changes,&cause);
3130    return client->noClientException;
3131}
3132
3133/***====================================================================***/
3134
3135static CARD32
3136_XkbCountAtoms(Atom *atoms,int maxAtoms,int *count)
3137{
3138register unsigned int i,bit,nAtoms;
3139register CARD32 atomsPresent;
3140
3141    for (i=nAtoms=atomsPresent=0,bit=1;i<maxAtoms;i++,bit<<=1) {
3142	if (atoms[i]!=None) {
3143	    atomsPresent|= bit;
3144	    nAtoms++;
3145	}
3146    }
3147    if (count)
3148	*count= nAtoms;
3149    return atomsPresent;
3150}
3151
3152static char *
3153_XkbWriteAtoms(char *wire,Atom *atoms,int maxAtoms,int swap)
3154{
3155register unsigned int i;
3156Atom *atm;
3157
3158    atm = (Atom *)wire;
3159    for (i=0;i<maxAtoms;i++) {
3160	if (atoms[i]!=None) {
3161	    *atm= atoms[i];
3162	    if (swap) {
3163		register int n;
3164		swapl(atm,n);
3165	    }
3166	    atm++;
3167	}
3168    }
3169    return (char *)atm;
3170}
3171
3172static Status
3173XkbComputeGetNamesReplySize(XkbDescPtr xkb,xkbGetNamesReply *rep)
3174{
3175register unsigned	which,length;
3176register int		i;
3177
3178    rep->minKeyCode= xkb->min_key_code;
3179    rep->maxKeyCode= xkb->max_key_code;
3180    which= rep->which;
3181    length= 0;
3182    if (xkb->names!=NULL) {
3183	 if (which&XkbKeycodesNameMask)		length++;
3184	 if (which&XkbGeometryNameMask)		length++;
3185	 if (which&XkbSymbolsNameMask)		length++;
3186	 if (which&XkbPhysSymbolsNameMask)	length++;
3187	 if (which&XkbTypesNameMask)		length++;
3188	 if (which&XkbCompatNameMask)		length++;
3189    }
3190    else which&= ~XkbComponentNamesMask;
3191
3192    if (xkb->map!=NULL) {
3193	if (which&XkbKeyTypeNamesMask)
3194	    length+= xkb->map->num_types;
3195	rep->nTypes= xkb->map->num_types;
3196	if (which&XkbKTLevelNamesMask) {
3197	    XkbKeyTypePtr	pType = xkb->map->types;
3198	    int			nKTLevels = 0;
3199
3200	    length+= XkbPaddedSize(xkb->map->num_types)/4;
3201	    for (i=0;i<xkb->map->num_types;i++,pType++) {
3202		if (pType->level_names!=NULL)
3203		    nKTLevels+= pType->num_levels;
3204	    }
3205	    rep->nKTLevels= nKTLevels;
3206	    length+= nKTLevels;
3207	}
3208    }
3209    else {
3210	rep->nTypes=    0;
3211	rep->nKTLevels= 0;
3212	which&= ~(XkbKeyTypeNamesMask|XkbKTLevelNamesMask);
3213    }
3214
3215    rep->minKeyCode= xkb->min_key_code;
3216    rep->maxKeyCode= xkb->max_key_code;
3217    rep->indicators= 0;
3218    rep->virtualMods= 0;
3219    rep->groupNames= 0;
3220    if (xkb->names!=NULL) {
3221	if (which&XkbIndicatorNamesMask) {
3222	    int nLeds;
3223	    rep->indicators=
3224		_XkbCountAtoms(xkb->names->indicators,XkbNumIndicators,&nLeds);
3225	    length+= nLeds;
3226	    if (nLeds==0)
3227		which&= ~XkbIndicatorNamesMask;
3228	}
3229
3230	if (which&XkbVirtualModNamesMask) {
3231	    int nVMods;
3232	    rep->virtualMods=
3233		_XkbCountAtoms(xkb->names->vmods,XkbNumVirtualMods,&nVMods);
3234	    length+= nVMods;
3235	    if (nVMods==0)
3236		which&= ~XkbVirtualModNamesMask;
3237	}
3238
3239	if (which&XkbGroupNamesMask) {
3240	    int nGroups;
3241	    rep->groupNames=
3242		_XkbCountAtoms(xkb->names->groups,XkbNumKbdGroups,&nGroups);
3243	    length+= nGroups;
3244	    if (nGroups==0)
3245		which&= ~XkbGroupNamesMask;
3246	}
3247
3248	if ((which&XkbKeyNamesMask)&&(xkb->names->keys))
3249	     length+= rep->nKeys;
3250	else which&= ~XkbKeyNamesMask;
3251
3252	if ((which&XkbKeyAliasesMask)&&
3253	    (xkb->names->key_aliases)&&(xkb->names->num_key_aliases>0)) {
3254	    rep->nKeyAliases= xkb->names->num_key_aliases;
3255	    length+= rep->nKeyAliases*2;
3256	}
3257	else {
3258	    which&= ~XkbKeyAliasesMask;
3259	    rep->nKeyAliases= 0;
3260	}
3261
3262	if ((which&XkbRGNamesMask)&&(xkb->names->num_rg>0))
3263	     length+= xkb->names->num_rg;
3264	else which&= ~XkbRGNamesMask;
3265    }
3266    else {
3267	which&= ~(XkbIndicatorNamesMask|XkbVirtualModNamesMask);
3268	which&= ~(XkbGroupNamesMask|XkbKeyNamesMask|XkbKeyAliasesMask);
3269	which&= ~XkbRGNamesMask;
3270    }
3271
3272    rep->length= length;
3273    rep->which= which;
3274    return Success;
3275}
3276
3277static int
3278XkbSendNames(ClientPtr client,XkbDescPtr xkb,xkbGetNamesReply *rep)
3279{
3280register unsigned 	i,length,which;
3281char *			start;
3282char *			desc;
3283register int            n;
3284
3285    length= rep->length*4;
3286    which= rep->which;
3287    if (client->swapped) {
3288	swaps(&rep->sequenceNumber,n);
3289	swapl(&rep->length,n);
3290	swapl(&rep->which,n);
3291	swaps(&rep->virtualMods,n);
3292	swapl(&rep->indicators,n);
3293    }
3294
3295    start = desc = (char *)ALLOCATE_LOCAL(length);
3296    if ( !start )
3297	return BadAlloc;
3298    if (xkb->names) {
3299        if (which&XkbKeycodesNameMask) {
3300            *((CARD32 *)desc)= xkb->names->keycodes;
3301            if (client->swapped) {
3302                swapl(desc,n);
3303            }
3304            desc+= 4;
3305        }
3306        if (which&XkbGeometryNameMask)  {
3307            *((CARD32 *)desc)= xkb->names->geometry;
3308            if (client->swapped) {
3309                swapl(desc,n);
3310            }
3311            desc+= 4;
3312        }
3313        if (which&XkbSymbolsNameMask) {
3314            *((CARD32 *)desc)= xkb->names->symbols;
3315            if (client->swapped) {
3316                swapl(desc,n);
3317            }
3318            desc+= 4;
3319        }
3320        if (which&XkbPhysSymbolsNameMask) {
3321            register CARD32 *atm= (CARD32 *)desc;
3322            atm[0]= (CARD32)xkb->names->phys_symbols;
3323            if (client->swapped) {
3324                swapl(&atm[0],n);
3325            }
3326            desc+= 4;
3327        }
3328        if (which&XkbTypesNameMask) {
3329            *((CARD32 *)desc)= (CARD32)xkb->names->types;
3330            if (client->swapped) {
3331                swapl(desc,n);
3332            }
3333            desc+= 4;
3334        }
3335        if (which&XkbCompatNameMask) {
3336            *((CARD32 *)desc)= (CARD32)xkb->names->compat;
3337            if (client->swapped) {
3338                swapl(desc,n);
3339            }
3340            desc+= 4;
3341        }
3342        if (which&XkbKeyTypeNamesMask) {
3343            register CARD32 *atm= (CARD32 *)desc;
3344            register XkbKeyTypePtr type= xkb->map->types;
3345
3346            for (i=0;i<xkb->map->num_types;i++,atm++,type++) {
3347                *atm= (CARD32)type->name;
3348                if (client->swapped) {
3349                    swapl(atm,n);
3350                }
3351            }
3352            desc= (char *)atm;
3353        }
3354        if (which&XkbKTLevelNamesMask && xkb->map) {
3355            XkbKeyTypePtr type = xkb->map->types;
3356            register CARD32 *atm;
3357            for (i=0;i<rep->nTypes;i++,type++) {
3358                *desc++ = type->num_levels;
3359            }
3360            desc+= XkbPaddedSize(rep->nTypes)-rep->nTypes;
3361
3362            atm= (CARD32 *)desc;
3363            type = xkb->map->types;
3364            for (i=0;i<xkb->map->num_types;i++,type++) {
3365                register unsigned l;
3366                if (type->level_names) {
3367                    for (l=0;l<type->num_levels;l++,atm++) {
3368                        *atm= type->level_names[l];
3369                        if (client->swapped) {
3370                            swapl(atm,n);
3371                        }
3372                    }
3373                    desc+= type->num_levels*4;
3374                }
3375            }
3376        }
3377        if (which&XkbIndicatorNamesMask) {
3378            desc= _XkbWriteAtoms(desc,xkb->names->indicators,XkbNumIndicators,
3379                                 client->swapped);
3380        }
3381        if (which&XkbVirtualModNamesMask) {
3382            desc= _XkbWriteAtoms(desc,xkb->names->vmods,XkbNumVirtualMods,
3383                                 client->swapped);
3384        }
3385        if (which&XkbGroupNamesMask) {
3386            desc= _XkbWriteAtoms(desc,xkb->names->groups,XkbNumKbdGroups,
3387                                 client->swapped);
3388        }
3389        if (which&XkbKeyNamesMask) {
3390            for (i=0;i<rep->nKeys;i++,desc+= sizeof(XkbKeyNameRec)) {
3391                *((XkbKeyNamePtr)desc)= xkb->names->keys[i+rep->firstKey];
3392            }
3393        }
3394        if (which&XkbKeyAliasesMask) {
3395            XkbKeyAliasPtr	pAl;
3396            pAl= xkb->names->key_aliases;
3397            for (i=0;i<rep->nKeyAliases;i++,pAl++,desc+=2*XkbKeyNameLength) {
3398                *((XkbKeyAliasPtr)desc)= *pAl;
3399            }
3400        }
3401        if ((which&XkbRGNamesMask)&&(rep->nRadioGroups>0)) {
3402            register CARD32	*atm= (CARD32 *)desc;
3403            for (i=0;i<rep->nRadioGroups;i++,atm++) {
3404                *atm= (CARD32)xkb->names->radio_groups[i];
3405                if (client->swapped) {
3406                    swapl(atm,n);
3407                }
3408            }
3409            desc+= rep->nRadioGroups*4;
3410        }
3411    }
3412
3413    if ((desc-start)!=(length)) {
3414	ErrorF("BOGUS LENGTH in write names, expected %d, got %ld\n",
3415					length, (unsigned long)(desc-start));
3416    }
3417    WriteToClient(client, SIZEOF(xkbGetNamesReply), (char *)rep);
3418    WriteToClient(client, length, start);
3419    DEALLOCATE_LOCAL((char *)start);
3420    return client->noClientException;
3421}
3422
3423int
3424ProcXkbGetNames(ClientPtr client)
3425{
3426    DeviceIntPtr	dev;
3427    XkbDescPtr		xkb;
3428    xkbGetNamesReply 	rep;
3429
3430    REQUEST(xkbGetNamesReq);
3431    REQUEST_SIZE_MATCH(xkbGetNamesReq);
3432
3433    if (!(client->xkbClientFlags&_XkbClientInitialized))
3434	return BadAccess;
3435
3436    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
3437    CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask);
3438
3439    xkb = dev->key->xkbInfo->desc;
3440    rep.type= X_Reply;
3441    rep.sequenceNumber= client->sequence;
3442    rep.length = 0;
3443    rep.deviceID = dev->id;
3444    rep.which = stuff->which;
3445    rep.nTypes = xkb->map->num_types;
3446    rep.firstKey = xkb->min_key_code;
3447    rep.nKeys = XkbNumKeys(xkb);
3448    if (xkb->names!=NULL) {
3449	rep.nKeyAliases= xkb->names->num_key_aliases;
3450	rep.nRadioGroups = xkb->names->num_rg;
3451    }
3452    else {
3453	rep.nKeyAliases= rep.nRadioGroups= 0;
3454    }
3455    XkbComputeGetNamesReplySize(xkb,&rep);
3456    return XkbSendNames(client,xkb,&rep);
3457}
3458
3459/***====================================================================***/
3460
3461static CARD32 *
3462_XkbCheckAtoms(CARD32 *wire,int nAtoms,int swapped,Atom *pError)
3463{
3464register int i;
3465
3466    for (i=0;i<nAtoms;i++,wire++) {
3467	if (swapped) {
3468	    register int n;
3469	    swapl(wire,n);
3470	}
3471	if ((((Atom)*wire)!=None)&&(!ValidAtom((Atom)*wire))) {
3472	    *pError= ((Atom)*wire);
3473	    return NULL;
3474	}
3475    }
3476    return wire;
3477}
3478
3479static CARD32 *
3480_XkbCheckMaskedAtoms(CARD32 *wire,int nAtoms,CARD32 present,int swapped,
3481								Atom *pError)
3482{
3483register unsigned i,bit;
3484
3485    for (i=0,bit=1;(i<nAtoms)&&(present);i++,bit<<=1) {
3486	if ((present&bit)==0)
3487	    continue;
3488	if (swapped) {
3489	    register int n;
3490	    swapl(wire,n);
3491	}
3492	if ((((Atom)*wire)!=None)&&(!ValidAtom(((Atom)*wire)))) {
3493	    *pError= (Atom)*wire;
3494	    return NULL;
3495	}
3496	wire++;
3497    }
3498    return wire;
3499}
3500
3501static Atom *
3502_XkbCopyMaskedAtoms(	Atom	*wire,
3503    			Atom	*dest,
3504			int   	 nAtoms,
3505			CARD32	 present)
3506{
3507register int i,bit;
3508
3509    for (i=0,bit=1;(i<nAtoms)&&(present);i++,bit<<=1) {
3510	if ((present&bit)==0)
3511	    continue;
3512	dest[i]= *wire++;
3513    }
3514    return wire;
3515}
3516
3517static Bool
3518_XkbCheckTypeName(Atom name,int typeNdx)
3519{
3520char *	str;
3521
3522    str= NameForAtom(name);
3523    if ((strcmp(str,"ONE_LEVEL")==0)||(strcmp(str,"TWO_LEVEL")==0)||
3524	(strcmp(str,"ALPHABETIC")==0)||(strcmp(str,"KEYPAD")==0))
3525	return False;
3526    return True;
3527}
3528
3529/* FIXME: Needs to set names on all core-sending devices. */
3530int
3531ProcXkbSetNames(ClientPtr client)
3532{
3533    DeviceIntPtr	 dev;
3534    XkbDescRec		*xkb;
3535    XkbNamesRec		*names;
3536    xkbNamesNotify	 nn;
3537    CARD32		*tmp;
3538    Atom		 bad;
3539
3540    REQUEST(xkbSetNamesReq);
3541    REQUEST_AT_LEAST_SIZE(xkbSetNamesReq);
3542
3543    if (!(client->xkbClientFlags&_XkbClientInitialized))
3544	return BadAccess;
3545
3546    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
3547    CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask);
3548
3549    xkb = dev->key->xkbInfo->desc;
3550    names = xkb->names;
3551    tmp = (CARD32 *)&stuff[1];
3552
3553    if (stuff->which&XkbKeycodesNameMask) {
3554	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
3555	if (!tmp) {
3556	    client->errorValue = bad;
3557	    return BadAtom;
3558	}
3559    }
3560    if (stuff->which&XkbGeometryNameMask) {
3561	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
3562	if (!tmp) {
3563	    client->errorValue = bad;
3564	    return BadAtom;
3565	}
3566    }
3567    if (stuff->which&XkbSymbolsNameMask) {
3568	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
3569	if (!tmp) {
3570	    client->errorValue = bad;
3571	    return BadAtom;
3572	}
3573    }
3574    if (stuff->which&XkbPhysSymbolsNameMask) {
3575	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
3576	if (!tmp) {
3577	    client->errorValue= bad;
3578	    return BadAtom;
3579	}
3580    }
3581    if (stuff->which&XkbTypesNameMask) {
3582	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
3583	if (!tmp) {
3584	    client->errorValue = bad;
3585	    return BadAtom;
3586	}
3587    }
3588    if (stuff->which&XkbCompatNameMask) {
3589	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
3590	if (!tmp) {
3591	    client->errorValue = bad;
3592	    return BadAtom;
3593	}
3594    }
3595    if (stuff->which&XkbKeyTypeNamesMask) {
3596	register int i;
3597	CARD32	*old;
3598	if ( stuff->nTypes<1 ) {
3599	    client->errorValue = _XkbErrCode2(0x02,stuff->nTypes);
3600	    return BadValue;
3601	}
3602	if ((unsigned)(stuff->firstType+stuff->nTypes-1)>=xkb->map->num_types) {
3603	    client->errorValue = _XkbErrCode4(0x03,stuff->firstType,
3604							stuff->nTypes,
3605							xkb->map->num_types);
3606	    return BadValue;
3607	}
3608	if (((unsigned)stuff->firstType)<=XkbLastRequiredType) {
3609	    client->errorValue = _XkbErrCode2(0x04,stuff->firstType);
3610	    return BadAccess;
3611	}
3612	old= tmp;
3613	tmp= _XkbCheckAtoms(tmp,stuff->nTypes,client->swapped,&bad);
3614	if (!tmp) {
3615	    client->errorValue= bad;
3616	    return BadAtom;
3617	}
3618	for (i=0;i<stuff->nTypes;i++,old++) {
3619	    if (!_XkbCheckTypeName((Atom)*old,stuff->firstType+i))
3620		client->errorValue= _XkbErrCode2(0x05,i);
3621	}
3622    }
3623    if (stuff->which&XkbKTLevelNamesMask) {
3624	register unsigned i;
3625	XkbKeyTypePtr	type;
3626	CARD8 *		width;
3627	if ( stuff->nKTLevels<1 ) {
3628	    client->errorValue = _XkbErrCode2(0x05,stuff->nKTLevels);
3629	    return BadValue;
3630	}
3631	if ((unsigned)(stuff->firstKTLevel+stuff->nKTLevels-1)>=
3632							xkb->map->num_types) {
3633	    client->errorValue = _XkbErrCode4(0x06,stuff->firstKTLevel,
3634				stuff->nKTLevels,xkb->map->num_types);
3635	    return BadValue;
3636	}
3637	width = (CARD8 *)tmp;
3638	tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels));
3639	type = &xkb->map->types[stuff->firstKTLevel];
3640	for (i=0;i<stuff->nKTLevels;i++,type++) {
3641	    if (width[i]==0)
3642		continue;
3643	    else if (width[i]!=type->num_levels) {
3644		client->errorValue= _XkbErrCode4(0x07,i+stuff->firstKTLevel,
3645						type->num_levels,width[i]);
3646		return BadMatch;
3647	    }
3648	    tmp= _XkbCheckAtoms(tmp,width[i],client->swapped,&bad);
3649	    if (!tmp) {
3650		client->errorValue= bad;
3651		return BadAtom;
3652	    }
3653	}
3654    }
3655    if (stuff->which&XkbIndicatorNamesMask) {
3656	if (stuff->indicators==0) {
3657	    client->errorValue= 0x08;
3658	    return BadMatch;
3659	}
3660	tmp= _XkbCheckMaskedAtoms(tmp,XkbNumIndicators,stuff->indicators,
3661							client->swapped,&bad);
3662	if (!tmp) {
3663	    client->errorValue= bad;
3664	    return BadAtom;
3665	}
3666    }
3667    if (stuff->which&XkbVirtualModNamesMask) {
3668	if (stuff->virtualMods==0) {
3669	    client->errorValue= 0x09;
3670	    return BadMatch;
3671	}
3672	tmp= _XkbCheckMaskedAtoms(tmp,XkbNumVirtualMods,
3673						(CARD32)stuff->virtualMods,
3674						client->swapped,&bad);
3675	if (!tmp) {
3676	    client->errorValue = bad;
3677	    return BadAtom;
3678	}
3679    }
3680    if (stuff->which&XkbGroupNamesMask) {
3681	if (stuff->groupNames==0) {
3682	    client->errorValue= 0x0a;
3683	    return BadMatch;
3684	}
3685	tmp= _XkbCheckMaskedAtoms(tmp,XkbNumKbdGroups,
3686						(CARD32)stuff->groupNames,
3687						client->swapped,&bad);
3688	if (!tmp) {
3689	    client->errorValue = bad;
3690	    return BadAtom;
3691	}
3692    }
3693    if (stuff->which&XkbKeyNamesMask) {
3694	if (stuff->firstKey<(unsigned)xkb->min_key_code) {
3695	    client->errorValue= _XkbErrCode3(0x0b,xkb->min_key_code,
3696							stuff->firstKey);
3697	    return BadValue;
3698	}
3699	if (((unsigned)(stuff->firstKey+stuff->nKeys-1)>xkb->max_key_code)||
3700							(stuff->nKeys<1)) {
3701	    client->errorValue= _XkbErrCode4(0x0c,xkb->max_key_code,
3702						stuff->firstKey,stuff->nKeys);
3703	    return BadValue;
3704	}
3705	tmp+= stuff->nKeys;
3706    }
3707    if ((stuff->which&XkbKeyAliasesMask)&&(stuff->nKeyAliases>0)) {
3708	tmp+= stuff->nKeyAliases*2;
3709    }
3710    if (stuff->which&XkbRGNamesMask) {
3711	if ( stuff->nRadioGroups<1 ) {
3712	    client->errorValue= _XkbErrCode2(0x0d,stuff->nRadioGroups);
3713	    return BadValue;
3714	}
3715	tmp= _XkbCheckAtoms(tmp,stuff->nRadioGroups,client->swapped,&bad);
3716	if (!tmp) {
3717	    client->errorValue= bad;
3718	    return BadAtom;
3719	}
3720    }
3721    if ((tmp-((CARD32 *)stuff))!=stuff->length) {
3722	client->errorValue = stuff->length;
3723	return BadLength;
3724    }
3725    if (XkbAllocNames(xkb,stuff->which,stuff->nRadioGroups,
3726					stuff->nKeyAliases)!=Success) {
3727	return BadAlloc;
3728    }
3729
3730    /* everything is okay -- update names */
3731    bzero(&nn,sizeof(xkbNamesNotify));
3732    nn.changed= stuff->which;
3733    tmp = (CARD32 *)&stuff[1];
3734    if (stuff->which&XkbKeycodesNameMask)
3735	names->keycodes= *tmp++;
3736    if (stuff->which&XkbGeometryNameMask)
3737	names->geometry= *tmp++;
3738    if (stuff->which&XkbSymbolsNameMask)
3739	names->symbols= *tmp++;
3740    if (stuff->which&XkbPhysSymbolsNameMask)
3741	names->phys_symbols= *tmp++;
3742    if (stuff->which&XkbTypesNameMask)
3743	names->types= *tmp++;
3744    if (stuff->which&XkbCompatNameMask)
3745	names->compat= *tmp++;
3746    if ((stuff->which&XkbKeyTypeNamesMask)&&(stuff->nTypes>0)) {
3747	register unsigned i;
3748	register XkbKeyTypePtr type;
3749
3750	type= &xkb->map->types[stuff->firstType];
3751	for (i=0;i<stuff->nTypes;i++,type++) {
3752	    type->name= *tmp++;
3753	}
3754	nn.firstType= stuff->firstType;
3755	nn.nTypes= stuff->nTypes;
3756    }
3757    if (stuff->which&XkbKTLevelNamesMask) {
3758	register XkbKeyTypePtr	type;
3759	register unsigned i;
3760	CARD8 *width;
3761
3762	width = (CARD8 *)tmp;
3763	tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels));
3764	type= &xkb->map->types[stuff->firstKTLevel];
3765	for (i=0;i<stuff->nKTLevels;i++,type++) {
3766	    if (width[i]>0) {
3767		if (type->level_names) {
3768		    register unsigned n;
3769		    for (n=0;n<width[i];n++) {
3770			type->level_names[n]= tmp[n];
3771		    }
3772		}
3773		tmp+= width[i];
3774	    }
3775	}
3776	nn.firstLevelName= 0;
3777	nn.nLevelNames= stuff->nTypes;
3778    }
3779    if (stuff->which&XkbIndicatorNamesMask) {
3780	tmp= _XkbCopyMaskedAtoms(tmp,names->indicators,XkbNumIndicators,
3781							stuff->indicators);
3782	nn.changedIndicators= stuff->indicators;
3783    }
3784    if (stuff->which&XkbVirtualModNamesMask) {
3785	tmp= _XkbCopyMaskedAtoms(tmp,names->vmods,XkbNumVirtualMods,
3786							stuff->virtualMods);
3787	nn.changedVirtualMods= stuff->virtualMods;
3788    }
3789    if (stuff->which&XkbGroupNamesMask) {
3790	tmp= _XkbCopyMaskedAtoms(tmp,names->groups,XkbNumKbdGroups,
3791							stuff->groupNames);
3792	nn.changedVirtualMods= stuff->groupNames;
3793    }
3794    if (stuff->which&XkbKeyNamesMask) {
3795	memcpy((char*)&names->keys[stuff->firstKey],(char *)tmp,
3796						stuff->nKeys*XkbKeyNameLength);
3797	tmp+= stuff->nKeys;
3798	nn.firstKey= stuff->firstKey;
3799	nn.nKeys= stuff->nKeys;
3800    }
3801    if (stuff->which&XkbKeyAliasesMask) {
3802	if (stuff->nKeyAliases>0) {
3803	    register int na= stuff->nKeyAliases;
3804	    if (XkbAllocNames(xkb,XkbKeyAliasesMask,0,na)!=Success)
3805		return BadAlloc;
3806	    memcpy((char *)names->key_aliases,(char *)tmp,
3807				stuff->nKeyAliases*sizeof(XkbKeyAliasRec));
3808	    tmp+= stuff->nKeyAliases*2;
3809	}
3810	else if (names->key_aliases!=NULL) {
3811	    _XkbFree(names->key_aliases);
3812	    names->key_aliases= NULL;
3813	    names->num_key_aliases= 0;
3814	}
3815	nn.nAliases= names->num_key_aliases;
3816    }
3817    if (stuff->which&XkbRGNamesMask) {
3818	if (stuff->nRadioGroups>0) {
3819	    register unsigned i,nrg;
3820	    nrg= stuff->nRadioGroups;
3821	    if (XkbAllocNames(xkb,XkbRGNamesMask,nrg,0)!=Success)
3822		return BadAlloc;
3823
3824	    for (i=0;i<stuff->nRadioGroups;i++) {
3825		names->radio_groups[i]= tmp[i];
3826	    }
3827	    tmp+= stuff->nRadioGroups;
3828	}
3829	else if (names->radio_groups) {
3830	    _XkbFree(names->radio_groups);
3831	    names->radio_groups= NULL;
3832	    names->num_rg= 0;
3833	}
3834	nn.nRadioGroups= names->num_rg;
3835    }
3836    if (nn.changed) {
3837	Bool needExtEvent;
3838	needExtEvent= (nn.changed&XkbIndicatorNamesMask)!=0;
3839	XkbSendNamesNotify(dev,&nn);
3840	if (needExtEvent) {
3841	    XkbSrvLedInfoPtr		sli;
3842	    xkbExtensionDeviceNotify	edev;
3843	    register int		i;
3844	    register unsigned		bit;
3845
3846	    sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,
3847							XkbXI_IndicatorsMask);
3848	    sli->namesPresent= 0;
3849	    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
3850		if (names->indicators[i]!=None)
3851		    sli->namesPresent|= bit;
3852	    }
3853	    bzero(&edev,sizeof(xkbExtensionDeviceNotify));
3854	    edev.reason=	XkbXI_IndicatorNamesMask;
3855	    edev.ledClass=	KbdFeedbackClass;
3856	    edev.ledID=		dev->kbdfeed->ctrl.id;
3857	    edev.ledsDefined= 	sli->namesPresent|sli->mapsPresent;
3858	    edev.ledState=	sli->effectiveState;
3859	    edev.firstBtn=	0;
3860	    edev.nBtns=		0;
3861	    edev.supported=	XkbXI_AllFeaturesMask;
3862	    edev.unsupported=	0;
3863	    XkbSendExtensionDeviceNotify(dev,client,&edev);
3864	}
3865    }
3866    return client->noClientException;
3867}
3868
3869/***====================================================================***/
3870
3871#include <X11/extensions/XKBgeom.h>
3872
3873#define	XkbSizeCountedString(s)  ((s)?((((2+strlen(s))+3)/4)*4):4)
3874
3875static char *
3876XkbWriteCountedString(char *wire,char *str,Bool swap)
3877{
3878CARD16	len,*pLen;
3879
3880    len= (str?strlen(str):0);
3881    pLen= (CARD16 *)wire;
3882    *pLen= len;
3883    if (swap) {
3884	register int n;
3885	swaps(pLen,n);
3886    }
3887    memcpy(&wire[2],str,len);
3888    wire+= ((2+len+3)/4)*4;
3889    return wire;
3890}
3891
3892static int
3893XkbSizeGeomProperties(XkbGeometryPtr geom)
3894{
3895register int 	i,size;
3896XkbPropertyPtr	prop;
3897
3898    for (size=i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
3899	size+= XkbSizeCountedString(prop->name);
3900	size+= XkbSizeCountedString(prop->value);
3901    }
3902    return size;
3903}
3904
3905static char *
3906XkbWriteGeomProperties(char *wire,XkbGeometryPtr geom,Bool swap)
3907{
3908register int 	i;
3909register XkbPropertyPtr	prop;
3910
3911    for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
3912	wire= XkbWriteCountedString(wire,prop->name,swap);
3913	wire= XkbWriteCountedString(wire,prop->value,swap);
3914    }
3915    return wire;
3916}
3917
3918static int
3919XkbSizeGeomKeyAliases(XkbGeometryPtr geom)
3920{
3921    return geom->num_key_aliases*(2*XkbKeyNameLength);
3922}
3923
3924static char *
3925XkbWriteGeomKeyAliases(char *wire,XkbGeometryPtr geom,Bool swap)
3926{
3927register int sz;
3928
3929    sz= geom->num_key_aliases*(XkbKeyNameLength*2);
3930    if (sz>0) {
3931	memcpy(wire,(char *)geom->key_aliases,sz);
3932	wire+= sz;
3933    }
3934    return wire;
3935}
3936
3937static int
3938XkbSizeGeomColors(XkbGeometryPtr geom)
3939{
3940register int 		i,size;
3941register XkbColorPtr	color;
3942
3943    for (i=size=0,color=geom->colors;i<geom->num_colors;i++,color++) {
3944	size+= XkbSizeCountedString(color->spec);
3945    }
3946    return size;
3947}
3948
3949static char *
3950XkbWriteGeomColors(char *wire,XkbGeometryPtr geom,Bool swap)
3951{
3952register int		i;
3953register XkbColorPtr	color;
3954
3955    for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) {
3956	wire= XkbWriteCountedString(wire,color->spec,swap);
3957    }
3958    return wire;
3959}
3960
3961static int
3962XkbSizeGeomShapes(XkbGeometryPtr geom)
3963{
3964register int		i,size;
3965register XkbShapePtr	shape;
3966
3967    for (i=size=0,shape=geom->shapes;i<geom->num_shapes;i++,shape++) {
3968	register int		n;
3969	register XkbOutlinePtr	ol;
3970	size+= SIZEOF(xkbShapeWireDesc);
3971	for (n=0,ol=shape->outlines;n<shape->num_outlines;n++,ol++) {
3972	    size+= SIZEOF(xkbOutlineWireDesc);
3973	    size+= ol->num_points*SIZEOF(xkbPointWireDesc);
3974	}
3975    }
3976    return size;
3977}
3978
3979static char *
3980XkbWriteGeomShapes(char *wire,XkbGeometryPtr geom,Bool swap)
3981{
3982int			i;
3983XkbShapePtr		shape;
3984xkbShapeWireDesc *	shapeWire;
3985
3986    for (i=0,shape=geom->shapes;i<geom->num_shapes;i++,shape++) {
3987	register int 		o;
3988	XkbOutlinePtr		ol;
3989	xkbOutlineWireDesc *	olWire;
3990	shapeWire= (xkbShapeWireDesc *)wire;
3991	shapeWire->name= shape->name;
3992	shapeWire->nOutlines= shape->num_outlines;
3993	if (shape->primary!=NULL)
3994	     shapeWire->primaryNdx= XkbOutlineIndex(shape,shape->primary);
3995	else shapeWire->primaryNdx= XkbNoShape;
3996	if (shape->approx!=NULL)
3997	     shapeWire->approxNdx= XkbOutlineIndex(shape,shape->approx);
3998	else shapeWire->approxNdx= XkbNoShape;
3999	if (swap) {
4000	    register int n;
4001	    swapl(&shapeWire->name,n);
4002	}
4003	wire= (char *)&shapeWire[1];
4004	for (o=0,ol=shape->outlines;o<shape->num_outlines;o++,ol++) {
4005	    register int	p;
4006	    XkbPointPtr		pt;
4007	    xkbPointWireDesc *	ptWire;
4008	    olWire= (xkbOutlineWireDesc *)wire;
4009	    olWire->nPoints= ol->num_points;
4010	    olWire->cornerRadius= ol->corner_radius;
4011	    wire= (char *)&olWire[1];
4012	    ptWire= (xkbPointWireDesc *)wire;
4013	    for (p=0,pt=ol->points;p<ol->num_points;p++,pt++) {
4014		ptWire[p].x= pt->x;
4015		ptWire[p].y= pt->y;
4016		if (swap) {
4017		    register int n;
4018		    swaps(&ptWire[p].x,n);
4019		    swaps(&ptWire[p].y,n);
4020		}
4021	    }
4022	    wire= (char *)&ptWire[ol->num_points];
4023	}
4024    }
4025    return wire;
4026}
4027
4028static int
4029XkbSizeGeomDoodads(int num_doodads,XkbDoodadPtr doodad)
4030{
4031register int	i,size;
4032
4033    for (i=size=0;i<num_doodads;i++,doodad++) {
4034	size+= SIZEOF(xkbAnyDoodadWireDesc);
4035	if (doodad->any.type==XkbTextDoodad) {
4036	    size+= XkbSizeCountedString(doodad->text.text);
4037	    size+= XkbSizeCountedString(doodad->text.font);
4038	}
4039	else if (doodad->any.type==XkbLogoDoodad) {
4040	    size+= XkbSizeCountedString(doodad->logo.logo_name);
4041	}
4042    }
4043    return size;
4044}
4045
4046static char *
4047XkbWriteGeomDoodads(char *wire,int num_doodads,XkbDoodadPtr doodad,Bool swap)
4048{
4049register int		i;
4050xkbDoodadWireDesc *	doodadWire;
4051
4052    for (i=0;i<num_doodads;i++,doodad++) {
4053	doodadWire= (xkbDoodadWireDesc *)wire;
4054	wire= (char *)&doodadWire[1];
4055	bzero(doodadWire,SIZEOF(xkbDoodadWireDesc));
4056	doodadWire->any.name= doodad->any.name;
4057	doodadWire->any.type= doodad->any.type;
4058	doodadWire->any.priority= doodad->any.priority;
4059	doodadWire->any.top= doodad->any.top;
4060	doodadWire->any.left= doodad->any.left;
4061	if (swap) {
4062	    register int n;
4063	    swapl(&doodadWire->any.name,n);
4064	    swaps(&doodadWire->any.top,n);
4065	    swaps(&doodadWire->any.left,n);
4066	}
4067	switch (doodad->any.type) {
4068	    case XkbOutlineDoodad:
4069	    case XkbSolidDoodad:
4070		doodadWire->shape.angle= doodad->shape.angle;
4071		doodadWire->shape.colorNdx= doodad->shape.color_ndx;
4072		doodadWire->shape.shapeNdx= doodad->shape.shape_ndx;
4073		if (swap) {
4074		    register int n;
4075		    swaps(&doodadWire->shape.angle,n);
4076		}
4077		break;
4078	    case XkbTextDoodad:
4079		doodadWire->text.angle= doodad->text.angle;
4080		doodadWire->text.width= doodad->text.width;
4081		doodadWire->text.height= doodad->text.height;
4082		doodadWire->text.colorNdx= doodad->text.color_ndx;
4083		if (swap) {
4084		    register int n;
4085		    swaps(&doodadWire->text.angle,n);
4086		    swaps(&doodadWire->text.width,n);
4087		    swaps(&doodadWire->text.height,n);
4088		}
4089		wire= XkbWriteCountedString(wire,doodad->text.text,swap);
4090		wire= XkbWriteCountedString(wire,doodad->text.font,swap);
4091		break;
4092	    case XkbIndicatorDoodad:
4093		doodadWire->indicator.shapeNdx= doodad->indicator.shape_ndx;
4094		doodadWire->indicator.onColorNdx=doodad->indicator.on_color_ndx;
4095		doodadWire->indicator.offColorNdx=
4096						doodad->indicator.off_color_ndx;
4097		break;
4098	    case XkbLogoDoodad:
4099		doodadWire->logo.angle= doodad->logo.angle;
4100		doodadWire->logo.colorNdx= doodad->logo.color_ndx;
4101		doodadWire->logo.shapeNdx= doodad->logo.shape_ndx;
4102		wire= XkbWriteCountedString(wire,doodad->logo.logo_name,swap);
4103		break;
4104	    default:
4105		ErrorF("Unknown doodad type %d in XkbWriteGeomDoodads\n",
4106			doodad->any.type);
4107		ErrorF("Ignored\n");
4108		break;
4109	}
4110    }
4111    return wire;
4112}
4113
4114static char *
4115XkbWriteGeomOverlay(char *wire,XkbOverlayPtr ol,Bool swap)
4116{
4117register int		r;
4118XkbOverlayRowPtr	row;
4119xkbOverlayWireDesc *	olWire;
4120
4121   olWire= (xkbOverlayWireDesc *)wire;
4122   olWire->name= ol->name;
4123   olWire->nRows= ol->num_rows;
4124   if (swap) {
4125	register int n;
4126	swapl(&olWire->name,n);
4127   }
4128   wire= (char *)&olWire[1];
4129   for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
4130   	unsigned int		k;
4131	XkbOverlayKeyPtr	key;
4132	xkbOverlayRowWireDesc *	rowWire;
4133	rowWire= (xkbOverlayRowWireDesc *)wire;
4134	rowWire->rowUnder= row->row_under;
4135	rowWire->nKeys= row->num_keys;
4136	wire= (char *)&rowWire[1];
4137	for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
4138	    xkbOverlayKeyWireDesc *	keyWire;
4139	    keyWire= (xkbOverlayKeyWireDesc *)wire;
4140	    memcpy(keyWire->over,key->over.name,XkbKeyNameLength);
4141	    memcpy(keyWire->under,key->under.name,XkbKeyNameLength);
4142	    wire= (char *)&keyWire[1];
4143	}
4144   }
4145   return wire;
4146}
4147
4148static int
4149XkbSizeGeomSections(XkbGeometryPtr geom)
4150{
4151register int 	i,size;
4152XkbSectionPtr	section;
4153
4154    for (i=size=0,section=geom->sections;i<geom->num_sections;i++,section++) {
4155	size+= SIZEOF(xkbSectionWireDesc);
4156	if (section->rows) {
4157	    int		r;
4158	    XkbRowPtr	row;
4159	    for (r=0,row=section->rows;r<section->num_rows;row++,r++) {
4160		size+= SIZEOF(xkbRowWireDesc);
4161		size+= row->num_keys*SIZEOF(xkbKeyWireDesc);
4162	    }
4163	}
4164	if (section->doodads)
4165	    size+= XkbSizeGeomDoodads(section->num_doodads,section->doodads);
4166	if (section->overlays) {
4167	    int			o;
4168	    XkbOverlayPtr	ol;
4169	    for (o=0,ol=section->overlays;o<section->num_overlays;o++,ol++) {
4170		int			r;
4171		XkbOverlayRowPtr	row;
4172		size+= SIZEOF(xkbOverlayWireDesc);
4173		for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
4174		   size+= SIZEOF(xkbOverlayRowWireDesc);
4175		   size+= row->num_keys*SIZEOF(xkbOverlayKeyWireDesc);
4176		}
4177	    }
4178	}
4179    }
4180    return size;
4181}
4182
4183static char *
4184XkbWriteGeomSections(char *wire,XkbGeometryPtr geom,Bool swap)
4185{
4186register int		i;
4187XkbSectionPtr		section;
4188xkbSectionWireDesc *	sectionWire;
4189
4190    for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) {
4191	sectionWire= (xkbSectionWireDesc *)wire;
4192	sectionWire->name= section->name;
4193	sectionWire->top= section->top;
4194	sectionWire->left= section->left;
4195	sectionWire->width= section->width;
4196	sectionWire->height= section->height;
4197	sectionWire->angle= section->angle;
4198	sectionWire->priority= section->priority;
4199	sectionWire->nRows= section->num_rows;
4200	sectionWire->nDoodads= section->num_doodads;
4201	sectionWire->nOverlays= section->num_overlays;
4202	sectionWire->pad= 0;
4203	if (swap) {
4204	    register int n;
4205	    swapl(&sectionWire->name,n);
4206	    swaps(&sectionWire->top,n);
4207	    swaps(&sectionWire->left,n);
4208	    swaps(&sectionWire->width,n);
4209	    swaps(&sectionWire->height,n);
4210	    swaps(&sectionWire->angle,n);
4211	}
4212	wire= (char *)&sectionWire[1];
4213	if (section->rows) {
4214	    int			r;
4215	    XkbRowPtr		row;
4216	    xkbRowWireDesc *	rowWire;
4217	    for (r=0,row=section->rows;r<section->num_rows;r++,row++) {
4218		rowWire= (xkbRowWireDesc *)wire;
4219		rowWire->top= row->top;
4220		rowWire->left= row->left;
4221		rowWire->nKeys= row->num_keys;
4222		rowWire->vertical= row->vertical;
4223		rowWire->pad= 0;
4224		if (swap) {
4225		    register int n;
4226		    swaps(&rowWire->top,n);
4227		    swaps(&rowWire->left,n);
4228		}
4229		wire= (char *)&rowWire[1];
4230		if (row->keys) {
4231		    int			k;
4232		    XkbKeyPtr		key;
4233		    xkbKeyWireDesc *	keyWire;
4234		    keyWire= (xkbKeyWireDesc *)wire;
4235		    for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
4236			memcpy(keyWire[k].name,key->name.name,XkbKeyNameLength);
4237			keyWire[k].gap= key->gap;
4238			keyWire[k].shapeNdx= key->shape_ndx;
4239			keyWire[k].colorNdx= key->color_ndx;
4240			if (swap) {
4241			    register int n;
4242			    swaps(&keyWire[k].gap,n);
4243			}
4244		    }
4245		    wire= (char *)&keyWire[row->num_keys];
4246		}
4247	    }
4248	}
4249	if (section->doodads) {
4250	    wire= XkbWriteGeomDoodads(wire,
4251	    			      section->num_doodads,section->doodads,
4252				      swap);
4253	}
4254	if (section->overlays) {
4255	    register int o;
4256	    for (o=0;o<section->num_overlays;o++) {
4257		wire= XkbWriteGeomOverlay(wire,&section->overlays[o],swap);
4258	    }
4259	}
4260    }
4261    return wire;
4262}
4263
4264static Status
4265XkbComputeGetGeometryReplySize(	XkbGeometryPtr		geom,
4266				xkbGetGeometryReply *	rep,
4267				Atom			name)
4268{
4269int	len;
4270
4271    if (geom!=NULL) {
4272	len= XkbSizeCountedString(geom->label_font);
4273	len+= XkbSizeGeomProperties(geom);
4274	len+= XkbSizeGeomColors(geom);
4275	len+= XkbSizeGeomShapes(geom);
4276	len+= XkbSizeGeomSections(geom);
4277	len+= XkbSizeGeomDoodads(geom->num_doodads,geom->doodads);
4278	len+= XkbSizeGeomKeyAliases(geom);
4279	rep->length= len/4;
4280	rep->found= True;
4281	rep->name= geom->name;
4282	rep->widthMM= geom->width_mm;
4283	rep->heightMM= geom->height_mm;
4284	rep->nProperties= geom->num_properties;
4285	rep->nColors= geom->num_colors;
4286	rep->nShapes= geom->num_shapes;
4287	rep->nSections= geom->num_sections;
4288	rep->nDoodads= geom->num_doodads;
4289	rep->nKeyAliases= geom->num_key_aliases;
4290	rep->baseColorNdx= XkbGeomColorIndex(geom,geom->base_color);
4291	rep->labelColorNdx= XkbGeomColorIndex(geom,geom->label_color);
4292    }
4293    else {
4294	rep->length= 0;
4295	rep->found= False;
4296	rep->name= name;
4297	rep->widthMM= rep->heightMM= 0;
4298	rep->nProperties= rep->nColors= rep->nShapes= 0;
4299	rep->nSections= rep->nDoodads= 0;
4300	rep->nKeyAliases= 0;
4301	rep->labelColorNdx= rep->baseColorNdx= 0;
4302    }
4303    return Success;
4304}
4305
4306static int
4307XkbSendGeometry(	ClientPtr		client,
4308			XkbGeometryPtr		geom,
4309			xkbGetGeometryReply *	rep,
4310			Bool			freeGeom)
4311{
4312    char	*desc,*start;
4313    int		 len;
4314
4315    if (geom!=NULL) {
4316	len= rep->length*4;
4317	start= desc= (char *)ALLOCATE_LOCAL(len);
4318	if (!start)
4319	    return BadAlloc;
4320	desc=  XkbWriteCountedString(desc,geom->label_font,client->swapped);
4321	if ( rep->nProperties>0 )
4322	    desc = XkbWriteGeomProperties(desc,geom,client->swapped);
4323	if ( rep->nColors>0 )
4324	    desc = XkbWriteGeomColors(desc,geom,client->swapped);
4325	if ( rep->nShapes>0 )
4326	    desc = XkbWriteGeomShapes(desc,geom,client->swapped);
4327	if ( rep->nSections>0 )
4328	    desc = XkbWriteGeomSections(desc,geom,client->swapped);
4329	if ( rep->nDoodads>0 )
4330	    desc = XkbWriteGeomDoodads(desc,geom->num_doodads,geom->doodads,
4331							  client->swapped);
4332	if ( rep->nKeyAliases>0 )
4333	    desc = XkbWriteGeomKeyAliases(desc,geom,client->swapped);
4334	if ((desc-start)!=(len)) {
4335	    ErrorF("BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n",
4336			len, (unsigned long)(desc-start));
4337	}
4338    }
4339    else {
4340	len= 0;
4341	start= NULL;
4342    }
4343    if (client->swapped) {
4344	register int n;
4345	swaps(&rep->sequenceNumber,n);
4346	swapl(&rep->length,n);
4347	swapl(&rep->name,n);
4348	swaps(&rep->widthMM,n);
4349	swaps(&rep->heightMM,n);
4350	swaps(&rep->nProperties,n);
4351	swaps(&rep->nColors,n);
4352	swaps(&rep->nShapes,n);
4353	swaps(&rep->nSections,n);
4354	swaps(&rep->nDoodads,n);
4355	swaps(&rep->nKeyAliases,n);
4356    }
4357    WriteToClient(client, SIZEOF(xkbGetGeometryReply), (char *)rep);
4358    if (len>0)
4359	WriteToClient(client, len, start);
4360    if (start!=NULL)
4361	DEALLOCATE_LOCAL((char *)start);
4362    if (freeGeom)
4363	XkbFreeGeometry(geom,XkbGeomAllMask,True);
4364    return client->noClientException;
4365}
4366
4367int
4368ProcXkbGetGeometry(ClientPtr client)
4369{
4370    DeviceIntPtr 	dev;
4371    xkbGetGeometryReply rep;
4372    XkbGeometryPtr	geom;
4373    Bool		shouldFree;
4374    Status		status;
4375
4376    REQUEST(xkbGetGeometryReq);
4377    REQUEST_SIZE_MATCH(xkbGetGeometryReq);
4378
4379    if (!(client->xkbClientFlags&_XkbClientInitialized))
4380	return BadAccess;
4381
4382    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
4383    CHK_ATOM_OR_NONE(stuff->name);
4384
4385    geom= XkbLookupNamedGeometry(dev,stuff->name,&shouldFree);
4386    rep.type= X_Reply;
4387    rep.deviceID= dev->id;
4388    rep.sequenceNumber= client->sequence;
4389    rep.length= 0;
4390    status= XkbComputeGetGeometryReplySize(geom,&rep,stuff->name);
4391    if (status!=Success)
4392	 return status;
4393    else return XkbSendGeometry(client,geom,&rep,shouldFree);
4394}
4395
4396/***====================================================================***/
4397
4398static char *
4399_GetCountedString(char **wire_inout,Bool swap)
4400{
4401char *	wire,*str;
4402CARD16	len,*plen;
4403
4404    wire= *wire_inout;
4405    plen= (CARD16 *)wire;
4406    if (swap) {
4407	register int n;
4408	swaps(plen,n);
4409    }
4410    len= *plen;
4411    str= (char *)_XkbAlloc(len+1);
4412    if (str) {
4413	memcpy(str,&wire[2],len);
4414	str[len]= '\0';
4415    }
4416    wire+= XkbPaddedSize(len+2);
4417    *wire_inout= wire;
4418    return str;
4419}
4420
4421static Status
4422_CheckSetDoodad(	char **		wire_inout,
4423			XkbGeometryPtr	geom,
4424			XkbSectionPtr	section,
4425			ClientPtr	client)
4426{
4427char *			wire;
4428xkbDoodadWireDesc *	dWire;
4429XkbDoodadPtr		doodad;
4430
4431    dWire= (xkbDoodadWireDesc *)(*wire_inout);
4432    wire= (char *)&dWire[1];
4433    if (client->swapped) {
4434	register int n;
4435	swapl(&dWire->any.name,n);
4436	swaps(&dWire->any.top,n);
4437	swaps(&dWire->any.left,n);
4438	swaps(&dWire->any.angle,n);
4439    }
4440    CHK_ATOM_ONLY(dWire->any.name);
4441    doodad= XkbAddGeomDoodad(geom,section,dWire->any.name);
4442    if (!doodad)
4443	return BadAlloc;
4444    doodad->any.type= dWire->any.type;
4445    doodad->any.priority= dWire->any.priority;
4446    doodad->any.top= dWire->any.top;
4447    doodad->any.left= dWire->any.left;
4448    doodad->any.angle= dWire->any.angle;
4449    switch (doodad->any.type) {
4450	case XkbOutlineDoodad:
4451	case XkbSolidDoodad:
4452	    if (dWire->shape.colorNdx>=geom->num_colors) {
4453		client->errorValue= _XkbErrCode3(0x40,geom->num_colors,
4454							dWire->shape.colorNdx);
4455		return BadMatch;
4456	    }
4457	    if (dWire->shape.shapeNdx>=geom->num_shapes) {
4458		client->errorValue= _XkbErrCode3(0x41,geom->num_shapes,
4459							dWire->shape.shapeNdx);
4460		return BadMatch;
4461	    }
4462	    doodad->shape.color_ndx= dWire->shape.colorNdx;
4463	    doodad->shape.shape_ndx= dWire->shape.shapeNdx;
4464	    break;
4465	case XkbTextDoodad:
4466	    if (dWire->text.colorNdx>=geom->num_colors) {
4467		client->errorValue= _XkbErrCode3(0x42,geom->num_colors,
4468							dWire->text.colorNdx);
4469		return BadMatch;
4470	    }
4471	    if (client->swapped) {
4472		register int n;
4473		swaps(&dWire->text.width,n);
4474		swaps(&dWire->text.height,n);
4475	    }
4476	    doodad->text.width= dWire->text.width;
4477	    doodad->text.height= dWire->text.height;
4478	    doodad->text.color_ndx= dWire->text.colorNdx;
4479	    doodad->text.text= _GetCountedString(&wire,client->swapped);
4480	    doodad->text.font= _GetCountedString(&wire,client->swapped);
4481	    break;
4482	case XkbIndicatorDoodad:
4483	    if (dWire->indicator.onColorNdx>=geom->num_colors) {
4484		client->errorValue= _XkbErrCode3(0x43,geom->num_colors,
4485						dWire->indicator.onColorNdx);
4486		return BadMatch;
4487	    }
4488	    if (dWire->indicator.offColorNdx>=geom->num_colors) {
4489		client->errorValue= _XkbErrCode3(0x44,geom->num_colors,
4490						dWire->indicator.offColorNdx);
4491		return BadMatch;
4492	    }
4493	    if (dWire->indicator.shapeNdx>=geom->num_shapes) {
4494		client->errorValue= _XkbErrCode3(0x45,geom->num_shapes,
4495						dWire->indicator.shapeNdx);
4496		return BadMatch;
4497	    }
4498	    doodad->indicator.shape_ndx= dWire->indicator.shapeNdx;
4499	    doodad->indicator.on_color_ndx= dWire->indicator.onColorNdx;
4500	    doodad->indicator.off_color_ndx= dWire->indicator.offColorNdx;
4501	    break;
4502	case XkbLogoDoodad:
4503	    if (dWire->logo.colorNdx>=geom->num_colors) {
4504		client->errorValue= _XkbErrCode3(0x46,geom->num_colors,
4505							dWire->logo.colorNdx);
4506		return BadMatch;
4507	    }
4508	    if (dWire->logo.shapeNdx>=geom->num_shapes) {
4509		client->errorValue= _XkbErrCode3(0x47,geom->num_shapes,
4510							dWire->logo.shapeNdx);
4511		return BadMatch;
4512	    }
4513	    doodad->logo.color_ndx= dWire->logo.colorNdx;
4514	    doodad->logo.shape_ndx= dWire->logo.shapeNdx;
4515	    doodad->logo.logo_name= _GetCountedString(&wire,client->swapped);
4516	    break;
4517	default:
4518	    client->errorValue= _XkbErrCode2(0x4F,dWire->any.type);
4519	    return BadValue;
4520    }
4521    *wire_inout= wire;
4522    return Success;
4523}
4524
4525static Status
4526_CheckSetOverlay(	char **		wire_inout,
4527			XkbGeometryPtr	geom,
4528			XkbSectionPtr	section,
4529			ClientPtr	client)
4530{
4531register int		r;
4532char *			wire;
4533XkbOverlayPtr		ol;
4534xkbOverlayWireDesc *	olWire;
4535xkbOverlayRowWireDesc *	rWire;
4536
4537    wire= *wire_inout;
4538    olWire= (xkbOverlayWireDesc *)wire;
4539    if (client->swapped) {
4540	register int n;
4541	swapl(&olWire->name,n);
4542    }
4543    CHK_ATOM_ONLY(olWire->name);
4544    ol= XkbAddGeomOverlay(section,olWire->name,olWire->nRows);
4545    rWire= (xkbOverlayRowWireDesc *)&olWire[1];
4546    for (r=0;r<olWire->nRows;r++) {
4547	register int		k;
4548	xkbOverlayKeyWireDesc *	kWire;
4549	XkbOverlayRowPtr	row;
4550
4551	if (rWire->rowUnder>section->num_rows) {
4552	    client->errorValue= _XkbErrCode4(0x20,r,section->num_rows,
4553							rWire->rowUnder);
4554	    return BadMatch;
4555	}
4556	row= XkbAddGeomOverlayRow(ol,rWire->rowUnder,rWire->nKeys);
4557	kWire= (xkbOverlayKeyWireDesc *)&rWire[1];
4558	for (k=0;k<rWire->nKeys;k++,kWire++) {
4559	    if (XkbAddGeomOverlayKey(ol,row,
4560	    		(char *)kWire->over,(char *)kWire->under)==NULL) {
4561		client->errorValue= _XkbErrCode3(0x21,r,k);
4562		return BadMatch;
4563	    }
4564	}
4565	rWire= (xkbOverlayRowWireDesc *)kWire;
4566    }
4567    olWire= (xkbOverlayWireDesc *)rWire;
4568    wire= (char *)olWire;
4569    *wire_inout= wire;
4570    return Success;
4571}
4572
4573static Status
4574_CheckSetSections( 	XkbGeometryPtr		geom,
4575			xkbSetGeometryReq *	req,
4576			char **			wire_inout,
4577			ClientPtr		client)
4578{
4579Status			status;
4580register int		s;
4581char *			wire;
4582xkbSectionWireDesc *	sWire;
4583XkbSectionPtr		section;
4584
4585    wire= *wire_inout;
4586    if (req->nSections<1)
4587	return Success;
4588    sWire= (xkbSectionWireDesc *)wire;
4589    for (s=0;s<req->nSections;s++) {
4590	register int		r;
4591	xkbRowWireDesc *	rWire;
4592	if (client->swapped) {
4593	    register int n;
4594	    swapl(&sWire->name,n);
4595	    swaps(&sWire->top,n);
4596	    swaps(&sWire->left,n);
4597	    swaps(&sWire->width,n);
4598	    swaps(&sWire->height,n);
4599	    swaps(&sWire->angle,n);
4600	}
4601	CHK_ATOM_ONLY(sWire->name);
4602	section= XkbAddGeomSection(geom,sWire->name,sWire->nRows,
4603					sWire->nDoodads,sWire->nOverlays);
4604	if (!section)
4605	    return BadAlloc;
4606	section->priority=	sWire->priority;
4607	section->top=		sWire->top;
4608	section->left=		sWire->left;
4609	section->width=		sWire->width;
4610	section->height=	sWire->height;
4611	section->angle=		sWire->angle;
4612	rWire= (xkbRowWireDesc *)&sWire[1];
4613	for (r=0;r<sWire->nRows;r++) {
4614	    register int	k;
4615	    XkbRowPtr		row;
4616	    xkbKeyWireDesc *	kWire;
4617	    if (client->swapped) {
4618		register int n;
4619		swaps(&rWire->top,n);
4620		swaps(&rWire->left,n);
4621	    }
4622	    row= XkbAddGeomRow(section,rWire->nKeys);
4623	    if (!row)
4624		return BadAlloc;
4625	    row->top= rWire->top;
4626	    row->left= rWire->left;
4627	    row->vertical= rWire->vertical;
4628	    kWire= (xkbKeyWireDesc *)&rWire[1];
4629	    for (k=0;k<rWire->nKeys;k++) {
4630		XkbKeyPtr	key;
4631		key= XkbAddGeomKey(row);
4632		if (!key)
4633		    return BadAlloc;
4634		memcpy(key->name.name,kWire[k].name,XkbKeyNameLength);
4635		key->gap= kWire[k].gap;
4636		key->shape_ndx= kWire[k].shapeNdx;
4637		key->color_ndx= kWire[k].colorNdx;
4638		if (key->shape_ndx>=geom->num_shapes) {
4639		    client->errorValue= _XkbErrCode3(0x10,key->shape_ndx,
4640							  geom->num_shapes);
4641		    return BadMatch;
4642		}
4643		if (key->color_ndx>=geom->num_colors) {
4644		    client->errorValue= _XkbErrCode3(0x11,key->color_ndx,
4645							  geom->num_colors);
4646		    return BadMatch;
4647		}
4648	    }
4649	    rWire= (xkbRowWireDesc *)&kWire[rWire->nKeys];
4650	}
4651	wire= (char *)rWire;
4652	if (sWire->nDoodads>0) {
4653	    register int d;
4654	    for (d=0;d<sWire->nDoodads;d++) {
4655		status=_CheckSetDoodad(&wire,geom,section,client);
4656		if (status!=Success)
4657		    return status;
4658	    }
4659	}
4660	if (sWire->nOverlays>0) {
4661	    register int o;
4662	    for (o=0;o<sWire->nOverlays;o++) {
4663		status= _CheckSetOverlay(&wire,geom,section,client);
4664		if (status!=Success)
4665		    return status;
4666	    }
4667	}
4668	sWire= (xkbSectionWireDesc *)wire;
4669    }
4670    wire= (char *)sWire;
4671    *wire_inout= wire;
4672    return Success;
4673}
4674
4675static Status
4676_CheckSetShapes( 	XkbGeometryPtr		geom,
4677			xkbSetGeometryReq *	req,
4678			char **			wire_inout,
4679			ClientPtr		client)
4680{
4681register int	i;
4682char *		wire;
4683
4684    wire= *wire_inout;
4685    if (req->nShapes<1) {
4686	client->errorValue= _XkbErrCode2(0x06,req->nShapes);
4687	return BadValue;
4688    }
4689    else {
4690	xkbShapeWireDesc *	shapeWire;
4691	XkbShapePtr		shape;
4692	register int		o;
4693	shapeWire= (xkbShapeWireDesc *)wire;
4694	for (i=0;i<req->nShapes;i++) {
4695	    xkbOutlineWireDesc *	olWire;
4696	    XkbOutlinePtr		ol;
4697	    shape= XkbAddGeomShape(geom,shapeWire->name,shapeWire->nOutlines);
4698	    if (!shape)
4699		return BadAlloc;
4700	    olWire= (xkbOutlineWireDesc *)(&shapeWire[1]);
4701	    for (o=0;o<shapeWire->nOutlines;o++) {
4702		register int		p;
4703		XkbPointPtr		pt;
4704		xkbPointWireDesc *	ptWire;
4705
4706		ol= XkbAddGeomOutline(shape,olWire->nPoints);
4707		if (!ol)
4708		    return BadAlloc;
4709		ol->corner_radius=	olWire->cornerRadius;
4710		ptWire= (xkbPointWireDesc *)&olWire[1];
4711		for (p=0,pt=ol->points;p<olWire->nPoints;p++,pt++) {
4712		    pt->x= ptWire[p].x;
4713		    pt->y= ptWire[p].y;
4714		    if (client->swapped) {
4715			register int n;
4716			swaps(&pt->x,n);
4717			swaps(&pt->y,n);
4718		    }
4719		}
4720		ol->num_points= olWire->nPoints;
4721		olWire= (xkbOutlineWireDesc *)(&ptWire[olWire->nPoints]);
4722	    }
4723	    if (shapeWire->primaryNdx!=XkbNoShape)
4724		shape->primary= &shape->outlines[shapeWire->primaryNdx];
4725	    if (shapeWire->approxNdx!=XkbNoShape)
4726		shape->approx= &shape->outlines[shapeWire->approxNdx];
4727	    shapeWire= (xkbShapeWireDesc *)olWire;
4728	}
4729	wire= (char *)shapeWire;
4730    }
4731    if (geom->num_shapes!=req->nShapes) {
4732	client->errorValue= _XkbErrCode3(0x07,geom->num_shapes,req->nShapes);
4733	return BadMatch;
4734    }
4735
4736    *wire_inout= wire;
4737    return Success;
4738}
4739
4740static Status
4741_CheckSetGeom(	XkbGeometryPtr		geom,
4742		xkbSetGeometryReq *	req,
4743		ClientPtr 		client)
4744{
4745register int	i;
4746Status		status;
4747char *		wire;
4748
4749    wire= (char *)&req[1];
4750    geom->label_font= _GetCountedString(&wire,client->swapped);
4751
4752    for (i=0;i<req->nProperties;i++) {
4753	char *name,*val;
4754	name= _GetCountedString(&wire,client->swapped);
4755        if (!name)
4756            return BadAlloc;
4757	val= _GetCountedString(&wire,client->swapped);
4758        if (!val) {
4759            xfree(name);
4760            return BadAlloc;
4761        }
4762	if (XkbAddGeomProperty(geom,name,val)==NULL) {
4763            xfree(name);
4764            xfree(val);
4765	    return BadAlloc;
4766        }
4767        xfree(name);
4768        xfree(val);
4769    }
4770
4771    if (req->nColors<2) {
4772	client->errorValue= _XkbErrCode3(0x01,2,req->nColors);
4773	return BadValue;
4774    }
4775    if (req->baseColorNdx>req->nColors) {
4776	client->errorValue=_XkbErrCode3(0x03,req->nColors,req->baseColorNdx);
4777	return BadMatch;
4778    }
4779    if (req->labelColorNdx>req->nColors) {
4780	client->errorValue= _XkbErrCode3(0x03,req->nColors,req->labelColorNdx);
4781	return BadMatch;
4782    }
4783    if (req->labelColorNdx==req->baseColorNdx) {
4784	client->errorValue= _XkbErrCode3(0x04,req->baseColorNdx,
4785                                         req->labelColorNdx);
4786	return BadMatch;
4787    }
4788
4789    for (i=0;i<req->nColors;i++) {
4790	char *name;
4791	name= _GetCountedString(&wire,client->swapped);
4792	if (!name)
4793            return BadAlloc;
4794        if (!XkbAddGeomColor(geom,name,geom->num_colors)) {
4795            xfree(name);
4796	    return BadAlloc;
4797        }
4798        xfree(name);
4799    }
4800    if (req->nColors!=geom->num_colors) {
4801	client->errorValue= _XkbErrCode3(0x05,req->nColors,geom->num_colors);
4802	return BadMatch;
4803    }
4804    geom->label_color= &geom->colors[req->labelColorNdx];
4805    geom->base_color= &geom->colors[req->baseColorNdx];
4806
4807    if ((status=_CheckSetShapes(geom,req,&wire,client))!=Success)
4808	return status;
4809
4810    if ((status=_CheckSetSections(geom,req,&wire,client))!=Success)
4811	return status;
4812
4813    for (i=0;i<req->nDoodads;i++) {
4814	status=_CheckSetDoodad(&wire,geom,NULL,client);
4815	if (status!=Success)
4816	    return status;
4817    }
4818
4819    for (i=0;i<req->nKeyAliases;i++) {
4820	if (XkbAddGeomKeyAlias(geom,&wire[XkbKeyNameLength],wire)==NULL)
4821	    return BadAlloc;
4822	wire+= 2*XkbKeyNameLength;
4823    }
4824    return Success;
4825}
4826
4827/* FIXME: Needs to set geom on all core-sending devices. */
4828int
4829ProcXkbSetGeometry(ClientPtr client)
4830{
4831    DeviceIntPtr 	dev;
4832    XkbGeometryPtr	geom,old;
4833    XkbGeometrySizesRec	sizes;
4834    Status		status;
4835    XkbDescPtr		xkb;
4836    Bool		new_name;
4837    xkbNewKeyboardNotify	nkn;
4838
4839    REQUEST(xkbSetGeometryReq);
4840    REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq);
4841
4842    if (!(client->xkbClientFlags&_XkbClientInitialized))
4843	return BadAccess;
4844
4845    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
4846    CHK_ATOM_OR_NONE(stuff->name);
4847
4848    xkb= dev->key->xkbInfo->desc;
4849    old= xkb->geom;
4850    xkb->geom= NULL;
4851
4852    sizes.which= 		XkbGeomAllMask;
4853    sizes.num_properties=	stuff->nProperties;
4854    sizes.num_colors=	  	stuff->nColors;
4855    sizes.num_shapes=	  	stuff->nShapes;
4856    sizes.num_sections=	  	stuff->nSections;
4857    sizes.num_doodads=	  	stuff->nDoodads;
4858    sizes.num_key_aliases=	stuff->nKeyAliases;
4859    if ((status= XkbAllocGeometry(xkb,&sizes))!=Success) {
4860	xkb->geom= old;
4861	return status;
4862    }
4863    geom= xkb->geom;
4864    geom->name= stuff->name;
4865    geom->width_mm= stuff->widthMM;
4866    geom->height_mm= stuff->heightMM;
4867    if ((status= _CheckSetGeom(geom,stuff,client))!=Success) {
4868	XkbFreeGeometry(geom,XkbGeomAllMask,True);
4869	xkb->geom= old;
4870	return status;
4871    }
4872    new_name= (xkb->names->geometry!=geom->name);
4873    xkb->names->geometry= geom->name;
4874    if (old)
4875    	XkbFreeGeometry(old,XkbGeomAllMask,True);
4876    if (new_name) {
4877	xkbNamesNotify	nn;
4878	bzero(&nn,sizeof(xkbNamesNotify));
4879	nn.changed= XkbGeometryNameMask;
4880	XkbSendNamesNotify(dev,&nn);
4881    }
4882    nkn.deviceID= nkn.oldDeviceID= dev->id;
4883    nkn.minKeyCode= nkn.oldMinKeyCode= xkb->min_key_code;
4884    nkn.maxKeyCode= nkn.oldMaxKeyCode= xkb->max_key_code;
4885    nkn.requestMajor=	XkbReqCode;
4886    nkn.requestMinor=	X_kbSetGeometry;
4887    nkn.changed=	XkbNKN_GeometryMask;
4888    XkbSendNewKeyboardNotify(dev,&nkn);
4889    return Success;
4890}
4891
4892/***====================================================================***/
4893
4894int
4895ProcXkbPerClientFlags(ClientPtr client)
4896{
4897    DeviceIntPtr 		dev;
4898    xkbPerClientFlagsReply 	rep;
4899    XkbInterestPtr		interest;
4900
4901    REQUEST(xkbPerClientFlagsReq);
4902    REQUEST_SIZE_MATCH(xkbPerClientFlagsReq);
4903
4904    if (!(client->xkbClientFlags&_XkbClientInitialized))
4905	return BadAccess;
4906
4907    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
4908    CHK_MASK_LEGAL(0x01,stuff->change,XkbPCF_AllFlagsMask);
4909    CHK_MASK_MATCH(0x02,stuff->change,stuff->value);
4910
4911    interest = XkbFindClientResource((DevicePtr)dev,client);
4912    rep.type= X_Reply;
4913    rep.length = 0;
4914    rep.sequenceNumber = client->sequence;
4915    if (stuff->change) {
4916	client->xkbClientFlags&= ~stuff->change;
4917	client->xkbClientFlags|= stuff->value;
4918    }
4919    if (stuff->change&XkbPCF_AutoResetControlsMask) {
4920	Bool	want;
4921	want= stuff->value&XkbPCF_AutoResetControlsMask;
4922	if (interest && !want) {
4923	    interest->autoCtrls= interest->autoCtrlValues= 0;
4924	}
4925	else if (want && (!interest)) {
4926	    XID id = FakeClientID(client->index);
4927	    AddResource(id,RT_XKBCLIENT,dev);
4928	    interest= XkbAddClientResource((DevicePtr)dev,client,id);
4929	    if (!interest)
4930		return BadAlloc;
4931	}
4932	if (interest && want ) {
4933	    register unsigned affect;
4934	    affect= stuff->ctrlsToChange;
4935
4936	    CHK_MASK_LEGAL(0x03,affect,XkbAllBooleanCtrlsMask);
4937	    CHK_MASK_MATCH(0x04,affect,stuff->autoCtrls);
4938	    CHK_MASK_MATCH(0x05,stuff->autoCtrls,stuff->autoCtrlValues);
4939
4940	    interest->autoCtrls&= ~affect;
4941	    interest->autoCtrlValues&= ~affect;
4942	    interest->autoCtrls|= stuff->autoCtrls&affect;
4943	    interest->autoCtrlValues|= stuff->autoCtrlValues&affect;
4944	}
4945    }
4946    rep.supported = XkbPCF_AllFlagsMask;
4947    rep.value= client->xkbClientFlags&XkbPCF_AllFlagsMask;
4948    if (interest) {
4949	rep.autoCtrls= interest->autoCtrls;
4950	rep.autoCtrlValues= interest->autoCtrlValues;
4951    }
4952    else {
4953	rep.autoCtrls= rep.autoCtrlValues= 0;
4954    }
4955    if ( client->swapped ) {
4956	register int n;
4957	swaps(&rep.sequenceNumber, n);
4958	swapl(&rep.supported,n);
4959	swapl(&rep.value,n);
4960	swapl(&rep.autoCtrls,n);
4961	swapl(&rep.autoCtrlValues,n);
4962    }
4963    WriteToClient(client,SIZEOF(xkbPerClientFlagsReply), (char *)&rep);
4964    return client->noClientException;
4965}
4966
4967/***====================================================================***/
4968
4969/* all latin-1 alphanumerics, plus parens, minus, underscore, slash */
4970/* and wildcards */
4971static unsigned char componentSpecLegal[] = {
4972        0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x87,
4973        0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07,
4974        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4975        0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
4976};
4977
4978/* same as above but accepts percent, plus and bar too */
4979static unsigned char componentExprLegal[] = {
4980        0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0xff, 0x87,
4981        0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x17,
4982        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4983        0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
4984};
4985
4986static char *
4987GetComponentSpec(unsigned char **pWire,Bool allowExpr,int *errRtrn)
4988{
4989int		len;
4990register int	i;
4991unsigned char	*wire,*str,*tmp,*legal;
4992
4993    if (allowExpr)	legal= &componentExprLegal[0];
4994    else		legal= &componentSpecLegal[0];
4995
4996    wire= *pWire;
4997    len= (*(unsigned char *)wire++);
4998    if (len>0) {
4999	str= (unsigned char *)_XkbCalloc(1, len+1);
5000	if (str) {
5001	    tmp= str;
5002	    for (i=0;i<len;i++) {
5003		if (legal[(*wire)/8]&(1<<((*wire)%8)))
5004		    *tmp++= *wire++;
5005		else wire++;
5006	    }
5007	    if (tmp!=str)
5008		*tmp++= '\0';
5009	    else {
5010		_XkbFree(str);
5011		str= NULL;
5012	    }
5013	}
5014	else {
5015	    *errRtrn= BadAlloc;
5016	}
5017    }
5018    else {
5019	str= NULL;
5020    }
5021    *pWire= wire;
5022    return (char *)str;
5023}
5024
5025/***====================================================================***/
5026
5027int
5028ProcXkbListComponents(ClientPtr client)
5029{
5030    DeviceIntPtr 		dev;
5031    xkbListComponentsReply 	rep;
5032    unsigned			len;
5033    int				status;
5034    unsigned char *		str;
5035    XkbSrvListInfoRec		list;
5036
5037    REQUEST(xkbListComponentsReq);
5038    REQUEST_AT_LEAST_SIZE(xkbListComponentsReq);
5039
5040    if (!(client->xkbClientFlags&_XkbClientInitialized))
5041	return BadAccess;
5042
5043    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
5044
5045    status= Success;
5046    str= (unsigned char *)&stuff[1];
5047    bzero(&list,sizeof(XkbSrvListInfoRec));
5048    list.maxRtrn= stuff->maxNames;
5049    list.pattern[_XkbListKeymaps]= GetComponentSpec(&str,False,&status);
5050    list.pattern[_XkbListKeycodes]= GetComponentSpec(&str,False,&status);
5051    list.pattern[_XkbListTypes]= GetComponentSpec(&str,False,&status);
5052    list.pattern[_XkbListCompat]= GetComponentSpec(&str,False,&status);
5053    list.pattern[_XkbListSymbols]= GetComponentSpec(&str,False,&status);
5054    list.pattern[_XkbListGeometry]= GetComponentSpec(&str,False,&status);
5055    if (status!=Success)
5056	return status;
5057    len= str-((unsigned char *)stuff);
5058    if ((XkbPaddedSize(len)/4)!=stuff->length)
5059	return BadLength;
5060    if ((status=XkbDDXList(dev,&list,client))!=Success) {
5061	if (list.pool) {
5062	    _XkbFree(list.pool);
5063	    list.pool= NULL;
5064	}
5065	return status;
5066    }
5067    bzero(&rep,sizeof(xkbListComponentsReply));
5068    rep.type= X_Reply;
5069    rep.deviceID = dev->id;
5070    rep.sequenceNumber = client->sequence;
5071    rep.length = XkbPaddedSize(list.nPool)/4;
5072    rep.nKeymaps = list.nFound[_XkbListKeymaps];
5073    rep.nKeycodes = list.nFound[_XkbListKeycodes];
5074    rep.nTypes = list.nFound[_XkbListTypes];
5075    rep.nCompatMaps = list.nFound[_XkbListCompat];
5076    rep.nSymbols = list.nFound[_XkbListSymbols];
5077    rep.nGeometries = list.nFound[_XkbListGeometry];
5078    rep.extra=	0;
5079    if (list.nTotal>list.maxRtrn)
5080	rep.extra = (list.nTotal-list.maxRtrn);
5081    if (client->swapped) {
5082	register int n;
5083	swaps(&rep.sequenceNumber,n);
5084	swapl(&rep.length,n);
5085	swaps(&rep.nKeymaps,n);
5086	swaps(&rep.nKeycodes,n);
5087	swaps(&rep.nTypes,n);
5088	swaps(&rep.nCompatMaps,n);
5089	swaps(&rep.nSymbols,n);
5090	swaps(&rep.nGeometries,n);
5091	swaps(&rep.extra,n);
5092    }
5093    WriteToClient(client,SIZEOF(xkbListComponentsReply),(char *)&rep);
5094    if (list.nPool && list.pool) {
5095	WriteToClient(client,XkbPaddedSize(list.nPool), (char *)list.pool);
5096	_XkbFree(list.pool);
5097	list.pool= NULL;
5098    }
5099    return client->noClientException;
5100}
5101
5102/***====================================================================***/
5103
5104int
5105ProcXkbGetKbdByName(ClientPtr client)
5106{
5107    DeviceIntPtr 		dev;
5108    DeviceIntPtr                tmpd;
5109    XkbFileInfo			finfo;
5110    xkbGetKbdByNameReply 	rep;
5111    xkbGetMapReply		mrep;
5112    xkbGetCompatMapReply	crep;
5113    xkbGetIndicatorMapReply	irep;
5114    xkbGetNamesReply		nrep;
5115    xkbGetGeometryReply		grep;
5116    XkbComponentNamesRec	names;
5117    XkbDescPtr			xkb;
5118    unsigned char *		str;
5119    char 			mapFile[PATH_MAX];
5120    unsigned			len;
5121    unsigned			fwant,fneed,reported;
5122    int				status;
5123    Bool			geom_changed;
5124    XkbSrvLedInfoPtr            old_sli;
5125    XkbSrvLedInfoPtr            sli;
5126
5127    REQUEST(xkbGetKbdByNameReq);
5128    REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq);
5129
5130    if (!(client->xkbClientFlags&_XkbClientInitialized))
5131	return BadAccess;
5132
5133    CHK_KBD_DEVICE(dev,stuff->deviceSpec);
5134
5135    xkb = dev->key->xkbInfo->desc;
5136    status= Success;
5137    str= (unsigned char *)&stuff[1];
5138    names.keymap= GetComponentSpec(&str,True,&status);
5139    names.keycodes= GetComponentSpec(&str,True,&status);
5140    names.types= GetComponentSpec(&str,True,&status);
5141    names.compat= GetComponentSpec(&str,True,&status);
5142    names.symbols= GetComponentSpec(&str,True,&status);
5143    names.geometry= GetComponentSpec(&str,True,&status);
5144    if (status!=Success)
5145	return status;
5146    len= str-((unsigned char *)stuff);
5147    if ((XkbPaddedSize(len)/4)!=stuff->length)
5148	return BadLength;
5149
5150    CHK_MASK_LEGAL(0x01,stuff->want,XkbGBN_AllComponentsMask);
5151    CHK_MASK_LEGAL(0x02,stuff->need,XkbGBN_AllComponentsMask);
5152
5153    if (stuff->load)
5154	 fwant= XkbGBN_AllComponentsMask;
5155    else fwant= stuff->want|stuff->need;
5156    if (!names.keymap) {
5157	if ((!names.compat)&&
5158    		(fwant&(XkbGBN_CompatMapMask|XkbGBN_IndicatorMapMask))) {
5159	    names.compat= _XkbDupString("%");
5160	}
5161	if ((!names.types)&&(fwant&(XkbGBN_TypesMask))) {
5162	    names.types= _XkbDupString("%");
5163	}
5164	if ((!names.symbols)&&(fwant&XkbGBN_SymbolsMask)) {
5165	    names.symbols= _XkbDupString("%");
5166	}
5167	geom_changed= ((names.geometry!=NULL)&&(strcmp(names.geometry,"%")!=0));
5168	if ((!names.geometry)&&(fwant&XkbGBN_GeometryMask)) {
5169	    names.geometry= _XkbDupString("%");
5170	    geom_changed= False;
5171	}
5172    }
5173    else {
5174	geom_changed= True;
5175    }
5176
5177    bzero(mapFile,PATH_MAX);
5178    rep.type= X_Reply;
5179    rep.deviceID = dev->id;
5180    rep.sequenceNumber = client->sequence;
5181    rep.length = 0;
5182    rep.minKeyCode = xkb->min_key_code;
5183    rep.maxKeyCode = xkb->max_key_code;
5184    rep.loaded=	False;
5185    fwant= XkbConvertGetByNameComponents(True,stuff->want)|XkmVirtualModsMask;
5186    fneed= XkbConvertGetByNameComponents(True,stuff->need);
5187    rep.reported= XkbConvertGetByNameComponents(False,fwant|fneed);
5188    if (stuff->load) {
5189	fneed|= XkmKeymapRequired;
5190	fwant|= XkmKeymapLegal;
5191    }
5192    if ((fwant|fneed)&XkmSymbolsMask) {
5193	fneed|= XkmKeyNamesIndex|XkmTypesIndex;
5194	fwant|= XkmIndicatorsIndex;
5195    }
5196
5197    /* We pass dev in here so we can get the old names out if needed. */
5198    rep.found = XkbDDXLoadKeymapByNames(dev,&names,fwant,fneed,&finfo,
5199                                        mapFile,PATH_MAX);
5200    rep.newKeyboard= False;
5201    rep.pad1= rep.pad2= rep.pad3= rep.pad4= 0;
5202
5203    stuff->want|= stuff->need;
5204    if (finfo.xkb==NULL)
5205	rep.reported= 0;
5206    else {
5207	if (stuff->load)
5208	    rep.loaded= True;
5209	if (stuff->load ||
5210		((rep.reported&XkbGBN_SymbolsMask) && (finfo.xkb->compat))) {
5211	    XkbChangesRec changes;
5212	    bzero(&changes,sizeof(changes));
5213	    XkbUpdateDescActions(finfo.xkb,
5214			finfo.xkb->min_key_code,XkbNumKeys(finfo.xkb),
5215			&changes);
5216	}
5217
5218	if (finfo.xkb->map==NULL)
5219	    rep.reported&= ~(XkbGBN_SymbolsMask|XkbGBN_TypesMask);
5220	else if (rep.reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask)) {
5221	    mrep.type= X_Reply;
5222	    mrep.deviceID = dev->id;
5223	    mrep.sequenceNumber= client->sequence;
5224	    mrep.length = ((SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2);
5225	    mrep.minKeyCode = finfo.xkb->min_key_code;
5226	    mrep.maxKeyCode = finfo.xkb->max_key_code;
5227	    mrep.present = 0;
5228	    mrep.totalSyms = mrep.totalActs =
5229		mrep.totalKeyBehaviors= mrep.totalKeyExplicit=
5230		mrep.totalModMapKeys= 0;
5231	    if (rep.reported&(XkbGBN_TypesMask|XkbGBN_ClientSymbolsMask)) {
5232		mrep.present|= XkbKeyTypesMask;
5233		mrep.firstType = 0;
5234		mrep.nTypes = mrep.totalTypes= finfo.xkb->map->num_types;
5235	    }
5236	    else {
5237		mrep.firstType = mrep.nTypes= 0;
5238		mrep.totalTypes= 0;
5239	    }
5240	    if (rep.reported&XkbGBN_ClientSymbolsMask) {
5241		mrep.present|= (XkbKeySymsMask|XkbModifierMapMask);
5242		mrep.firstKeySym = mrep.firstModMapKey= finfo.xkb->min_key_code;
5243		mrep.nKeySyms = mrep.nModMapKeys= XkbNumKeys(finfo.xkb);
5244	    }
5245	    else {
5246		mrep.firstKeySym= mrep.firstModMapKey= 0;
5247		mrep.nKeySyms= mrep.nModMapKeys= 0;
5248	    }
5249	    if (rep.reported&XkbGBN_ServerSymbolsMask) {
5250		mrep.present|= XkbAllServerInfoMask;
5251		mrep.virtualMods= ~0;
5252		mrep.firstKeyAct = mrep.firstKeyBehavior =
5253			mrep.firstKeyExplicit = finfo.xkb->min_key_code;
5254		mrep.nKeyActs = mrep.nKeyBehaviors =
5255			mrep.nKeyExplicit = XkbNumKeys(finfo.xkb);
5256	    }
5257	    else {
5258		mrep.virtualMods= 0;
5259		mrep.firstKeyAct= mrep.firstKeyBehavior=
5260			mrep.firstKeyExplicit = 0;
5261		mrep.nKeyActs= mrep.nKeyBehaviors= mrep.nKeyExplicit= 0;
5262	    }
5263	    XkbComputeGetMapReplySize(finfo.xkb,&mrep);
5264	    rep.length+= SIZEOF(xGenericReply)/4+mrep.length;
5265	}
5266	if (finfo.xkb->compat==NULL)
5267	    rep.reported&= ~XkbGBN_CompatMapMask;
5268	else if (rep.reported&XkbGBN_CompatMapMask) {
5269	    crep.type= X_Reply;
5270	    crep.deviceID= dev->id;
5271	    crep.sequenceNumber= client->sequence;
5272	    crep.length= 0;
5273	    crep.groups= XkbAllGroupsMask;
5274	    crep.firstSI= 0;
5275	    crep.nSI= crep.nTotalSI= finfo.xkb->compat->num_si;
5276	    XkbComputeGetCompatMapReplySize(finfo.xkb->compat,&crep);
5277	    rep.length+= SIZEOF(xGenericReply)/4+crep.length;
5278	}
5279	if (finfo.xkb->indicators==NULL)
5280	    rep.reported&= ~XkbGBN_IndicatorMapMask;
5281	else if (rep.reported&XkbGBN_IndicatorMapMask) {
5282	    irep.type= X_Reply;
5283	    irep.deviceID= dev->id;
5284	    irep.sequenceNumber= client->sequence;
5285	    irep.length= 0;
5286	    irep.which= XkbAllIndicatorsMask;
5287	    XkbComputeGetIndicatorMapReplySize(finfo.xkb->indicators,&irep);
5288	    rep.length+= SIZEOF(xGenericReply)/4+irep.length;
5289	}
5290	if (finfo.xkb->names==NULL)
5291	    rep.reported&= ~(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask);
5292	else if (rep.reported&(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask)) {
5293	    nrep.type= X_Reply;
5294	    nrep.deviceID= dev->id;
5295	    nrep.sequenceNumber= client->sequence;
5296	    nrep.length= 0;
5297	    nrep.minKeyCode= finfo.xkb->min_key_code;
5298	    nrep.maxKeyCode= finfo.xkb->max_key_code;
5299	    if (rep.reported&XkbGBN_OtherNamesMask) {
5300		nrep.which= XkbAllNamesMask;
5301		if (finfo.xkb->map!=NULL)
5302		     nrep.nTypes= finfo.xkb->map->num_types;
5303		else nrep.nTypes= 0;
5304		nrep.nKTLevels= 0;
5305		nrep.groupNames= XkbAllGroupsMask;
5306		nrep.virtualMods= XkbAllVirtualModsMask;
5307		nrep.indicators= XkbAllIndicatorsMask;
5308		nrep.nRadioGroups= finfo.xkb->names->num_rg;
5309	    }
5310	    else {
5311		nrep.which= 0;
5312		nrep.nTypes= 0;
5313		nrep.nKTLevels= 0;
5314		nrep.groupNames= 0;
5315		nrep.virtualMods= 0;
5316		nrep.indicators= 0;
5317		nrep.nRadioGroups= 0;
5318	    }
5319	    if (rep.reported&XkbGBN_KeyNamesMask) {
5320		nrep.which|= XkbKeyNamesMask;
5321		nrep.firstKey= finfo.xkb->min_key_code;
5322		nrep.nKeys= XkbNumKeys(finfo.xkb);
5323		nrep.nKeyAliases= finfo.xkb->names->num_key_aliases;
5324		if (nrep.nKeyAliases)
5325		    nrep.which|= XkbKeyAliasesMask;
5326	    }
5327	    else {
5328		nrep.which&= ~(XkbKeyNamesMask|XkbKeyAliasesMask);
5329		nrep.firstKey= nrep.nKeys= 0;
5330		nrep.nKeyAliases= 0;
5331	    }
5332	    XkbComputeGetNamesReplySize(finfo.xkb,&nrep);
5333	    rep.length+= SIZEOF(xGenericReply)/4+nrep.length;
5334	}
5335	if (finfo.xkb->geom==NULL)
5336	    rep.reported&= ~XkbGBN_GeometryMask;
5337	else if (rep.reported&XkbGBN_GeometryMask) {
5338	    grep.type= X_Reply;
5339	    grep.deviceID= dev->id;
5340	    grep.sequenceNumber= client->sequence;
5341	    grep.length= 0;
5342	    grep.found= True;
5343	    grep.pad= 0;
5344	    grep.widthMM= grep.heightMM= 0;
5345	    grep.nProperties= grep.nColors= grep.nShapes= 0;
5346	    grep.nSections= grep.nDoodads= 0;
5347	    grep.baseColorNdx= grep.labelColorNdx= 0;
5348	    XkbComputeGetGeometryReplySize(finfo.xkb->geom,&grep,None);
5349	    rep.length+= SIZEOF(xGenericReply)/4+grep.length;
5350	}
5351    }
5352
5353    reported= rep.reported;
5354    if ( client->swapped ) {
5355	register int n;
5356	swaps(&rep.sequenceNumber,n);
5357	swapl(&rep.length,n);
5358	swaps(&rep.found,n);
5359	swaps(&rep.reported,n);
5360    }
5361    WriteToClient(client,SIZEOF(xkbGetKbdByNameReply), (char *)&rep);
5362    if (reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask))
5363	XkbSendMap(client,finfo.xkb,&mrep);
5364    if (reported&XkbGBN_CompatMapMask)
5365	XkbSendCompatMap(client,finfo.xkb->compat,&crep);
5366    if (reported&XkbGBN_IndicatorMapMask)
5367	XkbSendIndicatorMap(client,finfo.xkb->indicators,&irep);
5368    if (reported&(XkbGBN_KeyNamesMask|XkbGBN_OtherNamesMask))
5369	XkbSendNames(client,finfo.xkb,&nrep);
5370    if (reported&XkbGBN_GeometryMask)
5371	XkbSendGeometry(client,finfo.xkb->geom,&grep,False);
5372    if (rep.loaded) {
5373	XkbDescPtr		old_xkb;
5374	xkbNewKeyboardNotify 	nkn;
5375	int 			i,nG,nTG;
5376	old_xkb= xkb;
5377	xkb= finfo.xkb;
5378	dev->key->xkbInfo->desc= xkb;
5379	finfo.xkb= old_xkb; /* so it'll get freed automatically */
5380
5381	*xkb->ctrls= *old_xkb->ctrls;
5382	for (nG=nTG=0,i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
5383	    nG= XkbKeyNumGroups(xkb,i);
5384	    if (nG>=XkbNumKbdGroups) {
5385		nTG= XkbNumKbdGroups;
5386		break;
5387	    }
5388	    if (nG>nTG) {
5389		nTG= nG;
5390	    }
5391	}
5392	xkb->ctrls->num_groups= nTG;
5393
5394        for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
5395            if (tmpd == dev ||
5396                (dev->id == inputInfo.keyboard->id && tmpd->key &&
5397                 tmpd->coreEvents)) {
5398
5399                memcpy(tmpd->key->modifierMap, xkb->map->modmap,
5400                       xkb->max_key_code + 1);
5401                if (tmpd != dev)
5402                    XkbCopyKeymap(dev->key->xkbInfo->desc,
5403                                  tmpd->key->xkbInfo->desc, True);
5404                XkbUpdateCoreDescription(tmpd, True);
5405
5406                if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) {
5407                    old_sli = tmpd->kbdfeed->xkb_sli;
5408                    tmpd->kbdfeed->xkb_sli = NULL;
5409                    sli = XkbAllocSrvLedInfo(tmpd, tmpd->kbdfeed, NULL, 0);
5410                    if (sli) {
5411                        sli->explicitState = old_sli->explicitState;
5412                        sli->effectiveState = old_sli->effectiveState;
5413                    }
5414                    tmpd->kbdfeed->xkb_sli = sli;
5415                    XkbFreeSrvLedInfo(old_sli);
5416                }
5417            }
5418        }
5419
5420        /* this should be either a MN or an NKN, depending on whether or not
5421         * the keycode range changed? */
5422	nkn.deviceID= nkn.oldDeviceID= dev->id;
5423	nkn.minKeyCode= finfo.xkb->min_key_code;
5424	nkn.maxKeyCode= finfo.xkb->max_key_code;
5425	nkn.oldMinKeyCode= xkb->min_key_code;
5426	nkn.oldMaxKeyCode= xkb->max_key_code;
5427	nkn.requestMajor= XkbReqCode;
5428	nkn.requestMinor= X_kbGetKbdByName;
5429	nkn.changed= XkbNKN_KeycodesMask;
5430	if (geom_changed)
5431	    nkn.changed|= XkbNKN_GeometryMask;
5432	XkbSendNewKeyboardNotify(dev,&nkn);
5433    }
5434    if ((finfo.xkb!=NULL)&&(finfo.xkb!=xkb)) {
5435	XkbFreeKeyboard(finfo.xkb,XkbAllComponentsMask,True);
5436	finfo.xkb= NULL;
5437    }
5438    if (names.keymap)	{ _XkbFree(names.keymap); names.keymap= NULL; }
5439    if (names.keycodes)	{ _XkbFree(names.keycodes); names.keycodes= NULL; }
5440    if (names.types)	{ _XkbFree(names.types); names.types= NULL; }
5441    if (names.compat)	{ _XkbFree(names.compat); names.compat= NULL; }
5442    if (names.symbols)	{ _XkbFree(names.symbols); names.symbols= NULL; }
5443    if (names.geometry)	{ _XkbFree(names.geometry); names.geometry= NULL; }
5444    return client->noClientException;
5445}
5446
5447/***====================================================================***/
5448
5449static int
5450ComputeDeviceLedInfoSize(	DeviceIntPtr		dev,
5451				unsigned int		what,
5452				XkbSrvLedInfoPtr	sli)
5453{
5454int			nNames,nMaps;
5455register unsigned 	n,bit;
5456
5457    if (sli==NULL)
5458	return 0;
5459    nNames= nMaps= 0;
5460    if ((what&XkbXI_IndicatorNamesMask)==0)
5461	sli->namesPresent= 0;
5462    if ((what&XkbXI_IndicatorMapsMask)==0)
5463	sli->mapsPresent= 0;
5464
5465    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
5466	if (sli->names && sli->names[n]!=None) {
5467	    sli->namesPresent|= bit;
5468	    nNames++;
5469	}
5470	if (sli->maps && XkbIM_InUse(&sli->maps[n])) {
5471	    sli->mapsPresent|= bit;
5472	    nMaps++;
5473	}
5474    }
5475    return (nNames*4)+(nMaps*SIZEOF(xkbIndicatorMapWireDesc));
5476}
5477
5478static int
5479CheckDeviceLedFBs(	DeviceIntPtr			dev,
5480			int				class,
5481			int				id,
5482			xkbGetDeviceInfoReply *		rep,
5483			ClientPtr			client)
5484{
5485int			nFBs= 0;
5486int			length= 0;
5487Bool			classOk;
5488
5489    if (class==XkbDfltXIClass) {
5490	if (dev->kbdfeed)	class= KbdFeedbackClass;
5491	else if (dev->leds)	class= LedFeedbackClass;
5492	else {
5493	    client->errorValue= _XkbErrCode2(XkbErr_BadClass,class);
5494	    return XkbKeyboardErrorCode;
5495	}
5496    }
5497    classOk= False;
5498    if ((dev->kbdfeed)&&((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) {
5499	KbdFeedbackPtr kf;
5500	classOk= True;
5501	for (kf= dev->kbdfeed;(kf);kf=kf->next) {
5502	    if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=kf->ctrl.id))
5503		continue;
5504	    nFBs++;
5505	    length+= SIZEOF(xkbDeviceLedsWireDesc);
5506	    if (!kf->xkb_sli)
5507		kf->xkb_sli= XkbAllocSrvLedInfo(dev,kf,NULL,0);
5508	    length+= ComputeDeviceLedInfoSize(dev,rep->present,kf->xkb_sli);
5509	    if (id!=XkbAllXIIds)
5510		break;
5511	}
5512    }
5513    if ((dev->leds)&&((class==LedFeedbackClass)||(class==XkbAllXIClasses))) {
5514	LedFeedbackPtr lf;
5515	classOk= True;
5516	for (lf= dev->leds;(lf);lf=lf->next) {
5517	    if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=lf->ctrl.id))
5518		continue;
5519	    nFBs++;
5520	    length+= SIZEOF(xkbDeviceLedsWireDesc);
5521	    if (!lf->xkb_sli)
5522		lf->xkb_sli= XkbAllocSrvLedInfo(dev,NULL,lf,0);
5523	    length+= ComputeDeviceLedInfoSize(dev,rep->present,lf->xkb_sli);
5524	    if (id!=XkbAllXIIds)
5525		break;
5526	}
5527    }
5528    if (nFBs>0) {
5529	if (rep->supported&XkbXI_IndicatorsMask) {
5530	    rep->nDeviceLedFBs= nFBs;
5531	    rep->length+= (length/4);
5532	}
5533	return Success;
5534    }
5535    if (classOk) client->errorValue= _XkbErrCode2(XkbErr_BadId,id);
5536    else	 client->errorValue= _XkbErrCode2(XkbErr_BadClass,class);
5537    return XkbKeyboardErrorCode;
5538}
5539
5540static int
5541SendDeviceLedInfo(	XkbSrvLedInfoPtr	sli,
5542			ClientPtr		client)
5543{
5544xkbDeviceLedsWireDesc	wire;
5545int			length;
5546
5547    length= 0;
5548    wire.ledClass= 		sli->class;
5549    wire.ledID= 		sli->id;
5550    wire.namesPresent= 		sli->namesPresent;
5551    wire.mapsPresent=   	sli->mapsPresent;
5552    wire.physIndicators= 	sli->physIndicators;
5553    wire.state=			sli->effectiveState;
5554    if (client->swapped) {
5555	register int n;
5556	swaps(&wire.ledClass,n);
5557	swaps(&wire.ledID,n);
5558	swapl(&wire.namesPresent,n);
5559	swapl(&wire.mapsPresent,n);
5560	swapl(&wire.physIndicators,n);
5561	swapl(&wire.state,n);
5562    }
5563    WriteToClient(client,SIZEOF(xkbDeviceLedsWireDesc),(char *)&wire);
5564    length+= SIZEOF(xkbDeviceLedsWireDesc);
5565    if (sli->namesPresent|sli->mapsPresent) {
5566	register unsigned i,bit;
5567	if (sli->namesPresent) {
5568	    CARD32	awire;
5569	    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
5570		if (sli->namesPresent&bit) {
5571		    awire= (CARD32)sli->names[i];
5572		    if (client->swapped) {
5573			register int n;
5574			swapl(&awire,n);
5575		    }
5576		    WriteToClient(client,4,(char *)&awire);
5577		    length+= 4;
5578		}
5579	    }
5580	}
5581	if (sli->mapsPresent) {
5582	    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
5583		xkbIndicatorMapWireDesc	iwire;
5584		if (sli->mapsPresent&bit) {
5585		    iwire.flags= 	sli->maps[i].flags;
5586		    iwire.whichGroups=	sli->maps[i].which_groups;
5587		    iwire.groups=	sli->maps[i].groups;
5588		    iwire.whichMods=	sli->maps[i].which_mods;
5589		    iwire.mods=		sli->maps[i].mods.mask;
5590		    iwire.realMods=	sli->maps[i].mods.real_mods;
5591		    iwire.virtualMods=	sli->maps[i].mods.vmods;
5592		    iwire.ctrls= 	sli->maps[i].ctrls;
5593		    if (client->swapped) {
5594			register int n;
5595			swaps(&iwire.virtualMods,n);
5596			swapl(&iwire.ctrls,n);
5597		    }
5598		    WriteToClient(client,SIZEOF(xkbIndicatorMapWireDesc),
5599								(char *)&iwire);
5600		    length+= SIZEOF(xkbIndicatorMapWireDesc);
5601		}
5602	    }
5603	}
5604    }
5605    return length;
5606}
5607
5608static int
5609SendDeviceLedFBs(	DeviceIntPtr	dev,
5610			int		class,
5611			int		id,
5612			unsigned	wantLength,
5613			ClientPtr	client)
5614{
5615int			length= 0;
5616
5617    if (class==XkbDfltXIClass) {
5618	if (dev->kbdfeed)	class= KbdFeedbackClass;
5619	else if (dev->leds)	class= LedFeedbackClass;
5620    }
5621    if ((dev->kbdfeed)&&
5622	((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) {
5623	KbdFeedbackPtr kf;
5624	for (kf= dev->kbdfeed;(kf);kf=kf->next) {
5625	    if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==kf->ctrl.id)) {
5626		length+= SendDeviceLedInfo(kf->xkb_sli,client);
5627		if (id!=XkbAllXIIds)
5628		    break;
5629	    }
5630	}
5631    }
5632    if ((dev->leds)&&
5633	((class==LedFeedbackClass)||(class==XkbAllXIClasses))) {
5634	LedFeedbackPtr lf;
5635	for (lf= dev->leds;(lf);lf=lf->next) {
5636	    if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==lf->ctrl.id)) {
5637		length+= SendDeviceLedInfo(lf->xkb_sli,client);
5638		if (id!=XkbAllXIIds)
5639		    break;
5640	    }
5641	}
5642    }
5643    if (length==wantLength)
5644	 return Success;
5645    else return BadLength;
5646}
5647
5648int
5649ProcXkbGetDeviceInfo(ClientPtr client)
5650{
5651DeviceIntPtr		dev;
5652xkbGetDeviceInfoReply	rep;
5653int			status,nDeviceLedFBs;
5654unsigned		length,nameLen;
5655CARD16			ledClass,ledID;
5656unsigned		wanted,supported;
5657char *			str;
5658
5659    REQUEST(xkbGetDeviceInfoReq);
5660    REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq);
5661
5662    if (!(client->xkbClientFlags&_XkbClientInitialized))
5663	return BadAccess;
5664
5665    wanted= stuff->wanted;
5666
5667    CHK_ANY_DEVICE(dev,stuff->deviceSpec);
5668    CHK_MASK_LEGAL(0x01,wanted,XkbXI_AllDeviceFeaturesMask);
5669
5670    if ((!dev->button)||((stuff->nBtns<1)&&(!stuff->allBtns)))
5671	wanted&= ~XkbXI_ButtonActionsMask;
5672    if ((!dev->kbdfeed)&&(!dev->leds))
5673	wanted&= ~XkbXI_IndicatorsMask;
5674
5675    nameLen= XkbSizeCountedString(dev->name);
5676    bzero((char *)&rep,SIZEOF(xkbGetDeviceInfoReply));
5677    rep.type = X_Reply;
5678    rep.deviceID= dev->id;
5679    rep.sequenceNumber = client->sequence;
5680    rep.length = nameLen/4;
5681    rep.present = wanted;
5682    rep.supported = XkbXI_AllDeviceFeaturesMask;
5683    rep.unsupported = 0;
5684    rep.firstBtnWanted = rep.nBtnsWanted = 0;
5685    rep.firstBtnRtrn = rep.nBtnsRtrn = 0;
5686    if (dev->button)
5687	 rep.totalBtns= dev->button->numButtons;
5688    else rep.totalBtns= 0;
5689    rep.devType=	dev->type;
5690    rep.hasOwnState=	(dev->key && dev->key->xkbInfo);
5691    rep.nDeviceLedFBs = 0;
5692    if (dev->kbdfeed)	rep.dfltKbdFB= dev->kbdfeed->ctrl.id;
5693    else		rep.dfltKbdFB= XkbXINone;
5694    if (dev->leds)	rep.dfltLedFB= dev->leds->ctrl.id;
5695    else		rep.dfltLedFB= XkbXINone;
5696
5697    ledClass= stuff->ledClass;
5698    ledID= stuff->ledID;
5699
5700    rep.firstBtnWanted= rep.nBtnsWanted= 0;
5701    rep.firstBtnRtrn= rep.nBtnsRtrn= 0;
5702    if (wanted&XkbXI_ButtonActionsMask) {
5703	if (stuff->allBtns) {
5704	    stuff->firstBtn= 0;
5705	    stuff->nBtns= dev->button->numButtons;
5706	}
5707
5708	if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) {
5709	    client->errorValue = _XkbErrCode4(0x02,dev->button->numButtons,
5710							stuff->firstBtn,
5711							stuff->nBtns);
5712	    return BadValue;
5713	}
5714	else {
5715	    rep.firstBtnWanted= stuff->firstBtn;
5716	    rep.nBtnsWanted= stuff->nBtns;
5717	    if (dev->button->xkb_acts!=NULL) {
5718		XkbAction *act;
5719		register int i;
5720
5721		rep.firstBtnRtrn= stuff->firstBtn;
5722		rep.nBtnsRtrn= stuff->nBtns;
5723		act= &dev->button->xkb_acts[rep.firstBtnWanted];
5724		for (i=0;i<rep.nBtnsRtrn;i++,act++) {
5725		    if (act->type!=XkbSA_NoAction)
5726			break;
5727		}
5728		rep.firstBtnRtrn+=	i;
5729		rep.nBtnsRtrn-=		i;
5730		act= &dev->button->xkb_acts[rep.firstBtnRtrn+rep.nBtnsRtrn-1];
5731		for (i=0;i<rep.nBtnsRtrn;i++,act--) {
5732		    if (act->type!=XkbSA_NoAction)
5733			break;
5734		}
5735		rep.nBtnsRtrn-=		i;
5736	    }
5737	    rep.length+= (rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc))/4;
5738	}
5739    }
5740
5741    if (wanted&XkbXI_IndicatorsMask) {
5742	status= CheckDeviceLedFBs(dev,ledClass,ledID,&rep,client);
5743	if (status!=Success)
5744	    return status;
5745    }
5746    length= rep.length*4;
5747    supported= rep.supported;
5748    nDeviceLedFBs = rep.nDeviceLedFBs;
5749    if (client->swapped) {
5750	register int n;
5751	swaps(&rep.sequenceNumber,n);
5752	swapl(&rep.length,n);
5753	swaps(&rep.present,n);
5754	swaps(&rep.supported,n);
5755	swaps(&rep.unsupported,n);
5756	swaps(&rep.nDeviceLedFBs,n);
5757	swapl(&rep.type,n);
5758    }
5759    WriteToClient(client,SIZEOF(xkbGetDeviceInfoReply), (char *)&rep);
5760
5761    str= (char*) ALLOCATE_LOCAL(nameLen);
5762    if (!str)
5763	return BadAlloc;
5764    XkbWriteCountedString(str,dev->name,client->swapped);
5765    WriteToClient(client,nameLen,str);
5766    DEALLOCATE_LOCAL(str);
5767    length-= nameLen;
5768
5769    if (rep.nBtnsRtrn>0) {
5770	int			sz;
5771	xkbActionWireDesc *	awire;
5772	sz= rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc);
5773	awire= (xkbActionWireDesc *)&dev->button->xkb_acts[rep.firstBtnRtrn];
5774	WriteToClient(client,sz,(char *)awire);
5775	length-= sz;
5776    }
5777    if (nDeviceLedFBs>0) {
5778	status= SendDeviceLedFBs(dev,ledClass,ledID,length,client);
5779	if (status!=Success)
5780	    return status;
5781    }
5782    else if (length!=0)  {
5783#ifdef DEBUG
5784	ErrorF("Internal Error!  BadLength in ProcXkbGetDeviceInfo\n");
5785	ErrorF("                 Wrote %d fewer bytes than expected\n",length);
5786#endif
5787	return BadLength;
5788    }
5789    if (stuff->wanted&(~supported)) {
5790	xkbExtensionDeviceNotify ed;
5791	bzero((char *)&ed,SIZEOF(xkbExtensionDeviceNotify));
5792	ed.ledClass=		ledClass;
5793	ed.ledID=		ledID;
5794	ed.ledsDefined= 	0;
5795	ed.ledState=		0;
5796	ed.firstBtn= ed.nBtns=	0;
5797	ed.reason=		XkbXI_UnsupportedFeatureMask;
5798	ed.supported=		supported;
5799	ed.unsupported=		stuff->wanted&(~supported);
5800	XkbSendExtensionDeviceNotify(dev,client,&ed);
5801    }
5802    return client->noClientException;
5803}
5804
5805static char *
5806CheckSetDeviceIndicators(	char *		wire,
5807				DeviceIntPtr	dev,
5808				int		num,
5809				int *		status_rtrn,
5810				ClientPtr	client)
5811{
5812xkbDeviceLedsWireDesc *	ledWire;
5813int			i;
5814XkbSrvLedInfoPtr 	sli;
5815
5816    ledWire= (xkbDeviceLedsWireDesc *)wire;
5817    for (i=0;i<num;i++) {
5818	if (client->swapped) {
5819	   register int n;
5820	   swaps(&ledWire->ledClass,n);
5821	   swaps(&ledWire->ledID,n);
5822	   swapl(&ledWire->namesPresent,n);
5823	   swapl(&ledWire->mapsPresent,n);
5824	   swapl(&ledWire->physIndicators,n);
5825	}
5826
5827        sli= XkbFindSrvLedInfo(dev,ledWire->ledClass,ledWire->ledID,
5828							XkbXI_IndicatorsMask);
5829	if (sli!=NULL) {
5830	    register int n;
5831	    register unsigned bit;
5832	    int nMaps,nNames;
5833	    CARD32 *atomWire;
5834	    xkbIndicatorMapWireDesc *mapWire;
5835
5836	    nMaps= nNames= 0;
5837	    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
5838		if (ledWire->namesPresent&bit)
5839		    nNames++;
5840		if (ledWire->mapsPresent&bit)
5841		    nMaps++;
5842	    }
5843	    atomWire= (CARD32 *)&ledWire[1];
5844	    if (nNames>0) {
5845		for (n=0;n<nNames;n++) {
5846		    if (client->swapped) {
5847			register int t;
5848			swapl(atomWire,t);
5849		    }
5850		    CHK_ATOM_OR_NONE3(((Atom)(*atomWire)),client->errorValue,
5851							*status_rtrn,NULL);
5852		    atomWire++;
5853		}
5854	    }
5855	    mapWire= (xkbIndicatorMapWireDesc *)atomWire;
5856	    if (nMaps>0) {
5857		for (n=0;n<nMaps;n++) {
5858		    if (client->swapped) {
5859			register int t;
5860			swaps(&mapWire->virtualMods,t);
5861			swapl(&mapWire->ctrls,t);
5862		    }
5863		    CHK_MASK_LEGAL3(0x21,mapWire->whichGroups,
5864						XkbIM_UseAnyGroup,
5865						client->errorValue,
5866						*status_rtrn,NULL);
5867		    CHK_MASK_LEGAL3(0x22,mapWire->whichMods,XkbIM_UseAnyMods,
5868						client->errorValue,
5869						*status_rtrn,NULL);
5870		    mapWire++;
5871		}
5872	    }
5873	    ledWire= (xkbDeviceLedsWireDesc *)mapWire;
5874	}
5875	else {
5876	    /* SHOULD NEVER HAPPEN */
5877	    return (char *)ledWire;
5878	}
5879    }
5880    return (char *)ledWire;
5881}
5882
5883static char *
5884SetDeviceIndicators(	char *			wire,
5885			DeviceIntPtr		dev,
5886			unsigned		changed,
5887			int			num,
5888			int *			status_rtrn,
5889			ClientPtr		client,
5890			xkbExtensionDeviceNotify *ev)
5891{
5892xkbDeviceLedsWireDesc *		ledWire;
5893int				i;
5894XkbEventCauseRec		cause;
5895unsigned			namec,mapc,statec;
5896xkbExtensionDeviceNotify	ed;
5897XkbChangesRec			changes;
5898DeviceIntPtr			kbd;
5899
5900    bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify));
5901    bzero((char *)&changes,sizeof(XkbChangesRec));
5902    XkbSetCauseXkbReq(&cause,X_kbSetDeviceInfo,client);
5903    ledWire= (xkbDeviceLedsWireDesc *)wire;
5904    for (i=0;i<num;i++) {
5905	register int			n;
5906	register unsigned 		bit;
5907	CARD32 *			atomWire;
5908	xkbIndicatorMapWireDesc *	mapWire;
5909	XkbSrvLedInfoPtr		sli;
5910
5911	namec= mapc= statec= 0;
5912    	sli= XkbFindSrvLedInfo(dev,ledWire->ledClass,ledWire->ledID,
5913						XkbXI_IndicatorMapsMask);
5914	if (!sli) {
5915	    /* SHOULD NEVER HAPPEN!! */
5916	    return (char *)ledWire;
5917	}
5918
5919	atomWire= (CARD32 *)&ledWire[1];
5920	if (changed&XkbXI_IndicatorNamesMask) {
5921	    namec= sli->namesPresent|ledWire->namesPresent;
5922	    bzero((char *)sli->names,XkbNumIndicators*sizeof(Atom));
5923	}
5924	if (ledWire->namesPresent) {
5925	    sli->namesPresent= ledWire->namesPresent;
5926	    bzero((char *)sli->names,XkbNumIndicators*sizeof(Atom));
5927	    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
5928		if (ledWire->namesPresent&bit) {
5929		     sli->names[n]= (Atom)*atomWire;
5930		     if (sli->names[n]==None)
5931			ledWire->namesPresent&= ~bit;
5932		     atomWire++;
5933		}
5934	    }
5935	}
5936	mapWire= (xkbIndicatorMapWireDesc *)atomWire;
5937	if (changed&XkbXI_IndicatorMapsMask) {
5938	    mapc= sli->mapsPresent|ledWire->mapsPresent;
5939	    sli->mapsPresent= ledWire->mapsPresent;
5940	    bzero((char*)sli->maps,XkbNumIndicators*sizeof(XkbIndicatorMapRec));
5941	}
5942	if (ledWire->mapsPresent) {
5943	    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
5944		if (ledWire->mapsPresent&bit) {
5945		    sli->maps[n].flags=		mapWire->flags;
5946		    sli->maps[n].which_groups=	mapWire->whichGroups;
5947		    sli->maps[n].groups=	mapWire->groups;
5948		    sli->maps[n].which_mods=	mapWire->whichMods;
5949		    sli->maps[n].mods.mask=	mapWire->mods;
5950		    sli->maps[n].mods.real_mods=mapWire->realMods;
5951		    sli->maps[n].mods.vmods=	mapWire->virtualMods;
5952		    sli->maps[n].ctrls=		mapWire->ctrls;
5953		    mapWire++;
5954		}
5955	    }
5956	}
5957	if (changed&XkbXI_IndicatorStateMask) {
5958	    statec= sli->effectiveState^ledWire->state;
5959	    sli->explicitState&= ~statec;
5960	    sli->explicitState|= (ledWire->state&statec);
5961	}
5962	if (namec)
5963	    XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause);
5964	if (mapc)
5965	    XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause);
5966	if (statec)
5967	    XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause);
5968
5969	kbd= dev;
5970	if ((sli->flags&XkbSLI_HasOwnState)==0)
5971	    kbd= (DeviceIntPtr)LookupKeyboardDevice();
5972
5973	XkbFlushLedEvents(dev,kbd,sli,&ed,&changes,&cause);
5974	ledWire= (xkbDeviceLedsWireDesc *)mapWire;
5975    }
5976    return (char *)ledWire;
5977}
5978
5979/* FIXME: Needs to set info on all core-sending devices. */
5980int
5981ProcXkbSetDeviceInfo(ClientPtr client)
5982{
5983DeviceIntPtr		dev;
5984unsigned		change;
5985char *			wire;
5986xkbExtensionDeviceNotify ed;
5987
5988    REQUEST(xkbSetDeviceInfoReq);
5989    REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq);
5990
5991    if (!(client->xkbClientFlags&_XkbClientInitialized))
5992	return BadAccess;
5993
5994    change= stuff->change;
5995
5996    CHK_ANY_DEVICE(dev,stuff->deviceSpec);
5997    CHK_MASK_LEGAL(0x01,change,XkbXI_AllFeaturesMask);
5998
5999    wire= (char *)&stuff[1];
6000    if (change&XkbXI_ButtonActionsMask) {
6001	if (!dev->button) {
6002	    client->errorValue = _XkbErrCode2(XkbErr_BadClass,ButtonClass);
6003	    return XkbKeyboardErrorCode;
6004	}
6005	if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) {
6006	    client->errorValue= _XkbErrCode4(0x02,stuff->firstBtn,stuff->nBtns,
6007						dev->button->numButtons);
6008	    return BadMatch;
6009	}
6010	wire+= (stuff->nBtns*SIZEOF(xkbActionWireDesc));
6011    }
6012    if (stuff->change&XkbXI_IndicatorsMask) {
6013	int status= Success;
6014	wire= CheckSetDeviceIndicators(wire,dev,stuff->nDeviceLedFBs,
6015							&status,client);
6016	if (status!=Success)
6017	    return status;
6018    }
6019    if (((wire-((char *)stuff))/4)!=stuff->length)
6020	return BadLength;
6021
6022    bzero((char *)&ed,SIZEOF(xkbExtensionDeviceNotify));
6023    ed.deviceID=	dev->id;
6024    wire= (char *)&stuff[1];
6025    if (change&XkbXI_ButtonActionsMask) {
6026	int			nBtns,sz,i;
6027	XkbAction *		acts;
6028	DeviceIntPtr		kbd;
6029
6030	nBtns= dev->button->numButtons;
6031	acts= dev->button->xkb_acts;
6032	if (acts==NULL) {
6033	    acts= _XkbTypedCalloc(nBtns,XkbAction);
6034	    if (!acts)
6035		return BadAlloc;
6036	    dev->button->xkb_acts= acts;
6037	}
6038	sz= stuff->nBtns*SIZEOF(xkbActionWireDesc);
6039	memcpy((char *)&acts[stuff->firstBtn],(char *)wire,sz);
6040	wire+= sz;
6041	ed.reason|=	XkbXI_ButtonActionsMask;
6042	ed.firstBtn=	stuff->firstBtn;
6043	ed.nBtns=	stuff->nBtns;
6044
6045	if (dev->key)	kbd= dev;
6046	else		kbd= (DeviceIntPtr)LookupKeyboardDevice();
6047	acts= &dev->button->xkb_acts[stuff->firstBtn];
6048	for (i=0;i<stuff->nBtns;i++,acts++) {
6049	    if (acts->type!=XkbSA_NoAction)
6050		XkbSetActionKeyMods(kbd->key->xkbInfo->desc,acts,0);
6051	}
6052    }
6053    if (stuff->change&XkbXI_IndicatorsMask) {
6054	int status= Success;
6055	wire= SetDeviceIndicators(wire,dev,change,stuff->nDeviceLedFBs,
6056							&status,client,&ed);
6057	if (status!=Success)
6058	    return status;
6059    }
6060    if ((stuff->change)&&(ed.reason))
6061	XkbSendExtensionDeviceNotify(dev,client,&ed);
6062    return client->noClientException;
6063}
6064
6065/***====================================================================***/
6066
6067int
6068ProcXkbSetDebuggingFlags(ClientPtr client)
6069{
6070CARD32 				newFlags,newCtrls,extraLength;
6071xkbSetDebuggingFlagsReply 	rep;
6072
6073    REQUEST(xkbSetDebuggingFlagsReq);
6074    REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq);
6075
6076    newFlags=  xkbDebugFlags&(~stuff->affectFlags);
6077    newFlags|= (stuff->flags&stuff->affectFlags);
6078    newCtrls=  xkbDebugCtrls&(~stuff->affectCtrls);
6079    newCtrls|= (stuff->ctrls&stuff->affectCtrls);
6080    if (xkbDebugFlags || newFlags || stuff->msgLength) {
6081	ErrorF("XkbDebug: Setting debug flags to 0x%lx\n",(long)newFlags);
6082	if (newCtrls!=xkbDebugCtrls)
6083	    ErrorF("XkbDebug: Setting debug controls to 0x%lx\n",(long)newCtrls);
6084    }
6085    extraLength= (stuff->length<<2)-sz_xkbSetDebuggingFlagsReq;
6086    if (stuff->msgLength>0) {
6087	char *msg;
6088	if (extraLength<XkbPaddedSize(stuff->msgLength)) {
6089	    ErrorF("XkbDebug: msgLength= %d, length= %ld (should be %d)\n",
6090			stuff->msgLength,(long)extraLength,
6091			XkbPaddedSize(stuff->msgLength));
6092	    return BadLength;
6093	}
6094	msg= (char *)&stuff[1];
6095	if (msg[stuff->msgLength-1]!='\0') {
6096	    ErrorF("XkbDebug: message not null-terminated\n");
6097	    return BadValue;
6098	}
6099	ErrorF("XkbDebug: %s\n",msg);
6100    }
6101    xkbDebugFlags = newFlags;
6102    xkbDebugCtrls = newCtrls;
6103
6104    XkbDisableLockActions= (xkbDebugCtrls&XkbDF_DisableLocks);
6105
6106    rep.type= X_Reply;
6107    rep.length = 0;
6108    rep.sequenceNumber = client->sequence;
6109    rep.currentFlags = newFlags;
6110    rep.currentCtrls = newCtrls;
6111    rep.supportedFlags = ~0;
6112    rep.supportedCtrls = ~0;
6113    if ( client->swapped ) {
6114	register int n;
6115	swaps(&rep.sequenceNumber, n);
6116	swapl(&rep.currentFlags, n);
6117	swapl(&rep.currentCtrls, n);
6118	swapl(&rep.supportedFlags, n);
6119	swapl(&rep.supportedCtrls, n);
6120    }
6121    WriteToClient(client,SIZEOF(xkbSetDebuggingFlagsReply), (char *)&rep);
6122    return client->noClientException;
6123}
6124
6125/***====================================================================***/
6126
6127static int
6128ProcXkbDispatch (ClientPtr client)
6129{
6130    REQUEST(xReq);
6131    switch (stuff->data)
6132    {
6133    case X_kbUseExtension:
6134	return ProcXkbUseExtension(client);
6135    case X_kbSelectEvents:
6136	return ProcXkbSelectEvents(client);
6137    case X_kbBell:
6138	return ProcXkbBell(client);
6139    case X_kbGetState:
6140	return ProcXkbGetState(client);
6141    case X_kbLatchLockState:
6142	return ProcXkbLatchLockState(client);
6143    case X_kbGetControls:
6144	return ProcXkbGetControls(client);
6145    case X_kbSetControls:
6146	return ProcXkbSetControls(client);
6147    case X_kbGetMap:
6148	return ProcXkbGetMap(client);
6149    case X_kbSetMap:
6150	return ProcXkbSetMap(client);
6151    case X_kbGetCompatMap:
6152	return ProcXkbGetCompatMap(client);
6153    case X_kbSetCompatMap:
6154	return ProcXkbSetCompatMap(client);
6155    case X_kbGetIndicatorState:
6156	return ProcXkbGetIndicatorState(client);
6157    case X_kbGetIndicatorMap:
6158	return ProcXkbGetIndicatorMap(client);
6159    case X_kbSetIndicatorMap:
6160	return ProcXkbSetIndicatorMap(client);
6161    case X_kbGetNamedIndicator:
6162	return ProcXkbGetNamedIndicator(client);
6163    case X_kbSetNamedIndicator:
6164	return ProcXkbSetNamedIndicator(client);
6165    case X_kbGetNames:
6166	return ProcXkbGetNames(client);
6167    case X_kbSetNames:
6168	return ProcXkbSetNames(client);
6169    case X_kbGetGeometry:
6170	return ProcXkbGetGeometry(client);
6171    case X_kbSetGeometry:
6172	return ProcXkbSetGeometry(client);
6173    case X_kbPerClientFlags:
6174	return ProcXkbPerClientFlags(client);
6175    case X_kbListComponents:
6176	return ProcXkbListComponents(client);
6177    case X_kbGetKbdByName:
6178	return ProcXkbGetKbdByName(client);
6179    case X_kbGetDeviceInfo:
6180	return ProcXkbGetDeviceInfo(client);
6181    case X_kbSetDeviceInfo:
6182	return ProcXkbSetDeviceInfo(client);
6183    case X_kbSetDebuggingFlags:
6184	return ProcXkbSetDebuggingFlags(client);
6185    default:
6186	return BadRequest;
6187    }
6188}
6189
6190static int
6191XkbClientGone(pointer data,XID id)
6192{
6193    DevicePtr	pXDev = (DevicePtr)data;
6194
6195    if (!XkbRemoveResourceClient(pXDev,id)) {
6196	ErrorF("Internal Error! bad RemoveResourceClient in XkbClientGone\n");
6197    }
6198    return 1;
6199}
6200
6201/*ARGSUSED*/
6202static void
6203XkbResetProc(ExtensionEntry *extEntry)
6204{
6205}
6206
6207void
6208XkbExtensionInit(void)
6209{
6210    ExtensionEntry *extEntry;
6211
6212    if ((extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors,
6213				 ProcXkbDispatch, SProcXkbDispatch,
6214				 XkbResetProc, StandardMinorOpcode))) {
6215	XkbReqCode = (unsigned char)extEntry->base;
6216	XkbEventBase = (unsigned char)extEntry->eventBase;
6217	XkbErrorBase = (unsigned char)extEntry->errorBase;
6218	XkbKeyboardErrorCode = XkbErrorBase+XkbKeyboard;
6219	RT_XKBCLIENT = CreateNewResourceType(XkbClientGone);
6220    }
6221    return;
6222}
6223
6224
6225