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