xkb.c revision 9ace9065
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 char *
4843_GetCountedString(char **wire_inout,Bool swap)
4844{
4845char *	wire,*str;
4846CARD16	len,*plen;
4847
4848    wire= *wire_inout;
4849    plen= (CARD16 *)wire;
4850    if (swap) {
4851	register int n;
4852	swaps(plen,n);
4853    }
4854    len= *plen;
4855    str= malloc(len+1);
4856    if (str) {
4857	memcpy(str,&wire[2],len);
4858	str[len]= '\0';
4859    }
4860    wire+= XkbPaddedSize(len+2);
4861    *wire_inout= wire;
4862    return str;
4863}
4864
4865static Status
4866_CheckSetDoodad(	char **		wire_inout,
4867			XkbGeometryPtr	geom,
4868			XkbSectionPtr	section,
4869			ClientPtr	client)
4870{
4871char *			wire;
4872xkbDoodadWireDesc *	dWire;
4873XkbDoodadPtr		doodad;
4874
4875    dWire= (xkbDoodadWireDesc *)(*wire_inout);
4876    wire= (char *)&dWire[1];
4877    if (client->swapped) {
4878	register int n;
4879	swapl(&dWire->any.name,n);
4880	swaps(&dWire->any.top,n);
4881	swaps(&dWire->any.left,n);
4882	swaps(&dWire->any.angle,n);
4883    }
4884    CHK_ATOM_ONLY(dWire->any.name);
4885    doodad= XkbAddGeomDoodad(geom,section,dWire->any.name);
4886    if (!doodad)
4887	return BadAlloc;
4888    doodad->any.type= dWire->any.type;
4889    doodad->any.priority= dWire->any.priority;
4890    doodad->any.top= dWire->any.top;
4891    doodad->any.left= dWire->any.left;
4892    doodad->any.angle= dWire->any.angle;
4893    switch (doodad->any.type) {
4894	case XkbOutlineDoodad:
4895	case XkbSolidDoodad:
4896	    if (dWire->shape.colorNdx>=geom->num_colors) {
4897		client->errorValue= _XkbErrCode3(0x40,geom->num_colors,
4898							dWire->shape.colorNdx);
4899		return BadMatch;
4900	    }
4901	    if (dWire->shape.shapeNdx>=geom->num_shapes) {
4902		client->errorValue= _XkbErrCode3(0x41,geom->num_shapes,
4903							dWire->shape.shapeNdx);
4904		return BadMatch;
4905	    }
4906	    doodad->shape.color_ndx= dWire->shape.colorNdx;
4907	    doodad->shape.shape_ndx= dWire->shape.shapeNdx;
4908	    break;
4909	case XkbTextDoodad:
4910	    if (dWire->text.colorNdx>=geom->num_colors) {
4911		client->errorValue= _XkbErrCode3(0x42,geom->num_colors,
4912							dWire->text.colorNdx);
4913		return BadMatch;
4914	    }
4915	    if (client->swapped) {
4916		register int n;
4917		swaps(&dWire->text.width,n);
4918		swaps(&dWire->text.height,n);
4919	    }
4920	    doodad->text.width= dWire->text.width;
4921	    doodad->text.height= dWire->text.height;
4922	    doodad->text.color_ndx= dWire->text.colorNdx;
4923	    doodad->text.text= _GetCountedString(&wire,client->swapped);
4924	    doodad->text.font= _GetCountedString(&wire,client->swapped);
4925	    break;
4926	case XkbIndicatorDoodad:
4927	    if (dWire->indicator.onColorNdx>=geom->num_colors) {
4928		client->errorValue= _XkbErrCode3(0x43,geom->num_colors,
4929						dWire->indicator.onColorNdx);
4930		return BadMatch;
4931	    }
4932	    if (dWire->indicator.offColorNdx>=geom->num_colors) {
4933		client->errorValue= _XkbErrCode3(0x44,geom->num_colors,
4934						dWire->indicator.offColorNdx);
4935		return BadMatch;
4936	    }
4937	    if (dWire->indicator.shapeNdx>=geom->num_shapes) {
4938		client->errorValue= _XkbErrCode3(0x45,geom->num_shapes,
4939						dWire->indicator.shapeNdx);
4940		return BadMatch;
4941	    }
4942	    doodad->indicator.shape_ndx= dWire->indicator.shapeNdx;
4943	    doodad->indicator.on_color_ndx= dWire->indicator.onColorNdx;
4944	    doodad->indicator.off_color_ndx= dWire->indicator.offColorNdx;
4945	    break;
4946	case XkbLogoDoodad:
4947	    if (dWire->logo.colorNdx>=geom->num_colors) {
4948		client->errorValue= _XkbErrCode3(0x46,geom->num_colors,
4949							dWire->logo.colorNdx);
4950		return BadMatch;
4951	    }
4952	    if (dWire->logo.shapeNdx>=geom->num_shapes) {
4953		client->errorValue= _XkbErrCode3(0x47,geom->num_shapes,
4954							dWire->logo.shapeNdx);
4955		return BadMatch;
4956	    }
4957	    doodad->logo.color_ndx= dWire->logo.colorNdx;
4958	    doodad->logo.shape_ndx= dWire->logo.shapeNdx;
4959	    doodad->logo.logo_name= _GetCountedString(&wire,client->swapped);
4960	    break;
4961	default:
4962	    client->errorValue= _XkbErrCode2(0x4F,dWire->any.type);
4963	    return BadValue;
4964    }
4965    *wire_inout= wire;
4966    return Success;
4967}
4968
4969static Status
4970_CheckSetOverlay(	char **		wire_inout,
4971			XkbGeometryPtr	geom,
4972			XkbSectionPtr	section,
4973			ClientPtr	client)
4974{
4975register int		r;
4976char *			wire;
4977XkbOverlayPtr		ol;
4978xkbOverlayWireDesc *	olWire;
4979xkbOverlayRowWireDesc *	rWire;
4980
4981    wire= *wire_inout;
4982    olWire= (xkbOverlayWireDesc *)wire;
4983    if (client->swapped) {
4984	register int n;
4985	swapl(&olWire->name,n);
4986    }
4987    CHK_ATOM_ONLY(olWire->name);
4988    ol= XkbAddGeomOverlay(section,olWire->name,olWire->nRows);
4989    rWire= (xkbOverlayRowWireDesc *)&olWire[1];
4990    for (r=0;r<olWire->nRows;r++) {
4991	register int		k;
4992	xkbOverlayKeyWireDesc *	kWire;
4993	XkbOverlayRowPtr	row;
4994
4995	if (rWire->rowUnder>section->num_rows) {
4996	    client->errorValue= _XkbErrCode4(0x20,r,section->num_rows,
4997							rWire->rowUnder);
4998	    return BadMatch;
4999	}
5000	row= XkbAddGeomOverlayRow(ol,rWire->rowUnder,rWire->nKeys);
5001	kWire= (xkbOverlayKeyWireDesc *)&rWire[1];
5002	for (k=0;k<rWire->nKeys;k++,kWire++) {
5003	    if (XkbAddGeomOverlayKey(ol,row,
5004	    		(char *)kWire->over,(char *)kWire->under)==NULL) {
5005		client->errorValue= _XkbErrCode3(0x21,r,k);
5006		return BadMatch;
5007	    }
5008	}
5009	rWire= (xkbOverlayRowWireDesc *)kWire;
5010    }
5011    olWire= (xkbOverlayWireDesc *)rWire;
5012    wire= (char *)olWire;
5013    *wire_inout= wire;
5014    return Success;
5015}
5016
5017static Status
5018_CheckSetSections( 	XkbGeometryPtr		geom,
5019			xkbSetGeometryReq *	req,
5020			char **			wire_inout,
5021			ClientPtr		client)
5022{
5023Status			status;
5024register int		s;
5025char *			wire;
5026xkbSectionWireDesc *	sWire;
5027XkbSectionPtr		section;
5028
5029    wire= *wire_inout;
5030    if (req->nSections<1)
5031	return Success;
5032    sWire= (xkbSectionWireDesc *)wire;
5033    for (s=0;s<req->nSections;s++) {
5034	register int		r;
5035	xkbRowWireDesc *	rWire;
5036	if (client->swapped) {
5037	    register int n;
5038	    swapl(&sWire->name,n);
5039	    swaps(&sWire->top,n);
5040	    swaps(&sWire->left,n);
5041	    swaps(&sWire->width,n);
5042	    swaps(&sWire->height,n);
5043	    swaps(&sWire->angle,n);
5044	}
5045	CHK_ATOM_ONLY(sWire->name);
5046	section= XkbAddGeomSection(geom,sWire->name,sWire->nRows,
5047					sWire->nDoodads,sWire->nOverlays);
5048	if (!section)
5049	    return BadAlloc;
5050	section->priority=	sWire->priority;
5051	section->top=		sWire->top;
5052	section->left=		sWire->left;
5053	section->width=		sWire->width;
5054	section->height=	sWire->height;
5055	section->angle=		sWire->angle;
5056	rWire= (xkbRowWireDesc *)&sWire[1];
5057	for (r=0;r<sWire->nRows;r++) {
5058	    register int	k;
5059	    XkbRowPtr		row;
5060	    xkbKeyWireDesc *	kWire;
5061	    if (client->swapped) {
5062		register int n;
5063		swaps(&rWire->top,n);
5064		swaps(&rWire->left,n);
5065	    }
5066	    row= XkbAddGeomRow(section,rWire->nKeys);
5067	    if (!row)
5068		return BadAlloc;
5069	    row->top= rWire->top;
5070	    row->left= rWire->left;
5071	    row->vertical= rWire->vertical;
5072	    kWire= (xkbKeyWireDesc *)&rWire[1];
5073	    for (k=0;k<rWire->nKeys;k++) {
5074		XkbKeyPtr	key;
5075		key= XkbAddGeomKey(row);
5076		if (!key)
5077		    return BadAlloc;
5078		memcpy(key->name.name,kWire[k].name,XkbKeyNameLength);
5079		key->gap= kWire[k].gap;
5080		key->shape_ndx= kWire[k].shapeNdx;
5081		key->color_ndx= kWire[k].colorNdx;
5082		if (key->shape_ndx>=geom->num_shapes) {
5083		    client->errorValue= _XkbErrCode3(0x10,key->shape_ndx,
5084							  geom->num_shapes);
5085		    return BadMatch;
5086		}
5087		if (key->color_ndx>=geom->num_colors) {
5088		    client->errorValue= _XkbErrCode3(0x11,key->color_ndx,
5089							  geom->num_colors);
5090		    return BadMatch;
5091		}
5092	    }
5093	    rWire= (xkbRowWireDesc *)&kWire[rWire->nKeys];
5094	}
5095	wire= (char *)rWire;
5096	if (sWire->nDoodads>0) {
5097	    register int d;
5098	    for (d=0;d<sWire->nDoodads;d++) {
5099		status=_CheckSetDoodad(&wire,geom,section,client);
5100		if (status!=Success)
5101		    return status;
5102	    }
5103	}
5104	if (sWire->nOverlays>0) {
5105	    register int o;
5106	    for (o=0;o<sWire->nOverlays;o++) {
5107		status= _CheckSetOverlay(&wire,geom,section,client);
5108		if (status!=Success)
5109		    return status;
5110	    }
5111	}
5112	sWire= (xkbSectionWireDesc *)wire;
5113    }
5114    wire= (char *)sWire;
5115    *wire_inout= wire;
5116    return Success;
5117}
5118
5119static Status
5120_CheckSetShapes( 	XkbGeometryPtr		geom,
5121			xkbSetGeometryReq *	req,
5122			char **			wire_inout,
5123			ClientPtr		client)
5124{
5125register int	i;
5126char *		wire;
5127
5128    wire= *wire_inout;
5129    if (req->nShapes<1) {
5130	client->errorValue= _XkbErrCode2(0x06,req->nShapes);
5131	return BadValue;
5132    }
5133    else {
5134	xkbShapeWireDesc *	shapeWire;
5135	XkbShapePtr		shape;
5136	register int		o;
5137	shapeWire= (xkbShapeWireDesc *)wire;
5138	for (i=0;i<req->nShapes;i++) {
5139	    xkbOutlineWireDesc *	olWire;
5140	    XkbOutlinePtr		ol;
5141	    shape= XkbAddGeomShape(geom,shapeWire->name,shapeWire->nOutlines);
5142	    if (!shape)
5143		return BadAlloc;
5144	    olWire= (xkbOutlineWireDesc *)(&shapeWire[1]);
5145	    for (o=0;o<shapeWire->nOutlines;o++) {
5146		register int		p;
5147		XkbPointPtr		pt;
5148		xkbPointWireDesc *	ptWire;
5149
5150		ol= XkbAddGeomOutline(shape,olWire->nPoints);
5151		if (!ol)
5152		    return BadAlloc;
5153		ol->corner_radius=	olWire->cornerRadius;
5154		ptWire= (xkbPointWireDesc *)&olWire[1];
5155		for (p=0,pt=ol->points;p<olWire->nPoints;p++,pt++) {
5156		    pt->x= ptWire[p].x;
5157		    pt->y= ptWire[p].y;
5158		    if (client->swapped) {
5159			register int n;
5160			swaps(&pt->x,n);
5161			swaps(&pt->y,n);
5162		    }
5163		}
5164		ol->num_points= olWire->nPoints;
5165		olWire= (xkbOutlineWireDesc *)(&ptWire[olWire->nPoints]);
5166	    }
5167	    if (shapeWire->primaryNdx!=XkbNoShape)
5168		shape->primary= &shape->outlines[shapeWire->primaryNdx];
5169	    if (shapeWire->approxNdx!=XkbNoShape)
5170		shape->approx= &shape->outlines[shapeWire->approxNdx];
5171	    shapeWire= (xkbShapeWireDesc *)olWire;
5172	}
5173	wire= (char *)shapeWire;
5174    }
5175    if (geom->num_shapes!=req->nShapes) {
5176	client->errorValue= _XkbErrCode3(0x07,geom->num_shapes,req->nShapes);
5177	return BadMatch;
5178    }
5179
5180    *wire_inout= wire;
5181    return Success;
5182}
5183
5184static Status
5185_CheckSetGeom(	XkbGeometryPtr		geom,
5186		xkbSetGeometryReq *	req,
5187		ClientPtr 		client)
5188{
5189register int	i;
5190Status		status;
5191char *		wire;
5192
5193    wire= (char *)&req[1];
5194    geom->label_font= _GetCountedString(&wire,client->swapped);
5195
5196    for (i=0;i<req->nProperties;i++) {
5197	char *name,*val;
5198	name= _GetCountedString(&wire,client->swapped);
5199        if (!name)
5200            return BadAlloc;
5201	val= _GetCountedString(&wire,client->swapped);
5202        if (!val) {
5203            free(name);
5204            return BadAlloc;
5205        }
5206	if (XkbAddGeomProperty(geom,name,val)==NULL) {
5207            free(name);
5208            free(val);
5209	    return BadAlloc;
5210        }
5211        free(name);
5212        free(val);
5213    }
5214
5215    if (req->nColors<2) {
5216	client->errorValue= _XkbErrCode3(0x01,2,req->nColors);
5217	return BadValue;
5218    }
5219    if (req->baseColorNdx>req->nColors) {
5220	client->errorValue=_XkbErrCode3(0x03,req->nColors,req->baseColorNdx);
5221	return BadMatch;
5222    }
5223    if (req->labelColorNdx>req->nColors) {
5224	client->errorValue= _XkbErrCode3(0x03,req->nColors,req->labelColorNdx);
5225	return BadMatch;
5226    }
5227    if (req->labelColorNdx==req->baseColorNdx) {
5228	client->errorValue= _XkbErrCode3(0x04,req->baseColorNdx,
5229                                         req->labelColorNdx);
5230	return BadMatch;
5231    }
5232
5233    for (i=0;i<req->nColors;i++) {
5234	char *name;
5235	name= _GetCountedString(&wire,client->swapped);
5236	if (!name)
5237            return BadAlloc;
5238        if (!XkbAddGeomColor(geom,name,geom->num_colors)) {
5239            free(name);
5240	    return BadAlloc;
5241        }
5242        free(name);
5243    }
5244    if (req->nColors!=geom->num_colors) {
5245	client->errorValue= _XkbErrCode3(0x05,req->nColors,geom->num_colors);
5246	return BadMatch;
5247    }
5248    geom->label_color= &geom->colors[req->labelColorNdx];
5249    geom->base_color= &geom->colors[req->baseColorNdx];
5250
5251    if ((status=_CheckSetShapes(geom,req,&wire,client))!=Success)
5252	return status;
5253
5254    if ((status=_CheckSetSections(geom,req,&wire,client))!=Success)
5255	return status;
5256
5257    for (i=0;i<req->nDoodads;i++) {
5258	status=_CheckSetDoodad(&wire,geom,NULL,client);
5259	if (status!=Success)
5260	    return status;
5261    }
5262
5263    for (i=0;i<req->nKeyAliases;i++) {
5264	if (XkbAddGeomKeyAlias(geom,&wire[XkbKeyNameLength],wire)==NULL)
5265	    return BadAlloc;
5266	wire+= 2*XkbKeyNameLength;
5267    }
5268    return Success;
5269}
5270
5271static int
5272_XkbSetGeometry(ClientPtr client, DeviceIntPtr dev, xkbSetGeometryReq *stuff)
5273{
5274    XkbDescPtr		xkb;
5275    Bool		new_name;
5276    xkbNewKeyboardNotify	nkn;
5277    XkbGeometryPtr	geom,old;
5278    XkbGeometrySizesRec	sizes;
5279    Status		status;
5280
5281    xkb= dev->key->xkbInfo->desc;
5282    old= xkb->geom;
5283    xkb->geom= NULL;
5284
5285    sizes.which=		XkbGeomAllMask;
5286    sizes.num_properties=	stuff->nProperties;
5287    sizes.num_colors=	stuff->nColors;
5288    sizes.num_shapes=	stuff->nShapes;
5289    sizes.num_sections=	stuff->nSections;
5290    sizes.num_doodads=	stuff->nDoodads;
5291    sizes.num_key_aliases=	stuff->nKeyAliases;
5292    if ((status= XkbAllocGeometry(xkb,&sizes))!=Success) {
5293        xkb->geom= old;
5294        return status;
5295    }
5296    geom= xkb->geom;
5297    geom->name= stuff->name;
5298    geom->width_mm= stuff->widthMM;
5299    geom->height_mm= stuff->heightMM;
5300    if ((status= _CheckSetGeom(geom,stuff,client))!=Success) {
5301        XkbFreeGeometry(geom,XkbGeomAllMask,TRUE);
5302        xkb->geom= old;
5303        return status;
5304    }
5305    new_name= (xkb->names->geometry!=geom->name);
5306    xkb->names->geometry= geom->name;
5307    if (old)
5308        XkbFreeGeometry(old,XkbGeomAllMask,TRUE);
5309    if (new_name) {
5310        xkbNamesNotify	nn;
5311        memset(&nn, 0, sizeof(xkbNamesNotify));
5312        nn.changed= XkbGeometryNameMask;
5313        XkbSendNamesNotify(dev,&nn);
5314    }
5315    nkn.deviceID= nkn.oldDeviceID= dev->id;
5316    nkn.minKeyCode= nkn.oldMinKeyCode= xkb->min_key_code;
5317    nkn.maxKeyCode= nkn.oldMaxKeyCode= xkb->max_key_code;
5318    nkn.requestMajor=	XkbReqCode;
5319    nkn.requestMinor=	X_kbSetGeometry;
5320    nkn.changed=	XkbNKN_GeometryMask;
5321    XkbSendNewKeyboardNotify(dev,&nkn);
5322    return Success;
5323}
5324
5325int
5326ProcXkbSetGeometry(ClientPtr client)
5327{
5328    DeviceIntPtr        dev;
5329    int                 rc;
5330
5331    REQUEST(xkbSetGeometryReq);
5332    REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq);
5333
5334    if (!(client->xkbClientFlags&_XkbClientInitialized))
5335	return BadAccess;
5336
5337    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
5338    CHK_ATOM_OR_NONE(stuff->name);
5339
5340    rc = _XkbSetGeometry(client, dev, stuff);
5341    if (rc != Success)
5342        return rc;
5343
5344    if (stuff->deviceSpec == XkbUseCoreKbd)
5345    {
5346        DeviceIntPtr other;
5347        for (other = inputInfo.devices; other; other = other->next)
5348        {
5349            if ((other != dev) && other->key && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev)
5350            {
5351                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
5352                if (rc == Success)
5353                    _XkbSetGeometry(client, other, stuff);
5354            }
5355        }
5356    }
5357
5358    return Success;
5359}
5360
5361/***====================================================================***/
5362
5363int
5364ProcXkbPerClientFlags(ClientPtr client)
5365{
5366    DeviceIntPtr 		dev;
5367    xkbPerClientFlagsReply 	rep;
5368    XkbInterestPtr		interest;
5369    Mask access_mode = DixGetAttrAccess | DixSetAttrAccess;
5370
5371    REQUEST(xkbPerClientFlagsReq);
5372    REQUEST_SIZE_MATCH(xkbPerClientFlagsReq);
5373
5374    if (!(client->xkbClientFlags&_XkbClientInitialized))
5375	return BadAccess;
5376
5377    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
5378    CHK_MASK_LEGAL(0x01,stuff->change,XkbPCF_AllFlagsMask);
5379    CHK_MASK_MATCH(0x02,stuff->change,stuff->value);
5380
5381    interest = XkbFindClientResource((DevicePtr)dev,client);
5382    memset(&rep, 0, sizeof(xkbPerClientFlagsReply));
5383    rep.type= X_Reply;
5384    rep.length = 0;
5385    rep.sequenceNumber = client->sequence;
5386    if (stuff->change) {
5387	client->xkbClientFlags&= ~stuff->change;
5388	client->xkbClientFlags|= stuff->value;
5389    }
5390    if (stuff->change&XkbPCF_AutoResetControlsMask) {
5391	Bool	want;
5392	want= stuff->value&XkbPCF_AutoResetControlsMask;
5393	if (interest && !want) {
5394	    interest->autoCtrls= interest->autoCtrlValues= 0;
5395	}
5396	else if (want && (!interest)) {
5397	    XID id = FakeClientID(client->index);
5398	    if (!AddResource(id,RT_XKBCLIENT,dev))
5399		return BadAlloc;
5400	    interest= XkbAddClientResource((DevicePtr)dev,client,id);
5401	    if (!interest)
5402		return BadAlloc;
5403	}
5404	if (interest && want ) {
5405	    register unsigned affect;
5406	    affect= stuff->ctrlsToChange;
5407
5408	    CHK_MASK_LEGAL(0x03,affect,XkbAllBooleanCtrlsMask);
5409	    CHK_MASK_MATCH(0x04,affect,stuff->autoCtrls);
5410	    CHK_MASK_MATCH(0x05,stuff->autoCtrls,stuff->autoCtrlValues);
5411
5412	    interest->autoCtrls&= ~affect;
5413	    interest->autoCtrlValues&= ~affect;
5414	    interest->autoCtrls|= stuff->autoCtrls&affect;
5415	    interest->autoCtrlValues|= stuff->autoCtrlValues&affect;
5416	}
5417    }
5418    rep.supported = XkbPCF_AllFlagsMask;
5419    rep.value= client->xkbClientFlags&XkbPCF_AllFlagsMask;
5420    if (interest) {
5421	rep.autoCtrls= interest->autoCtrls;
5422	rep.autoCtrlValues= interest->autoCtrlValues;
5423    }
5424    else {
5425	rep.autoCtrls= rep.autoCtrlValues= 0;
5426    }
5427    if ( client->swapped ) {
5428	register int n;
5429	swaps(&rep.sequenceNumber, n);
5430	swapl(&rep.supported,n);
5431	swapl(&rep.value,n);
5432	swapl(&rep.autoCtrls,n);
5433	swapl(&rep.autoCtrlValues,n);
5434    }
5435    WriteToClient(client,SIZEOF(xkbPerClientFlagsReply), (char *)&rep);
5436    return Success;
5437}
5438
5439/***====================================================================***/
5440
5441/* all latin-1 alphanumerics, plus parens, minus, underscore, slash */
5442/* and wildcards */
5443static unsigned char componentSpecLegal[] = {
5444        0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x87,
5445        0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07,
5446        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5447        0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
5448};
5449
5450/* same as above but accepts percent, plus and bar too */
5451static unsigned char componentExprLegal[] = {
5452        0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0xff, 0x87,
5453        0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x17,
5454        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5455        0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
5456};
5457
5458static char *
5459GetComponentSpec(unsigned char **pWire,Bool allowExpr,int *errRtrn)
5460{
5461int		len;
5462register int	i;
5463unsigned char	*wire,*str,*tmp,*legal;
5464
5465    if (allowExpr)	legal= &componentExprLegal[0];
5466    else		legal= &componentSpecLegal[0];
5467
5468    wire= *pWire;
5469    len= (*(unsigned char *)wire++);
5470    if (len>0) {
5471	str= calloc(1, len+1);
5472	if (str) {
5473	    tmp= str;
5474	    for (i=0;i<len;i++) {
5475		if (legal[(*wire)/8]&(1<<((*wire)%8)))
5476		    *tmp++= *wire++;
5477		else wire++;
5478	    }
5479	    if (tmp!=str)
5480		*tmp++= '\0';
5481	    else {
5482		free(str);
5483		str= NULL;
5484	    }
5485	}
5486	else {
5487	    *errRtrn= BadAlloc;
5488	}
5489    }
5490    else {
5491	str= NULL;
5492    }
5493    *pWire= wire;
5494    return (char *)str;
5495}
5496
5497/***====================================================================***/
5498
5499int
5500ProcXkbListComponents(ClientPtr client)
5501{
5502    DeviceIntPtr 		dev;
5503    xkbListComponentsReply 	rep;
5504    unsigned			len;
5505    int				status;
5506    unsigned char *		str;
5507    XkbSrvListInfoRec		list;
5508
5509    REQUEST(xkbListComponentsReq);
5510    REQUEST_AT_LEAST_SIZE(xkbListComponentsReq);
5511
5512    if (!(client->xkbClientFlags&_XkbClientInitialized))
5513	return BadAccess;
5514
5515    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
5516
5517    status= Success;
5518    str= (unsigned char *)&stuff[1];
5519    memset(&list, 0, sizeof(XkbSrvListInfoRec));
5520    list.maxRtrn= stuff->maxNames;
5521    list.pattern[_XkbListKeycodes]= GetComponentSpec(&str,FALSE,&status);
5522    list.pattern[_XkbListTypes]= GetComponentSpec(&str,FALSE,&status);
5523    list.pattern[_XkbListCompat]= GetComponentSpec(&str,FALSE,&status);
5524    list.pattern[_XkbListSymbols]= GetComponentSpec(&str,FALSE,&status);
5525    list.pattern[_XkbListGeometry]= GetComponentSpec(&str,FALSE,&status);
5526    if (status!=Success)
5527	return status;
5528    len= str-((unsigned char *)stuff);
5529    if ((XkbPaddedSize(len)/4)!=stuff->length)
5530	return BadLength;
5531    if ((status=XkbDDXList(dev,&list,client))!=Success) {
5532	free(list.pool);
5533	list.pool = NULL;
5534	return status;
5535    }
5536    memset(&rep, 0, sizeof(xkbListComponentsReply));
5537    rep.type= X_Reply;
5538    rep.deviceID = dev->id;
5539    rep.sequenceNumber = client->sequence;
5540    rep.length = XkbPaddedSize(list.nPool)/4;
5541    rep.nKeymaps = 0;
5542    rep.nKeycodes = list.nFound[_XkbListKeycodes];
5543    rep.nTypes = list.nFound[_XkbListTypes];
5544    rep.nCompatMaps = list.nFound[_XkbListCompat];
5545    rep.nSymbols = list.nFound[_XkbListSymbols];
5546    rep.nGeometries = list.nFound[_XkbListGeometry];
5547    rep.extra=	0;
5548    if (list.nTotal>list.maxRtrn)
5549	rep.extra = (list.nTotal-list.maxRtrn);
5550    if (client->swapped) {
5551	register int n;
5552	swaps(&rep.sequenceNumber,n);
5553	swapl(&rep.length,n);
5554	swaps(&rep.nKeymaps,n);
5555	swaps(&rep.nKeycodes,n);
5556	swaps(&rep.nTypes,n);
5557	swaps(&rep.nCompatMaps,n);
5558	swaps(&rep.nSymbols,n);
5559	swaps(&rep.nGeometries,n);
5560	swaps(&rep.extra,n);
5561    }
5562    WriteToClient(client,SIZEOF(xkbListComponentsReply),(char *)&rep);
5563    if (list.nPool && list.pool) {
5564	WriteToClient(client,XkbPaddedSize(list.nPool), (char *)list.pool);
5565	free(list.pool);
5566	list.pool= NULL;
5567    }
5568    return Success;
5569}
5570
5571/***====================================================================***/
5572
5573int
5574ProcXkbGetKbdByName(ClientPtr client)
5575{
5576    DeviceIntPtr 		dev;
5577    DeviceIntPtr                tmpd;
5578    xkbGetKbdByNameReply 	rep = {0};
5579    xkbGetMapReply		mrep = {0};
5580    xkbGetCompatMapReply	crep = {0};
5581    xkbGetIndicatorMapReply	irep = {0};
5582    xkbGetNamesReply		nrep = {0};
5583    xkbGetGeometryReply		grep = {0};
5584    XkbComponentNamesRec	names = {0};
5585    XkbDescPtr			xkb, new;
5586    unsigned char *		str;
5587    char 			mapFile[PATH_MAX];
5588    unsigned			len;
5589    unsigned			fwant,fneed,reported;
5590    int				status;
5591    Bool			geom_changed;
5592    XkbSrvLedInfoPtr            old_sli;
5593    XkbSrvLedInfoPtr            sli;
5594    Mask access_mode = DixGetAttrAccess | DixManageAccess;
5595
5596    REQUEST(xkbGetKbdByNameReq);
5597    REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq);
5598
5599    if (!(client->xkbClientFlags&_XkbClientInitialized))
5600	return BadAccess;
5601
5602    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
5603
5604    xkb = dev->key->xkbInfo->desc;
5605    status= Success;
5606    str= (unsigned char *)&stuff[1];
5607    if (GetComponentSpec(&str,TRUE,&status)) /* keymap, unsupported */
5608        return BadMatch;
5609    names.keycodes= GetComponentSpec(&str,TRUE,&status);
5610    names.types= GetComponentSpec(&str,TRUE,&status);
5611    names.compat= GetComponentSpec(&str,TRUE,&status);
5612    names.symbols= GetComponentSpec(&str,TRUE,&status);
5613    names.geometry= GetComponentSpec(&str,TRUE,&status);
5614    if (status!=Success)
5615	return status;
5616    len= str-((unsigned char *)stuff);
5617    if ((XkbPaddedSize(len)/4)!=stuff->length)
5618	return BadLength;
5619
5620    CHK_MASK_LEGAL(0x01,stuff->want,XkbGBN_AllComponentsMask);
5621    CHK_MASK_LEGAL(0x02,stuff->need,XkbGBN_AllComponentsMask);
5622
5623    if (stuff->load)
5624	 fwant= XkbGBN_AllComponentsMask;
5625    else fwant= stuff->want|stuff->need;
5626    if ((!names.compat)&&
5627        (fwant&(XkbGBN_CompatMapMask|XkbGBN_IndicatorMapMask))) {
5628        names.compat= _XkbDupString("%");
5629    }
5630    if ((!names.types)&&(fwant&(XkbGBN_TypesMask))) {
5631        names.types= _XkbDupString("%");
5632    }
5633    if ((!names.symbols)&&(fwant&XkbGBN_SymbolsMask)) {
5634        names.symbols= _XkbDupString("%");
5635    }
5636    geom_changed= ((names.geometry!=NULL)&&(strcmp(names.geometry,"%")!=0));
5637    if ((!names.geometry)&&(fwant&XkbGBN_GeometryMask)) {
5638        names.geometry= _XkbDupString("%");
5639        geom_changed= FALSE;
5640    }
5641
5642    memset(mapFile, 0, PATH_MAX);
5643    rep.type= X_Reply;
5644    rep.deviceID = dev->id;
5645    rep.sequenceNumber = client->sequence;
5646    rep.length = 0;
5647    rep.minKeyCode = xkb->min_key_code;
5648    rep.maxKeyCode = xkb->max_key_code;
5649    rep.loaded=	FALSE;
5650    fwant= XkbConvertGetByNameComponents(TRUE,stuff->want)|XkmVirtualModsMask;
5651    fneed= XkbConvertGetByNameComponents(TRUE,stuff->need);
5652    rep.reported= XkbConvertGetByNameComponents(FALSE,fwant|fneed);
5653    if (stuff->load) {
5654	fneed|= XkmKeymapRequired;
5655	fwant|= XkmKeymapLegal;
5656    }
5657    if ((fwant|fneed)&XkmSymbolsMask) {
5658	fneed|= XkmKeyNamesIndex|XkmTypesIndex;
5659	fwant|= XkmIndicatorsIndex;
5660    }
5661
5662    /* We pass dev in here so we can get the old names out if needed. */
5663    rep.found = XkbDDXLoadKeymapByNames(dev,&names,fwant,fneed,&new,
5664                                        mapFile,PATH_MAX);
5665    rep.newKeyboard= FALSE;
5666    rep.pad1= rep.pad2= rep.pad3= rep.pad4= 0;
5667
5668    stuff->want|= stuff->need;
5669    if (new==NULL)
5670	rep.reported= 0;
5671    else {
5672	if (stuff->load)
5673	    rep.loaded= TRUE;
5674	if (stuff->load ||
5675		((rep.reported&XkbGBN_SymbolsMask) && (new->compat))) {
5676	    XkbChangesRec changes;
5677	    memset(&changes, 0, sizeof(changes));
5678	    XkbUpdateDescActions(new,
5679			new->min_key_code,XkbNumKeys(new),
5680			&changes);
5681	}
5682
5683	if (new->map==NULL)
5684	    rep.reported&= ~(XkbGBN_SymbolsMask|XkbGBN_TypesMask);
5685	else if (rep.reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask)) {
5686	    mrep.type= X_Reply;
5687	    mrep.deviceID = dev->id;
5688	    mrep.sequenceNumber= client->sequence;
5689	    mrep.length = ((SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2);
5690	    mrep.minKeyCode = new->min_key_code;
5691	    mrep.maxKeyCode = new->max_key_code;
5692	    mrep.present = 0;
5693	    mrep.totalSyms = mrep.totalActs =
5694		mrep.totalKeyBehaviors= mrep.totalKeyExplicit=
5695		mrep.totalModMapKeys= mrep.totalVModMapKeys= 0;
5696	    if (rep.reported&(XkbGBN_TypesMask|XkbGBN_ClientSymbolsMask)) {
5697		mrep.present|= XkbKeyTypesMask;
5698		mrep.firstType = 0;
5699		mrep.nTypes = mrep.totalTypes= new->map->num_types;
5700	    }
5701	    else {
5702		mrep.firstType = mrep.nTypes= 0;
5703		mrep.totalTypes= 0;
5704	    }
5705	    if (rep.reported&XkbGBN_ClientSymbolsMask) {
5706		mrep.present|= (XkbKeySymsMask|XkbModifierMapMask);
5707		mrep.firstKeySym = mrep.firstModMapKey= new->min_key_code;
5708		mrep.nKeySyms = mrep.nModMapKeys= XkbNumKeys(new);
5709	    }
5710	    else {
5711		mrep.firstKeySym= mrep.firstModMapKey= 0;
5712		mrep.nKeySyms= mrep.nModMapKeys= 0;
5713	    }
5714	    if (rep.reported&XkbGBN_ServerSymbolsMask) {
5715		mrep.present|= XkbAllServerInfoMask;
5716		mrep.virtualMods= ~0;
5717		mrep.firstKeyAct = mrep.firstKeyBehavior =
5718			mrep.firstKeyExplicit = new->min_key_code;
5719		mrep.nKeyActs = mrep.nKeyBehaviors =
5720			mrep.nKeyExplicit = XkbNumKeys(new);
5721		mrep.firstVModMapKey= new->min_key_code;
5722		mrep.nVModMapKeys= XkbNumKeys(new);
5723	    }
5724	    else {
5725		mrep.virtualMods= 0;
5726		mrep.firstKeyAct= mrep.firstKeyBehavior=
5727			mrep.firstKeyExplicit = 0;
5728		mrep.nKeyActs= mrep.nKeyBehaviors= mrep.nKeyExplicit= 0;
5729	    }
5730	    XkbComputeGetMapReplySize(new,&mrep);
5731	    rep.length+= SIZEOF(xGenericReply)/4+mrep.length;
5732	}
5733	if (new->compat==NULL)
5734	    rep.reported&= ~XkbGBN_CompatMapMask;
5735	else if (rep.reported&XkbGBN_CompatMapMask) {
5736	    crep.type= X_Reply;
5737	    crep.deviceID= dev->id;
5738	    crep.sequenceNumber= client->sequence;
5739	    crep.length= 0;
5740	    crep.groups= XkbAllGroupsMask;
5741	    crep.firstSI= 0;
5742	    crep.nSI= crep.nTotalSI= new->compat->num_si;
5743	    XkbComputeGetCompatMapReplySize(new->compat,&crep);
5744	    rep.length+= SIZEOF(xGenericReply)/4+crep.length;
5745	}
5746	if (new->indicators==NULL)
5747	    rep.reported&= ~XkbGBN_IndicatorMapMask;
5748	else if (rep.reported&XkbGBN_IndicatorMapMask) {
5749	    irep.type= X_Reply;
5750	    irep.deviceID= dev->id;
5751	    irep.sequenceNumber= client->sequence;
5752	    irep.length= 0;
5753	    irep.which= XkbAllIndicatorsMask;
5754	    XkbComputeGetIndicatorMapReplySize(new->indicators,&irep);
5755	    rep.length+= SIZEOF(xGenericReply)/4+irep.length;
5756	}
5757	if (new->names==NULL)
5758	    rep.reported&= ~(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask);
5759	else if (rep.reported&(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask)) {
5760	    nrep.type= X_Reply;
5761	    nrep.deviceID= dev->id;
5762	    nrep.sequenceNumber= client->sequence;
5763	    nrep.length= 0;
5764	    nrep.minKeyCode= new->min_key_code;
5765	    nrep.maxKeyCode= new->max_key_code;
5766	    if (rep.reported&XkbGBN_OtherNamesMask) {
5767		nrep.which= XkbAllNamesMask;
5768		if (new->map!=NULL)
5769		     nrep.nTypes= new->map->num_types;
5770		else nrep.nTypes= 0;
5771		nrep.nKTLevels= 0;
5772		nrep.groupNames= XkbAllGroupsMask;
5773		nrep.virtualMods= XkbAllVirtualModsMask;
5774		nrep.indicators= XkbAllIndicatorsMask;
5775		nrep.nRadioGroups= new->names->num_rg;
5776	    }
5777	    else {
5778		nrep.which= 0;
5779		nrep.nTypes= 0;
5780		nrep.nKTLevels= 0;
5781		nrep.groupNames= 0;
5782		nrep.virtualMods= 0;
5783		nrep.indicators= 0;
5784		nrep.nRadioGroups= 0;
5785	    }
5786	    if (rep.reported&XkbGBN_KeyNamesMask) {
5787		nrep.which|= XkbKeyNamesMask;
5788		nrep.firstKey= new->min_key_code;
5789		nrep.nKeys= XkbNumKeys(new);
5790		nrep.nKeyAliases= new->names->num_key_aliases;
5791		if (nrep.nKeyAliases)
5792		    nrep.which|= XkbKeyAliasesMask;
5793	    }
5794	    else {
5795		nrep.which&= ~(XkbKeyNamesMask|XkbKeyAliasesMask);
5796		nrep.firstKey= nrep.nKeys= 0;
5797		nrep.nKeyAliases= 0;
5798	    }
5799	    XkbComputeGetNamesReplySize(new,&nrep);
5800	    rep.length+= SIZEOF(xGenericReply)/4+nrep.length;
5801	}
5802	if (new->geom==NULL)
5803	    rep.reported&= ~XkbGBN_GeometryMask;
5804	else if (rep.reported&XkbGBN_GeometryMask) {
5805	    grep.type= X_Reply;
5806	    grep.deviceID= dev->id;
5807	    grep.sequenceNumber= client->sequence;
5808	    grep.length= 0;
5809	    grep.found= TRUE;
5810	    grep.pad= 0;
5811	    grep.widthMM= grep.heightMM= 0;
5812	    grep.nProperties= grep.nColors= grep.nShapes= 0;
5813	    grep.nSections= grep.nDoodads= 0;
5814	    grep.baseColorNdx= grep.labelColorNdx= 0;
5815	    XkbComputeGetGeometryReplySize(new->geom,&grep,None);
5816	    rep.length+= SIZEOF(xGenericReply)/4+grep.length;
5817	}
5818    }
5819
5820    reported= rep.reported;
5821    if ( client->swapped ) {
5822	register int n;
5823	swaps(&rep.sequenceNumber,n);
5824	swapl(&rep.length,n);
5825	swaps(&rep.found,n);
5826	swaps(&rep.reported,n);
5827    }
5828    WriteToClient(client,SIZEOF(xkbGetKbdByNameReply), (char *)&rep);
5829    if (reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask))
5830	XkbSendMap(client,new,&mrep);
5831    if (reported&XkbGBN_CompatMapMask)
5832	XkbSendCompatMap(client,new->compat,&crep);
5833    if (reported&XkbGBN_IndicatorMapMask)
5834	XkbSendIndicatorMap(client,new->indicators,&irep);
5835    if (reported&(XkbGBN_KeyNamesMask|XkbGBN_OtherNamesMask))
5836	XkbSendNames(client,new,&nrep);
5837    if (reported&XkbGBN_GeometryMask)
5838	XkbSendGeometry(client,new->geom,&grep,FALSE);
5839    if (rep.loaded) {
5840	XkbDescPtr		old_xkb;
5841	xkbNewKeyboardNotify 	nkn;
5842	int 			i,nG,nTG;
5843	old_xkb= xkb;
5844	xkb= new;
5845	dev->key->xkbInfo->desc= xkb;
5846	new= old_xkb; /* so it'll get freed automatically */
5847
5848	*xkb->ctrls= *old_xkb->ctrls;
5849	for (nG=nTG=0,i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
5850	    nG= XkbKeyNumGroups(xkb,i);
5851	    if (nG>=XkbNumKbdGroups) {
5852		nTG= XkbNumKbdGroups;
5853		break;
5854	    }
5855	    if (nG>nTG) {
5856		nTG= nG;
5857	    }
5858	}
5859	xkb->ctrls->num_groups= nTG;
5860
5861        for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
5862            if ((tmpd == dev) || (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) {
5863                if (tmpd != dev)
5864                    XkbCopyDeviceKeymap(tmpd, dev);
5865
5866                if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) {
5867                    old_sli = tmpd->kbdfeed->xkb_sli;
5868                    tmpd->kbdfeed->xkb_sli = NULL;
5869                    sli = XkbAllocSrvLedInfo(tmpd, tmpd->kbdfeed, NULL, 0);
5870                    if (sli) {
5871                        sli->explicitState = old_sli->explicitState;
5872                        sli->effectiveState = old_sli->effectiveState;
5873                    }
5874                    tmpd->kbdfeed->xkb_sli = sli;
5875                    XkbFreeSrvLedInfo(old_sli);
5876                }
5877            }
5878        }
5879
5880	nkn.deviceID= nkn.oldDeviceID= dev->id;
5881	nkn.minKeyCode= new->min_key_code;
5882	nkn.maxKeyCode= new->max_key_code;
5883	nkn.oldMinKeyCode= xkb->min_key_code;
5884	nkn.oldMaxKeyCode= xkb->max_key_code;
5885	nkn.requestMajor= XkbReqCode;
5886	nkn.requestMinor= X_kbGetKbdByName;
5887	nkn.changed= XkbNKN_KeycodesMask;
5888	if (geom_changed)
5889	    nkn.changed|= XkbNKN_GeometryMask;
5890	XkbSendNewKeyboardNotify(dev,&nkn);
5891
5892	if (!IsMaster(dev) && dev->u.master)
5893	{
5894	    DeviceIntPtr master = dev->u.master;
5895	    if (master->u.lastSlave == dev)
5896	    {
5897		XkbCopyDeviceKeymap(dev->u.master, dev);
5898		XkbSendNewKeyboardNotify(dev,&nkn);
5899	    }
5900	}
5901    }
5902    if ((new!=NULL)&&(new!=xkb)) {
5903	XkbFreeKeyboard(new,XkbAllComponentsMask,TRUE);
5904	new= NULL;
5905    }
5906    XkbFreeComponentNames(&names, FALSE);
5907    return Success;
5908}
5909
5910/***====================================================================***/
5911
5912static int
5913ComputeDeviceLedInfoSize(	DeviceIntPtr		dev,
5914				unsigned int		what,
5915				XkbSrvLedInfoPtr	sli)
5916{
5917int			nNames,nMaps;
5918register unsigned 	n,bit;
5919
5920    if (sli==NULL)
5921	return 0;
5922    nNames= nMaps= 0;
5923    if ((what&XkbXI_IndicatorNamesMask)==0)
5924	sli->namesPresent= 0;
5925    if ((what&XkbXI_IndicatorMapsMask)==0)
5926	sli->mapsPresent= 0;
5927
5928    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
5929	if (sli->names && sli->names[n]!=None) {
5930	    sli->namesPresent|= bit;
5931	    nNames++;
5932	}
5933	if (sli->maps && XkbIM_InUse(&sli->maps[n])) {
5934	    sli->mapsPresent|= bit;
5935	    nMaps++;
5936	}
5937    }
5938    return (nNames*4)+(nMaps*SIZEOF(xkbIndicatorMapWireDesc));
5939}
5940
5941static int
5942CheckDeviceLedFBs(	DeviceIntPtr			dev,
5943			int				class,
5944			int				id,
5945			xkbGetDeviceInfoReply *		rep,
5946			ClientPtr			client)
5947{
5948int			nFBs= 0;
5949int			length= 0;
5950Bool			classOk;
5951
5952    if (class==XkbDfltXIClass) {
5953	if (dev->kbdfeed)	class= KbdFeedbackClass;
5954	else if (dev->leds)	class= LedFeedbackClass;
5955	else {
5956	    client->errorValue= _XkbErrCode2(XkbErr_BadClass,class);
5957	    return XkbKeyboardErrorCode;
5958	}
5959    }
5960    classOk= FALSE;
5961    if ((dev->kbdfeed)&&((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) {
5962	KbdFeedbackPtr kf;
5963	classOk= TRUE;
5964	for (kf= dev->kbdfeed;(kf);kf=kf->next) {
5965	    if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=kf->ctrl.id))
5966		continue;
5967	    nFBs++;
5968	    length+= SIZEOF(xkbDeviceLedsWireDesc);
5969	    if (!kf->xkb_sli)
5970		kf->xkb_sli= XkbAllocSrvLedInfo(dev,kf,NULL,0);
5971	    length+= ComputeDeviceLedInfoSize(dev,rep->present,kf->xkb_sli);
5972	    if (id!=XkbAllXIIds)
5973		break;
5974	}
5975    }
5976    if ((dev->leds)&&((class==LedFeedbackClass)||(class==XkbAllXIClasses))) {
5977	LedFeedbackPtr lf;
5978	classOk= TRUE;
5979	for (lf= dev->leds;(lf);lf=lf->next) {
5980	    if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=lf->ctrl.id))
5981		continue;
5982	    nFBs++;
5983	    length+= SIZEOF(xkbDeviceLedsWireDesc);
5984	    if (!lf->xkb_sli)
5985		lf->xkb_sli= XkbAllocSrvLedInfo(dev,NULL,lf,0);
5986	    length+= ComputeDeviceLedInfoSize(dev,rep->present,lf->xkb_sli);
5987	    if (id!=XkbAllXIIds)
5988		break;
5989	}
5990    }
5991    if (nFBs>0) {
5992        rep->nDeviceLedFBs= nFBs;
5993        rep->length+= (length/4);
5994	return Success;
5995    }
5996    if (classOk) client->errorValue= _XkbErrCode2(XkbErr_BadId,id);
5997    else	 client->errorValue= _XkbErrCode2(XkbErr_BadClass,class);
5998    return XkbKeyboardErrorCode;
5999}
6000
6001static int
6002SendDeviceLedInfo(	XkbSrvLedInfoPtr	sli,
6003			ClientPtr		client)
6004{
6005xkbDeviceLedsWireDesc	wire;
6006int			length;
6007
6008    length= 0;
6009    wire.ledClass= 		sli->class;
6010    wire.ledID= 		sli->id;
6011    wire.namesPresent= 		sli->namesPresent;
6012    wire.mapsPresent=   	sli->mapsPresent;
6013    wire.physIndicators= 	sli->physIndicators;
6014    wire.state=			sli->effectiveState;
6015    if (client->swapped) {
6016	register int n;
6017	swaps(&wire.ledClass,n);
6018	swaps(&wire.ledID,n);
6019	swapl(&wire.namesPresent,n);
6020	swapl(&wire.mapsPresent,n);
6021	swapl(&wire.physIndicators,n);
6022	swapl(&wire.state,n);
6023    }
6024    WriteToClient(client,SIZEOF(xkbDeviceLedsWireDesc),(char *)&wire);
6025    length+= SIZEOF(xkbDeviceLedsWireDesc);
6026    if (sli->namesPresent|sli->mapsPresent) {
6027	register unsigned i,bit;
6028	if (sli->namesPresent) {
6029	    CARD32	awire;
6030	    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
6031		if (sli->namesPresent&bit) {
6032		    awire= (CARD32)sli->names[i];
6033		    if (client->swapped) {
6034			register int n;
6035			swapl(&awire,n);
6036		    }
6037		    WriteToClient(client,4,(char *)&awire);
6038		    length+= 4;
6039		}
6040	    }
6041	}
6042	if (sli->mapsPresent) {
6043	    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
6044		xkbIndicatorMapWireDesc	iwire;
6045		if (sli->mapsPresent&bit) {
6046		    iwire.flags= 	sli->maps[i].flags;
6047		    iwire.whichGroups=	sli->maps[i].which_groups;
6048		    iwire.groups=	sli->maps[i].groups;
6049		    iwire.whichMods=	sli->maps[i].which_mods;
6050		    iwire.mods=		sli->maps[i].mods.mask;
6051		    iwire.realMods=	sli->maps[i].mods.real_mods;
6052		    iwire.virtualMods=	sli->maps[i].mods.vmods;
6053		    iwire.ctrls= 	sli->maps[i].ctrls;
6054		    if (client->swapped) {
6055			register int n;
6056			swaps(&iwire.virtualMods,n);
6057			swapl(&iwire.ctrls,n);
6058		    }
6059		    WriteToClient(client,SIZEOF(xkbIndicatorMapWireDesc),
6060								(char *)&iwire);
6061		    length+= SIZEOF(xkbIndicatorMapWireDesc);
6062		}
6063	    }
6064	}
6065    }
6066    return length;
6067}
6068
6069static int
6070SendDeviceLedFBs(	DeviceIntPtr	dev,
6071			int		class,
6072			int		id,
6073			unsigned	wantLength,
6074			ClientPtr	client)
6075{
6076int			length= 0;
6077
6078    if (class==XkbDfltXIClass) {
6079	if (dev->kbdfeed)	class= KbdFeedbackClass;
6080	else if (dev->leds)	class= LedFeedbackClass;
6081    }
6082    if ((dev->kbdfeed)&&
6083	((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) {
6084	KbdFeedbackPtr kf;
6085	for (kf= dev->kbdfeed;(kf);kf=kf->next) {
6086	    if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==kf->ctrl.id)) {
6087		length+= SendDeviceLedInfo(kf->xkb_sli,client);
6088		if (id!=XkbAllXIIds)
6089		    break;
6090	    }
6091	}
6092    }
6093    if ((dev->leds)&&
6094	((class==LedFeedbackClass)||(class==XkbAllXIClasses))) {
6095	LedFeedbackPtr lf;
6096	for (lf= dev->leds;(lf);lf=lf->next) {
6097	    if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==lf->ctrl.id)) {
6098		length+= SendDeviceLedInfo(lf->xkb_sli,client);
6099		if (id!=XkbAllXIIds)
6100		    break;
6101	    }
6102	}
6103    }
6104    if (length==wantLength)
6105	 return Success;
6106    else return BadLength;
6107}
6108
6109int
6110ProcXkbGetDeviceInfo(ClientPtr client)
6111{
6112DeviceIntPtr		dev;
6113xkbGetDeviceInfoReply	rep;
6114int			status,nDeviceLedFBs;
6115unsigned		length,nameLen;
6116CARD16			ledClass,ledID;
6117unsigned		wanted;
6118char *			str;
6119
6120    REQUEST(xkbGetDeviceInfoReq);
6121    REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq);
6122
6123    if (!(client->xkbClientFlags&_XkbClientInitialized))
6124	return BadAccess;
6125
6126    wanted= stuff->wanted;
6127
6128    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
6129    CHK_MASK_LEGAL(0x01,wanted,XkbXI_AllDeviceFeaturesMask);
6130
6131    if ((!dev->button)||((stuff->nBtns<1)&&(!stuff->allBtns)))
6132	wanted&= ~XkbXI_ButtonActionsMask;
6133    if ((!dev->kbdfeed)&&(!dev->leds))
6134	wanted&= ~XkbXI_IndicatorsMask;
6135
6136    nameLen= XkbSizeCountedString(dev->name);
6137    memset((char *)&rep, 0, SIZEOF(xkbGetDeviceInfoReply));
6138    rep.type = X_Reply;
6139    rep.deviceID= dev->id;
6140    rep.sequenceNumber = client->sequence;
6141    rep.length = nameLen/4;
6142    rep.present = wanted;
6143    rep.supported = XkbXI_AllDeviceFeaturesMask;
6144    rep.unsupported = 0;
6145    rep.firstBtnWanted = rep.nBtnsWanted = 0;
6146    rep.firstBtnRtrn = rep.nBtnsRtrn = 0;
6147    if (dev->button)
6148	 rep.totalBtns= dev->button->numButtons;
6149    else rep.totalBtns= 0;
6150    rep.devType=	dev->xinput_type;
6151    rep.hasOwnState=	(dev->key && dev->key->xkbInfo);
6152    rep.nDeviceLedFBs = 0;
6153    if (dev->kbdfeed)	rep.dfltKbdFB= dev->kbdfeed->ctrl.id;
6154    else		rep.dfltKbdFB= XkbXINone;
6155    if (dev->leds)	rep.dfltLedFB= dev->leds->ctrl.id;
6156    else		rep.dfltLedFB= XkbXINone;
6157
6158    ledClass= stuff->ledClass;
6159    ledID= stuff->ledID;
6160
6161    rep.firstBtnWanted= rep.nBtnsWanted= 0;
6162    rep.firstBtnRtrn= rep.nBtnsRtrn= 0;
6163    if (wanted&XkbXI_ButtonActionsMask) {
6164	if (stuff->allBtns) {
6165	    stuff->firstBtn= 0;
6166	    stuff->nBtns= dev->button->numButtons;
6167	}
6168
6169	if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) {
6170	    client->errorValue = _XkbErrCode4(0x02,dev->button->numButtons,
6171							stuff->firstBtn,
6172							stuff->nBtns);
6173	    return BadValue;
6174	}
6175	else {
6176	    rep.firstBtnWanted= stuff->firstBtn;
6177	    rep.nBtnsWanted= stuff->nBtns;
6178	    if (dev->button->xkb_acts!=NULL) {
6179		XkbAction *act;
6180		register int i;
6181
6182		rep.firstBtnRtrn= stuff->firstBtn;
6183		rep.nBtnsRtrn= stuff->nBtns;
6184		act= &dev->button->xkb_acts[rep.firstBtnWanted];
6185		for (i=0;i<rep.nBtnsRtrn;i++,act++) {
6186		    if (act->type!=XkbSA_NoAction)
6187			break;
6188		}
6189		rep.firstBtnRtrn+=	i;
6190		rep.nBtnsRtrn-=		i;
6191		act= &dev->button->xkb_acts[rep.firstBtnRtrn+rep.nBtnsRtrn-1];
6192		for (i=0;i<rep.nBtnsRtrn;i++,act--) {
6193		    if (act->type!=XkbSA_NoAction)
6194			break;
6195		}
6196		rep.nBtnsRtrn-=		i;
6197	    }
6198	    rep.length+= (rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc))/4;
6199	}
6200    }
6201
6202    if (wanted&XkbXI_IndicatorsMask) {
6203	status= CheckDeviceLedFBs(dev,ledClass,ledID,&rep,client);
6204	if (status!=Success)
6205	    return status;
6206    }
6207    length= rep.length*4;
6208    nDeviceLedFBs = rep.nDeviceLedFBs;
6209    if (client->swapped) {
6210	register int n;
6211	swaps(&rep.sequenceNumber,n);
6212	swapl(&rep.length,n);
6213	swaps(&rep.present,n);
6214	swaps(&rep.supported,n);
6215	swaps(&rep.unsupported,n);
6216	swaps(&rep.nDeviceLedFBs,n);
6217	swapl(&rep.type,n);
6218    }
6219    WriteToClient(client,SIZEOF(xkbGetDeviceInfoReply), (char *)&rep);
6220
6221    str= malloc(nameLen);
6222    if (!str)
6223	return BadAlloc;
6224    XkbWriteCountedString(str,dev->name,client->swapped);
6225    WriteToClient(client,nameLen,str);
6226    free(str);
6227    length-= nameLen;
6228
6229    if (rep.nBtnsRtrn>0) {
6230	int			sz;
6231	xkbActionWireDesc *	awire;
6232	sz= rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc);
6233	awire= (xkbActionWireDesc *)&dev->button->xkb_acts[rep.firstBtnRtrn];
6234	WriteToClient(client,sz,(char *)awire);
6235	length-= sz;
6236    }
6237    if (nDeviceLedFBs>0) {
6238	status= SendDeviceLedFBs(dev,ledClass,ledID,length,client);
6239	if (status!=Success)
6240	    return status;
6241    }
6242    else if (length!=0)  {
6243	ErrorF("[xkb] Internal Error!  BadLength in ProcXkbGetDeviceInfo\n");
6244	ErrorF("[xkb]                  Wrote %d fewer bytes than expected\n",length);
6245	return BadLength;
6246    }
6247    return Success;
6248}
6249
6250static char *
6251CheckSetDeviceIndicators(	char *		wire,
6252				DeviceIntPtr	dev,
6253				int		num,
6254				int *		status_rtrn,
6255				ClientPtr	client)
6256{
6257xkbDeviceLedsWireDesc *	ledWire;
6258int			i;
6259XkbSrvLedInfoPtr 	sli;
6260
6261    ledWire= (xkbDeviceLedsWireDesc *)wire;
6262    for (i=0;i<num;i++) {
6263	if (client->swapped) {
6264	   register int n;
6265	   swaps(&ledWire->ledClass,n);
6266	   swaps(&ledWire->ledID,n);
6267	   swapl(&ledWire->namesPresent,n);
6268	   swapl(&ledWire->mapsPresent,n);
6269	   swapl(&ledWire->physIndicators,n);
6270	}
6271
6272        sli= XkbFindSrvLedInfo(dev,ledWire->ledClass,ledWire->ledID,
6273							XkbXI_IndicatorsMask);
6274	if (sli!=NULL) {
6275	    register int n;
6276	    register unsigned bit;
6277	    int nMaps,nNames;
6278	    CARD32 *atomWire;
6279	    xkbIndicatorMapWireDesc *mapWire;
6280
6281	    nMaps= nNames= 0;
6282	    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
6283		if (ledWire->namesPresent&bit)
6284		    nNames++;
6285		if (ledWire->mapsPresent&bit)
6286		    nMaps++;
6287	    }
6288	    atomWire= (CARD32 *)&ledWire[1];
6289	    if (nNames>0) {
6290		for (n=0;n<nNames;n++) {
6291		    if (client->swapped) {
6292			register int t;
6293			swapl(atomWire,t);
6294		    }
6295		    CHK_ATOM_OR_NONE3(((Atom)(*atomWire)),client->errorValue,
6296							*status_rtrn,NULL);
6297		    atomWire++;
6298		}
6299	    }
6300	    mapWire= (xkbIndicatorMapWireDesc *)atomWire;
6301	    if (nMaps>0) {
6302		for (n=0;n<nMaps;n++) {
6303		    if (client->swapped) {
6304			register int t;
6305			swaps(&mapWire->virtualMods,t);
6306			swapl(&mapWire->ctrls,t);
6307		    }
6308		    CHK_MASK_LEGAL3(0x21,mapWire->whichGroups,
6309						XkbIM_UseAnyGroup,
6310						client->errorValue,
6311						*status_rtrn,NULL);
6312		    CHK_MASK_LEGAL3(0x22,mapWire->whichMods,XkbIM_UseAnyMods,
6313						client->errorValue,
6314						*status_rtrn,NULL);
6315		    mapWire++;
6316		}
6317	    }
6318	    ledWire= (xkbDeviceLedsWireDesc *)mapWire;
6319	}
6320	else {
6321	    /* SHOULD NEVER HAPPEN */
6322	    return (char *)ledWire;
6323	}
6324    }
6325    return (char *)ledWire;
6326}
6327
6328static char *
6329SetDeviceIndicators(	char *			wire,
6330			DeviceIntPtr		dev,
6331			unsigned		changed,
6332			int			num,
6333			int *			status_rtrn,
6334			ClientPtr		client,
6335			xkbExtensionDeviceNotify *ev)
6336{
6337xkbDeviceLedsWireDesc *		ledWire;
6338int				i;
6339XkbEventCauseRec		cause;
6340unsigned			namec,mapc,statec;
6341xkbExtensionDeviceNotify	ed;
6342XkbChangesRec			changes;
6343DeviceIntPtr			kbd;
6344
6345    memset((char *)&ed, 0, sizeof(xkbExtensionDeviceNotify));
6346    memset((char *)&changes, 0, sizeof(XkbChangesRec));
6347    XkbSetCauseXkbReq(&cause,X_kbSetDeviceInfo,client);
6348    ledWire= (xkbDeviceLedsWireDesc *)wire;
6349    for (i=0;i<num;i++) {
6350	register int			n;
6351	register unsigned 		bit;
6352	CARD32 *			atomWire;
6353	xkbIndicatorMapWireDesc *	mapWire;
6354	XkbSrvLedInfoPtr		sli;
6355
6356	namec= mapc= statec= 0;
6357    	sli= XkbFindSrvLedInfo(dev,ledWire->ledClass,ledWire->ledID,
6358						XkbXI_IndicatorMapsMask);
6359	if (!sli) {
6360	    /* SHOULD NEVER HAPPEN!! */
6361	    return (char *)ledWire;
6362	}
6363
6364	atomWire= (CARD32 *)&ledWire[1];
6365	if (changed&XkbXI_IndicatorNamesMask) {
6366	    namec= sli->namesPresent|ledWire->namesPresent;
6367	    memset((char *)sli->names, 0, XkbNumIndicators*sizeof(Atom));
6368	}
6369	if (ledWire->namesPresent) {
6370	    sli->namesPresent= ledWire->namesPresent;
6371	    memset((char *)sli->names, 0, XkbNumIndicators*sizeof(Atom));
6372	    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
6373		if (ledWire->namesPresent&bit) {
6374		     sli->names[n]= (Atom)*atomWire;
6375		     if (sli->names[n]==None)
6376			ledWire->namesPresent&= ~bit;
6377		     atomWire++;
6378		}
6379	    }
6380	}
6381	mapWire= (xkbIndicatorMapWireDesc *)atomWire;
6382	if (changed&XkbXI_IndicatorMapsMask) {
6383	    mapc= sli->mapsPresent|ledWire->mapsPresent;
6384	    sli->mapsPresent= ledWire->mapsPresent;
6385	    memset((char*)sli->maps, 0, XkbNumIndicators*sizeof(XkbIndicatorMapRec));
6386	}
6387	if (ledWire->mapsPresent) {
6388	    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
6389		if (ledWire->mapsPresent&bit) {
6390		    sli->maps[n].flags=		mapWire->flags;
6391		    sli->maps[n].which_groups=	mapWire->whichGroups;
6392		    sli->maps[n].groups=	mapWire->groups;
6393		    sli->maps[n].which_mods=	mapWire->whichMods;
6394		    sli->maps[n].mods.mask=	mapWire->mods;
6395		    sli->maps[n].mods.real_mods=mapWire->realMods;
6396		    sli->maps[n].mods.vmods=	mapWire->virtualMods;
6397		    sli->maps[n].ctrls=		mapWire->ctrls;
6398		    mapWire++;
6399		}
6400	    }
6401	}
6402	if (changed&XkbXI_IndicatorStateMask) {
6403	    statec= sli->effectiveState^ledWire->state;
6404	    sli->explicitState&= ~statec;
6405	    sli->explicitState|= (ledWire->state&statec);
6406	}
6407	if (namec)
6408	    XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause);
6409	if (mapc)
6410	    XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause);
6411	if (statec)
6412	    XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause);
6413
6414	kbd= dev;
6415	if ((sli->flags&XkbSLI_HasOwnState)==0)
6416	    kbd = inputInfo.keyboard;
6417
6418	XkbFlushLedEvents(dev,kbd,sli,&ed,&changes,&cause);
6419	ledWire= (xkbDeviceLedsWireDesc *)mapWire;
6420    }
6421    return (char *)ledWire;
6422}
6423
6424
6425static int
6426_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev,
6427                  xkbSetDeviceInfoReq *stuff)
6428{
6429    char                       *wire;
6430
6431    wire= (char *)&stuff[1];
6432    if (stuff->change&XkbXI_ButtonActionsMask) {
6433	if (!dev->button) {
6434	    client->errorValue = _XkbErrCode2(XkbErr_BadClass,ButtonClass);
6435	    return XkbKeyboardErrorCode;
6436	}
6437	if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) {
6438	    client->errorValue= _XkbErrCode4(0x02,stuff->firstBtn,stuff->nBtns,
6439						dev->button->numButtons);
6440	    return BadMatch;
6441	}
6442	wire+= (stuff->nBtns*SIZEOF(xkbActionWireDesc));
6443    }
6444    if (stuff->change&XkbXI_IndicatorsMask) {
6445	int status= Success;
6446	wire= CheckSetDeviceIndicators(wire,dev,stuff->nDeviceLedFBs,
6447							&status,client);
6448	if (status!=Success)
6449	    return status;
6450    }
6451    if (((wire-((char *)stuff))/4)!=stuff->length)
6452	return BadLength;
6453
6454    return Success;
6455}
6456
6457static int
6458_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev,
6459                       xkbSetDeviceInfoReq *stuff)
6460{
6461    char                       *wire;
6462    xkbExtensionDeviceNotify    ed;
6463
6464    memset((char *)&ed, 0, SIZEOF(xkbExtensionDeviceNotify));
6465    ed.deviceID=	dev->id;
6466    wire= (char *)&stuff[1];
6467    if (stuff->change&XkbXI_ButtonActionsMask) {
6468	int			nBtns,sz,i;
6469	XkbAction *		acts;
6470	DeviceIntPtr		kbd;
6471
6472	nBtns= dev->button->numButtons;
6473	acts= dev->button->xkb_acts;
6474	if (acts==NULL) {
6475	    acts= calloc(nBtns, sizeof(XkbAction));
6476	    if (!acts)
6477		return BadAlloc;
6478	    dev->button->xkb_acts= acts;
6479	}
6480	sz= stuff->nBtns*SIZEOF(xkbActionWireDesc);
6481	memcpy((char *)&acts[stuff->firstBtn],(char *)wire,sz);
6482	wire+= sz;
6483	ed.reason|=	XkbXI_ButtonActionsMask;
6484	ed.firstBtn=	stuff->firstBtn;
6485	ed.nBtns=	stuff->nBtns;
6486
6487	if (dev->key)	kbd= dev;
6488	else		kbd= inputInfo.keyboard;
6489	acts= &dev->button->xkb_acts[stuff->firstBtn];
6490	for (i=0;i<stuff->nBtns;i++,acts++) {
6491	    if (acts->type!=XkbSA_NoAction)
6492		XkbSetActionKeyMods(kbd->key->xkbInfo->desc,acts,0);
6493	}
6494    }
6495    if (stuff->change&XkbXI_IndicatorsMask) {
6496	int status= Success;
6497	wire= SetDeviceIndicators(wire,dev,stuff->change,
6498				  stuff->nDeviceLedFBs, &status,client,&ed);
6499	if (status!=Success)
6500	    return status;
6501    }
6502    if ((stuff->change)&&(ed.reason))
6503	XkbSendExtensionDeviceNotify(dev,client,&ed);
6504    return Success;
6505}
6506
6507int
6508ProcXkbSetDeviceInfo(ClientPtr client)
6509{
6510    DeviceIntPtr        dev;
6511    int                 rc;
6512
6513    REQUEST(xkbSetDeviceInfoReq);
6514    REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq);
6515
6516    if (!(client->xkbClientFlags&_XkbClientInitialized))
6517	return BadAccess;
6518
6519    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
6520    CHK_MASK_LEGAL(0x01,stuff->change,XkbXI_AllFeaturesMask);
6521
6522    rc = _XkbSetDeviceInfoCheck(client, dev, stuff);
6523
6524    if (rc != Success)
6525        return rc;
6526
6527    if (stuff->deviceSpec == XkbUseCoreKbd || stuff->deviceSpec == XkbUseCorePtr)
6528    {
6529        DeviceIntPtr other;
6530        for (other = inputInfo.devices; other; other = other->next)
6531        {
6532            if (((other != dev) && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) &&
6533                ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
6534                (stuff->deviceSpec == XkbUseCorePtr && other->button)))
6535            {
6536                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
6537                if (rc == Success)
6538                {
6539                    rc = _XkbSetDeviceInfoCheck(client, other, stuff);
6540                    if (rc != Success)
6541                        return rc;
6542                }
6543            }
6544        }
6545    }
6546
6547    /* checks done, apply */
6548    rc = _XkbSetDeviceInfo(client, dev, stuff);
6549    if (rc != Success)
6550        return rc;
6551
6552    if (stuff->deviceSpec == XkbUseCoreKbd || stuff->deviceSpec == XkbUseCorePtr)
6553    {
6554        DeviceIntPtr other;
6555        for (other = inputInfo.devices; other; other = other->next)
6556        {
6557            if (((other != dev) && !IsMaster(other) && GetMaster(other, MASTER_KEYBOARD) == dev) &&
6558                ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
6559                (stuff->deviceSpec == XkbUseCorePtr && other->button)))
6560            {
6561                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
6562                if (rc == Success)
6563                {
6564                    rc = _XkbSetDeviceInfo(client, other, stuff);
6565                    if (rc != Success)
6566                        return rc;
6567                }
6568            }
6569        }
6570    }
6571
6572    return Success;
6573}
6574
6575/***====================================================================***/
6576
6577int
6578ProcXkbSetDebuggingFlags(ClientPtr client)
6579{
6580CARD32 				newFlags,newCtrls,extraLength;
6581xkbSetDebuggingFlagsReply 	rep;
6582int rc;
6583
6584    REQUEST(xkbSetDebuggingFlagsReq);
6585    REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq);
6586
6587    rc = XaceHook(XACE_SERVER_ACCESS, client, DixDebugAccess);
6588    if (rc != Success)
6589	return rc;
6590
6591    newFlags=  xkbDebugFlags&(~stuff->affectFlags);
6592    newFlags|= (stuff->flags&stuff->affectFlags);
6593    newCtrls=  xkbDebugCtrls&(~stuff->affectCtrls);
6594    newCtrls|= (stuff->ctrls&stuff->affectCtrls);
6595    if (xkbDebugFlags || newFlags || stuff->msgLength) {
6596	ErrorF("[xkb] XkbDebug: Setting debug flags to 0x%lx\n",(long)newFlags);
6597	if (newCtrls!=xkbDebugCtrls)
6598	    ErrorF("[xkb] XkbDebug: Setting debug controls to 0x%lx\n",(long)newCtrls);
6599    }
6600    extraLength= (stuff->length<<2)-sz_xkbSetDebuggingFlagsReq;
6601    if (stuff->msgLength>0) {
6602	char *msg;
6603	if (extraLength<XkbPaddedSize(stuff->msgLength)) {
6604	    ErrorF("[xkb] XkbDebug: msgLength= %d, length= %ld (should be %d)\n",
6605			stuff->msgLength,(long)extraLength,
6606			XkbPaddedSize(stuff->msgLength));
6607	    return BadLength;
6608	}
6609	msg= (char *)&stuff[1];
6610	if (msg[stuff->msgLength-1]!='\0') {
6611	    ErrorF("[xkb] XkbDebug: message not null-terminated\n");
6612	    return BadValue;
6613	}
6614	ErrorF("[xkb] XkbDebug: %s\n",msg);
6615    }
6616    xkbDebugFlags = newFlags;
6617    xkbDebugCtrls = newCtrls;
6618
6619    rep.type= X_Reply;
6620    rep.length = 0;
6621    rep.sequenceNumber = client->sequence;
6622    rep.currentFlags = newFlags;
6623    rep.currentCtrls = newCtrls;
6624    rep.supportedFlags = ~0;
6625    rep.supportedCtrls = ~0;
6626    if ( client->swapped ) {
6627	register int n;
6628	swaps(&rep.sequenceNumber, n);
6629	swapl(&rep.currentFlags, n);
6630	swapl(&rep.currentCtrls, n);
6631	swapl(&rep.supportedFlags, n);
6632	swapl(&rep.supportedCtrls, n);
6633    }
6634    WriteToClient(client,SIZEOF(xkbSetDebuggingFlagsReply), (char *)&rep);
6635    return Success;
6636}
6637
6638/***====================================================================***/
6639
6640static int
6641ProcXkbDispatch (ClientPtr client)
6642{
6643    REQUEST(xReq);
6644    switch (stuff->data)
6645    {
6646    case X_kbUseExtension:
6647	return ProcXkbUseExtension(client);
6648    case X_kbSelectEvents:
6649	return ProcXkbSelectEvents(client);
6650    case X_kbBell:
6651	return ProcXkbBell(client);
6652    case X_kbGetState:
6653	return ProcXkbGetState(client);
6654    case X_kbLatchLockState:
6655	return ProcXkbLatchLockState(client);
6656    case X_kbGetControls:
6657	return ProcXkbGetControls(client);
6658    case X_kbSetControls:
6659	return ProcXkbSetControls(client);
6660    case X_kbGetMap:
6661	return ProcXkbGetMap(client);
6662    case X_kbSetMap:
6663	return ProcXkbSetMap(client);
6664    case X_kbGetCompatMap:
6665	return ProcXkbGetCompatMap(client);
6666    case X_kbSetCompatMap:
6667	return ProcXkbSetCompatMap(client);
6668    case X_kbGetIndicatorState:
6669	return ProcXkbGetIndicatorState(client);
6670    case X_kbGetIndicatorMap:
6671	return ProcXkbGetIndicatorMap(client);
6672    case X_kbSetIndicatorMap:
6673	return ProcXkbSetIndicatorMap(client);
6674    case X_kbGetNamedIndicator:
6675	return ProcXkbGetNamedIndicator(client);
6676    case X_kbSetNamedIndicator:
6677	return ProcXkbSetNamedIndicator(client);
6678    case X_kbGetNames:
6679	return ProcXkbGetNames(client);
6680    case X_kbSetNames:
6681	return ProcXkbSetNames(client);
6682    case X_kbGetGeometry:
6683	return ProcXkbGetGeometry(client);
6684    case X_kbSetGeometry:
6685	return ProcXkbSetGeometry(client);
6686    case X_kbPerClientFlags:
6687	return ProcXkbPerClientFlags(client);
6688    case X_kbListComponents:
6689	return ProcXkbListComponents(client);
6690    case X_kbGetKbdByName:
6691	return ProcXkbGetKbdByName(client);
6692    case X_kbGetDeviceInfo:
6693	return ProcXkbGetDeviceInfo(client);
6694    case X_kbSetDeviceInfo:
6695	return ProcXkbSetDeviceInfo(client);
6696    case X_kbSetDebuggingFlags:
6697	return ProcXkbSetDebuggingFlags(client);
6698    default:
6699	return BadRequest;
6700    }
6701}
6702
6703static int
6704XkbClientGone(pointer data,XID id)
6705{
6706    DevicePtr	pXDev = (DevicePtr)data;
6707
6708    if (!XkbRemoveResourceClient(pXDev,id)) {
6709	ErrorF("[xkb] Internal Error! bad RemoveResourceClient in XkbClientGone\n");
6710    }
6711    return 1;
6712}
6713
6714void
6715XkbExtensionInit(void)
6716{
6717    ExtensionEntry *extEntry;
6718
6719    RT_XKBCLIENT = CreateNewResourceType(XkbClientGone, "XkbClient");
6720    if (!RT_XKBCLIENT)
6721	return;
6722
6723    if (!XkbInitPrivates())
6724	return;
6725
6726    if ((extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors,
6727				 ProcXkbDispatch, SProcXkbDispatch,
6728				 NULL, StandardMinorOpcode))) {
6729	XkbReqCode = (unsigned char)extEntry->base;
6730	XkbEventBase = (unsigned char)extEntry->eventBase;
6731	XkbErrorBase = (unsigned char)extEntry->errorBase;
6732	XkbKeyboardErrorCode = XkbErrorBase+XkbKeyboard;
6733    }
6734    return;
6735}
6736
6737
6738