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