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