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