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