xkb.c revision 52397711
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;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;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                (other->kbdfeed || other->leds) &&
3442                (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) == Success))
3443            {
3444                rc = _XkbCreateIndicatorMap(other, stuff->indicator,
3445                                            stuff->ledClass, stuff->ledID,
3446                                            &map, &led, TRUE);
3447                if (rc != Success || !map)
3448                    return rc;
3449            }
3450        }
3451    }
3452
3453    /* All checks passed, let's do it */
3454    rc = _XkbSetNamedIndicator(client, dev, stuff);
3455    if (rc != Success)
3456        return rc;
3457
3458    if (stuff->deviceSpec == XkbUseCoreKbd ||
3459        stuff->deviceSpec == XkbUseCorePtr)
3460    {
3461        DeviceIntPtr other;
3462        for (other = inputInfo.devices; other; other = other->next)
3463        {
3464            if ((other != dev) && !other->isMaster && (other->u.master == dev) &&
3465                (other->kbdfeed || other->leds) &&
3466                (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) == Success))
3467            {
3468                _XkbSetNamedIndicator(client, other, stuff);
3469            }
3470        }
3471    }
3472
3473    return client->noClientException;
3474}
3475
3476/***====================================================================***/
3477
3478static CARD32
3479_XkbCountAtoms(Atom *atoms,int maxAtoms,int *count)
3480{
3481register unsigned int i,bit,nAtoms;
3482register CARD32 atomsPresent;
3483
3484    for (i=nAtoms=atomsPresent=0,bit=1;i<maxAtoms;i++,bit<<=1) {
3485	if (atoms[i]!=None) {
3486	    atomsPresent|= bit;
3487	    nAtoms++;
3488	}
3489    }
3490    if (count)
3491	*count= nAtoms;
3492    return atomsPresent;
3493}
3494
3495static char *
3496_XkbWriteAtoms(char *wire,Atom *atoms,int maxAtoms,int swap)
3497{
3498register unsigned int i;
3499Atom *atm;
3500
3501    atm = (Atom *)wire;
3502    for (i=0;i<maxAtoms;i++) {
3503	if (atoms[i]!=None) {
3504	    *atm= atoms[i];
3505	    if (swap) {
3506		register int n;
3507		swapl(atm,n);
3508	    }
3509	    atm++;
3510	}
3511    }
3512    return (char *)atm;
3513}
3514
3515static Status
3516XkbComputeGetNamesReplySize(XkbDescPtr xkb,xkbGetNamesReply *rep)
3517{
3518register unsigned	which,length;
3519register int		i;
3520
3521    rep->minKeyCode= xkb->min_key_code;
3522    rep->maxKeyCode= xkb->max_key_code;
3523    which= rep->which;
3524    length= 0;
3525    if (xkb->names!=NULL) {
3526	 if (which&XkbKeycodesNameMask)		length++;
3527	 if (which&XkbGeometryNameMask)		length++;
3528	 if (which&XkbSymbolsNameMask)		length++;
3529	 if (which&XkbPhysSymbolsNameMask)	length++;
3530	 if (which&XkbTypesNameMask)		length++;
3531	 if (which&XkbCompatNameMask)		length++;
3532    }
3533    else which&= ~XkbComponentNamesMask;
3534
3535    if (xkb->map!=NULL) {
3536	if (which&XkbKeyTypeNamesMask)
3537	    length+= xkb->map->num_types;
3538	rep->nTypes= xkb->map->num_types;
3539	if (which&XkbKTLevelNamesMask) {
3540	    XkbKeyTypePtr	pType = xkb->map->types;
3541	    int			nKTLevels = 0;
3542
3543	    length+= XkbPaddedSize(xkb->map->num_types)/4;
3544	    for (i=0;i<xkb->map->num_types;i++,pType++) {
3545		if (pType->level_names!=NULL)
3546		    nKTLevels+= pType->num_levels;
3547	    }
3548	    rep->nKTLevels= nKTLevels;
3549	    length+= nKTLevels;
3550	}
3551    }
3552    else {
3553	rep->nTypes=    0;
3554	rep->nKTLevels= 0;
3555	which&= ~(XkbKeyTypeNamesMask|XkbKTLevelNamesMask);
3556    }
3557
3558    rep->minKeyCode= xkb->min_key_code;
3559    rep->maxKeyCode= xkb->max_key_code;
3560    rep->indicators= 0;
3561    rep->virtualMods= 0;
3562    rep->groupNames= 0;
3563    if (xkb->names!=NULL) {
3564	if (which&XkbIndicatorNamesMask) {
3565	    int nLeds;
3566	    rep->indicators=
3567		_XkbCountAtoms(xkb->names->indicators,XkbNumIndicators,&nLeds);
3568	    length+= nLeds;
3569	    if (nLeds==0)
3570		which&= ~XkbIndicatorNamesMask;
3571	}
3572
3573	if (which&XkbVirtualModNamesMask) {
3574	    int nVMods;
3575	    rep->virtualMods=
3576		_XkbCountAtoms(xkb->names->vmods,XkbNumVirtualMods,&nVMods);
3577	    length+= nVMods;
3578	    if (nVMods==0)
3579		which&= ~XkbVirtualModNamesMask;
3580	}
3581
3582	if (which&XkbGroupNamesMask) {
3583	    int nGroups;
3584	    rep->groupNames=
3585		_XkbCountAtoms(xkb->names->groups,XkbNumKbdGroups,&nGroups);
3586	    length+= nGroups;
3587	    if (nGroups==0)
3588		which&= ~XkbGroupNamesMask;
3589	}
3590
3591	if ((which&XkbKeyNamesMask)&&(xkb->names->keys))
3592	     length+= rep->nKeys;
3593	else which&= ~XkbKeyNamesMask;
3594
3595	if ((which&XkbKeyAliasesMask)&&
3596	    (xkb->names->key_aliases)&&(xkb->names->num_key_aliases>0)) {
3597	    rep->nKeyAliases= xkb->names->num_key_aliases;
3598	    length+= rep->nKeyAliases*2;
3599	}
3600	else {
3601	    which&= ~XkbKeyAliasesMask;
3602	    rep->nKeyAliases= 0;
3603	}
3604
3605	if ((which&XkbRGNamesMask)&&(xkb->names->num_rg>0))
3606	     length+= xkb->names->num_rg;
3607	else which&= ~XkbRGNamesMask;
3608    }
3609    else {
3610	which&= ~(XkbIndicatorNamesMask|XkbVirtualModNamesMask);
3611	which&= ~(XkbGroupNamesMask|XkbKeyNamesMask|XkbKeyAliasesMask);
3612	which&= ~XkbRGNamesMask;
3613    }
3614
3615    rep->length= length;
3616    rep->which= which;
3617    return Success;
3618}
3619
3620static int
3621XkbSendNames(ClientPtr client,XkbDescPtr xkb,xkbGetNamesReply *rep)
3622{
3623register unsigned 	i,length,which;
3624char *			start;
3625char *			desc;
3626register int            n;
3627
3628    length= rep->length*4;
3629    which= rep->which;
3630    if (client->swapped) {
3631	swaps(&rep->sequenceNumber,n);
3632	swapl(&rep->length,n);
3633	swapl(&rep->which,n);
3634	swaps(&rep->virtualMods,n);
3635	swapl(&rep->indicators,n);
3636    }
3637
3638    start = desc = (char *)xalloc(length);
3639    if ( !start )
3640	return BadAlloc;
3641    if (xkb->names) {
3642        if (which&XkbKeycodesNameMask) {
3643            *((CARD32 *)desc)= xkb->names->keycodes;
3644            if (client->swapped) {
3645                swapl(desc,n);
3646            }
3647            desc+= 4;
3648        }
3649        if (which&XkbGeometryNameMask)  {
3650            *((CARD32 *)desc)= xkb->names->geometry;
3651            if (client->swapped) {
3652                swapl(desc,n);
3653            }
3654            desc+= 4;
3655        }
3656        if (which&XkbSymbolsNameMask) {
3657            *((CARD32 *)desc)= xkb->names->symbols;
3658            if (client->swapped) {
3659                swapl(desc,n);
3660            }
3661            desc+= 4;
3662        }
3663        if (which&XkbPhysSymbolsNameMask) {
3664            register CARD32 *atm= (CARD32 *)desc;
3665            atm[0]= (CARD32)xkb->names->phys_symbols;
3666            if (client->swapped) {
3667                swapl(&atm[0],n);
3668            }
3669            desc+= 4;
3670        }
3671        if (which&XkbTypesNameMask) {
3672            *((CARD32 *)desc)= (CARD32)xkb->names->types;
3673            if (client->swapped) {
3674                swapl(desc,n);
3675            }
3676            desc+= 4;
3677        }
3678        if (which&XkbCompatNameMask) {
3679            *((CARD32 *)desc)= (CARD32)xkb->names->compat;
3680            if (client->swapped) {
3681                swapl(desc,n);
3682            }
3683            desc+= 4;
3684        }
3685        if (which&XkbKeyTypeNamesMask) {
3686            register CARD32 *atm= (CARD32 *)desc;
3687            register XkbKeyTypePtr type= xkb->map->types;
3688
3689            for (i=0;i<xkb->map->num_types;i++,atm++,type++) {
3690                *atm= (CARD32)type->name;
3691                if (client->swapped) {
3692                    swapl(atm,n);
3693                }
3694            }
3695            desc= (char *)atm;
3696        }
3697        if (which&XkbKTLevelNamesMask && xkb->map) {
3698            XkbKeyTypePtr type = xkb->map->types;
3699            register CARD32 *atm;
3700            for (i=0;i<rep->nTypes;i++,type++) {
3701                *desc++ = type->num_levels;
3702            }
3703            desc+= XkbPaddedSize(rep->nTypes)-rep->nTypes;
3704
3705            atm= (CARD32 *)desc;
3706            type = xkb->map->types;
3707            for (i=0;i<xkb->map->num_types;i++,type++) {
3708                register unsigned l;
3709                if (type->level_names) {
3710                    for (l=0;l<type->num_levels;l++,atm++) {
3711                        *atm= type->level_names[l];
3712                        if (client->swapped) {
3713                            swapl(atm,n);
3714                        }
3715                    }
3716                    desc+= type->num_levels*4;
3717                }
3718            }
3719        }
3720        if (which&XkbIndicatorNamesMask) {
3721            desc= _XkbWriteAtoms(desc,xkb->names->indicators,XkbNumIndicators,
3722                                 client->swapped);
3723        }
3724        if (which&XkbVirtualModNamesMask) {
3725            desc= _XkbWriteAtoms(desc,xkb->names->vmods,XkbNumVirtualMods,
3726                                 client->swapped);
3727        }
3728        if (which&XkbGroupNamesMask) {
3729            desc= _XkbWriteAtoms(desc,xkb->names->groups,XkbNumKbdGroups,
3730                                 client->swapped);
3731        }
3732        if (which&XkbKeyNamesMask) {
3733            for (i=0;i<rep->nKeys;i++,desc+= sizeof(XkbKeyNameRec)) {
3734                *((XkbKeyNamePtr)desc)= xkb->names->keys[i+rep->firstKey];
3735            }
3736        }
3737        if (which&XkbKeyAliasesMask) {
3738            XkbKeyAliasPtr	pAl;
3739            pAl= xkb->names->key_aliases;
3740            for (i=0;i<rep->nKeyAliases;i++,pAl++,desc+=2*XkbKeyNameLength) {
3741                *((XkbKeyAliasPtr)desc)= *pAl;
3742            }
3743        }
3744        if ((which&XkbRGNamesMask)&&(rep->nRadioGroups>0)) {
3745            register CARD32	*atm= (CARD32 *)desc;
3746            for (i=0;i<rep->nRadioGroups;i++,atm++) {
3747                *atm= (CARD32)xkb->names->radio_groups[i];
3748                if (client->swapped) {
3749                    swapl(atm,n);
3750                }
3751            }
3752            desc+= rep->nRadioGroups*4;
3753        }
3754    }
3755
3756    if ((desc-start)!=(length)) {
3757	ErrorF("[xkb] BOGUS LENGTH in write names, expected %d, got %ld\n",
3758					length, (unsigned long)(desc-start));
3759    }
3760    WriteToClient(client, SIZEOF(xkbGetNamesReply), (char *)rep);
3761    WriteToClient(client, length, start);
3762    xfree((char *)start);
3763    return client->noClientException;
3764}
3765
3766int
3767ProcXkbGetNames(ClientPtr client)
3768{
3769    DeviceIntPtr	dev;
3770    XkbDescPtr		xkb;
3771    xkbGetNamesReply 	rep;
3772
3773    REQUEST(xkbGetNamesReq);
3774    REQUEST_SIZE_MATCH(xkbGetNamesReq);
3775
3776    if (!(client->xkbClientFlags&_XkbClientInitialized))
3777	return BadAccess;
3778
3779    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
3780    CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask);
3781
3782    xkb = dev->key->xkbInfo->desc;
3783    rep.type= X_Reply;
3784    rep.sequenceNumber= client->sequence;
3785    rep.length = 0;
3786    rep.deviceID = dev->id;
3787    rep.which = stuff->which;
3788    rep.nTypes = xkb->map->num_types;
3789    rep.firstKey = xkb->min_key_code;
3790    rep.nKeys = XkbNumKeys(xkb);
3791    if (xkb->names!=NULL) {
3792	rep.nKeyAliases= xkb->names->num_key_aliases;
3793	rep.nRadioGroups = xkb->names->num_rg;
3794    }
3795    else {
3796	rep.nKeyAliases= rep.nRadioGroups= 0;
3797    }
3798    XkbComputeGetNamesReplySize(xkb,&rep);
3799    return XkbSendNames(client,xkb,&rep);
3800}
3801
3802/***====================================================================***/
3803
3804static CARD32 *
3805_XkbCheckAtoms(CARD32 *wire,int nAtoms,int swapped,Atom *pError)
3806{
3807register int i;
3808
3809    for (i=0;i<nAtoms;i++,wire++) {
3810	if (swapped) {
3811	    register int n;
3812	    swapl(wire,n);
3813	}
3814	if ((((Atom)*wire)!=None)&&(!ValidAtom((Atom)*wire))) {
3815	    *pError= ((Atom)*wire);
3816	    return NULL;
3817	}
3818    }
3819    return wire;
3820}
3821
3822static CARD32 *
3823_XkbCheckMaskedAtoms(CARD32 *wire,int nAtoms,CARD32 present,int swapped,
3824								Atom *pError)
3825{
3826register unsigned i,bit;
3827
3828    for (i=0,bit=1;(i<nAtoms)&&(present);i++,bit<<=1) {
3829	if ((present&bit)==0)
3830	    continue;
3831	if (swapped) {
3832	    register int n;
3833	    swapl(wire,n);
3834	}
3835	if ((((Atom)*wire)!=None)&&(!ValidAtom(((Atom)*wire)))) {
3836	    *pError= (Atom)*wire;
3837	    return NULL;
3838	}
3839	wire++;
3840    }
3841    return wire;
3842}
3843
3844static Atom *
3845_XkbCopyMaskedAtoms(	Atom	*wire,
3846    			Atom	*dest,
3847			int   	 nAtoms,
3848			CARD32	 present)
3849{
3850register int i,bit;
3851
3852    for (i=0,bit=1;(i<nAtoms)&&(present);i++,bit<<=1) {
3853	if ((present&bit)==0)
3854	    continue;
3855	dest[i]= *wire++;
3856    }
3857    return wire;
3858}
3859
3860static Bool
3861_XkbCheckTypeName(Atom name,int typeNdx)
3862{
3863char *	str;
3864
3865    str= NameForAtom(name);
3866    if ((strcmp(str,"ONE_LEVEL")==0)||(strcmp(str,"TWO_LEVEL")==0)||
3867	(strcmp(str,"ALPHABETIC")==0)||(strcmp(str,"KEYPAD")==0))
3868	return False;
3869    return True;
3870}
3871
3872/**
3873 * Check the device-dependent data in the request against the device. Returns
3874 * Success, or the appropriate error code.
3875 */
3876static int
3877_XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
3878                  xkbSetNamesReq *stuff, CARD32 *data)
3879{
3880    XkbDescRec		*xkb;
3881    XkbNamesRec		*names;
3882    CARD32		*tmp;
3883    Atom		 bad;
3884
3885    tmp = data;
3886    xkb = dev->key->xkbInfo->desc;
3887    names = xkb->names;
3888
3889
3890    if (stuff->which & XkbKeyTypeNamesMask) {
3891        int i;
3892        CARD32	*old;
3893        if ( stuff->nTypes<1 ) {
3894            client->errorValue = _XkbErrCode2(0x02,stuff->nTypes);
3895            return BadValue;
3896        }
3897        if ((unsigned)(stuff->firstType+stuff->nTypes-1)>=xkb->map->num_types) {
3898            client->errorValue = _XkbErrCode4(0x03,stuff->firstType,
3899                    stuff->nTypes,
3900                    xkb->map->num_types);
3901            return BadValue;
3902        }
3903        if (((unsigned)stuff->firstType)<=XkbLastRequiredType) {
3904            client->errorValue = _XkbErrCode2(0x04,stuff->firstType);
3905            return BadAccess;
3906        }
3907        old= tmp;
3908        tmp= _XkbCheckAtoms(tmp,stuff->nTypes,client->swapped,&bad);
3909        if (!tmp) {
3910            client->errorValue= bad;
3911            return BadAtom;
3912        }
3913        for (i=0;i<stuff->nTypes;i++,old++) {
3914            if (!_XkbCheckTypeName((Atom)*old,stuff->firstType+i))
3915                client->errorValue= _XkbErrCode2(0x05,i);
3916        }
3917    }
3918    if (stuff->which&XkbKTLevelNamesMask) {
3919        unsigned i;
3920        XkbKeyTypePtr	type;
3921        CARD8 *		width;
3922        if ( stuff->nKTLevels<1 ) {
3923            client->errorValue = _XkbErrCode2(0x05,stuff->nKTLevels);
3924            return BadValue;
3925        }
3926        if ((unsigned)(stuff->firstKTLevel+stuff->nKTLevels-1)>=
3927                xkb->map->num_types) {
3928            client->errorValue = _XkbErrCode4(0x06,stuff->firstKTLevel,
3929                    stuff->nKTLevels,xkb->map->num_types);
3930            return BadValue;
3931        }
3932        width = (CARD8 *)tmp;
3933        tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels));
3934        type = &xkb->map->types[stuff->firstKTLevel];
3935        for (i=0;i<stuff->nKTLevels;i++,type++) {
3936            if (width[i]==0)
3937                continue;
3938            else if (width[i]!=type->num_levels) {
3939                client->errorValue= _XkbErrCode4(0x07,i+stuff->firstKTLevel,
3940                        type->num_levels,width[i]);
3941                return BadMatch;
3942            }
3943            tmp= _XkbCheckAtoms(tmp,width[i],client->swapped,&bad);
3944            if (!tmp) {
3945                client->errorValue= bad;
3946                return BadAtom;
3947            }
3948        }
3949    }
3950    if (stuff->which&XkbIndicatorNamesMask) {
3951        if (stuff->indicators==0) {
3952            client->errorValue= 0x08;
3953            return BadMatch;
3954        }
3955        tmp= _XkbCheckMaskedAtoms(tmp,XkbNumIndicators,stuff->indicators,
3956                client->swapped,&bad);
3957        if (!tmp) {
3958            client->errorValue= bad;
3959            return BadAtom;
3960        }
3961    }
3962    if (stuff->which&XkbVirtualModNamesMask) {
3963        if (stuff->virtualMods==0) {
3964            client->errorValue= 0x09;
3965            return BadMatch;
3966        }
3967        tmp= _XkbCheckMaskedAtoms(tmp,XkbNumVirtualMods,
3968                (CARD32)stuff->virtualMods,
3969                client->swapped,&bad);
3970        if (!tmp) {
3971            client->errorValue = bad;
3972            return BadAtom;
3973        }
3974    }
3975    if (stuff->which&XkbGroupNamesMask) {
3976        if (stuff->groupNames==0) {
3977            client->errorValue= 0x0a;
3978            return BadMatch;
3979        }
3980        tmp= _XkbCheckMaskedAtoms(tmp,XkbNumKbdGroups,
3981                (CARD32)stuff->groupNames,
3982                client->swapped,&bad);
3983        if (!tmp) {
3984            client->errorValue = bad;
3985            return BadAtom;
3986        }
3987    }
3988    if (stuff->which&XkbKeyNamesMask) {
3989        if (stuff->firstKey<(unsigned)xkb->min_key_code) {
3990            client->errorValue= _XkbErrCode3(0x0b,xkb->min_key_code,
3991                    stuff->firstKey);
3992            return BadValue;
3993        }
3994        if (((unsigned)(stuff->firstKey+stuff->nKeys-1)>xkb->max_key_code)||
3995                (stuff->nKeys<1)) {
3996            client->errorValue= _XkbErrCode4(0x0c,xkb->max_key_code,
3997                    stuff->firstKey,stuff->nKeys);
3998            return BadValue;
3999        }
4000        tmp+= stuff->nKeys;
4001    }
4002    if ((stuff->which&XkbKeyAliasesMask)&&(stuff->nKeyAliases>0)) {
4003        tmp+= stuff->nKeyAliases*2;
4004    }
4005    if (stuff->which&XkbRGNamesMask) {
4006        if ( stuff->nRadioGroups<1 ) {
4007            client->errorValue= _XkbErrCode2(0x0d,stuff->nRadioGroups);
4008            return BadValue;
4009        }
4010        tmp= _XkbCheckAtoms(tmp,stuff->nRadioGroups,client->swapped,&bad);
4011        if (!tmp) {
4012            client->errorValue= bad;
4013            return BadAtom;
4014        }
4015    }
4016    if ((tmp-((CARD32 *)stuff))!=stuff->length) {
4017        client->errorValue = stuff->length;
4018        return BadLength;
4019    }
4020
4021
4022
4023    return Success;
4024}
4025
4026static int
4027_XkbSetNames(ClientPtr client, DeviceIntPtr dev, xkbSetNamesReq *stuff)
4028{
4029    XkbDescRec		*xkb;
4030    XkbNamesRec		*names;
4031    CARD32		*tmp;
4032    xkbNamesNotify	 nn;
4033
4034    tmp = (CARD32 *)&stuff[1];
4035    xkb = dev->key->xkbInfo->desc;
4036    names = xkb->names;
4037
4038    if (XkbAllocNames(xkb,stuff->which,stuff->nRadioGroups,
4039                stuff->nKeyAliases)!=Success) {
4040        return BadAlloc;
4041    }
4042
4043    bzero(&nn,sizeof(xkbNamesNotify));
4044    nn.changed= stuff->which;
4045    tmp = (CARD32 *)&stuff[1];
4046    if (stuff->which&XkbKeycodesNameMask)
4047        names->keycodes= *tmp++;
4048    if (stuff->which&XkbGeometryNameMask)
4049        names->geometry= *tmp++;
4050    if (stuff->which&XkbSymbolsNameMask)
4051        names->symbols= *tmp++;
4052    if (stuff->which&XkbPhysSymbolsNameMask)
4053        names->phys_symbols= *tmp++;
4054    if (stuff->which&XkbTypesNameMask)
4055        names->types= *tmp++;
4056    if (stuff->which&XkbCompatNameMask)
4057        names->compat= *tmp++;
4058    if ((stuff->which&XkbKeyTypeNamesMask)&&(stuff->nTypes>0)) {
4059        register unsigned i;
4060        register XkbKeyTypePtr type;
4061
4062        type= &xkb->map->types[stuff->firstType];
4063        for (i=0;i<stuff->nTypes;i++,type++) {
4064            type->name= *tmp++;
4065        }
4066        nn.firstType= stuff->firstType;
4067        nn.nTypes= stuff->nTypes;
4068    }
4069    if (stuff->which&XkbKTLevelNamesMask) {
4070        register XkbKeyTypePtr	type;
4071        register unsigned i;
4072        CARD8 *width;
4073
4074        width = (CARD8 *)tmp;
4075        tmp= (CARD32 *)(((char *)tmp)+XkbPaddedSize(stuff->nKTLevels));
4076        type= &xkb->map->types[stuff->firstKTLevel];
4077        for (i=0;i<stuff->nKTLevels;i++,type++) {
4078            if (width[i]>0) {
4079                if (type->level_names) {
4080                    register unsigned n;
4081                    for (n=0;n<width[i];n++) {
4082                        type->level_names[n]= tmp[n];
4083                    }
4084                }
4085                tmp+= width[i];
4086            }
4087        }
4088        nn.firstLevelName= 0;
4089        nn.nLevelNames= stuff->nTypes;
4090    }
4091    if (stuff->which&XkbIndicatorNamesMask) {
4092        tmp= _XkbCopyMaskedAtoms(tmp,names->indicators,XkbNumIndicators,
4093                stuff->indicators);
4094        nn.changedIndicators= stuff->indicators;
4095    }
4096    if (stuff->which&XkbVirtualModNamesMask) {
4097        tmp= _XkbCopyMaskedAtoms(tmp,names->vmods,XkbNumVirtualMods,
4098                stuff->virtualMods);
4099        nn.changedVirtualMods= stuff->virtualMods;
4100    }
4101    if (stuff->which&XkbGroupNamesMask) {
4102        tmp= _XkbCopyMaskedAtoms(tmp,names->groups,XkbNumKbdGroups,
4103                stuff->groupNames);
4104        nn.changedVirtualMods= stuff->groupNames;
4105    }
4106    if (stuff->which&XkbKeyNamesMask) {
4107        memcpy((char*)&names->keys[stuff->firstKey],(char *)tmp,
4108                stuff->nKeys*XkbKeyNameLength);
4109        tmp+= stuff->nKeys;
4110        nn.firstKey= stuff->firstKey;
4111        nn.nKeys= stuff->nKeys;
4112    }
4113    if (stuff->which&XkbKeyAliasesMask) {
4114        if (stuff->nKeyAliases>0) {
4115            register int na= stuff->nKeyAliases;
4116            if (XkbAllocNames(xkb,XkbKeyAliasesMask,0,na)!=Success)
4117                return BadAlloc;
4118            memcpy((char *)names->key_aliases,(char *)tmp,
4119                    stuff->nKeyAliases*sizeof(XkbKeyAliasRec));
4120            tmp+= stuff->nKeyAliases*2;
4121        }
4122        else if (names->key_aliases!=NULL) {
4123            _XkbFree(names->key_aliases);
4124            names->key_aliases= NULL;
4125            names->num_key_aliases= 0;
4126        }
4127        nn.nAliases= names->num_key_aliases;
4128    }
4129    if (stuff->which&XkbRGNamesMask) {
4130        if (stuff->nRadioGroups>0) {
4131            register unsigned i,nrg;
4132            nrg= stuff->nRadioGroups;
4133            if (XkbAllocNames(xkb,XkbRGNamesMask,nrg,0)!=Success)
4134                return BadAlloc;
4135
4136            for (i=0;i<stuff->nRadioGroups;i++) {
4137                names->radio_groups[i]= tmp[i];
4138            }
4139            tmp+= stuff->nRadioGroups;
4140        }
4141        else if (names->radio_groups) {
4142            _XkbFree(names->radio_groups);
4143            names->radio_groups= NULL;
4144            names->num_rg= 0;
4145        }
4146        nn.nRadioGroups= names->num_rg;
4147    }
4148    if (nn.changed) {
4149        Bool needExtEvent;
4150        needExtEvent= (nn.changed&XkbIndicatorNamesMask)!=0;
4151        XkbSendNamesNotify(dev,&nn);
4152        if (needExtEvent) {
4153            XkbSrvLedInfoPtr		sli;
4154            xkbExtensionDeviceNotify	edev;
4155            register int		i;
4156            register unsigned		bit;
4157
4158            sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,
4159                    XkbXI_IndicatorsMask);
4160            sli->namesPresent= 0;
4161            for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
4162                if (names->indicators[i]!=None)
4163                    sli->namesPresent|= bit;
4164            }
4165            bzero(&edev,sizeof(xkbExtensionDeviceNotify));
4166            edev.reason=	XkbXI_IndicatorNamesMask;
4167            edev.ledClass=	KbdFeedbackClass;
4168            edev.ledID=		dev->kbdfeed->ctrl.id;
4169            edev.ledsDefined= 	sli->namesPresent|sli->mapsPresent;
4170            edev.ledState=	sli->effectiveState;
4171            edev.firstBtn=	0;
4172            edev.nBtns=		0;
4173            edev.supported=	XkbXI_AllFeaturesMask;
4174            edev.unsupported=	0;
4175            XkbSendExtensionDeviceNotify(dev,client,&edev);
4176        }
4177    }
4178    return Success;
4179}
4180
4181int
4182ProcXkbSetNames(ClientPtr client)
4183{
4184    DeviceIntPtr	 dev;
4185    CARD32		*tmp;
4186    Atom                 bad;
4187    int                  rc;
4188
4189    REQUEST(xkbSetNamesReq);
4190    REQUEST_AT_LEAST_SIZE(xkbSetNamesReq);
4191
4192    if (!(client->xkbClientFlags&_XkbClientInitialized))
4193	return BadAccess;
4194
4195    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
4196    CHK_MASK_LEGAL(0x01,stuff->which,XkbAllNamesMask);
4197
4198    /* check device-independent stuff */
4199    tmp = (CARD32 *)&stuff[1];
4200
4201    if (stuff->which&XkbKeycodesNameMask) {
4202	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
4203	if (!tmp) {
4204	    client->errorValue = bad;
4205	    return BadAtom;
4206	}
4207    }
4208    if (stuff->which&XkbGeometryNameMask) {
4209	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
4210	if (!tmp) {
4211	    client->errorValue = bad;
4212	    return BadAtom;
4213	}
4214    }
4215    if (stuff->which&XkbSymbolsNameMask) {
4216	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
4217	if (!tmp) {
4218	    client->errorValue = bad;
4219	    return BadAtom;
4220	}
4221    }
4222    if (stuff->which&XkbPhysSymbolsNameMask) {
4223	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
4224	if (!tmp) {
4225	    client->errorValue= bad;
4226	    return BadAtom;
4227	}
4228    }
4229    if (stuff->which&XkbTypesNameMask) {
4230	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
4231	if (!tmp) {
4232	    client->errorValue = bad;
4233	    return BadAtom;
4234	}
4235    }
4236    if (stuff->which&XkbCompatNameMask) {
4237	tmp= _XkbCheckAtoms(tmp,1,client->swapped,&bad);
4238	if (!tmp) {
4239	    client->errorValue = bad;
4240	    return BadAtom;
4241	}
4242    }
4243
4244    /* start of device-dependent tests */
4245    rc = _XkbSetNamesCheck(client, dev, stuff, tmp);
4246    if (rc != Success)
4247        return rc;
4248
4249    if (stuff->deviceSpec == XkbUseCoreKbd)
4250    {
4251        DeviceIntPtr other;
4252        for (other = inputInfo.devices; other; other = other->next)
4253        {
4254            if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
4255            {
4256
4257                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
4258                if (rc == Success)
4259                {
4260                    rc = _XkbSetNamesCheck(client, other, stuff, tmp);
4261                    if (rc != Success)
4262                        return rc;
4263                }
4264            }
4265        }
4266    }
4267
4268    /* everything is okay -- update names */
4269
4270    rc = _XkbSetNames(client, dev, stuff);
4271    if (rc != Success)
4272        return rc;
4273
4274    if (stuff->deviceSpec == XkbUseCoreKbd)
4275    {
4276        DeviceIntPtr other;
4277        for (other = inputInfo.devices; other; other = other->next)
4278        {
4279            if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
4280            {
4281
4282                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
4283                if (rc == Success)
4284                    _XkbSetNames(client, other, stuff);
4285            }
4286        }
4287    }
4288
4289    /* everything is okay -- update names */
4290
4291    return client->noClientException;
4292}
4293
4294/***====================================================================***/
4295
4296#include "xkbgeom.h"
4297
4298#define	XkbSizeCountedString(s)  ((s)?((((2+strlen(s))+3)/4)*4):4)
4299
4300static char *
4301XkbWriteCountedString(char *wire,char *str,Bool swap)
4302{
4303CARD16	len,*pLen;
4304
4305    len= (str?strlen(str):0);
4306    pLen= (CARD16 *)wire;
4307    *pLen= len;
4308    if (swap) {
4309	register int n;
4310	swaps(pLen,n);
4311    }
4312    memcpy(&wire[2],str,len);
4313    wire+= ((2+len+3)/4)*4;
4314    return wire;
4315}
4316
4317static int
4318XkbSizeGeomProperties(XkbGeometryPtr geom)
4319{
4320register int 	i,size;
4321XkbPropertyPtr	prop;
4322
4323    for (size=i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
4324	size+= XkbSizeCountedString(prop->name);
4325	size+= XkbSizeCountedString(prop->value);
4326    }
4327    return size;
4328}
4329
4330static char *
4331XkbWriteGeomProperties(char *wire,XkbGeometryPtr geom,Bool swap)
4332{
4333register int 	i;
4334register XkbPropertyPtr	prop;
4335
4336    for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
4337	wire= XkbWriteCountedString(wire,prop->name,swap);
4338	wire= XkbWriteCountedString(wire,prop->value,swap);
4339    }
4340    return wire;
4341}
4342
4343static int
4344XkbSizeGeomKeyAliases(XkbGeometryPtr geom)
4345{
4346    return geom->num_key_aliases*(2*XkbKeyNameLength);
4347}
4348
4349static char *
4350XkbWriteGeomKeyAliases(char *wire,XkbGeometryPtr geom,Bool swap)
4351{
4352register int sz;
4353
4354    sz= geom->num_key_aliases*(XkbKeyNameLength*2);
4355    if (sz>0) {
4356	memcpy(wire,(char *)geom->key_aliases,sz);
4357	wire+= sz;
4358    }
4359    return wire;
4360}
4361
4362static int
4363XkbSizeGeomColors(XkbGeometryPtr geom)
4364{
4365register int 		i,size;
4366register XkbColorPtr	color;
4367
4368    for (i=size=0,color=geom->colors;i<geom->num_colors;i++,color++) {
4369	size+= XkbSizeCountedString(color->spec);
4370    }
4371    return size;
4372}
4373
4374static char *
4375XkbWriteGeomColors(char *wire,XkbGeometryPtr geom,Bool swap)
4376{
4377register int		i;
4378register XkbColorPtr	color;
4379
4380    for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) {
4381	wire= XkbWriteCountedString(wire,color->spec,swap);
4382    }
4383    return wire;
4384}
4385
4386static int
4387XkbSizeGeomShapes(XkbGeometryPtr geom)
4388{
4389register int		i,size;
4390register XkbShapePtr	shape;
4391
4392    for (i=size=0,shape=geom->shapes;i<geom->num_shapes;i++,shape++) {
4393	register int		n;
4394	register XkbOutlinePtr	ol;
4395	size+= SIZEOF(xkbShapeWireDesc);
4396	for (n=0,ol=shape->outlines;n<shape->num_outlines;n++,ol++) {
4397	    size+= SIZEOF(xkbOutlineWireDesc);
4398	    size+= ol->num_points*SIZEOF(xkbPointWireDesc);
4399	}
4400    }
4401    return size;
4402}
4403
4404static char *
4405XkbWriteGeomShapes(char *wire,XkbGeometryPtr geom,Bool swap)
4406{
4407int			i;
4408XkbShapePtr		shape;
4409xkbShapeWireDesc *	shapeWire;
4410
4411    for (i=0,shape=geom->shapes;i<geom->num_shapes;i++,shape++) {
4412	register int 		o;
4413	XkbOutlinePtr		ol;
4414	xkbOutlineWireDesc *	olWire;
4415	shapeWire= (xkbShapeWireDesc *)wire;
4416	shapeWire->name= shape->name;
4417	shapeWire->nOutlines= shape->num_outlines;
4418	if (shape->primary!=NULL)
4419	     shapeWire->primaryNdx= XkbOutlineIndex(shape,shape->primary);
4420	else shapeWire->primaryNdx= XkbNoShape;
4421	if (shape->approx!=NULL)
4422	     shapeWire->approxNdx= XkbOutlineIndex(shape,shape->approx);
4423	else shapeWire->approxNdx= XkbNoShape;
4424	if (swap) {
4425	    register int n;
4426	    swapl(&shapeWire->name,n);
4427	}
4428	wire= (char *)&shapeWire[1];
4429	for (o=0,ol=shape->outlines;o<shape->num_outlines;o++,ol++) {
4430	    register int	p;
4431	    XkbPointPtr		pt;
4432	    xkbPointWireDesc *	ptWire;
4433	    olWire= (xkbOutlineWireDesc *)wire;
4434	    olWire->nPoints= ol->num_points;
4435	    olWire->cornerRadius= ol->corner_radius;
4436	    wire= (char *)&olWire[1];
4437	    ptWire= (xkbPointWireDesc *)wire;
4438	    for (p=0,pt=ol->points;p<ol->num_points;p++,pt++) {
4439		ptWire[p].x= pt->x;
4440		ptWire[p].y= pt->y;
4441		if (swap) {
4442		    register int n;
4443		    swaps(&ptWire[p].x,n);
4444		    swaps(&ptWire[p].y,n);
4445		}
4446	    }
4447	    wire= (char *)&ptWire[ol->num_points];
4448	}
4449    }
4450    return wire;
4451}
4452
4453static int
4454XkbSizeGeomDoodads(int num_doodads,XkbDoodadPtr doodad)
4455{
4456register int	i,size;
4457
4458    for (i=size=0;i<num_doodads;i++,doodad++) {
4459	size+= SIZEOF(xkbAnyDoodadWireDesc);
4460	if (doodad->any.type==XkbTextDoodad) {
4461	    size+= XkbSizeCountedString(doodad->text.text);
4462	    size+= XkbSizeCountedString(doodad->text.font);
4463	}
4464	else if (doodad->any.type==XkbLogoDoodad) {
4465	    size+= XkbSizeCountedString(doodad->logo.logo_name);
4466	}
4467    }
4468    return size;
4469}
4470
4471static char *
4472XkbWriteGeomDoodads(char *wire,int num_doodads,XkbDoodadPtr doodad,Bool swap)
4473{
4474register int		i;
4475xkbDoodadWireDesc *	doodadWire;
4476
4477    for (i=0;i<num_doodads;i++,doodad++) {
4478	doodadWire= (xkbDoodadWireDesc *)wire;
4479	wire= (char *)&doodadWire[1];
4480	bzero(doodadWire,SIZEOF(xkbDoodadWireDesc));
4481	doodadWire->any.name= doodad->any.name;
4482	doodadWire->any.type= doodad->any.type;
4483	doodadWire->any.priority= doodad->any.priority;
4484	doodadWire->any.top= doodad->any.top;
4485	doodadWire->any.left= doodad->any.left;
4486	if (swap) {
4487	    register int n;
4488	    swapl(&doodadWire->any.name,n);
4489	    swaps(&doodadWire->any.top,n);
4490	    swaps(&doodadWire->any.left,n);
4491	}
4492	switch (doodad->any.type) {
4493	    case XkbOutlineDoodad:
4494	    case XkbSolidDoodad:
4495		doodadWire->shape.angle= doodad->shape.angle;
4496		doodadWire->shape.colorNdx= doodad->shape.color_ndx;
4497		doodadWire->shape.shapeNdx= doodad->shape.shape_ndx;
4498		if (swap) {
4499		    register int n;
4500		    swaps(&doodadWire->shape.angle,n);
4501		}
4502		break;
4503	    case XkbTextDoodad:
4504		doodadWire->text.angle= doodad->text.angle;
4505		doodadWire->text.width= doodad->text.width;
4506		doodadWire->text.height= doodad->text.height;
4507		doodadWire->text.colorNdx= doodad->text.color_ndx;
4508		if (swap) {
4509		    register int n;
4510		    swaps(&doodadWire->text.angle,n);
4511		    swaps(&doodadWire->text.width,n);
4512		    swaps(&doodadWire->text.height,n);
4513		}
4514		wire= XkbWriteCountedString(wire,doodad->text.text,swap);
4515		wire= XkbWriteCountedString(wire,doodad->text.font,swap);
4516		break;
4517	    case XkbIndicatorDoodad:
4518		doodadWire->indicator.shapeNdx= doodad->indicator.shape_ndx;
4519		doodadWire->indicator.onColorNdx=doodad->indicator.on_color_ndx;
4520		doodadWire->indicator.offColorNdx=
4521						doodad->indicator.off_color_ndx;
4522		break;
4523	    case XkbLogoDoodad:
4524		doodadWire->logo.angle= doodad->logo.angle;
4525		doodadWire->logo.colorNdx= doodad->logo.color_ndx;
4526		doodadWire->logo.shapeNdx= doodad->logo.shape_ndx;
4527		wire= XkbWriteCountedString(wire,doodad->logo.logo_name,swap);
4528		break;
4529	    default:
4530		ErrorF("[xkb] Unknown doodad type %d in XkbWriteGeomDoodads\n",
4531			doodad->any.type);
4532		ErrorF("[xkb] Ignored\n");
4533		break;
4534	}
4535    }
4536    return wire;
4537}
4538
4539static char *
4540XkbWriteGeomOverlay(char *wire,XkbOverlayPtr ol,Bool swap)
4541{
4542register int		r;
4543XkbOverlayRowPtr	row;
4544xkbOverlayWireDesc *	olWire;
4545
4546   olWire= (xkbOverlayWireDesc *)wire;
4547   olWire->name= ol->name;
4548   olWire->nRows= ol->num_rows;
4549   if (swap) {
4550	register int n;
4551	swapl(&olWire->name,n);
4552   }
4553   wire= (char *)&olWire[1];
4554   for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
4555   	unsigned int		k;
4556	XkbOverlayKeyPtr	key;
4557	xkbOverlayRowWireDesc *	rowWire;
4558	rowWire= (xkbOverlayRowWireDesc *)wire;
4559	rowWire->rowUnder= row->row_under;
4560	rowWire->nKeys= row->num_keys;
4561	wire= (char *)&rowWire[1];
4562	for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
4563	    xkbOverlayKeyWireDesc *	keyWire;
4564	    keyWire= (xkbOverlayKeyWireDesc *)wire;
4565	    memcpy(keyWire->over,key->over.name,XkbKeyNameLength);
4566	    memcpy(keyWire->under,key->under.name,XkbKeyNameLength);
4567	    wire= (char *)&keyWire[1];
4568	}
4569   }
4570   return wire;
4571}
4572
4573static int
4574XkbSizeGeomSections(XkbGeometryPtr geom)
4575{
4576register int 	i,size;
4577XkbSectionPtr	section;
4578
4579    for (i=size=0,section=geom->sections;i<geom->num_sections;i++,section++) {
4580	size+= SIZEOF(xkbSectionWireDesc);
4581	if (section->rows) {
4582	    int		r;
4583	    XkbRowPtr	row;
4584	    for (r=0,row=section->rows;r<section->num_rows;row++,r++) {
4585		size+= SIZEOF(xkbRowWireDesc);
4586		size+= row->num_keys*SIZEOF(xkbKeyWireDesc);
4587	    }
4588	}
4589	if (section->doodads)
4590	    size+= XkbSizeGeomDoodads(section->num_doodads,section->doodads);
4591	if (section->overlays) {
4592	    int			o;
4593	    XkbOverlayPtr	ol;
4594	    for (o=0,ol=section->overlays;o<section->num_overlays;o++,ol++) {
4595		int			r;
4596		XkbOverlayRowPtr	row;
4597		size+= SIZEOF(xkbOverlayWireDesc);
4598		for (r=0,row=ol->rows;r<ol->num_rows;r++,row++) {
4599		   size+= SIZEOF(xkbOverlayRowWireDesc);
4600		   size+= row->num_keys*SIZEOF(xkbOverlayKeyWireDesc);
4601		}
4602	    }
4603	}
4604    }
4605    return size;
4606}
4607
4608static char *
4609XkbWriteGeomSections(char *wire,XkbGeometryPtr geom,Bool swap)
4610{
4611register int		i;
4612XkbSectionPtr		section;
4613xkbSectionWireDesc *	sectionWire;
4614
4615    for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) {
4616	sectionWire= (xkbSectionWireDesc *)wire;
4617	sectionWire->name= section->name;
4618	sectionWire->top= section->top;
4619	sectionWire->left= section->left;
4620	sectionWire->width= section->width;
4621	sectionWire->height= section->height;
4622	sectionWire->angle= section->angle;
4623	sectionWire->priority= section->priority;
4624	sectionWire->nRows= section->num_rows;
4625	sectionWire->nDoodads= section->num_doodads;
4626	sectionWire->nOverlays= section->num_overlays;
4627	sectionWire->pad= 0;
4628	if (swap) {
4629	    register int n;
4630	    swapl(&sectionWire->name,n);
4631	    swaps(&sectionWire->top,n);
4632	    swaps(&sectionWire->left,n);
4633	    swaps(&sectionWire->width,n);
4634	    swaps(&sectionWire->height,n);
4635	    swaps(&sectionWire->angle,n);
4636	}
4637	wire= (char *)&sectionWire[1];
4638	if (section->rows) {
4639	    int			r;
4640	    XkbRowPtr		row;
4641	    xkbRowWireDesc *	rowWire;
4642	    for (r=0,row=section->rows;r<section->num_rows;r++,row++) {
4643		rowWire= (xkbRowWireDesc *)wire;
4644		rowWire->top= row->top;
4645		rowWire->left= row->left;
4646		rowWire->nKeys= row->num_keys;
4647		rowWire->vertical= row->vertical;
4648		rowWire->pad= 0;
4649		if (swap) {
4650		    register int n;
4651		    swaps(&rowWire->top,n);
4652		    swaps(&rowWire->left,n);
4653		}
4654		wire= (char *)&rowWire[1];
4655		if (row->keys) {
4656		    int			k;
4657		    XkbKeyPtr		key;
4658		    xkbKeyWireDesc *	keyWire;
4659		    keyWire= (xkbKeyWireDesc *)wire;
4660		    for (k=0,key=row->keys;k<row->num_keys;k++,key++) {
4661			memcpy(keyWire[k].name,key->name.name,XkbKeyNameLength);
4662			keyWire[k].gap= key->gap;
4663			keyWire[k].shapeNdx= key->shape_ndx;
4664			keyWire[k].colorNdx= key->color_ndx;
4665			if (swap) {
4666			    register int n;
4667			    swaps(&keyWire[k].gap,n);
4668			}
4669		    }
4670		    wire= (char *)&keyWire[row->num_keys];
4671		}
4672	    }
4673	}
4674	if (section->doodads) {
4675	    wire= XkbWriteGeomDoodads(wire,
4676	    			      section->num_doodads,section->doodads,
4677				      swap);
4678	}
4679	if (section->overlays) {
4680	    register int o;
4681	    for (o=0;o<section->num_overlays;o++) {
4682		wire= XkbWriteGeomOverlay(wire,&section->overlays[o],swap);
4683	    }
4684	}
4685    }
4686    return wire;
4687}
4688
4689static Status
4690XkbComputeGetGeometryReplySize(	XkbGeometryPtr		geom,
4691				xkbGetGeometryReply *	rep,
4692				Atom			name)
4693{
4694int	len;
4695
4696    if (geom!=NULL) {
4697	len= XkbSizeCountedString(geom->label_font);
4698	len+= XkbSizeGeomProperties(geom);
4699	len+= XkbSizeGeomColors(geom);
4700	len+= XkbSizeGeomShapes(geom);
4701	len+= XkbSizeGeomSections(geom);
4702	len+= XkbSizeGeomDoodads(geom->num_doodads,geom->doodads);
4703	len+= XkbSizeGeomKeyAliases(geom);
4704	rep->length= len/4;
4705	rep->found= True;
4706	rep->name= geom->name;
4707	rep->widthMM= geom->width_mm;
4708	rep->heightMM= geom->height_mm;
4709	rep->nProperties= geom->num_properties;
4710	rep->nColors= geom->num_colors;
4711	rep->nShapes= geom->num_shapes;
4712	rep->nSections= geom->num_sections;
4713	rep->nDoodads= geom->num_doodads;
4714	rep->nKeyAliases= geom->num_key_aliases;
4715	rep->baseColorNdx= XkbGeomColorIndex(geom,geom->base_color);
4716	rep->labelColorNdx= XkbGeomColorIndex(geom,geom->label_color);
4717    }
4718    else {
4719	rep->length= 0;
4720	rep->found= False;
4721	rep->name= name;
4722	rep->widthMM= rep->heightMM= 0;
4723	rep->nProperties= rep->nColors= rep->nShapes= 0;
4724	rep->nSections= rep->nDoodads= 0;
4725	rep->nKeyAliases= 0;
4726	rep->labelColorNdx= rep->baseColorNdx= 0;
4727    }
4728    return Success;
4729}
4730
4731static int
4732XkbSendGeometry(	ClientPtr		client,
4733			XkbGeometryPtr		geom,
4734			xkbGetGeometryReply *	rep,
4735			Bool			freeGeom)
4736{
4737    char	*desc,*start;
4738    int		 len;
4739
4740    if (geom!=NULL) {
4741	len= rep->length*4;
4742	start= desc= (char *)xalloc(len);
4743	if (!start)
4744	    return BadAlloc;
4745	desc=  XkbWriteCountedString(desc,geom->label_font,client->swapped);
4746	if ( rep->nProperties>0 )
4747	    desc = XkbWriteGeomProperties(desc,geom,client->swapped);
4748	if ( rep->nColors>0 )
4749	    desc = XkbWriteGeomColors(desc,geom,client->swapped);
4750	if ( rep->nShapes>0 )
4751	    desc = XkbWriteGeomShapes(desc,geom,client->swapped);
4752	if ( rep->nSections>0 )
4753	    desc = XkbWriteGeomSections(desc,geom,client->swapped);
4754	if ( rep->nDoodads>0 )
4755	    desc = XkbWriteGeomDoodads(desc,geom->num_doodads,geom->doodads,
4756							  client->swapped);
4757	if ( rep->nKeyAliases>0 )
4758	    desc = XkbWriteGeomKeyAliases(desc,geom,client->swapped);
4759	if ((desc-start)!=(len)) {
4760	    ErrorF("[xkb] BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n",
4761			len, (unsigned long)(desc-start));
4762	}
4763    }
4764    else {
4765	len= 0;
4766	start= NULL;
4767    }
4768    if (client->swapped) {
4769	register int n;
4770	swaps(&rep->sequenceNumber,n);
4771	swapl(&rep->length,n);
4772	swapl(&rep->name,n);
4773	swaps(&rep->widthMM,n);
4774	swaps(&rep->heightMM,n);
4775	swaps(&rep->nProperties,n);
4776	swaps(&rep->nColors,n);
4777	swaps(&rep->nShapes,n);
4778	swaps(&rep->nSections,n);
4779	swaps(&rep->nDoodads,n);
4780	swaps(&rep->nKeyAliases,n);
4781    }
4782    WriteToClient(client, SIZEOF(xkbGetGeometryReply), (char *)rep);
4783    if (len>0)
4784	WriteToClient(client, len, start);
4785    if (start!=NULL)
4786	xfree((char *)start);
4787    if (freeGeom)
4788	XkbFreeGeometry(geom,XkbGeomAllMask,True);
4789    return client->noClientException;
4790}
4791
4792int
4793ProcXkbGetGeometry(ClientPtr client)
4794{
4795    DeviceIntPtr 	dev;
4796    xkbGetGeometryReply rep;
4797    XkbGeometryPtr	geom;
4798    Bool		shouldFree;
4799    Status		status;
4800
4801    REQUEST(xkbGetGeometryReq);
4802    REQUEST_SIZE_MATCH(xkbGetGeometryReq);
4803
4804    if (!(client->xkbClientFlags&_XkbClientInitialized))
4805	return BadAccess;
4806
4807    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
4808    CHK_ATOM_OR_NONE(stuff->name);
4809
4810    geom= XkbLookupNamedGeometry(dev,stuff->name,&shouldFree);
4811    rep.type= X_Reply;
4812    rep.deviceID= dev->id;
4813    rep.sequenceNumber= client->sequence;
4814    rep.length= 0;
4815    status= XkbComputeGetGeometryReplySize(geom,&rep,stuff->name);
4816    if (status!=Success)
4817	 return status;
4818    else return XkbSendGeometry(client,geom,&rep,shouldFree);
4819}
4820
4821/***====================================================================***/
4822
4823static char *
4824_GetCountedString(char **wire_inout,Bool swap)
4825{
4826char *	wire,*str;
4827CARD16	len,*plen;
4828
4829    wire= *wire_inout;
4830    plen= (CARD16 *)wire;
4831    if (swap) {
4832	register int n;
4833	swaps(plen,n);
4834    }
4835    len= *plen;
4836    str= (char *)_XkbAlloc(len+1);
4837    if (str) {
4838	memcpy(str,&wire[2],len);
4839	str[len]= '\0';
4840    }
4841    wire+= XkbPaddedSize(len+2);
4842    *wire_inout= wire;
4843    return str;
4844}
4845
4846static Status
4847_CheckSetDoodad(	char **		wire_inout,
4848			XkbGeometryPtr	geom,
4849			XkbSectionPtr	section,
4850			ClientPtr	client)
4851{
4852char *			wire;
4853xkbDoodadWireDesc *	dWire;
4854XkbDoodadPtr		doodad;
4855
4856    dWire= (xkbDoodadWireDesc *)(*wire_inout);
4857    wire= (char *)&dWire[1];
4858    if (client->swapped) {
4859	register int n;
4860	swapl(&dWire->any.name,n);
4861	swaps(&dWire->any.top,n);
4862	swaps(&dWire->any.left,n);
4863	swaps(&dWire->any.angle,n);
4864    }
4865    CHK_ATOM_ONLY(dWire->any.name);
4866    doodad= XkbAddGeomDoodad(geom,section,dWire->any.name);
4867    if (!doodad)
4868	return BadAlloc;
4869    doodad->any.type= dWire->any.type;
4870    doodad->any.priority= dWire->any.priority;
4871    doodad->any.top= dWire->any.top;
4872    doodad->any.left= dWire->any.left;
4873    doodad->any.angle= dWire->any.angle;
4874    switch (doodad->any.type) {
4875	case XkbOutlineDoodad:
4876	case XkbSolidDoodad:
4877	    if (dWire->shape.colorNdx>=geom->num_colors) {
4878		client->errorValue= _XkbErrCode3(0x40,geom->num_colors,
4879							dWire->shape.colorNdx);
4880		return BadMatch;
4881	    }
4882	    if (dWire->shape.shapeNdx>=geom->num_shapes) {
4883		client->errorValue= _XkbErrCode3(0x41,geom->num_shapes,
4884							dWire->shape.shapeNdx);
4885		return BadMatch;
4886	    }
4887	    doodad->shape.color_ndx= dWire->shape.colorNdx;
4888	    doodad->shape.shape_ndx= dWire->shape.shapeNdx;
4889	    break;
4890	case XkbTextDoodad:
4891	    if (dWire->text.colorNdx>=geom->num_colors) {
4892		client->errorValue= _XkbErrCode3(0x42,geom->num_colors,
4893							dWire->text.colorNdx);
4894		return BadMatch;
4895	    }
4896	    if (client->swapped) {
4897		register int n;
4898		swaps(&dWire->text.width,n);
4899		swaps(&dWire->text.height,n);
4900	    }
4901	    doodad->text.width= dWire->text.width;
4902	    doodad->text.height= dWire->text.height;
4903	    doodad->text.color_ndx= dWire->text.colorNdx;
4904	    doodad->text.text= _GetCountedString(&wire,client->swapped);
4905	    doodad->text.font= _GetCountedString(&wire,client->swapped);
4906	    break;
4907	case XkbIndicatorDoodad:
4908	    if (dWire->indicator.onColorNdx>=geom->num_colors) {
4909		client->errorValue= _XkbErrCode3(0x43,geom->num_colors,
4910						dWire->indicator.onColorNdx);
4911		return BadMatch;
4912	    }
4913	    if (dWire->indicator.offColorNdx>=geom->num_colors) {
4914		client->errorValue= _XkbErrCode3(0x44,geom->num_colors,
4915						dWire->indicator.offColorNdx);
4916		return BadMatch;
4917	    }
4918	    if (dWire->indicator.shapeNdx>=geom->num_shapes) {
4919		client->errorValue= _XkbErrCode3(0x45,geom->num_shapes,
4920						dWire->indicator.shapeNdx);
4921		return BadMatch;
4922	    }
4923	    doodad->indicator.shape_ndx= dWire->indicator.shapeNdx;
4924	    doodad->indicator.on_color_ndx= dWire->indicator.onColorNdx;
4925	    doodad->indicator.off_color_ndx= dWire->indicator.offColorNdx;
4926	    break;
4927	case XkbLogoDoodad:
4928	    if (dWire->logo.colorNdx>=geom->num_colors) {
4929		client->errorValue= _XkbErrCode3(0x46,geom->num_colors,
4930							dWire->logo.colorNdx);
4931		return BadMatch;
4932	    }
4933	    if (dWire->logo.shapeNdx>=geom->num_shapes) {
4934		client->errorValue= _XkbErrCode3(0x47,geom->num_shapes,
4935							dWire->logo.shapeNdx);
4936		return BadMatch;
4937	    }
4938	    doodad->logo.color_ndx= dWire->logo.colorNdx;
4939	    doodad->logo.shape_ndx= dWire->logo.shapeNdx;
4940	    doodad->logo.logo_name= _GetCountedString(&wire,client->swapped);
4941	    break;
4942	default:
4943	    client->errorValue= _XkbErrCode2(0x4F,dWire->any.type);
4944	    return BadValue;
4945    }
4946    *wire_inout= wire;
4947    return Success;
4948}
4949
4950static Status
4951_CheckSetOverlay(	char **		wire_inout,
4952			XkbGeometryPtr	geom,
4953			XkbSectionPtr	section,
4954			ClientPtr	client)
4955{
4956register int		r;
4957char *			wire;
4958XkbOverlayPtr		ol;
4959xkbOverlayWireDesc *	olWire;
4960xkbOverlayRowWireDesc *	rWire;
4961
4962    wire= *wire_inout;
4963    olWire= (xkbOverlayWireDesc *)wire;
4964    if (client->swapped) {
4965	register int n;
4966	swapl(&olWire->name,n);
4967    }
4968    CHK_ATOM_ONLY(olWire->name);
4969    ol= XkbAddGeomOverlay(section,olWire->name,olWire->nRows);
4970    rWire= (xkbOverlayRowWireDesc *)&olWire[1];
4971    for (r=0;r<olWire->nRows;r++) {
4972	register int		k;
4973	xkbOverlayKeyWireDesc *	kWire;
4974	XkbOverlayRowPtr	row;
4975
4976	if (rWire->rowUnder>section->num_rows) {
4977	    client->errorValue= _XkbErrCode4(0x20,r,section->num_rows,
4978							rWire->rowUnder);
4979	    return BadMatch;
4980	}
4981	row= XkbAddGeomOverlayRow(ol,rWire->rowUnder,rWire->nKeys);
4982	kWire= (xkbOverlayKeyWireDesc *)&rWire[1];
4983	for (k=0;k<rWire->nKeys;k++,kWire++) {
4984	    if (XkbAddGeomOverlayKey(ol,row,
4985	    		(char *)kWire->over,(char *)kWire->under)==NULL) {
4986		client->errorValue= _XkbErrCode3(0x21,r,k);
4987		return BadMatch;
4988	    }
4989	}
4990	rWire= (xkbOverlayRowWireDesc *)kWire;
4991    }
4992    olWire= (xkbOverlayWireDesc *)rWire;
4993    wire= (char *)olWire;
4994    *wire_inout= wire;
4995    return Success;
4996}
4997
4998static Status
4999_CheckSetSections( 	XkbGeometryPtr		geom,
5000			xkbSetGeometryReq *	req,
5001			char **			wire_inout,
5002			ClientPtr		client)
5003{
5004Status			status;
5005register int		s;
5006char *			wire;
5007xkbSectionWireDesc *	sWire;
5008XkbSectionPtr		section;
5009
5010    wire= *wire_inout;
5011    if (req->nSections<1)
5012	return Success;
5013    sWire= (xkbSectionWireDesc *)wire;
5014    for (s=0;s<req->nSections;s++) {
5015	register int		r;
5016	xkbRowWireDesc *	rWire;
5017	if (client->swapped) {
5018	    register int n;
5019	    swapl(&sWire->name,n);
5020	    swaps(&sWire->top,n);
5021	    swaps(&sWire->left,n);
5022	    swaps(&sWire->width,n);
5023	    swaps(&sWire->height,n);
5024	    swaps(&sWire->angle,n);
5025	}
5026	CHK_ATOM_ONLY(sWire->name);
5027	section= XkbAddGeomSection(geom,sWire->name,sWire->nRows,
5028					sWire->nDoodads,sWire->nOverlays);
5029	if (!section)
5030	    return BadAlloc;
5031	section->priority=	sWire->priority;
5032	section->top=		sWire->top;
5033	section->left=		sWire->left;
5034	section->width=		sWire->width;
5035	section->height=	sWire->height;
5036	section->angle=		sWire->angle;
5037	rWire= (xkbRowWireDesc *)&sWire[1];
5038	for (r=0;r<sWire->nRows;r++) {
5039	    register int	k;
5040	    XkbRowPtr		row;
5041	    xkbKeyWireDesc *	kWire;
5042	    if (client->swapped) {
5043		register int n;
5044		swaps(&rWire->top,n);
5045		swaps(&rWire->left,n);
5046	    }
5047	    row= XkbAddGeomRow(section,rWire->nKeys);
5048	    if (!row)
5049		return BadAlloc;
5050	    row->top= rWire->top;
5051	    row->left= rWire->left;
5052	    row->vertical= rWire->vertical;
5053	    kWire= (xkbKeyWireDesc *)&rWire[1];
5054	    for (k=0;k<rWire->nKeys;k++) {
5055		XkbKeyPtr	key;
5056		key= XkbAddGeomKey(row);
5057		if (!key)
5058		    return BadAlloc;
5059		memcpy(key->name.name,kWire[k].name,XkbKeyNameLength);
5060		key->gap= kWire[k].gap;
5061		key->shape_ndx= kWire[k].shapeNdx;
5062		key->color_ndx= kWire[k].colorNdx;
5063		if (key->shape_ndx>=geom->num_shapes) {
5064		    client->errorValue= _XkbErrCode3(0x10,key->shape_ndx,
5065							  geom->num_shapes);
5066		    return BadMatch;
5067		}
5068		if (key->color_ndx>=geom->num_colors) {
5069		    client->errorValue= _XkbErrCode3(0x11,key->color_ndx,
5070							  geom->num_colors);
5071		    return BadMatch;
5072		}
5073	    }
5074	    rWire= (xkbRowWireDesc *)&kWire[rWire->nKeys];
5075	}
5076	wire= (char *)rWire;
5077	if (sWire->nDoodads>0) {
5078	    register int d;
5079	    for (d=0;d<sWire->nDoodads;d++) {
5080		status=_CheckSetDoodad(&wire,geom,section,client);
5081		if (status!=Success)
5082		    return status;
5083	    }
5084	}
5085	if (sWire->nOverlays>0) {
5086	    register int o;
5087	    for (o=0;o<sWire->nOverlays;o++) {
5088		status= _CheckSetOverlay(&wire,geom,section,client);
5089		if (status!=Success)
5090		    return status;
5091	    }
5092	}
5093	sWire= (xkbSectionWireDesc *)wire;
5094    }
5095    wire= (char *)sWire;
5096    *wire_inout= wire;
5097    return Success;
5098}
5099
5100static Status
5101_CheckSetShapes( 	XkbGeometryPtr		geom,
5102			xkbSetGeometryReq *	req,
5103			char **			wire_inout,
5104			ClientPtr		client)
5105{
5106register int	i;
5107char *		wire;
5108
5109    wire= *wire_inout;
5110    if (req->nShapes<1) {
5111	client->errorValue= _XkbErrCode2(0x06,req->nShapes);
5112	return BadValue;
5113    }
5114    else {
5115	xkbShapeWireDesc *	shapeWire;
5116	XkbShapePtr		shape;
5117	register int		o;
5118	shapeWire= (xkbShapeWireDesc *)wire;
5119	for (i=0;i<req->nShapes;i++) {
5120	    xkbOutlineWireDesc *	olWire;
5121	    XkbOutlinePtr		ol;
5122	    shape= XkbAddGeomShape(geom,shapeWire->name,shapeWire->nOutlines);
5123	    if (!shape)
5124		return BadAlloc;
5125	    olWire= (xkbOutlineWireDesc *)(&shapeWire[1]);
5126	    for (o=0;o<shapeWire->nOutlines;o++) {
5127		register int		p;
5128		XkbPointPtr		pt;
5129		xkbPointWireDesc *	ptWire;
5130
5131		ol= XkbAddGeomOutline(shape,olWire->nPoints);
5132		if (!ol)
5133		    return BadAlloc;
5134		ol->corner_radius=	olWire->cornerRadius;
5135		ptWire= (xkbPointWireDesc *)&olWire[1];
5136		for (p=0,pt=ol->points;p<olWire->nPoints;p++,pt++) {
5137		    pt->x= ptWire[p].x;
5138		    pt->y= ptWire[p].y;
5139		    if (client->swapped) {
5140			register int n;
5141			swaps(&pt->x,n);
5142			swaps(&pt->y,n);
5143		    }
5144		}
5145		ol->num_points= olWire->nPoints;
5146		olWire= (xkbOutlineWireDesc *)(&ptWire[olWire->nPoints]);
5147	    }
5148	    if (shapeWire->primaryNdx!=XkbNoShape)
5149		shape->primary= &shape->outlines[shapeWire->primaryNdx];
5150	    if (shapeWire->approxNdx!=XkbNoShape)
5151		shape->approx= &shape->outlines[shapeWire->approxNdx];
5152	    shapeWire= (xkbShapeWireDesc *)olWire;
5153	}
5154	wire= (char *)shapeWire;
5155    }
5156    if (geom->num_shapes!=req->nShapes) {
5157	client->errorValue= _XkbErrCode3(0x07,geom->num_shapes,req->nShapes);
5158	return BadMatch;
5159    }
5160
5161    *wire_inout= wire;
5162    return Success;
5163}
5164
5165static Status
5166_CheckSetGeom(	XkbGeometryPtr		geom,
5167		xkbSetGeometryReq *	req,
5168		ClientPtr 		client)
5169{
5170register int	i;
5171Status		status;
5172char *		wire;
5173
5174    wire= (char *)&req[1];
5175    geom->label_font= _GetCountedString(&wire,client->swapped);
5176
5177    for (i=0;i<req->nProperties;i++) {
5178	char *name,*val;
5179	name= _GetCountedString(&wire,client->swapped);
5180        if (!name)
5181            return BadAlloc;
5182	val= _GetCountedString(&wire,client->swapped);
5183        if (!val) {
5184            xfree(name);
5185            return BadAlloc;
5186        }
5187	if (XkbAddGeomProperty(geom,name,val)==NULL) {
5188            xfree(name);
5189            xfree(val);
5190	    return BadAlloc;
5191        }
5192        xfree(name);
5193        xfree(val);
5194    }
5195
5196    if (req->nColors<2) {
5197	client->errorValue= _XkbErrCode3(0x01,2,req->nColors);
5198	return BadValue;
5199    }
5200    if (req->baseColorNdx>req->nColors) {
5201	client->errorValue=_XkbErrCode3(0x03,req->nColors,req->baseColorNdx);
5202	return BadMatch;
5203    }
5204    if (req->labelColorNdx>req->nColors) {
5205	client->errorValue= _XkbErrCode3(0x03,req->nColors,req->labelColorNdx);
5206	return BadMatch;
5207    }
5208    if (req->labelColorNdx==req->baseColorNdx) {
5209	client->errorValue= _XkbErrCode3(0x04,req->baseColorNdx,
5210                                         req->labelColorNdx);
5211	return BadMatch;
5212    }
5213
5214    for (i=0;i<req->nColors;i++) {
5215	char *name;
5216	name= _GetCountedString(&wire,client->swapped);
5217	if (!name)
5218            return BadAlloc;
5219        if (!XkbAddGeomColor(geom,name,geom->num_colors)) {
5220            xfree(name);
5221	    return BadAlloc;
5222        }
5223        xfree(name);
5224    }
5225    if (req->nColors!=geom->num_colors) {
5226	client->errorValue= _XkbErrCode3(0x05,req->nColors,geom->num_colors);
5227	return BadMatch;
5228    }
5229    geom->label_color= &geom->colors[req->labelColorNdx];
5230    geom->base_color= &geom->colors[req->baseColorNdx];
5231
5232    if ((status=_CheckSetShapes(geom,req,&wire,client))!=Success)
5233	return status;
5234
5235    if ((status=_CheckSetSections(geom,req,&wire,client))!=Success)
5236	return status;
5237
5238    for (i=0;i<req->nDoodads;i++) {
5239	status=_CheckSetDoodad(&wire,geom,NULL,client);
5240	if (status!=Success)
5241	    return status;
5242    }
5243
5244    for (i=0;i<req->nKeyAliases;i++) {
5245	if (XkbAddGeomKeyAlias(geom,&wire[XkbKeyNameLength],wire)==NULL)
5246	    return BadAlloc;
5247	wire+= 2*XkbKeyNameLength;
5248    }
5249    return Success;
5250}
5251
5252static int
5253_XkbSetGeometry(ClientPtr client, DeviceIntPtr dev, xkbSetGeometryReq *stuff)
5254{
5255    XkbDescPtr		xkb;
5256    Bool		new_name;
5257    xkbNewKeyboardNotify	nkn;
5258    XkbGeometryPtr	geom,old;
5259    XkbGeometrySizesRec	sizes;
5260    Status		status;
5261
5262    xkb= dev->key->xkbInfo->desc;
5263    old= xkb->geom;
5264    xkb->geom= NULL;
5265
5266    sizes.which=		XkbGeomAllMask;
5267    sizes.num_properties=	stuff->nProperties;
5268    sizes.num_colors=	stuff->nColors;
5269    sizes.num_shapes=	stuff->nShapes;
5270    sizes.num_sections=	stuff->nSections;
5271    sizes.num_doodads=	stuff->nDoodads;
5272    sizes.num_key_aliases=	stuff->nKeyAliases;
5273    if ((status= XkbAllocGeometry(xkb,&sizes))!=Success) {
5274        xkb->geom= old;
5275        return status;
5276    }
5277    geom= xkb->geom;
5278    geom->name= stuff->name;
5279    geom->width_mm= stuff->widthMM;
5280    geom->height_mm= stuff->heightMM;
5281    if ((status= _CheckSetGeom(geom,stuff,client))!=Success) {
5282        XkbFreeGeometry(geom,XkbGeomAllMask,True);
5283        xkb->geom= old;
5284        return status;
5285    }
5286    new_name= (xkb->names->geometry!=geom->name);
5287    xkb->names->geometry= geom->name;
5288    if (old)
5289        XkbFreeGeometry(old,XkbGeomAllMask,True);
5290    if (new_name) {
5291        xkbNamesNotify	nn;
5292        bzero(&nn,sizeof(xkbNamesNotify));
5293        nn.changed= XkbGeometryNameMask;
5294        XkbSendNamesNotify(dev,&nn);
5295    }
5296    nkn.deviceID= nkn.oldDeviceID= dev->id;
5297    nkn.minKeyCode= nkn.oldMinKeyCode= xkb->min_key_code;
5298    nkn.maxKeyCode= nkn.oldMaxKeyCode= xkb->max_key_code;
5299    nkn.requestMajor=	XkbReqCode;
5300    nkn.requestMinor=	X_kbSetGeometry;
5301    nkn.changed=	XkbNKN_GeometryMask;
5302    XkbSendNewKeyboardNotify(dev,&nkn);
5303    return Success;
5304}
5305
5306int
5307ProcXkbSetGeometry(ClientPtr client)
5308{
5309    DeviceIntPtr        dev;
5310    int                 rc;
5311
5312    REQUEST(xkbSetGeometryReq);
5313    REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq);
5314
5315    if (!(client->xkbClientFlags&_XkbClientInitialized))
5316	return BadAccess;
5317
5318    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
5319    CHK_ATOM_OR_NONE(stuff->name);
5320
5321    rc = _XkbSetGeometry(client, dev, stuff);
5322    if (rc != Success)
5323        return rc;
5324
5325    if (stuff->deviceSpec == XkbUseCoreKbd)
5326    {
5327        DeviceIntPtr other;
5328        for (other = inputInfo.devices; other; other = other->next)
5329        {
5330            if ((other != dev) && other->key && !other->isMaster && (other->u.master == dev))
5331            {
5332                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
5333                if (rc == Success)
5334                    _XkbSetGeometry(client, other, stuff);
5335            }
5336        }
5337    }
5338
5339    return Success;
5340}
5341
5342/***====================================================================***/
5343
5344int
5345ProcXkbPerClientFlags(ClientPtr client)
5346{
5347    DeviceIntPtr 		dev;
5348    xkbPerClientFlagsReply 	rep;
5349    XkbInterestPtr		interest;
5350    Mask access_mode = DixGetAttrAccess | DixSetAttrAccess;
5351
5352    REQUEST(xkbPerClientFlagsReq);
5353    REQUEST_SIZE_MATCH(xkbPerClientFlagsReq);
5354
5355    if (!(client->xkbClientFlags&_XkbClientInitialized))
5356	return BadAccess;
5357
5358    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
5359    CHK_MASK_LEGAL(0x01,stuff->change,XkbPCF_AllFlagsMask);
5360    CHK_MASK_MATCH(0x02,stuff->change,stuff->value);
5361
5362    interest = XkbFindClientResource((DevicePtr)dev,client);
5363    rep.type= X_Reply;
5364    rep.length = 0;
5365    rep.sequenceNumber = client->sequence;
5366    if (stuff->change) {
5367	client->xkbClientFlags&= ~stuff->change;
5368	client->xkbClientFlags|= stuff->value;
5369    }
5370    if (stuff->change&XkbPCF_AutoResetControlsMask) {
5371	Bool	want;
5372	want= stuff->value&XkbPCF_AutoResetControlsMask;
5373	if (interest && !want) {
5374	    interest->autoCtrls= interest->autoCtrlValues= 0;
5375	}
5376	else if (want && (!interest)) {
5377	    XID id = FakeClientID(client->index);
5378	    AddResource(id,RT_XKBCLIENT,dev);
5379	    interest= XkbAddClientResource((DevicePtr)dev,client,id);
5380	    if (!interest)
5381		return BadAlloc;
5382	}
5383	if (interest && want ) {
5384	    register unsigned affect;
5385	    affect= stuff->ctrlsToChange;
5386
5387	    CHK_MASK_LEGAL(0x03,affect,XkbAllBooleanCtrlsMask);
5388	    CHK_MASK_MATCH(0x04,affect,stuff->autoCtrls);
5389	    CHK_MASK_MATCH(0x05,stuff->autoCtrls,stuff->autoCtrlValues);
5390
5391	    interest->autoCtrls&= ~affect;
5392	    interest->autoCtrlValues&= ~affect;
5393	    interest->autoCtrls|= stuff->autoCtrls&affect;
5394	    interest->autoCtrlValues|= stuff->autoCtrlValues&affect;
5395	}
5396    }
5397    rep.supported = XkbPCF_AllFlagsMask;
5398    rep.value= client->xkbClientFlags&XkbPCF_AllFlagsMask;
5399    if (interest) {
5400	rep.autoCtrls= interest->autoCtrls;
5401	rep.autoCtrlValues= interest->autoCtrlValues;
5402    }
5403    else {
5404	rep.autoCtrls= rep.autoCtrlValues= 0;
5405    }
5406    if ( client->swapped ) {
5407	register int n;
5408	swaps(&rep.sequenceNumber, n);
5409	swapl(&rep.supported,n);
5410	swapl(&rep.value,n);
5411	swapl(&rep.autoCtrls,n);
5412	swapl(&rep.autoCtrlValues,n);
5413    }
5414    WriteToClient(client,SIZEOF(xkbPerClientFlagsReply), (char *)&rep);
5415    return client->noClientException;
5416}
5417
5418/***====================================================================***/
5419
5420/* all latin-1 alphanumerics, plus parens, minus, underscore, slash */
5421/* and wildcards */
5422static unsigned char componentSpecLegal[] = {
5423        0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x87,
5424        0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07,
5425        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5426        0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
5427};
5428
5429/* same as above but accepts percent, plus and bar too */
5430static unsigned char componentExprLegal[] = {
5431        0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0xff, 0x87,
5432        0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x17,
5433        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5434        0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
5435};
5436
5437static char *
5438GetComponentSpec(unsigned char **pWire,Bool allowExpr,int *errRtrn)
5439{
5440int		len;
5441register int	i;
5442unsigned char	*wire,*str,*tmp,*legal;
5443
5444    if (allowExpr)	legal= &componentExprLegal[0];
5445    else		legal= &componentSpecLegal[0];
5446
5447    wire= *pWire;
5448    len= (*(unsigned char *)wire++);
5449    if (len>0) {
5450	str= (unsigned char *)_XkbCalloc(1, len+1);
5451	if (str) {
5452	    tmp= str;
5453	    for (i=0;i<len;i++) {
5454		if (legal[(*wire)/8]&(1<<((*wire)%8)))
5455		    *tmp++= *wire++;
5456		else wire++;
5457	    }
5458	    if (tmp!=str)
5459		*tmp++= '\0';
5460	    else {
5461		_XkbFree(str);
5462		str= NULL;
5463	    }
5464	}
5465	else {
5466	    *errRtrn= BadAlloc;
5467	}
5468    }
5469    else {
5470	str= NULL;
5471    }
5472    *pWire= wire;
5473    return (char *)str;
5474}
5475
5476/***====================================================================***/
5477
5478int
5479ProcXkbListComponents(ClientPtr client)
5480{
5481    DeviceIntPtr 		dev;
5482    xkbListComponentsReply 	rep;
5483    unsigned			len;
5484    int				status;
5485    unsigned char *		str;
5486    XkbSrvListInfoRec		list;
5487
5488    REQUEST(xkbListComponentsReq);
5489    REQUEST_AT_LEAST_SIZE(xkbListComponentsReq);
5490
5491    if (!(client->xkbClientFlags&_XkbClientInitialized))
5492	return BadAccess;
5493
5494    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
5495
5496    status= Success;
5497    str= (unsigned char *)&stuff[1];
5498    bzero(&list,sizeof(XkbSrvListInfoRec));
5499    list.maxRtrn= stuff->maxNames;
5500    list.pattern[_XkbListKeymaps]= GetComponentSpec(&str,False,&status);
5501    list.pattern[_XkbListKeycodes]= GetComponentSpec(&str,False,&status);
5502    list.pattern[_XkbListTypes]= GetComponentSpec(&str,False,&status);
5503    list.pattern[_XkbListCompat]= GetComponentSpec(&str,False,&status);
5504    list.pattern[_XkbListSymbols]= GetComponentSpec(&str,False,&status);
5505    list.pattern[_XkbListGeometry]= GetComponentSpec(&str,False,&status);
5506    if (status!=Success)
5507	return status;
5508    len= str-((unsigned char *)stuff);
5509    if ((XkbPaddedSize(len)/4)!=stuff->length)
5510	return BadLength;
5511    if ((status=XkbDDXList(dev,&list,client))!=Success) {
5512	if (list.pool) {
5513	    _XkbFree(list.pool);
5514	    list.pool= NULL;
5515	}
5516	return status;
5517    }
5518    bzero(&rep,sizeof(xkbListComponentsReply));
5519    rep.type= X_Reply;
5520    rep.deviceID = dev->id;
5521    rep.sequenceNumber = client->sequence;
5522    rep.length = XkbPaddedSize(list.nPool)/4;
5523    rep.nKeymaps = list.nFound[_XkbListKeymaps];
5524    rep.nKeycodes = list.nFound[_XkbListKeycodes];
5525    rep.nTypes = list.nFound[_XkbListTypes];
5526    rep.nCompatMaps = list.nFound[_XkbListCompat];
5527    rep.nSymbols = list.nFound[_XkbListSymbols];
5528    rep.nGeometries = list.nFound[_XkbListGeometry];
5529    rep.extra=	0;
5530    if (list.nTotal>list.maxRtrn)
5531	rep.extra = (list.nTotal-list.maxRtrn);
5532    if (client->swapped) {
5533	register int n;
5534	swaps(&rep.sequenceNumber,n);
5535	swapl(&rep.length,n);
5536	swaps(&rep.nKeymaps,n);
5537	swaps(&rep.nKeycodes,n);
5538	swaps(&rep.nTypes,n);
5539	swaps(&rep.nCompatMaps,n);
5540	swaps(&rep.nSymbols,n);
5541	swaps(&rep.nGeometries,n);
5542	swaps(&rep.extra,n);
5543    }
5544    WriteToClient(client,SIZEOF(xkbListComponentsReply),(char *)&rep);
5545    if (list.nPool && list.pool) {
5546	WriteToClient(client,XkbPaddedSize(list.nPool), (char *)list.pool);
5547	_XkbFree(list.pool);
5548	list.pool= NULL;
5549    }
5550    return client->noClientException;
5551}
5552
5553/***====================================================================***/
5554
5555int
5556ProcXkbGetKbdByName(ClientPtr client)
5557{
5558    DeviceIntPtr 		dev;
5559    DeviceIntPtr                tmpd;
5560    xkbGetKbdByNameReply 	rep;
5561    xkbGetMapReply		mrep;
5562    xkbGetCompatMapReply	crep;
5563    xkbGetIndicatorMapReply	irep;
5564    xkbGetNamesReply		nrep;
5565    xkbGetGeometryReply		grep;
5566    XkbComponentNamesRec	names;
5567    XkbDescPtr			xkb, new;
5568    unsigned char *		str;
5569    char 			mapFile[PATH_MAX];
5570    unsigned			len;
5571    unsigned			fwant,fneed,reported;
5572    int				status;
5573    Bool			geom_changed;
5574    XkbSrvLedInfoPtr            old_sli;
5575    XkbSrvLedInfoPtr            sli;
5576    Mask access_mode = DixGetAttrAccess | DixManageAccess;
5577
5578    REQUEST(xkbGetKbdByNameReq);
5579    REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq);
5580
5581    if (!(client->xkbClientFlags&_XkbClientInitialized))
5582	return BadAccess;
5583
5584    CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
5585
5586    xkb = dev->key->xkbInfo->desc;
5587    status= Success;
5588    str= (unsigned char *)&stuff[1];
5589    names.keymap= GetComponentSpec(&str,True,&status);
5590    names.keycodes= GetComponentSpec(&str,True,&status);
5591    names.types= GetComponentSpec(&str,True,&status);
5592    names.compat= GetComponentSpec(&str,True,&status);
5593    names.symbols= GetComponentSpec(&str,True,&status);
5594    names.geometry= GetComponentSpec(&str,True,&status);
5595    if (status!=Success)
5596	return status;
5597    len= str-((unsigned char *)stuff);
5598    if ((XkbPaddedSize(len)/4)!=stuff->length)
5599	return BadLength;
5600
5601    CHK_MASK_LEGAL(0x01,stuff->want,XkbGBN_AllComponentsMask);
5602    CHK_MASK_LEGAL(0x02,stuff->need,XkbGBN_AllComponentsMask);
5603
5604    if (stuff->load)
5605	 fwant= XkbGBN_AllComponentsMask;
5606    else fwant= stuff->want|stuff->need;
5607    if ((!names.compat)&&
5608        (fwant&(XkbGBN_CompatMapMask|XkbGBN_IndicatorMapMask))) {
5609        names.compat= _XkbDupString("%");
5610    }
5611    if ((!names.types)&&(fwant&(XkbGBN_TypesMask))) {
5612        names.types= _XkbDupString("%");
5613    }
5614    if ((!names.symbols)&&(fwant&XkbGBN_SymbolsMask)) {
5615        names.symbols= _XkbDupString("%");
5616    }
5617    geom_changed= ((names.geometry!=NULL)&&(strcmp(names.geometry,"%")!=0));
5618    if ((!names.geometry)&&(fwant&XkbGBN_GeometryMask)) {
5619        names.geometry= _XkbDupString("%");
5620        geom_changed= False;
5621    }
5622
5623    bzero(mapFile,PATH_MAX);
5624    rep.type= X_Reply;
5625    rep.deviceID = dev->id;
5626    rep.sequenceNumber = client->sequence;
5627    rep.length = 0;
5628    rep.minKeyCode = xkb->min_key_code;
5629    rep.maxKeyCode = xkb->max_key_code;
5630    rep.loaded=	False;
5631    fwant= XkbConvertGetByNameComponents(True,stuff->want)|XkmVirtualModsMask;
5632    fneed= XkbConvertGetByNameComponents(True,stuff->need);
5633    rep.reported= XkbConvertGetByNameComponents(False,fwant|fneed);
5634    if (stuff->load) {
5635	fneed|= XkmKeymapRequired;
5636	fwant|= XkmKeymapLegal;
5637    }
5638    if ((fwant|fneed)&XkmSymbolsMask) {
5639	fneed|= XkmKeyNamesIndex|XkmTypesIndex;
5640	fwant|= XkmIndicatorsIndex;
5641    }
5642
5643    /* We pass dev in here so we can get the old names out if needed. */
5644    rep.found = XkbDDXLoadKeymapByNames(dev,&names,fwant,fneed,&new,
5645                                        mapFile,PATH_MAX);
5646    rep.newKeyboard= False;
5647    rep.pad1= rep.pad2= rep.pad3= rep.pad4= 0;
5648
5649    stuff->want|= stuff->need;
5650    if (new==NULL)
5651	rep.reported= 0;
5652    else {
5653	if (stuff->load)
5654	    rep.loaded= True;
5655	if (stuff->load ||
5656		((rep.reported&XkbGBN_SymbolsMask) && (new->compat))) {
5657	    XkbChangesRec changes;
5658	    bzero(&changes,sizeof(changes));
5659	    XkbUpdateDescActions(new,
5660			new->min_key_code,XkbNumKeys(new),
5661			&changes);
5662	}
5663
5664	if (new->map==NULL)
5665	    rep.reported&= ~(XkbGBN_SymbolsMask|XkbGBN_TypesMask);
5666	else if (rep.reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask)) {
5667	    mrep.type= X_Reply;
5668	    mrep.deviceID = dev->id;
5669	    mrep.sequenceNumber= client->sequence;
5670	    mrep.length = ((SIZEOF(xkbGetMapReply)-SIZEOF(xGenericReply))>>2);
5671	    mrep.minKeyCode = new->min_key_code;
5672	    mrep.maxKeyCode = new->max_key_code;
5673	    mrep.present = 0;
5674	    mrep.totalSyms = mrep.totalActs =
5675		mrep.totalKeyBehaviors= mrep.totalKeyExplicit=
5676		mrep.totalModMapKeys= mrep.totalVModMapKeys= 0;
5677	    if (rep.reported&(XkbGBN_TypesMask|XkbGBN_ClientSymbolsMask)) {
5678		mrep.present|= XkbKeyTypesMask;
5679		mrep.firstType = 0;
5680		mrep.nTypes = mrep.totalTypes= new->map->num_types;
5681	    }
5682	    else {
5683		mrep.firstType = mrep.nTypes= 0;
5684		mrep.totalTypes= 0;
5685	    }
5686	    if (rep.reported&XkbGBN_ClientSymbolsMask) {
5687		mrep.present|= (XkbKeySymsMask|XkbModifierMapMask);
5688		mrep.firstKeySym = mrep.firstModMapKey= new->min_key_code;
5689		mrep.nKeySyms = mrep.nModMapKeys= XkbNumKeys(new);
5690	    }
5691	    else {
5692		mrep.firstKeySym= mrep.firstModMapKey= 0;
5693		mrep.nKeySyms= mrep.nModMapKeys= 0;
5694	    }
5695	    if (rep.reported&XkbGBN_ServerSymbolsMask) {
5696		mrep.present|= XkbAllServerInfoMask;
5697		mrep.virtualMods= ~0;
5698		mrep.firstKeyAct = mrep.firstKeyBehavior =
5699			mrep.firstKeyExplicit = new->min_key_code;
5700		mrep.nKeyActs = mrep.nKeyBehaviors =
5701			mrep.nKeyExplicit = XkbNumKeys(new);
5702		mrep.firstVModMapKey= new->min_key_code;
5703		mrep.nVModMapKeys= XkbNumKeys(new);
5704	    }
5705	    else {
5706		mrep.virtualMods= 0;
5707		mrep.firstKeyAct= mrep.firstKeyBehavior=
5708			mrep.firstKeyExplicit = 0;
5709		mrep.nKeyActs= mrep.nKeyBehaviors= mrep.nKeyExplicit= 0;
5710	    }
5711	    XkbComputeGetMapReplySize(new,&mrep);
5712	    rep.length+= SIZEOF(xGenericReply)/4+mrep.length;
5713	}
5714	if (new->compat==NULL)
5715	    rep.reported&= ~XkbGBN_CompatMapMask;
5716	else if (rep.reported&XkbGBN_CompatMapMask) {
5717	    crep.type= X_Reply;
5718	    crep.deviceID= dev->id;
5719	    crep.sequenceNumber= client->sequence;
5720	    crep.length= 0;
5721	    crep.groups= XkbAllGroupsMask;
5722	    crep.firstSI= 0;
5723	    crep.nSI= crep.nTotalSI= new->compat->num_si;
5724	    XkbComputeGetCompatMapReplySize(new->compat,&crep);
5725	    rep.length+= SIZEOF(xGenericReply)/4+crep.length;
5726	}
5727	if (new->indicators==NULL)
5728	    rep.reported&= ~XkbGBN_IndicatorMapMask;
5729	else if (rep.reported&XkbGBN_IndicatorMapMask) {
5730	    irep.type= X_Reply;
5731	    irep.deviceID= dev->id;
5732	    irep.sequenceNumber= client->sequence;
5733	    irep.length= 0;
5734	    irep.which= XkbAllIndicatorsMask;
5735	    XkbComputeGetIndicatorMapReplySize(new->indicators,&irep);
5736	    rep.length+= SIZEOF(xGenericReply)/4+irep.length;
5737	}
5738	if (new->names==NULL)
5739	    rep.reported&= ~(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask);
5740	else if (rep.reported&(XkbGBN_OtherNamesMask|XkbGBN_KeyNamesMask)) {
5741	    nrep.type= X_Reply;
5742	    nrep.deviceID= dev->id;
5743	    nrep.sequenceNumber= client->sequence;
5744	    nrep.length= 0;
5745	    nrep.minKeyCode= new->min_key_code;
5746	    nrep.maxKeyCode= new->max_key_code;
5747	    if (rep.reported&XkbGBN_OtherNamesMask) {
5748		nrep.which= XkbAllNamesMask;
5749		if (new->map!=NULL)
5750		     nrep.nTypes= new->map->num_types;
5751		else nrep.nTypes= 0;
5752		nrep.nKTLevels= 0;
5753		nrep.groupNames= XkbAllGroupsMask;
5754		nrep.virtualMods= XkbAllVirtualModsMask;
5755		nrep.indicators= XkbAllIndicatorsMask;
5756		nrep.nRadioGroups= new->names->num_rg;
5757	    }
5758	    else {
5759		nrep.which= 0;
5760		nrep.nTypes= 0;
5761		nrep.nKTLevels= 0;
5762		nrep.groupNames= 0;
5763		nrep.virtualMods= 0;
5764		nrep.indicators= 0;
5765		nrep.nRadioGroups= 0;
5766	    }
5767	    if (rep.reported&XkbGBN_KeyNamesMask) {
5768		nrep.which|= XkbKeyNamesMask;
5769		nrep.firstKey= new->min_key_code;
5770		nrep.nKeys= XkbNumKeys(new);
5771		nrep.nKeyAliases= new->names->num_key_aliases;
5772		if (nrep.nKeyAliases)
5773		    nrep.which|= XkbKeyAliasesMask;
5774	    }
5775	    else {
5776		nrep.which&= ~(XkbKeyNamesMask|XkbKeyAliasesMask);
5777		nrep.firstKey= nrep.nKeys= 0;
5778		nrep.nKeyAliases= 0;
5779	    }
5780	    XkbComputeGetNamesReplySize(new,&nrep);
5781	    rep.length+= SIZEOF(xGenericReply)/4+nrep.length;
5782	}
5783	if (new->geom==NULL)
5784	    rep.reported&= ~XkbGBN_GeometryMask;
5785	else if (rep.reported&XkbGBN_GeometryMask) {
5786	    grep.type= X_Reply;
5787	    grep.deviceID= dev->id;
5788	    grep.sequenceNumber= client->sequence;
5789	    grep.length= 0;
5790	    grep.found= True;
5791	    grep.pad= 0;
5792	    grep.widthMM= grep.heightMM= 0;
5793	    grep.nProperties= grep.nColors= grep.nShapes= 0;
5794	    grep.nSections= grep.nDoodads= 0;
5795	    grep.baseColorNdx= grep.labelColorNdx= 0;
5796	    XkbComputeGetGeometryReplySize(new->geom,&grep,None);
5797	    rep.length+= SIZEOF(xGenericReply)/4+grep.length;
5798	}
5799    }
5800
5801    reported= rep.reported;
5802    if ( client->swapped ) {
5803	register int n;
5804	swaps(&rep.sequenceNumber,n);
5805	swapl(&rep.length,n);
5806	swaps(&rep.found,n);
5807	swaps(&rep.reported,n);
5808    }
5809    WriteToClient(client,SIZEOF(xkbGetKbdByNameReply), (char *)&rep);
5810    if (reported&(XkbGBN_SymbolsMask|XkbGBN_TypesMask))
5811	XkbSendMap(client,new,&mrep);
5812    if (reported&XkbGBN_CompatMapMask)
5813	XkbSendCompatMap(client,new->compat,&crep);
5814    if (reported&XkbGBN_IndicatorMapMask)
5815	XkbSendIndicatorMap(client,new->indicators,&irep);
5816    if (reported&(XkbGBN_KeyNamesMask|XkbGBN_OtherNamesMask))
5817	XkbSendNames(client,new,&nrep);
5818    if (reported&XkbGBN_GeometryMask)
5819	XkbSendGeometry(client,new->geom,&grep,False);
5820    if (rep.loaded) {
5821	XkbDescPtr		old_xkb;
5822	xkbNewKeyboardNotify 	nkn;
5823	int 			i,nG,nTG;
5824	old_xkb= xkb;
5825	xkb= new;
5826	dev->key->xkbInfo->desc= xkb;
5827	new= old_xkb; /* so it'll get freed automatically */
5828
5829	*xkb->ctrls= *old_xkb->ctrls;
5830	for (nG=nTG=0,i=xkb->min_key_code;i<=xkb->max_key_code;i++) {
5831	    nG= XkbKeyNumGroups(xkb,i);
5832	    if (nG>=XkbNumKbdGroups) {
5833		nTG= XkbNumKbdGroups;
5834		break;
5835	    }
5836	    if (nG>nTG) {
5837		nTG= nG;
5838	    }
5839	}
5840	xkb->ctrls->num_groups= nTG;
5841
5842        for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
5843            if (tmpd == dev ||
5844                (dev->id == inputInfo.keyboard->id && tmpd->key &&
5845                 tmpd->coreEvents)) {
5846
5847                memcpy(tmpd->key->modifierMap, xkb->map->modmap,
5848                       xkb->max_key_code + 1);
5849                if (tmpd != dev)
5850                    XkbCopyKeymap(dev->key->xkbInfo->desc,
5851                                  tmpd->key->xkbInfo->desc, True);
5852                XkbUpdateCoreDescription(tmpd, True);
5853
5854                if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) {
5855                    old_sli = tmpd->kbdfeed->xkb_sli;
5856                    tmpd->kbdfeed->xkb_sli = NULL;
5857                    sli = XkbAllocSrvLedInfo(tmpd, tmpd->kbdfeed, NULL, 0);
5858                    if (sli) {
5859                        sli->explicitState = old_sli->explicitState;
5860                        sli->effectiveState = old_sli->effectiveState;
5861                    }
5862                    tmpd->kbdfeed->xkb_sli = sli;
5863                    XkbFreeSrvLedInfo(old_sli);
5864                }
5865            }
5866        }
5867
5868        /* this should be either a MN or an NKN, depending on whether or not
5869         * the keycode range changed? */
5870	nkn.deviceID= nkn.oldDeviceID= dev->id;
5871	nkn.minKeyCode= new->min_key_code;
5872	nkn.maxKeyCode= new->max_key_code;
5873	nkn.oldMinKeyCode= xkb->min_key_code;
5874	nkn.oldMaxKeyCode= xkb->max_key_code;
5875	nkn.requestMajor= XkbReqCode;
5876	nkn.requestMinor= X_kbGetKbdByName;
5877	nkn.changed= XkbNKN_KeycodesMask;
5878	if (geom_changed)
5879	    nkn.changed|= XkbNKN_GeometryMask;
5880	XkbSendNewKeyboardNotify(dev,&nkn);
5881    }
5882    if ((new!=NULL)&&(new!=xkb)) {
5883	XkbFreeKeyboard(new,XkbAllComponentsMask,True);
5884	new= NULL;
5885    }
5886    if (names.keymap)	{ _XkbFree(names.keymap); names.keymap= NULL; }
5887    if (names.keycodes)	{ _XkbFree(names.keycodes); names.keycodes= NULL; }
5888    if (names.types)	{ _XkbFree(names.types); names.types= NULL; }
5889    if (names.compat)	{ _XkbFree(names.compat); names.compat= NULL; }
5890    if (names.symbols)	{ _XkbFree(names.symbols); names.symbols= NULL; }
5891    if (names.geometry)	{ _XkbFree(names.geometry); names.geometry= NULL; }
5892    return client->noClientException;
5893}
5894
5895/***====================================================================***/
5896
5897static int
5898ComputeDeviceLedInfoSize(	DeviceIntPtr		dev,
5899				unsigned int		what,
5900				XkbSrvLedInfoPtr	sli)
5901{
5902int			nNames,nMaps;
5903register unsigned 	n,bit;
5904
5905    if (sli==NULL)
5906	return 0;
5907    nNames= nMaps= 0;
5908    if ((what&XkbXI_IndicatorNamesMask)==0)
5909	sli->namesPresent= 0;
5910    if ((what&XkbXI_IndicatorMapsMask)==0)
5911	sli->mapsPresent= 0;
5912
5913    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
5914	if (sli->names && sli->names[n]!=None) {
5915	    sli->namesPresent|= bit;
5916	    nNames++;
5917	}
5918	if (sli->maps && XkbIM_InUse(&sli->maps[n])) {
5919	    sli->mapsPresent|= bit;
5920	    nMaps++;
5921	}
5922    }
5923    return (nNames*4)+(nMaps*SIZEOF(xkbIndicatorMapWireDesc));
5924}
5925
5926static int
5927CheckDeviceLedFBs(	DeviceIntPtr			dev,
5928			int				class,
5929			int				id,
5930			xkbGetDeviceInfoReply *		rep,
5931			ClientPtr			client)
5932{
5933int			nFBs= 0;
5934int			length= 0;
5935Bool			classOk;
5936
5937    if (class==XkbDfltXIClass) {
5938	if (dev->kbdfeed)	class= KbdFeedbackClass;
5939	else if (dev->leds)	class= LedFeedbackClass;
5940	else {
5941	    client->errorValue= _XkbErrCode2(XkbErr_BadClass,class);
5942	    return XkbKeyboardErrorCode;
5943	}
5944    }
5945    classOk= False;
5946    if ((dev->kbdfeed)&&((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) {
5947	KbdFeedbackPtr kf;
5948	classOk= True;
5949	for (kf= dev->kbdfeed;(kf);kf=kf->next) {
5950	    if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=kf->ctrl.id))
5951		continue;
5952	    nFBs++;
5953	    length+= SIZEOF(xkbDeviceLedsWireDesc);
5954	    if (!kf->xkb_sli)
5955		kf->xkb_sli= XkbAllocSrvLedInfo(dev,kf,NULL,0);
5956	    length+= ComputeDeviceLedInfoSize(dev,rep->present,kf->xkb_sli);
5957	    if (id!=XkbAllXIIds)
5958		break;
5959	}
5960    }
5961    if ((dev->leds)&&((class==LedFeedbackClass)||(class==XkbAllXIClasses))) {
5962	LedFeedbackPtr lf;
5963	classOk= True;
5964	for (lf= dev->leds;(lf);lf=lf->next) {
5965	    if ((id!=XkbAllXIIds)&&(id!=XkbDfltXIId)&&(id!=lf->ctrl.id))
5966		continue;
5967	    nFBs++;
5968	    length+= SIZEOF(xkbDeviceLedsWireDesc);
5969	    if (!lf->xkb_sli)
5970		lf->xkb_sli= XkbAllocSrvLedInfo(dev,NULL,lf,0);
5971	    length+= ComputeDeviceLedInfoSize(dev,rep->present,lf->xkb_sli);
5972	    if (id!=XkbAllXIIds)
5973		break;
5974	}
5975    }
5976    if (nFBs>0) {
5977	if (rep->supported&XkbXI_IndicatorsMask) {
5978	    rep->nDeviceLedFBs= nFBs;
5979	    rep->length+= (length/4);
5980	}
5981	return Success;
5982    }
5983    if (classOk) client->errorValue= _XkbErrCode2(XkbErr_BadId,id);
5984    else	 client->errorValue= _XkbErrCode2(XkbErr_BadClass,class);
5985    return XkbKeyboardErrorCode;
5986}
5987
5988static int
5989SendDeviceLedInfo(	XkbSrvLedInfoPtr	sli,
5990			ClientPtr		client)
5991{
5992xkbDeviceLedsWireDesc	wire;
5993int			length;
5994
5995    length= 0;
5996    wire.ledClass= 		sli->class;
5997    wire.ledID= 		sli->id;
5998    wire.namesPresent= 		sli->namesPresent;
5999    wire.mapsPresent=   	sli->mapsPresent;
6000    wire.physIndicators= 	sli->physIndicators;
6001    wire.state=			sli->effectiveState;
6002    if (client->swapped) {
6003	register int n;
6004	swaps(&wire.ledClass,n);
6005	swaps(&wire.ledID,n);
6006	swapl(&wire.namesPresent,n);
6007	swapl(&wire.mapsPresent,n);
6008	swapl(&wire.physIndicators,n);
6009	swapl(&wire.state,n);
6010    }
6011    WriteToClient(client,SIZEOF(xkbDeviceLedsWireDesc),(char *)&wire);
6012    length+= SIZEOF(xkbDeviceLedsWireDesc);
6013    if (sli->namesPresent|sli->mapsPresent) {
6014	register unsigned i,bit;
6015	if (sli->namesPresent) {
6016	    CARD32	awire;
6017	    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
6018		if (sli->namesPresent&bit) {
6019		    awire= (CARD32)sli->names[i];
6020		    if (client->swapped) {
6021			register int n;
6022			swapl(&awire,n);
6023		    }
6024		    WriteToClient(client,4,(char *)&awire);
6025		    length+= 4;
6026		}
6027	    }
6028	}
6029	if (sli->mapsPresent) {
6030	    for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
6031		xkbIndicatorMapWireDesc	iwire;
6032		if (sli->mapsPresent&bit) {
6033		    iwire.flags= 	sli->maps[i].flags;
6034		    iwire.whichGroups=	sli->maps[i].which_groups;
6035		    iwire.groups=	sli->maps[i].groups;
6036		    iwire.whichMods=	sli->maps[i].which_mods;
6037		    iwire.mods=		sli->maps[i].mods.mask;
6038		    iwire.realMods=	sli->maps[i].mods.real_mods;
6039		    iwire.virtualMods=	sli->maps[i].mods.vmods;
6040		    iwire.ctrls= 	sli->maps[i].ctrls;
6041		    if (client->swapped) {
6042			register int n;
6043			swaps(&iwire.virtualMods,n);
6044			swapl(&iwire.ctrls,n);
6045		    }
6046		    WriteToClient(client,SIZEOF(xkbIndicatorMapWireDesc),
6047								(char *)&iwire);
6048		    length+= SIZEOF(xkbIndicatorMapWireDesc);
6049		}
6050	    }
6051	}
6052    }
6053    return length;
6054}
6055
6056static int
6057SendDeviceLedFBs(	DeviceIntPtr	dev,
6058			int		class,
6059			int		id,
6060			unsigned	wantLength,
6061			ClientPtr	client)
6062{
6063int			length= 0;
6064
6065    if (class==XkbDfltXIClass) {
6066	if (dev->kbdfeed)	class= KbdFeedbackClass;
6067	else if (dev->leds)	class= LedFeedbackClass;
6068    }
6069    if ((dev->kbdfeed)&&
6070	((class==KbdFeedbackClass)||(class==XkbAllXIClasses))) {
6071	KbdFeedbackPtr kf;
6072	for (kf= dev->kbdfeed;(kf);kf=kf->next) {
6073	    if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==kf->ctrl.id)) {
6074		length+= SendDeviceLedInfo(kf->xkb_sli,client);
6075		if (id!=XkbAllXIIds)
6076		    break;
6077	    }
6078	}
6079    }
6080    if ((dev->leds)&&
6081	((class==LedFeedbackClass)||(class==XkbAllXIClasses))) {
6082	LedFeedbackPtr lf;
6083	for (lf= dev->leds;(lf);lf=lf->next) {
6084	    if ((id==XkbAllXIIds)||(id==XkbDfltXIId)||(id==lf->ctrl.id)) {
6085		length+= SendDeviceLedInfo(lf->xkb_sli,client);
6086		if (id!=XkbAllXIIds)
6087		    break;
6088	    }
6089	}
6090    }
6091    if (length==wantLength)
6092	 return Success;
6093    else return BadLength;
6094}
6095
6096int
6097ProcXkbGetDeviceInfo(ClientPtr client)
6098{
6099DeviceIntPtr		dev;
6100xkbGetDeviceInfoReply	rep;
6101int			status,nDeviceLedFBs;
6102unsigned		length,nameLen;
6103CARD16			ledClass,ledID;
6104unsigned		wanted,supported;
6105char *			str;
6106
6107    REQUEST(xkbGetDeviceInfoReq);
6108    REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq);
6109
6110    if (!(client->xkbClientFlags&_XkbClientInitialized))
6111	return BadAccess;
6112
6113    wanted= stuff->wanted;
6114
6115    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
6116    CHK_MASK_LEGAL(0x01,wanted,XkbXI_AllDeviceFeaturesMask);
6117
6118    if ((!dev->button)||((stuff->nBtns<1)&&(!stuff->allBtns)))
6119	wanted&= ~XkbXI_ButtonActionsMask;
6120    if ((!dev->kbdfeed)&&(!dev->leds))
6121	wanted&= ~XkbXI_IndicatorsMask;
6122
6123    nameLen= XkbSizeCountedString(dev->name);
6124    bzero((char *)&rep,SIZEOF(xkbGetDeviceInfoReply));
6125    rep.type = X_Reply;
6126    rep.deviceID= dev->id;
6127    rep.sequenceNumber = client->sequence;
6128    rep.length = nameLen/4;
6129    rep.present = wanted;
6130    rep.supported = XkbXI_AllDeviceFeaturesMask;
6131    rep.unsupported = 0;
6132    rep.firstBtnWanted = rep.nBtnsWanted = 0;
6133    rep.firstBtnRtrn = rep.nBtnsRtrn = 0;
6134    if (dev->button)
6135	 rep.totalBtns= dev->button->numButtons;
6136    else rep.totalBtns= 0;
6137    rep.devType=	dev->type;
6138    rep.hasOwnState=	(dev->key && dev->key->xkbInfo);
6139    rep.nDeviceLedFBs = 0;
6140    if (dev->kbdfeed)	rep.dfltKbdFB= dev->kbdfeed->ctrl.id;
6141    else		rep.dfltKbdFB= XkbXINone;
6142    if (dev->leds)	rep.dfltLedFB= dev->leds->ctrl.id;
6143    else		rep.dfltLedFB= XkbXINone;
6144
6145    ledClass= stuff->ledClass;
6146    ledID= stuff->ledID;
6147
6148    rep.firstBtnWanted= rep.nBtnsWanted= 0;
6149    rep.firstBtnRtrn= rep.nBtnsRtrn= 0;
6150    if (wanted&XkbXI_ButtonActionsMask) {
6151	if (stuff->allBtns) {
6152	    stuff->firstBtn= 0;
6153	    stuff->nBtns= dev->button->numButtons;
6154	}
6155
6156	if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) {
6157	    client->errorValue = _XkbErrCode4(0x02,dev->button->numButtons,
6158							stuff->firstBtn,
6159							stuff->nBtns);
6160	    return BadValue;
6161	}
6162	else {
6163	    rep.firstBtnWanted= stuff->firstBtn;
6164	    rep.nBtnsWanted= stuff->nBtns;
6165	    if (dev->button->xkb_acts!=NULL) {
6166		XkbAction *act;
6167		register int i;
6168
6169		rep.firstBtnRtrn= stuff->firstBtn;
6170		rep.nBtnsRtrn= stuff->nBtns;
6171		act= &dev->button->xkb_acts[rep.firstBtnWanted];
6172		for (i=0;i<rep.nBtnsRtrn;i++,act++) {
6173		    if (act->type!=XkbSA_NoAction)
6174			break;
6175		}
6176		rep.firstBtnRtrn+=	i;
6177		rep.nBtnsRtrn-=		i;
6178		act= &dev->button->xkb_acts[rep.firstBtnRtrn+rep.nBtnsRtrn-1];
6179		for (i=0;i<rep.nBtnsRtrn;i++,act--) {
6180		    if (act->type!=XkbSA_NoAction)
6181			break;
6182		}
6183		rep.nBtnsRtrn-=		i;
6184	    }
6185	    rep.length+= (rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc))/4;
6186	}
6187    }
6188
6189    if (wanted&XkbXI_IndicatorsMask) {
6190	status= CheckDeviceLedFBs(dev,ledClass,ledID,&rep,client);
6191	if (status!=Success)
6192	    return status;
6193    }
6194    length= rep.length*4;
6195    supported= rep.supported;
6196    nDeviceLedFBs = rep.nDeviceLedFBs;
6197    if (client->swapped) {
6198	register int n;
6199	swaps(&rep.sequenceNumber,n);
6200	swapl(&rep.length,n);
6201	swaps(&rep.present,n);
6202	swaps(&rep.supported,n);
6203	swaps(&rep.unsupported,n);
6204	swaps(&rep.nDeviceLedFBs,n);
6205	swapl(&rep.type,n);
6206    }
6207    WriteToClient(client,SIZEOF(xkbGetDeviceInfoReply), (char *)&rep);
6208
6209    str= (char*) xalloc(nameLen);
6210    if (!str)
6211	return BadAlloc;
6212    XkbWriteCountedString(str,dev->name,client->swapped);
6213    WriteToClient(client,nameLen,str);
6214    xfree(str);
6215    length-= nameLen;
6216
6217    if (rep.nBtnsRtrn>0) {
6218	int			sz;
6219	xkbActionWireDesc *	awire;
6220	sz= rep.nBtnsRtrn*SIZEOF(xkbActionWireDesc);
6221	awire= (xkbActionWireDesc *)&dev->button->xkb_acts[rep.firstBtnRtrn];
6222	WriteToClient(client,sz,(char *)awire);
6223	length-= sz;
6224    }
6225    if (nDeviceLedFBs>0) {
6226	status= SendDeviceLedFBs(dev,ledClass,ledID,length,client);
6227	if (status!=Success)
6228	    return status;
6229    }
6230    else if (length!=0)  {
6231	ErrorF("[xkb] Internal Error!  BadLength in ProcXkbGetDeviceInfo\n");
6232	ErrorF("[xkb]                  Wrote %d fewer bytes than expected\n",length);
6233	return BadLength;
6234    }
6235    if (stuff->wanted&(~supported)) {
6236	xkbExtensionDeviceNotify ed;
6237	bzero((char *)&ed,SIZEOF(xkbExtensionDeviceNotify));
6238	ed.ledClass=		ledClass;
6239	ed.ledID=		ledID;
6240	ed.ledsDefined= 	0;
6241	ed.ledState=		0;
6242	ed.firstBtn= ed.nBtns=	0;
6243	ed.reason=		XkbXI_UnsupportedFeatureMask;
6244	ed.supported=		supported;
6245	ed.unsupported=		stuff->wanted&(~supported);
6246	XkbSendExtensionDeviceNotify(dev,client,&ed);
6247    }
6248    return client->noClientException;
6249}
6250
6251static char *
6252CheckSetDeviceIndicators(	char *		wire,
6253				DeviceIntPtr	dev,
6254				int		num,
6255				int *		status_rtrn,
6256				ClientPtr	client)
6257{
6258xkbDeviceLedsWireDesc *	ledWire;
6259int			i;
6260XkbSrvLedInfoPtr 	sli;
6261
6262    ledWire= (xkbDeviceLedsWireDesc *)wire;
6263    for (i=0;i<num;i++) {
6264	if (client->swapped) {
6265	   register int n;
6266	   swaps(&ledWire->ledClass,n);
6267	   swaps(&ledWire->ledID,n);
6268	   swapl(&ledWire->namesPresent,n);
6269	   swapl(&ledWire->mapsPresent,n);
6270	   swapl(&ledWire->physIndicators,n);
6271	}
6272
6273        sli= XkbFindSrvLedInfo(dev,ledWire->ledClass,ledWire->ledID,
6274							XkbXI_IndicatorsMask);
6275	if (sli!=NULL) {
6276	    register int n;
6277	    register unsigned bit;
6278	    int nMaps,nNames;
6279	    CARD32 *atomWire;
6280	    xkbIndicatorMapWireDesc *mapWire;
6281
6282	    nMaps= nNames= 0;
6283	    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
6284		if (ledWire->namesPresent&bit)
6285		    nNames++;
6286		if (ledWire->mapsPresent&bit)
6287		    nMaps++;
6288	    }
6289	    atomWire= (CARD32 *)&ledWire[1];
6290	    if (nNames>0) {
6291		for (n=0;n<nNames;n++) {
6292		    if (client->swapped) {
6293			register int t;
6294			swapl(atomWire,t);
6295		    }
6296		    CHK_ATOM_OR_NONE3(((Atom)(*atomWire)),client->errorValue,
6297							*status_rtrn,NULL);
6298		    atomWire++;
6299		}
6300	    }
6301	    mapWire= (xkbIndicatorMapWireDesc *)atomWire;
6302	    if (nMaps>0) {
6303		for (n=0;n<nMaps;n++) {
6304		    if (client->swapped) {
6305			register int t;
6306			swaps(&mapWire->virtualMods,t);
6307			swapl(&mapWire->ctrls,t);
6308		    }
6309		    CHK_MASK_LEGAL3(0x21,mapWire->whichGroups,
6310						XkbIM_UseAnyGroup,
6311						client->errorValue,
6312						*status_rtrn,NULL);
6313		    CHK_MASK_LEGAL3(0x22,mapWire->whichMods,XkbIM_UseAnyMods,
6314						client->errorValue,
6315						*status_rtrn,NULL);
6316		    mapWire++;
6317		}
6318	    }
6319	    ledWire= (xkbDeviceLedsWireDesc *)mapWire;
6320	}
6321	else {
6322	    /* SHOULD NEVER HAPPEN */
6323	    return (char *)ledWire;
6324	}
6325    }
6326    return (char *)ledWire;
6327}
6328
6329static char *
6330SetDeviceIndicators(	char *			wire,
6331			DeviceIntPtr		dev,
6332			unsigned		changed,
6333			int			num,
6334			int *			status_rtrn,
6335			ClientPtr		client,
6336			xkbExtensionDeviceNotify *ev)
6337{
6338xkbDeviceLedsWireDesc *		ledWire;
6339int				i;
6340XkbEventCauseRec		cause;
6341unsigned			namec,mapc,statec;
6342xkbExtensionDeviceNotify	ed;
6343XkbChangesRec			changes;
6344DeviceIntPtr			kbd;
6345
6346    bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify));
6347    bzero((char *)&changes,sizeof(XkbChangesRec));
6348    XkbSetCauseXkbReq(&cause,X_kbSetDeviceInfo,client);
6349    ledWire= (xkbDeviceLedsWireDesc *)wire;
6350    for (i=0;i<num;i++) {
6351	register int			n;
6352	register unsigned 		bit;
6353	CARD32 *			atomWire;
6354	xkbIndicatorMapWireDesc *	mapWire;
6355	XkbSrvLedInfoPtr		sli;
6356
6357	namec= mapc= statec= 0;
6358    	sli= XkbFindSrvLedInfo(dev,ledWire->ledClass,ledWire->ledID,
6359						XkbXI_IndicatorMapsMask);
6360	if (!sli) {
6361	    /* SHOULD NEVER HAPPEN!! */
6362	    return (char *)ledWire;
6363	}
6364
6365	atomWire= (CARD32 *)&ledWire[1];
6366	if (changed&XkbXI_IndicatorNamesMask) {
6367	    namec= sli->namesPresent|ledWire->namesPresent;
6368	    bzero((char *)sli->names,XkbNumIndicators*sizeof(Atom));
6369	}
6370	if (ledWire->namesPresent) {
6371	    sli->namesPresent= ledWire->namesPresent;
6372	    bzero((char *)sli->names,XkbNumIndicators*sizeof(Atom));
6373	    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
6374		if (ledWire->namesPresent&bit) {
6375		     sli->names[n]= (Atom)*atomWire;
6376		     if (sli->names[n]==None)
6377			ledWire->namesPresent&= ~bit;
6378		     atomWire++;
6379		}
6380	    }
6381	}
6382	mapWire= (xkbIndicatorMapWireDesc *)atomWire;
6383	if (changed&XkbXI_IndicatorMapsMask) {
6384	    mapc= sli->mapsPresent|ledWire->mapsPresent;
6385	    sli->mapsPresent= ledWire->mapsPresent;
6386	    bzero((char*)sli->maps,XkbNumIndicators*sizeof(XkbIndicatorMapRec));
6387	}
6388	if (ledWire->mapsPresent) {
6389	    for (n=0,bit=1;n<XkbNumIndicators;n++,bit<<=1) {
6390		if (ledWire->mapsPresent&bit) {
6391		    sli->maps[n].flags=		mapWire->flags;
6392		    sli->maps[n].which_groups=	mapWire->whichGroups;
6393		    sli->maps[n].groups=	mapWire->groups;
6394		    sli->maps[n].which_mods=	mapWire->whichMods;
6395		    sli->maps[n].mods.mask=	mapWire->mods;
6396		    sli->maps[n].mods.real_mods=mapWire->realMods;
6397		    sli->maps[n].mods.vmods=	mapWire->virtualMods;
6398		    sli->maps[n].ctrls=		mapWire->ctrls;
6399		    mapWire++;
6400		}
6401	    }
6402	}
6403	if (changed&XkbXI_IndicatorStateMask) {
6404	    statec= sli->effectiveState^ledWire->state;
6405	    sli->explicitState&= ~statec;
6406	    sli->explicitState|= (ledWire->state&statec);
6407	}
6408	if (namec)
6409	    XkbApplyLedNameChanges(dev,sli,namec,&ed,&changes,&cause);
6410	if (mapc)
6411	    XkbApplyLedMapChanges(dev,sli,mapc,&ed,&changes,&cause);
6412	if (statec)
6413	    XkbApplyLedStateChanges(dev,sli,statec,&ed,&changes,&cause);
6414
6415	kbd= dev;
6416	if ((sli->flags&XkbSLI_HasOwnState)==0)
6417	    kbd = inputInfo.keyboard;
6418
6419	XkbFlushLedEvents(dev,kbd,sli,&ed,&changes,&cause);
6420	ledWire= (xkbDeviceLedsWireDesc *)mapWire;
6421    }
6422    return (char *)ledWire;
6423}
6424
6425
6426static int
6427_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev,
6428                  xkbSetDeviceInfoReq *stuff)
6429{
6430    char                       *wire;
6431
6432    wire= (char *)&stuff[1];
6433    if (stuff->change&XkbXI_ButtonActionsMask) {
6434	if (!dev->button) {
6435	    client->errorValue = _XkbErrCode2(XkbErr_BadClass,ButtonClass);
6436	    return XkbKeyboardErrorCode;
6437	}
6438	if ((stuff->firstBtn+stuff->nBtns)>dev->button->numButtons) {
6439	    client->errorValue= _XkbErrCode4(0x02,stuff->firstBtn,stuff->nBtns,
6440						dev->button->numButtons);
6441	    return BadMatch;
6442	}
6443	wire+= (stuff->nBtns*SIZEOF(xkbActionWireDesc));
6444    }
6445    if (stuff->change&XkbXI_IndicatorsMask) {
6446	int status= Success;
6447	wire= CheckSetDeviceIndicators(wire,dev,stuff->nDeviceLedFBs,
6448							&status,client);
6449	if (status!=Success)
6450	    return status;
6451    }
6452    if (((wire-((char *)stuff))/4)!=stuff->length)
6453	return BadLength;
6454
6455    return Success;
6456}
6457
6458static int
6459_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev,
6460                       xkbSetDeviceInfoReq *stuff)
6461{
6462    char                       *wire;
6463    xkbExtensionDeviceNotify    ed;
6464
6465    bzero((char *)&ed,SIZEOF(xkbExtensionDeviceNotify));
6466    ed.deviceID=	dev->id;
6467    wire= (char *)&stuff[1];
6468    if (stuff->change&XkbXI_ButtonActionsMask) {
6469	int			nBtns,sz,i;
6470	XkbAction *		acts;
6471	DeviceIntPtr		kbd;
6472
6473	nBtns= dev->button->numButtons;
6474	acts= dev->button->xkb_acts;
6475	if (acts==NULL) {
6476	    acts= _XkbTypedCalloc(nBtns,XkbAction);
6477	    if (!acts)
6478		return BadAlloc;
6479	    dev->button->xkb_acts= acts;
6480	}
6481	sz= stuff->nBtns*SIZEOF(xkbActionWireDesc);
6482	memcpy((char *)&acts[stuff->firstBtn],(char *)wire,sz);
6483	wire+= sz;
6484	ed.reason|=	XkbXI_ButtonActionsMask;
6485	ed.firstBtn=	stuff->firstBtn;
6486	ed.nBtns=	stuff->nBtns;
6487
6488	if (dev->key)	kbd= dev;
6489	else		kbd= inputInfo.keyboard;
6490	acts= &dev->button->xkb_acts[stuff->firstBtn];
6491	for (i=0;i<stuff->nBtns;i++,acts++) {
6492	    if (acts->type!=XkbSA_NoAction)
6493		XkbSetActionKeyMods(kbd->key->xkbInfo->desc,acts,0);
6494	}
6495    }
6496    if (stuff->change&XkbXI_IndicatorsMask) {
6497	int status= Success;
6498	wire= SetDeviceIndicators(wire,dev,stuff->change,
6499				  stuff->nDeviceLedFBs, &status,client,&ed);
6500	if (status!=Success)
6501	    return status;
6502    }
6503    if ((stuff->change)&&(ed.reason))
6504	XkbSendExtensionDeviceNotify(dev,client,&ed);
6505    return Success;
6506}
6507
6508int
6509ProcXkbSetDeviceInfo(ClientPtr client)
6510{
6511    DeviceIntPtr        dev;
6512    int                 rc;
6513
6514    REQUEST(xkbSetDeviceInfoReq);
6515    REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq);
6516
6517    if (!(client->xkbClientFlags&_XkbClientInitialized))
6518	return BadAccess;
6519
6520    CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
6521    CHK_MASK_LEGAL(0x01,stuff->change,XkbXI_AllFeaturesMask);
6522
6523    rc = _XkbSetDeviceInfoCheck(client, dev, stuff);
6524
6525    if (rc != Success)
6526        return rc;
6527
6528    if (stuff->deviceSpec == XkbUseCoreKbd || stuff->deviceSpec == XkbUseCorePtr)
6529    {
6530        DeviceIntPtr other;
6531        for (other = inputInfo.devices; other; other = other->next)
6532        {
6533            if (((other != dev) && !other->isMaster && (other->u.master == dev)) &&
6534                ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
6535                (stuff->deviceSpec == XkbUseCorePtr && other->button)))
6536            {
6537                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
6538                if (rc == Success)
6539                {
6540                    rc = _XkbSetDeviceInfoCheck(client, other, stuff);
6541                    if (rc != Success)
6542                        return rc;
6543                }
6544            }
6545        }
6546    }
6547
6548    /* checks done, apply */
6549    rc = _XkbSetDeviceInfo(client, dev, stuff);
6550    if (rc != Success)
6551        return rc;
6552
6553    if (stuff->deviceSpec == XkbUseCoreKbd || stuff->deviceSpec == XkbUseCorePtr)
6554    {
6555        DeviceIntPtr other;
6556        for (other = inputInfo.devices; other; other = other->next)
6557        {
6558            if (((other != dev) && !other->isMaster && (other->u.master == dev)) &&
6559                ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
6560                (stuff->deviceSpec == XkbUseCorePtr && other->button)))
6561            {
6562                rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixManageAccess);
6563                if (rc == Success)
6564                {
6565                    rc = _XkbSetDeviceInfo(client, other, stuff);
6566                    if (rc != Success)
6567                        return rc;
6568                }
6569            }
6570        }
6571    }
6572
6573    return client->noClientException;
6574}
6575
6576/***====================================================================***/
6577
6578int
6579ProcXkbSetDebuggingFlags(ClientPtr client)
6580{
6581CARD32 				newFlags,newCtrls,extraLength;
6582xkbSetDebuggingFlagsReply 	rep;
6583int rc;
6584
6585    REQUEST(xkbSetDebuggingFlagsReq);
6586    REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq);
6587
6588    rc = XaceHook(XACE_SERVER_ACCESS, client, DixDebugAccess);
6589    if (rc != Success)
6590	return rc;
6591
6592    newFlags=  xkbDebugFlags&(~stuff->affectFlags);
6593    newFlags|= (stuff->flags&stuff->affectFlags);
6594    newCtrls=  xkbDebugCtrls&(~stuff->affectCtrls);
6595    newCtrls|= (stuff->ctrls&stuff->affectCtrls);
6596    if (xkbDebugFlags || newFlags || stuff->msgLength) {
6597	ErrorF("[xkb] XkbDebug: Setting debug flags to 0x%lx\n",(long)newFlags);
6598	if (newCtrls!=xkbDebugCtrls)
6599	    ErrorF("[xkb] XkbDebug: Setting debug controls to 0x%lx\n",(long)newCtrls);
6600    }
6601    extraLength= (stuff->length<<2)-sz_xkbSetDebuggingFlagsReq;
6602    if (stuff->msgLength>0) {
6603	char *msg;
6604	if (extraLength<XkbPaddedSize(stuff->msgLength)) {
6605	    ErrorF("[xkb] XkbDebug: msgLength= %d, length= %ld (should be %d)\n",
6606			stuff->msgLength,(long)extraLength,
6607			XkbPaddedSize(stuff->msgLength));
6608	    return BadLength;
6609	}
6610	msg= (char *)&stuff[1];
6611	if (msg[stuff->msgLength-1]!='\0') {
6612	    ErrorF("[xkb] XkbDebug: message not null-terminated\n");
6613	    return BadValue;
6614	}
6615	ErrorF("[xkb] XkbDebug: %s\n",msg);
6616    }
6617    xkbDebugFlags = newFlags;
6618    xkbDebugCtrls = newCtrls;
6619
6620    XkbDisableLockActions= (xkbDebugCtrls&XkbDF_DisableLocks);
6621
6622    rep.type= X_Reply;
6623    rep.length = 0;
6624    rep.sequenceNumber = client->sequence;
6625    rep.currentFlags = newFlags;
6626    rep.currentCtrls = newCtrls;
6627    rep.supportedFlags = ~0;
6628    rep.supportedCtrls = ~0;
6629    if ( client->swapped ) {
6630	register int n;
6631	swaps(&rep.sequenceNumber, n);
6632	swapl(&rep.currentFlags, n);
6633	swapl(&rep.currentCtrls, n);
6634	swapl(&rep.supportedFlags, n);
6635	swapl(&rep.supportedCtrls, n);
6636    }
6637    WriteToClient(client,SIZEOF(xkbSetDebuggingFlagsReply), (char *)&rep);
6638    return client->noClientException;
6639}
6640
6641/***====================================================================***/
6642
6643static int
6644ProcXkbDispatch (ClientPtr client)
6645{
6646    REQUEST(xReq);
6647    switch (stuff->data)
6648    {
6649    case X_kbUseExtension:
6650	return ProcXkbUseExtension(client);
6651    case X_kbSelectEvents:
6652	return ProcXkbSelectEvents(client);
6653    case X_kbBell:
6654	return ProcXkbBell(client);
6655    case X_kbGetState:
6656	return ProcXkbGetState(client);
6657    case X_kbLatchLockState:
6658	return ProcXkbLatchLockState(client);
6659    case X_kbGetControls:
6660	return ProcXkbGetControls(client);
6661    case X_kbSetControls:
6662	return ProcXkbSetControls(client);
6663    case X_kbGetMap:
6664	return ProcXkbGetMap(client);
6665    case X_kbSetMap:
6666	return ProcXkbSetMap(client);
6667    case X_kbGetCompatMap:
6668	return ProcXkbGetCompatMap(client);
6669    case X_kbSetCompatMap:
6670	return ProcXkbSetCompatMap(client);
6671    case X_kbGetIndicatorState:
6672	return ProcXkbGetIndicatorState(client);
6673    case X_kbGetIndicatorMap:
6674	return ProcXkbGetIndicatorMap(client);
6675    case X_kbSetIndicatorMap:
6676	return ProcXkbSetIndicatorMap(client);
6677    case X_kbGetNamedIndicator:
6678	return ProcXkbGetNamedIndicator(client);
6679    case X_kbSetNamedIndicator:
6680	return ProcXkbSetNamedIndicator(client);
6681    case X_kbGetNames:
6682	return ProcXkbGetNames(client);
6683    case X_kbSetNames:
6684	return ProcXkbSetNames(client);
6685    case X_kbGetGeometry:
6686	return ProcXkbGetGeometry(client);
6687    case X_kbSetGeometry:
6688	return ProcXkbSetGeometry(client);
6689    case X_kbPerClientFlags:
6690	return ProcXkbPerClientFlags(client);
6691    case X_kbListComponents:
6692	return ProcXkbListComponents(client);
6693    case X_kbGetKbdByName:
6694	return ProcXkbGetKbdByName(client);
6695    case X_kbGetDeviceInfo:
6696	return ProcXkbGetDeviceInfo(client);
6697    case X_kbSetDeviceInfo:
6698	return ProcXkbSetDeviceInfo(client);
6699    case X_kbSetDebuggingFlags:
6700	return ProcXkbSetDebuggingFlags(client);
6701    default:
6702	return BadRequest;
6703    }
6704}
6705
6706static int
6707XkbClientGone(pointer data,XID id)
6708{
6709    DevicePtr	pXDev = (DevicePtr)data;
6710
6711    if (!XkbRemoveResourceClient(pXDev,id)) {
6712	ErrorF("[xkb] Internal Error! bad RemoveResourceClient in XkbClientGone\n");
6713    }
6714    return 1;
6715}
6716
6717void
6718XkbExtensionInit(void)
6719{
6720    ExtensionEntry *extEntry;
6721
6722    if ((extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors,
6723				 ProcXkbDispatch, SProcXkbDispatch,
6724				 NULL, StandardMinorOpcode))) {
6725	XkbReqCode = (unsigned char)extEntry->base;
6726	XkbEventBase = (unsigned char)extEntry->eventBase;
6727	XkbErrorBase = (unsigned char)extEntry->errorBase;
6728	XkbKeyboardErrorCode = XkbErrorBase+XkbKeyboard;
6729	RT_XKBCLIENT = CreateNewResourceType(XkbClientGone);
6730    }
6731    return;
6732}
6733
6734
6735