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,Bool doswap)1599 CheckKeyTypes(ClientPtr client,
1600 XkbDescPtr xkb,
1601 xkbSetMapReq * req,
1602 xkbKeyTypeWireDesc ** wireRtrn,
1603 int *nMapsRtrn, CARD8 *mapWidthRtrn, Bool doswap)
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 && doswap) {
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 && doswap) {
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 && doswap) {
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,Bool doswap)1721 CheckKeySyms(ClientPtr client,
1722 XkbDescPtr xkb,
1723 xkbSetMapReq * req,
1724 int nTypes,
1725 CARD8 *mapWidths,
1726 CARD16 *symsPerKey, xkbSymMapWireDesc ** wireRtrn, int *errorRtrn, Bool doswap)
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 && doswap) {
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 /**
2386 * Check if the given request can be applied to the given device but don't
2387 * actually do anything, except swap values when client->swapped and doswap are both true.
2388 */
2389 static int
_XkbSetMapChecks(ClientPtr client,DeviceIntPtr dev,xkbSetMapReq * req,char * values,Bool doswap)2390 _XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq * req,
2391 char *values, Bool doswap)
2392 {
2393 XkbSrvInfoPtr xkbi;
2394 XkbDescPtr xkb;
2395 int error;
2396 int nTypes = 0, nActions;
2397 CARD8 mapWidths[XkbMaxLegalKeyCode + 1] = { 0 };
2398 CARD16 symsPerKey[XkbMaxLegalKeyCode + 1] = { 0 };
2399 XkbSymMapPtr map;
2400 int i;
2401
2402 if (!dev->key)
2403 return 0;
2404
2405 xkbi = dev->key->xkbInfo;
2406 xkb = xkbi->desc;
2407
2408 if ((xkb->min_key_code != req->minKeyCode) ||
2409 (xkb->max_key_code != req->maxKeyCode)) {
2410 if (client->xkbClientFlags & _XkbClientIsAncient) {
2411 /* pre 1.0 versions of Xlib have a bug */
2412 req->minKeyCode = xkb->min_key_code;
2413 req->maxKeyCode = xkb->max_key_code;
2414 }
2415 else {
2416 if (!XkbIsLegalKeycode(req->minKeyCode)) {
2417 client->errorValue =
2418 _XkbErrCode3(2, req->minKeyCode, req->maxKeyCode);
2419 return BadValue;
2420 }
2421 if (req->minKeyCode > req->maxKeyCode) {
2422 client->errorValue =
2423 _XkbErrCode3(3, req->minKeyCode, req->maxKeyCode);
2424 return BadMatch;
2425 }
2426 }
2427 }
2428
2429 if ((req->present & XkbKeyTypesMask) &&
2430 (!CheckKeyTypes(client, xkb, req, (xkbKeyTypeWireDesc **) &values,
2431 &nTypes, mapWidths, doswap))) {
2432 client->errorValue = nTypes;
2433 return BadValue;
2434 }
2435 else {
2436 nTypes = xkb->map->num_types;
2437 }
2438
2439 /* symsPerKey/mapWidths must be filled regardless of client-side flags */
2440 map = &xkb->map->key_sym_map[xkb->min_key_code];
2441 for (i = xkb->min_key_code; i < xkb->max_key_code; i++, map++) {
2442 register int g, ng, w;
2443
2444 ng = XkbNumGroups(map->group_info);
2445 for (w = g = 0; g < ng; g++) {
2446 if (map->kt_index[g] >= (unsigned) nTypes) {
2447 client->errorValue = _XkbErrCode4(0x13, i, g, map->kt_index[g]);
2448 return BadValue;
2449 }
2450 if (mapWidths[map->kt_index[g]] > w)
2451 w = mapWidths[map->kt_index[g]];
2452 }
2453 symsPerKey[i] = w * ng;
2454 }
2455
2456 if ((req->present & XkbKeySymsMask) &&
2457 (!CheckKeySyms(client, xkb, req, nTypes, mapWidths, symsPerKey,
2458 (xkbSymMapWireDesc **) &values, &error, doswap))) {
2459 client->errorValue = error;
2460 return BadValue;
2461 }
2462
2463 if ((req->present & XkbKeyActionsMask) &&
2464 (!CheckKeyActions(xkb, req, nTypes, mapWidths, symsPerKey,
2465 (CARD8 **) &values, &nActions))) {
2466 client->errorValue = nActions;
2467 return BadValue;
2468 }
2469
2470 if ((req->present & XkbKeyBehaviorsMask) &&
2471 (!CheckKeyBehaviors
2472 (xkb, req, (xkbBehaviorWireDesc **) &values, &error))) {
2473 client->errorValue = error;
2474 return BadValue;
2475 }
2476
2477 if ((req->present & XkbVirtualModsMask) &&
2478 (!CheckVirtualMods(xkb, req, (CARD8 **) &values, &error))) {
2479 client->errorValue = error;
2480 return BadValue;
2481 }
2482 if ((req->present & XkbExplicitComponentsMask) &&
2483 (!CheckKeyExplicit(xkb, req, (CARD8 **) &values, &error))) {
2484 client->errorValue = error;
2485 return BadValue;
2486 }
2487 if ((req->present & XkbModifierMapMask) &&
2488 (!CheckModifierMap(xkb, req, (CARD8 **) &values, &error))) {
2489 client->errorValue = error;
2490 return BadValue;
2491 }
2492 if ((req->present & XkbVirtualModMapMask) &&
2493 (!CheckVirtualModMap
2494 (xkb, req, (xkbVModMapWireDesc **) &values, &error))) {
2495 client->errorValue = error;
2496 return BadValue;
2497 }
2498
2499 if (((values - ((char *) req)) / 4) != req->length) {
2500 ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after check)\n");
2501 client->errorValue = values - ((char *) &req[1]);
2502 return BadLength;
2503 }
2504
2505 return Success;
2506 }
2507
2508 /**
2509 * Apply the given request on the given device.
2510 */
2511 static int
_XkbSetMap(ClientPtr client,DeviceIntPtr dev,xkbSetMapReq * req,char * values)2512 _XkbSetMap(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq * req, char *values)
2513 {
2514 XkbEventCauseRec cause;
2515 XkbChangesRec change;
2516 Bool sentNKN;
2517 XkbSrvInfoPtr xkbi;
2518 XkbDescPtr xkb;
2519
2520 if (!dev->key)
2521 return Success;
2522
2523 xkbi = dev->key->xkbInfo;
2524 xkb = xkbi->desc;
2525
2526 XkbSetCauseXkbReq(&cause, X_kbSetMap, client);
2527 memset(&change, 0, sizeof(change));
2528 sentNKN = FALSE;
2529 if ((xkb->min_key_code != req->minKeyCode) ||
2530 (xkb->max_key_code != req->maxKeyCode)) {
2531 Status status;
2532 xkbNewKeyboardNotify nkn;
2533
2534 nkn.deviceID = nkn.oldDeviceID = dev->id;
2535 nkn.oldMinKeyCode = xkb->min_key_code;
2536 nkn.oldMaxKeyCode = xkb->max_key_code;
2537 status = XkbChangeKeycodeRange(xkb, req->minKeyCode,
2538 req->maxKeyCode, &change);
2539 if (status != Success)
2540 return status; /* oh-oh. what about the other keyboards? */
2541 nkn.minKeyCode = xkb->min_key_code;
2542 nkn.maxKeyCode = xkb->max_key_code;
2543 nkn.requestMajor = XkbReqCode;
2544 nkn.requestMinor = X_kbSetMap;
2545 nkn.changed = XkbNKN_KeycodesMask;
2546 XkbSendNewKeyboardNotify(dev, &nkn);
2547 sentNKN = TRUE;
2548 }
2549
2550 if (req->present & XkbKeyTypesMask) {
2551 values = SetKeyTypes(xkb, req, (xkbKeyTypeWireDesc *) values, &change);
2552 if (!values)
2553 goto allocFailure;
2554 }
2555 if (req->present & XkbKeySymsMask) {
2556 values =
2557 SetKeySyms(client, xkb, req, (xkbSymMapWireDesc *) values, &change,
2558 dev);
2559 if (!values)
2560 goto allocFailure;
2561 }
2562 if (req->present & XkbKeyActionsMask) {
2563 values = SetKeyActions(xkb, req, (CARD8 *) values, &change);
2564 if (!values)
2565 goto allocFailure;
2566 }
2567 if (req->present & XkbKeyBehaviorsMask) {
2568 values =
2569 SetKeyBehaviors(xkbi, req, (xkbBehaviorWireDesc *) values, &change);
2570 if (!values)
2571 goto allocFailure;
2572 }
2573 if (req->present & XkbVirtualModsMask)
2574 values = SetVirtualMods(xkbi, req, (CARD8 *) values, &change);
2575 if (req->present & XkbExplicitComponentsMask)
2576 values = SetKeyExplicit(xkbi, req, (CARD8 *) values, &change);
2577 if (req->present & XkbModifierMapMask)
2578 values = SetModifierMap(xkbi, req, (CARD8 *) values, &change);
2579 if (req->present & XkbVirtualModMapMask)
2580 values =
2581 SetVirtualModMap(xkbi, req, (xkbVModMapWireDesc *) values, &change);
2582 if (((values - ((char *) req)) / 4) != req->length) {
2583 ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after set)\n");
2584 client->errorValue = values - ((char *) &req[1]);
2585 return BadLength;
2586 }
2587 if (req->flags & XkbSetMapRecomputeActions) {
2588 KeyCode first, last, firstMM, lastMM;
2589
2590 if (change.map.num_key_syms > 0) {
2591 first = change.map.first_key_sym;
2592 last = first + change.map.num_key_syms - 1;
2593 }
2594 else
2595 first = last = 0;
2596 if (change.map.num_modmap_keys > 0) {
2597 firstMM = change.map.first_modmap_key;
2598 lastMM = firstMM + change.map.num_modmap_keys - 1;
2599 }
2600 else
2601 firstMM = lastMM = 0;
2602 if ((last > 0) && (lastMM > 0)) {
2603 if (firstMM < first)
2604 first = firstMM;
2605 if (lastMM > last)
2606 last = lastMM;
2607 }
2608 else if (lastMM > 0) {
2609 first = firstMM;
2610 last = lastMM;
2611 }
2612 if (last > 0) {
2613 unsigned check = 0;
2614
2615 XkbUpdateActions(dev, first, (last - first + 1), &change, &check,
2616 &cause);
2617 if (check)
2618 XkbCheckSecondaryEffects(xkbi, check, &change, &cause);
2619 }
2620 }
2621 if (!sentNKN)
2622 XkbSendNotification(dev, &change, &cause);
2623
2624 return Success;
2625 allocFailure:
2626 return BadAlloc;
2627 }
2628
2629 int
ProcXkbSetMap(ClientPtr client)2630 ProcXkbSetMap(ClientPtr client)
2631 {
2632 DeviceIntPtr dev;
2633 char *tmp;
2634 int rc;
2635
2636 REQUEST(xkbSetMapReq);
2637 REQUEST_AT_LEAST_SIZE(xkbSetMapReq);
2638
2639 if (!(client->xkbClientFlags & _XkbClientInitialized))
2640 return BadAccess;
2641
2642 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
2643 CHK_MASK_LEGAL(0x01, stuff->present, XkbAllMapComponentsMask);
2644
2645 tmp = (char *) &stuff[1];
2646
2647 /* Check if we can to the SetMap on the requested device. If this
2648 succeeds, do the same thing for all extension devices (if needed).
2649 If any of them fails, fail. */
2650 rc = _XkbSetMapChecks(client, dev, stuff, tmp, TRUE);
2651
2652 if (rc != Success)
2653 return rc;
2654
2655 DeviceIntPtr master = GetMaster(dev, MASTER_KEYBOARD);
2656
2657 if (stuff->deviceSpec == XkbUseCoreKbd) {
2658 DeviceIntPtr other;
2659
2660 for (other = inputInfo.devices; other; other = other->next) {
2661 if ((other != dev) && other->key && !IsMaster(other) &&
2662 GetMaster(other, MASTER_KEYBOARD) == dev) {
2663 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
2664 DixManageAccess);
2665 if (rc == Success) {
2666 rc = _XkbSetMapChecks(client, other, stuff, tmp, FALSE);
2667 if (rc != Success)
2668 return rc;
2669 }
2670 }
2671 }
2672 } else {
2673 DeviceIntPtr other;
2674
2675 for (other = inputInfo.devices; other; other = other->next) {
2676 if (other != dev && GetMaster(other, MASTER_KEYBOARD) != dev &&
2677 (other != master || dev != master->lastSlave))
2678 continue;
2679
2680 rc = _XkbSetMapChecks(client, other, stuff, tmp, FALSE);
2681 if (rc != Success)
2682 return rc;
2683 }
2684 }
2685
2686 /* We know now that we will succeed with the SetMap. In theory anyway. */
2687 rc = _XkbSetMap(client, dev, stuff, tmp);
2688 if (rc != Success)
2689 return rc;
2690
2691 if (stuff->deviceSpec == XkbUseCoreKbd) {
2692 DeviceIntPtr other;
2693
2694 for (other = inputInfo.devices; other; other = other->next) {
2695 if ((other != dev) && other->key && !IsMaster(other) &&
2696 GetMaster(other, MASTER_KEYBOARD) == dev) {
2697 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
2698 DixManageAccess);
2699 if (rc == Success)
2700 _XkbSetMap(client, other, stuff, tmp);
2701 /* ignore rc. if the SetMap failed although the check above
2702 reported true there isn't much we can do. we still need to
2703 set all other devices, hoping that at least they stay in
2704 sync. */
2705 }
2706 }
2707 } else {
2708 DeviceIntPtr other;
2709
2710 for (other = inputInfo.devices; other; other = other->next) {
2711 if (other != dev && GetMaster(other, MASTER_KEYBOARD) != dev &&
2712 (other != master || dev != master->lastSlave))
2713 continue;
2714
2715 _XkbSetMap(client, other, stuff, tmp); //ignore rc
2716 }
2717 }
2718
2719 return Success;
2720 }
2721
2722 /***====================================================================***/
2723
2724 static Status
XkbComputeGetCompatMapReplySize(XkbCompatMapPtr compat,xkbGetCompatMapReply * rep)2725 XkbComputeGetCompatMapReplySize(XkbCompatMapPtr compat,
2726 xkbGetCompatMapReply * rep)
2727 {
2728 unsigned size, nGroups;
2729
2730 nGroups = 0;
2731 if (rep->groups != 0) {
2732 register int i, bit;
2733
2734 for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2735 if (rep->groups & bit)
2736 nGroups++;
2737 }
2738 }
2739 size = nGroups * SIZEOF(xkbModsWireDesc);
2740 size += (rep->nSI * SIZEOF(xkbSymInterpretWireDesc));
2741 rep->length = size / 4;
2742 return Success;
2743 }
2744
2745 static int
XkbSendCompatMap(ClientPtr client,XkbCompatMapPtr compat,xkbGetCompatMapReply * rep)2746 XkbSendCompatMap(ClientPtr client,
2747 XkbCompatMapPtr compat, xkbGetCompatMapReply * rep)
2748 {
2749 char *data;
2750 int size;
2751
2752 if (rep->length > 0) {
2753 data = xallocarray(rep->length, 4);
2754 if (data) {
2755 register unsigned i, bit;
2756 xkbModsWireDesc *grp;
2757 XkbSymInterpretPtr sym = &compat->sym_interpret[rep->firstSI];
2758 xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *) data;
2759
2760 size = rep->length * 4;
2761
2762 for (i = 0; i < rep->nSI; i++, sym++, wire++) {
2763 wire->sym = sym->sym;
2764 wire->mods = sym->mods;
2765 wire->match = sym->match;
2766 wire->virtualMod = sym->virtual_mod;
2767 wire->flags = sym->flags;
2768 memcpy((char *) &wire->act, (char *) &sym->act,
2769 sz_xkbActionWireDesc);
2770 if (client->swapped) {
2771 swapl(&wire->sym);
2772 }
2773 }
2774 if (rep->groups) {
2775 grp = (xkbModsWireDesc *) wire;
2776 for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2777 if (rep->groups & bit) {
2778 grp->mask = compat->groups[i].mask;
2779 grp->realMods = compat->groups[i].real_mods;
2780 grp->virtualMods = compat->groups[i].vmods;
2781 if (client->swapped) {
2782 swaps(&grp->virtualMods);
2783 }
2784 grp++;
2785 }
2786 }
2787 wire = (xkbSymInterpretWireDesc *) grp;
2788 }
2789 }
2790 else
2791 return BadAlloc;
2792 }
2793 else
2794 data = NULL;
2795
2796 if (client->swapped) {
2797 swaps(&rep->sequenceNumber);
2798 swapl(&rep->length);
2799 swaps(&rep->firstSI);
2800 swaps(&rep->nSI);
2801 swaps(&rep->nTotalSI);
2802 }
2803
2804 WriteToClient(client, SIZEOF(xkbGetCompatMapReply), rep);
2805 if (data) {
2806 WriteToClient(client, size, data);
2807 free((char *) data);
2808 }
2809 return Success;
2810 }
2811
2812 int
ProcXkbGetCompatMap(ClientPtr client)2813 ProcXkbGetCompatMap(ClientPtr client)
2814 {
2815 xkbGetCompatMapReply rep;
2816 DeviceIntPtr dev;
2817 XkbDescPtr xkb;
2818 XkbCompatMapPtr compat;
2819
2820 REQUEST(xkbGetCompatMapReq);
2821 REQUEST_SIZE_MATCH(xkbGetCompatMapReq);
2822
2823 if (!(client->xkbClientFlags & _XkbClientInitialized))
2824 return BadAccess;
2825
2826 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
2827
2828 xkb = dev->key->xkbInfo->desc;
2829 compat = xkb->compat;
2830
2831 rep = (xkbGetCompatMapReply) {
2832 .type = X_Reply,
2833 .sequenceNumber = client->sequence,
2834 .length = 0,
2835 .deviceID = dev->id,
2836 .firstSI = stuff->firstSI,
2837 .nSI = stuff->nSI
2838 };
2839 if (stuff->getAllSI) {
2840 rep.firstSI = 0;
2841 rep.nSI = compat->num_si;
2842 }
2843 else if ((((unsigned) stuff->nSI) > 0) &&
2844 ((unsigned) (stuff->firstSI + stuff->nSI - 1) >= compat->num_si)) {
2845 client->errorValue = _XkbErrCode2(0x05, compat->num_si);
2846 return BadValue;
2847 }
2848 rep.nTotalSI = compat->num_si;
2849 rep.groups = stuff->groups;
2850 XkbComputeGetCompatMapReplySize(compat, &rep);
2851 return XkbSendCompatMap(client, compat, &rep);
2852 }
2853
2854 /**
2855 * Apply the given request on the given device.
2856 * If dryRun is TRUE, then value checks are performed, but the device isn't
2857 * modified.
2858 */
2859 static int
_XkbSetCompatMap(ClientPtr client,DeviceIntPtr dev,xkbSetCompatMapReq * req,char * data,BOOL dryRun)2860 _XkbSetCompatMap(ClientPtr client, DeviceIntPtr dev,
2861 xkbSetCompatMapReq * req, char *data, BOOL dryRun)
2862 {
2863 XkbSrvInfoPtr xkbi;
2864 XkbDescPtr xkb;
2865 XkbCompatMapPtr compat;
2866 int nGroups;
2867 unsigned i, bit;
2868
2869 xkbi = dev->key->xkbInfo;
2870 xkb = xkbi->desc;
2871 compat = xkb->compat;
2872
2873 if ((req->nSI > 0) || (req->truncateSI)) {
2874 xkbSymInterpretWireDesc *wire;
2875
2876 if (req->firstSI > compat->num_si) {
2877 client->errorValue = _XkbErrCode2(0x02, compat->num_si);
2878 return BadValue;
2879 }
2880 wire = (xkbSymInterpretWireDesc *) data;
2881 wire += req->nSI;
2882 data = (char *) wire;
2883 }
2884
2885 nGroups = 0;
2886 if (req->groups != 0) {
2887 for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2888 if (req->groups & bit)
2889 nGroups++;
2890 }
2891 }
2892 data += nGroups * SIZEOF(xkbModsWireDesc);
2893 if (((data - ((char *) req)) / 4) != req->length) {
2894 return BadLength;
2895 }
2896
2897 /* Done all the checks we can do */
2898 if (dryRun)
2899 return Success;
2900
2901 data = (char *) &req[1];
2902 if (req->nSI > 0) {
2903 xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *) data;
2904 XkbSymInterpretPtr sym;
2905 unsigned int skipped = 0;
2906
2907 if ((unsigned) (req->firstSI + req->nSI) > compat->num_si) {
2908 compat->num_si = req->firstSI + req->nSI;
2909 compat->sym_interpret = reallocarray(compat->sym_interpret,
2910 compat->num_si,
2911 sizeof(XkbSymInterpretRec));
2912 if (!compat->sym_interpret) {
2913 compat->num_si = 0;
2914 return BadAlloc;
2915 }
2916 }
2917 else if (req->truncateSI) {
2918 compat->num_si = req->firstSI + req->nSI;
2919 }
2920 sym = &compat->sym_interpret[req->firstSI];
2921 for (i = 0; i < req->nSI; i++, wire++) {
2922 if (client->swapped) {
2923 swapl(&wire->sym);
2924 }
2925 if (wire->sym == NoSymbol && wire->match == XkbSI_AnyOfOrNone &&
2926 (wire->mods & 0xff) == 0xff &&
2927 wire->act.type == XkbSA_XFree86Private) {
2928 ErrorF("XKB: Skipping broken Any+AnyOfOrNone(All) -> Private "
2929 "action from client\n");
2930 skipped++;
2931 continue;
2932 }
2933 sym->sym = wire->sym;
2934 sym->mods = wire->mods;
2935 sym->match = wire->match;
2936 sym->flags = wire->flags;
2937 sym->virtual_mod = wire->virtualMod;
2938 memcpy((char *) &sym->act, (char *) &wire->act,
2939 SIZEOF(xkbActionWireDesc));
2940 sym++;
2941 }
2942 if (skipped) {
2943 if (req->firstSI + req->nSI < compat->num_si)
2944 memmove(sym, sym + skipped,
2945 (compat->num_si - req->firstSI - req->nSI) *
2946 sizeof(*sym));
2947 compat->num_si -= skipped;
2948 }
2949 data = (char *) wire;
2950 }
2951 else if (req->truncateSI) {
2952 compat->num_si = req->firstSI;
2953 }
2954
2955 if (req->groups != 0) {
2956 xkbModsWireDesc *wire = (xkbModsWireDesc *) data;
2957
2958 for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2959 if (req->groups & bit) {
2960 if (client->swapped) {
2961 swaps(&wire->virtualMods);
2962 }
2963 compat->groups[i].mask = wire->realMods;
2964 compat->groups[i].real_mods = wire->realMods;
2965 compat->groups[i].vmods = wire->virtualMods;
2966 if (wire->virtualMods != 0) {
2967 unsigned tmp;
2968
2969 tmp = XkbMaskForVMask(xkb, wire->virtualMods);
2970 compat->groups[i].mask |= tmp;
2971 }
2972 data += SIZEOF(xkbModsWireDesc);
2973 wire = (xkbModsWireDesc *) data;
2974 }
2975 }
2976 }
2977 i = XkbPaddedSize((data - ((char *) req)));
2978 if ((i / 4) != req->length) {
2979 ErrorF("[xkb] Internal length error on read in _XkbSetCompatMap\n");
2980 return BadLength;
2981 }
2982
2983 if (dev->xkb_interest) {
2984 xkbCompatMapNotify ev;
2985
2986 ev.deviceID = dev->id;
2987 ev.changedGroups = req->groups;
2988 ev.firstSI = req->firstSI;
2989 ev.nSI = req->nSI;
2990 ev.nTotalSI = compat->num_si;
2991 XkbSendCompatMapNotify(dev, &ev);
2992 }
2993
2994 if (req->recomputeActions) {
2995 XkbChangesRec change;
2996 unsigned check;
2997 XkbEventCauseRec cause;
2998
2999 XkbSetCauseXkbReq(&cause, X_kbSetCompatMap, client);
3000 memset(&change, 0, sizeof(XkbChangesRec));
3001 XkbUpdateActions(dev, xkb->min_key_code, XkbNumKeys(xkb), &change,
3002 &check, &cause);
3003 if (check)
3004 XkbCheckSecondaryEffects(xkbi, check, &change, &cause);
3005 XkbSendNotification(dev, &change, &cause);
3006 }
3007 return Success;
3008 }
3009
3010 int
ProcXkbSetCompatMap(ClientPtr client)3011 ProcXkbSetCompatMap(ClientPtr client)
3012 {
3013 DeviceIntPtr dev;
3014 char *data;
3015 int rc;
3016
3017 REQUEST(xkbSetCompatMapReq);
3018 REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq);
3019
3020 if (!(client->xkbClientFlags & _XkbClientInitialized))
3021 return BadAccess;
3022
3023 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
3024
3025 data = (char *) &stuff[1];
3026
3027 /* check first using a dry-run */
3028 rc = _XkbSetCompatMap(client, dev, stuff, data, TRUE);
3029 if (rc != Success)
3030 return rc;
3031 if (stuff->deviceSpec == XkbUseCoreKbd) {
3032 DeviceIntPtr other;
3033
3034 for (other = inputInfo.devices; other; other = other->next) {
3035 if ((other != dev) && other->key && !IsMaster(other) &&
3036 GetMaster(other, MASTER_KEYBOARD) == dev) {
3037 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
3038 DixManageAccess);
3039 if (rc == Success) {
3040 /* dry-run */
3041 rc = _XkbSetCompatMap(client, other, stuff, data, TRUE);
3042 if (rc != Success)
3043 return rc;
3044 }
3045 }
3046 }
3047 }
3048
3049 /* Yay, the dry-runs succeed. Let's apply */
3050 rc = _XkbSetCompatMap(client, dev, stuff, data, FALSE);
3051 if (rc != Success)
3052 return rc;
3053 if (stuff->deviceSpec == XkbUseCoreKbd) {
3054 DeviceIntPtr other;
3055
3056 for (other = inputInfo.devices; other; other = other->next) {
3057 if ((other != dev) && other->key && !IsMaster(other) &&
3058 GetMaster(other, MASTER_KEYBOARD) == dev) {
3059 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
3060 DixManageAccess);
3061 if (rc == Success) {
3062 rc = _XkbSetCompatMap(client, other, stuff, data, FALSE);
3063 if (rc != Success)
3064 return rc;
3065 }
3066 }
3067 }
3068 }
3069
3070 return Success;
3071 }
3072
3073 /***====================================================================***/
3074
3075 int
ProcXkbGetIndicatorState(ClientPtr client)3076 ProcXkbGetIndicatorState(ClientPtr client)
3077 {
3078 xkbGetIndicatorStateReply rep;
3079 XkbSrvLedInfoPtr sli;
3080 DeviceIntPtr dev;
3081
3082 REQUEST(xkbGetIndicatorStateReq);
3083 REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq);
3084
3085 if (!(client->xkbClientFlags & _XkbClientInitialized))
3086 return BadAccess;
3087
3088 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
3089
3090 sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
3091 XkbXI_IndicatorStateMask);
3092 if (!sli)
3093 return BadAlloc;
3094
3095 rep = (xkbGetIndicatorStateReply) {
3096 .type = X_Reply,
3097 .deviceID = dev->id,
3098 .sequenceNumber = client->sequence,
3099 .length = 0,
3100 .state = sli->effectiveState
3101 };
3102
3103 if (client->swapped) {
3104 swaps(&rep.sequenceNumber);
3105 swapl(&rep.state);
3106 }
3107 WriteToClient(client, SIZEOF(xkbGetIndicatorStateReply), &rep);
3108 return Success;
3109 }
3110
3111 /***====================================================================***/
3112
3113 static Status
XkbComputeGetIndicatorMapReplySize(XkbIndicatorPtr indicators,xkbGetIndicatorMapReply * rep)3114 XkbComputeGetIndicatorMapReplySize(XkbIndicatorPtr indicators,
3115 xkbGetIndicatorMapReply * rep)
3116 {
3117 register int i, bit;
3118 int nIndicators;
3119
3120 rep->realIndicators = indicators->phys_indicators;
3121 for (i = nIndicators = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3122 if (rep->which & bit)
3123 nIndicators++;
3124 }
3125 rep->length = (nIndicators * SIZEOF(xkbIndicatorMapWireDesc)) / 4;
3126 rep->nIndicators = nIndicators;
3127 return Success;
3128 }
3129
3130 static int
XkbSendIndicatorMap(ClientPtr client,XkbIndicatorPtr indicators,xkbGetIndicatorMapReply * rep)3131 XkbSendIndicatorMap(ClientPtr client,
3132 XkbIndicatorPtr indicators, xkbGetIndicatorMapReply * rep)
3133 {
3134 int length;
3135 CARD8 *map;
3136 register int i;
3137 register unsigned bit;
3138
3139 if (rep->length > 0) {
3140 CARD8 *to;
3141
3142 to = map = xallocarray(rep->length, 4);
3143 if (map) {
3144 xkbIndicatorMapWireDesc *wire = (xkbIndicatorMapWireDesc *) to;
3145
3146 length = rep->length * 4;
3147
3148 for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3149 if (rep->which & bit) {
3150 wire->flags = indicators->maps[i].flags;
3151 wire->whichGroups = indicators->maps[i].which_groups;
3152 wire->groups = indicators->maps[i].groups;
3153 wire->whichMods = indicators->maps[i].which_mods;
3154 wire->mods = indicators->maps[i].mods.mask;
3155 wire->realMods = indicators->maps[i].mods.real_mods;
3156 wire->virtualMods = indicators->maps[i].mods.vmods;
3157 wire->ctrls = indicators->maps[i].ctrls;
3158 if (client->swapped) {
3159 swaps(&wire->virtualMods);
3160 swapl(&wire->ctrls);
3161 }
3162 wire++;
3163 }
3164 }
3165 to = (CARD8 *) wire;
3166 if ((to - map) != length) {
3167 client->errorValue = _XkbErrCode2(0xff, length);
3168 free(map);
3169 return BadLength;
3170 }
3171 }
3172 else
3173 return BadAlloc;
3174 }
3175 else
3176 map = NULL;
3177 if (client->swapped) {
3178 swaps(&rep->sequenceNumber);
3179 swapl(&rep->length);
3180 swapl(&rep->which);
3181 swapl(&rep->realIndicators);
3182 }
3183 WriteToClient(client, SIZEOF(xkbGetIndicatorMapReply), rep);
3184 if (map) {
3185 WriteToClient(client, length, map);
3186 free((char *) map);
3187 }
3188 return Success;
3189 }
3190
3191 int
ProcXkbGetIndicatorMap(ClientPtr client)3192 ProcXkbGetIndicatorMap(ClientPtr client)
3193 {
3194 xkbGetIndicatorMapReply rep;
3195 DeviceIntPtr dev;
3196 XkbDescPtr xkb;
3197 XkbIndicatorPtr leds;
3198
3199 REQUEST(xkbGetIndicatorMapReq);
3200 REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq);
3201
3202 if (!(client->xkbClientFlags & _XkbClientInitialized))
3203 return BadAccess;
3204
3205 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
3206
3207 xkb = dev->key->xkbInfo->desc;
3208 leds = xkb->indicators;
3209
3210 rep = (xkbGetIndicatorMapReply) {
3211 .type = X_Reply,
3212 .deviceID = dev->id,
3213 .sequenceNumber = client->sequence,
3214 .length = 0,
3215 .which = stuff->which
3216 };
3217 XkbComputeGetIndicatorMapReplySize(leds, &rep);
3218 return XkbSendIndicatorMap(client, leds, &rep);
3219 }
3220
3221 /**
3222 * Apply the given map to the given device. Which specifies which components
3223 * to apply.
3224 */
3225 static int
_XkbSetIndicatorMap(ClientPtr client,DeviceIntPtr dev,int which,xkbIndicatorMapWireDesc * desc)3226 _XkbSetIndicatorMap(ClientPtr client, DeviceIntPtr dev,
3227 int which, xkbIndicatorMapWireDesc * desc)
3228 {
3229 XkbSrvInfoPtr xkbi;
3230 XkbSrvLedInfoPtr sli;
3231 XkbEventCauseRec cause;
3232 int i, bit;
3233
3234 xkbi = dev->key->xkbInfo;
3235
3236 sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
3237 XkbXI_IndicatorMapsMask);
3238 if (!sli)
3239 return BadAlloc;
3240
3241 for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3242 if (which & bit) {
3243 sli->maps[i].flags = desc->flags;
3244 sli->maps[i].which_groups = desc->whichGroups;
3245 sli->maps[i].groups = desc->groups;
3246 sli->maps[i].which_mods = desc->whichMods;
3247 sli->maps[i].mods.mask = desc->mods;
3248 sli->maps[i].mods.real_mods = desc->mods;
3249 sli->maps[i].mods.vmods = desc->virtualMods;
3250 sli->maps[i].ctrls = desc->ctrls;
3251 if (desc->virtualMods != 0) {
3252 unsigned tmp;
3253
3254 tmp = XkbMaskForVMask(xkbi->desc, desc->virtualMods);
3255 sli->maps[i].mods.mask = desc->mods | tmp;
3256 }
3257 desc++;
3258 }
3259 }
3260
3261 XkbSetCauseXkbReq(&cause, X_kbSetIndicatorMap, client);
3262 XkbApplyLedMapChanges(dev, sli, which, NULL, NULL, &cause);
3263
3264 return Success;
3265 }
3266
3267 int
ProcXkbSetIndicatorMap(ClientPtr client)3268 ProcXkbSetIndicatorMap(ClientPtr client)
3269 {
3270 int i, bit;
3271 int nIndicators;
3272 DeviceIntPtr dev;
3273 xkbIndicatorMapWireDesc *from;
3274 int rc;
3275
3276 REQUEST(xkbSetIndicatorMapReq);
3277 REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq);
3278
3279 if (!(client->xkbClientFlags & _XkbClientInitialized))
3280 return BadAccess;
3281
3282 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
3283
3284 if (stuff->which == 0)
3285 return Success;
3286
3287 for (nIndicators = i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3288 if (stuff->which & bit)
3289 nIndicators++;
3290 }
3291 if (stuff->length != ((SIZEOF(xkbSetIndicatorMapReq) +
3292 (nIndicators * SIZEOF(xkbIndicatorMapWireDesc))) /
3293 4)) {
3294 return BadLength;
3295 }
3296
3297 from = (xkbIndicatorMapWireDesc *) &stuff[1];
3298 for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3299 if (stuff->which & bit) {
3300 if (client->swapped) {
3301 swaps(&from->virtualMods);
3302 swapl(&from->ctrls);
3303 }
3304 CHK_MASK_LEGAL(i, from->whichGroups, XkbIM_UseAnyGroup);
3305 CHK_MASK_LEGAL(i, from->whichMods, XkbIM_UseAnyMods);
3306 from++;
3307 }
3308 }
3309
3310 from = (xkbIndicatorMapWireDesc *) &stuff[1];
3311 rc = _XkbSetIndicatorMap(client, dev, stuff->which, from);
3312 if (rc != Success)
3313 return rc;
3314
3315 if (stuff->deviceSpec == XkbUseCoreKbd) {
3316 DeviceIntPtr other;
3317
3318 for (other = inputInfo.devices; other; other = other->next) {
3319 if ((other != dev) && other->key && !IsMaster(other) &&
3320 GetMaster(other, MASTER_KEYBOARD) == dev) {
3321 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
3322 DixSetAttrAccess);
3323 if (rc == Success)
3324 _XkbSetIndicatorMap(client, other, stuff->which, from);
3325 }
3326 }
3327 }
3328
3329 return Success;
3330 }
3331
3332 /***====================================================================***/
3333
3334 int
ProcXkbGetNamedIndicator(ClientPtr client)3335 ProcXkbGetNamedIndicator(ClientPtr client)
3336 {
3337 DeviceIntPtr dev;
3338 xkbGetNamedIndicatorReply rep;
3339 register int i = 0;
3340 XkbSrvLedInfoPtr sli;
3341 XkbIndicatorMapPtr map = NULL;
3342
3343 REQUEST(xkbGetNamedIndicatorReq);
3344 REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq);
3345
3346 if (!(client->xkbClientFlags & _XkbClientInitialized))
3347 return BadAccess;
3348
3349 CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
3350 CHK_ATOM_ONLY(stuff->indicator);
3351
3352 sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID, 0);
3353 if (!sli)
3354 return BadAlloc;
3355
3356 i = 0;
3357 map = NULL;
3358 if ((sli->names) && (sli->maps)) {
3359 for (i = 0; i < XkbNumIndicators; i++) {
3360 if (stuff->indicator == sli->names[i]) {
3361 map = &sli->maps[i];
3362 break;
3363 }
3364 }
3365 }
3366
3367 rep = (xkbGetNamedIndicatorReply) {
3368 .type = X_Reply,
3369 .sequenceNumber = client->sequence,
3370 .length = 0,
3371 .deviceID = dev->id,
3372 .indicator = stuff->indicator
3373 };
3374 if (map != NULL) {
3375 rep.found = TRUE;
3376 rep.on = ((sli->effectiveState & (1 << i)) != 0);
3377 rep.realIndicator = ((sli->physIndicators & (1 << i)) != 0);
3378 rep.ndx = i;
3379 rep.flags = map->flags;
3380 rep.whichGroups = map->which_groups;
3381 rep.groups = map->groups;
3382 rep.whichMods = map->which_mods;
3383 rep.mods = map->mods.mask;
3384 rep.realMods = map->mods.real_mods;
3385 rep.virtualMods = map->mods.vmods;
3386 rep.ctrls = map->ctrls;
3387 rep.supported = TRUE;
3388 }
3389 else {
3390 rep.found = FALSE;
3391 rep.on = FALSE;
3392 rep.realIndicator = FALSE;
3393 rep.ndx = XkbNoIndicator;
3394 rep.flags = 0;
3395 rep.whichGroups = 0;
3396 rep.groups = 0;
3397 rep.whichMods = 0;
3398 rep.mods = 0;
3399 rep.realMods = 0;
3400 rep.virtualMods = 0;
3401 rep.ctrls = 0;
3402 rep.supported = TRUE;
3403 }
3404 if (client->swapped) {
3405 swapl(&rep.length);
3406 swaps(&rep.sequenceNumber);
3407 swapl(&rep.indicator);
3408 swaps(&rep.virtualMods);
3409 swapl(&rep.ctrls);
3410 }
3411
3412 WriteToClient(client, SIZEOF(xkbGetNamedIndicatorReply), &rep);
3413 return Success;
3414 }
3415
3416 /**
3417 * Find the IM on the device.
3418 * Returns the map, or NULL if the map doesn't exist.
3419 * If the return value is NULL, led_return is undefined. Otherwise, led_return
3420 * is set to the led index of the map.
3421 */
3422 static XkbIndicatorMapPtr
_XkbFindNamedIndicatorMap(XkbSrvLedInfoPtr sli,Atom indicator,int * led_return)3423 _XkbFindNamedIndicatorMap(XkbSrvLedInfoPtr sli, Atom indicator, int *led_return)
3424 {
3425 XkbIndicatorMapPtr map;
3426
3427 /* search for the right indicator */
3428 map = NULL;
3429 if (sli->names && sli->maps) {
3430 int led;
3431
3432 for (led = 0; (led < XkbNumIndicators) && (map == NULL); led++) {
3433 if (sli->names[led] == indicator) {
3434 map = &sli->maps[led];
3435 *led_return = led;
3436 break;
3437 }
3438 }
3439 }
3440
3441 return map;
3442 }
3443
3444 /**
3445 * Creates an indicator map on the device. If dryRun is TRUE, it only checks
3446 * if creation is possible, but doesn't actually create it.
3447 */
3448 static int
_XkbCreateIndicatorMap(DeviceIntPtr dev,Atom indicator,int ledClass,int ledID,XkbIndicatorMapPtr * map_return,int * led_return,Bool dryRun)3449 _XkbCreateIndicatorMap(DeviceIntPtr dev, Atom indicator,
3450 int ledClass, int ledID,
3451 XkbIndicatorMapPtr * map_return, int *led_return,
3452 Bool dryRun)
3453 {
3454 XkbSrvLedInfoPtr sli;
3455 XkbIndicatorMapPtr map;
3456 int led;
3457
3458 sli = XkbFindSrvLedInfo(dev, ledClass, ledID, XkbXI_IndicatorsMask);
3459 if (!sli)
3460 return BadAlloc;
3461
3462 map = _XkbFindNamedIndicatorMap(sli, indicator, &led);
3463
3464 if (!map) {
3465 /* find first unused indicator maps and assign the name to it */
3466 for (led = 0, map = NULL; (led < XkbNumIndicators) && (map == NULL);
3467 led++) {
3468 if ((sli->names) && (sli->maps) && (sli->names[led] == None) &&
3469 (!XkbIM_InUse(&sli->maps[led]))) {
3470 map = &sli->maps[led];
3471 if (!dryRun)
3472 sli->names[led] = indicator;
3473 break;
3474 }
3475 }
3476 }
3477
3478 if (!map)
3479 return BadAlloc;
3480
3481 *led_return = led;
3482 *map_return = map;
3483 return Success;
3484 }
3485
3486 static int
_XkbSetNamedIndicator(ClientPtr client,DeviceIntPtr dev,xkbSetNamedIndicatorReq * stuff)3487 _XkbSetNamedIndicator(ClientPtr client, DeviceIntPtr dev,
3488 xkbSetNamedIndicatorReq * stuff)
3489 {
3490 unsigned int extDevReason;
3491 unsigned int statec, namec, mapc;
3492 XkbSrvLedInfoPtr sli;
3493 int led = 0;
3494 XkbIndicatorMapPtr map;
3495 DeviceIntPtr kbd;
3496 XkbEventCauseRec cause;
3497 xkbExtensionDeviceNotify ed;
3498 XkbChangesRec changes;
3499 int rc;
3500
3501 rc = _XkbCreateIndicatorMap(dev, stuff->indicator, stuff->ledClass,
3502 stuff->ledID, &map, &led, FALSE);
3503 if (rc != Success || !map) /* oh-oh */
3504 return rc;
3505
3506 sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID,
3507 XkbXI_IndicatorsMask);
3508 if (!sli)
3509 return BadAlloc;
3510
3511 namec = mapc = statec = 0;
3512 extDevReason = 0;
3513
3514 namec |= (1 << led);
3515 sli->namesPresent |= ((stuff->indicator != None) ? (1 << led) : 0);
3516 extDevReason |= XkbXI_IndicatorNamesMask;
3517
3518 if (stuff->setMap) {
3519 map->flags = stuff->flags;
3520 map->which_groups = stuff->whichGroups;
3521 map->groups = stuff->groups;
3522 map->which_mods = stuff->whichMods;
3523 map->mods.mask = stuff->realMods;
3524 map->mods.real_mods = stuff->realMods;
3525 map->mods.vmods = stuff->virtualMods;
3526 map->ctrls = stuff->ctrls;
3527 mapc |= (1 << led);
3528 }
3529
3530 if ((stuff->setState) && ((map->flags & XkbIM_NoExplicit) == 0)) {
3531 if (stuff->on)
3532 sli->explicitState |= (1 << led);
3533 else
3534 sli->explicitState &= ~(1 << led);
3535 statec |= ((sli->effectiveState ^ sli->explicitState) & (1 << led));
3536 }
3537
3538 memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify));
3539 memset((char *) &changes, 0, sizeof(XkbChangesRec));
3540 XkbSetCauseXkbReq(&cause, X_kbSetNamedIndicator, client);
3541 if (namec)
3542 XkbApplyLedNameChanges(dev, sli, namec, &ed, &changes, &cause);
3543 if (mapc)
3544 XkbApplyLedMapChanges(dev, sli, mapc, &ed, &changes, &cause);
3545 if (statec)
3546 XkbApplyLedStateChanges(dev, sli, statec, &ed, &changes, &cause);
3547
3548 kbd = dev;
3549 if ((sli->flags & XkbSLI_HasOwnState) == 0)
3550 kbd = inputInfo.keyboard;
3551 XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause);
3552
3553 return Success;
3554 }
3555
3556 int
ProcXkbSetNamedIndicator(ClientPtr client)3557 ProcXkbSetNamedIndicator(ClientPtr client)
3558 {
3559 int rc;
3560 DeviceIntPtr dev;
3561 int led = 0;
3562 XkbIndicatorMapPtr map;
3563
3564 REQUEST(xkbSetNamedIndicatorReq);
3565 REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq);
3566
3567 if (!(client->xkbClientFlags & _XkbClientInitialized))
3568 return BadAccess;
3569
3570 CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
3571 CHK_ATOM_ONLY(stuff->indicator);
3572 CHK_MASK_LEGAL(0x10, stuff->whichGroups, XkbIM_UseAnyGroup);
3573 CHK_MASK_LEGAL(0x11, stuff->whichMods, XkbIM_UseAnyMods);
3574
3575 /* Dry-run for checks */
3576 rc = _XkbCreateIndicatorMap(dev, stuff->indicator,
3577 stuff->ledClass, stuff->ledID,
3578 &map, &led, TRUE);
3579 if (rc != Success || !map) /* couldn't be created or didn't exist */
3580 return rc;
3581
3582 if (stuff->deviceSpec == XkbUseCoreKbd ||
3583 stuff->deviceSpec == XkbUseCorePtr) {
3584 DeviceIntPtr other;
3585
3586 for (other = inputInfo.devices; other; other = other->next) {
3587 if ((other != dev) && !IsMaster(other) &&
3588 GetMaster(other, MASTER_KEYBOARD) == dev && (other->kbdfeed ||
3589 other->leds) &&
3590 (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess)
3591 == Success)) {
3592 rc = _XkbCreateIndicatorMap(other, stuff->indicator,
3593 stuff->ledClass, stuff->ledID, &map,
3594 &led, TRUE);
3595 if (rc != Success || !map)
3596 return rc;
3597 }
3598 }
3599 }
3600
3601 /* All checks passed, let's do it */
3602 rc = _XkbSetNamedIndicator(client, dev, stuff);
3603 if (rc != Success)
3604 return rc;
3605
3606 if (stuff->deviceSpec == XkbUseCoreKbd ||
3607 stuff->deviceSpec == XkbUseCorePtr) {
3608 DeviceIntPtr other;
3609
3610 for (other = inputInfo.devices; other; other = other->next) {
3611 if ((other != dev) && !IsMaster(other) &&
3612 GetMaster(other, MASTER_KEYBOARD) == dev && (other->kbdfeed ||
3613 other->leds) &&
3614 (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess)
3615 == Success)) {
3616 _XkbSetNamedIndicator(client, other, stuff);
3617 }
3618 }
3619 }
3620
3621 return Success;
3622 }
3623
3624 /***====================================================================***/
3625
3626 static CARD32
_XkbCountAtoms(Atom * atoms,int maxAtoms,int * count)3627 _XkbCountAtoms(Atom *atoms, int maxAtoms, int *count)
3628 {
3629 register unsigned int i, bit, nAtoms;
3630 register CARD32 atomsPresent;
3631
3632 for (i = nAtoms = atomsPresent = 0, bit = 1; i < maxAtoms; i++, bit <<= 1) {
3633 if (atoms[i] != None) {
3634 atomsPresent |= bit;
3635 nAtoms++;
3636 }
3637 }
3638 if (count)
3639 *count = nAtoms;
3640 return atomsPresent;
3641 }
3642
3643 static char *
_XkbWriteAtoms(char * wire,Atom * atoms,int maxAtoms,int swap)3644 _XkbWriteAtoms(char *wire, Atom *atoms, int maxAtoms, int swap)
3645 {
3646 register unsigned int i;
3647 Atom *atm;
3648
3649 atm = (Atom *) wire;
3650 for (i = 0; i < maxAtoms; i++) {
3651 if (atoms[i] != None) {
3652 *atm = atoms[i];
3653 if (swap) {
3654 swapl(atm);
3655 }
3656 atm++;
3657 }
3658 }
3659 return (char *) atm;
3660 }
3661
3662 static Status
XkbComputeGetNamesReplySize(XkbDescPtr xkb,xkbGetNamesReply * rep)3663 XkbComputeGetNamesReplySize(XkbDescPtr xkb, xkbGetNamesReply * rep)
3664 {
3665 register unsigned which, length;
3666 register int i;
3667
3668 rep->minKeyCode = xkb->min_key_code;
3669 rep->maxKeyCode = xkb->max_key_code;
3670 which = rep->which;
3671 length = 0;
3672 if (xkb->names != NULL) {
3673 if (which & XkbKeycodesNameMask)
3674 length++;
3675 if (which & XkbGeometryNameMask)
3676 length++;
3677 if (which & XkbSymbolsNameMask)
3678 length++;
3679 if (which & XkbPhysSymbolsNameMask)
3680 length++;
3681 if (which & XkbTypesNameMask)
3682 length++;
3683 if (which & XkbCompatNameMask)
3684 length++;
3685 }
3686 else
3687 which &= ~XkbComponentNamesMask;
3688
3689 if (xkb->map != NULL) {
3690 if (which & XkbKeyTypeNamesMask)
3691 length += xkb->map->num_types;
3692 rep->nTypes = xkb->map->num_types;
3693 if (which & XkbKTLevelNamesMask) {
3694 XkbKeyTypePtr pType = xkb->map->types;
3695 int nKTLevels = 0;
3696
3697 length += XkbPaddedSize(xkb->map->num_types) / 4;
3698 for (i = 0; i < xkb->map->num_types; i++, pType++) {
3699 if (pType->level_names != NULL)
3700 nKTLevels += pType->num_levels;
3701 }
3702 rep->nKTLevels = nKTLevels;
3703 length += nKTLevels;
3704 }
3705 }
3706 else {
3707 rep->nTypes = 0;
3708 rep->nKTLevels = 0;
3709 which &= ~(XkbKeyTypeNamesMask | XkbKTLevelNamesMask);
3710 }
3711
3712 rep->minKeyCode = xkb->min_key_code;
3713 rep->maxKeyCode = xkb->max_key_code;
3714 rep->indicators = 0;
3715 rep->virtualMods = 0;
3716 rep->groupNames = 0;
3717 if (xkb->names != NULL) {
3718 if (which & XkbIndicatorNamesMask) {
3719 int nLeds;
3720
3721 rep->indicators =
3722 _XkbCountAtoms(xkb->names->indicators, XkbNumIndicators,
3723 &nLeds);
3724 length += nLeds;
3725 if (nLeds == 0)
3726 which &= ~XkbIndicatorNamesMask;
3727 }
3728
3729 if (which & XkbVirtualModNamesMask) {
3730 int nVMods;
3731
3732 rep->virtualMods =
3733 _XkbCountAtoms(xkb->names->vmods, XkbNumVirtualMods, &nVMods);
3734 length += nVMods;
3735 if (nVMods == 0)
3736 which &= ~XkbVirtualModNamesMask;
3737 }
3738
3739 if (which & XkbGroupNamesMask) {
3740 int nGroups;
3741
3742 rep->groupNames =
3743 _XkbCountAtoms(xkb->names->groups, XkbNumKbdGroups, &nGroups);
3744 length += nGroups;
3745 if (nGroups == 0)
3746 which &= ~XkbGroupNamesMask;
3747 }
3748
3749 if ((which & XkbKeyNamesMask) && (xkb->names->keys))
3750 length += rep->nKeys;
3751 else
3752 which &= ~XkbKeyNamesMask;
3753
3754 if ((which & XkbKeyAliasesMask) &&
3755 (xkb->names->key_aliases) && (xkb->names->num_key_aliases > 0)) {
3756 rep->nKeyAliases = xkb->names->num_key_aliases;
3757 length += rep->nKeyAliases * 2;
3758 }
3759 else {
3760 which &= ~XkbKeyAliasesMask;
3761 rep->nKeyAliases = 0;
3762 }
3763
3764 if ((which & XkbRGNamesMask) && (xkb->names->num_rg > 0))
3765 length += xkb->names->num_rg;
3766 else
3767 which &= ~XkbRGNamesMask;
3768 }
3769 else {
3770 which &= ~(XkbIndicatorNamesMask | XkbVirtualModNamesMask);
3771 which &= ~(XkbGroupNamesMask | XkbKeyNamesMask | XkbKeyAliasesMask);
3772 which &= ~XkbRGNamesMask;
3773 }
3774
3775 rep->length = length;
3776 rep->which = which;
3777 return Success;
3778 }
3779
3780 static int
XkbSendNames(ClientPtr client,XkbDescPtr xkb,xkbGetNamesReply * rep)3781 XkbSendNames(ClientPtr client, XkbDescPtr xkb, xkbGetNamesReply * rep)
3782 {
3783 register unsigned i, length, which;
3784 char *start;
3785 char *desc;
3786
3787 length = rep->length * 4;
3788 which = rep->which;
3789 if (client->swapped) {
3790 swaps(&rep->sequenceNumber);
3791 swapl(&rep->length);
3792 swapl(&rep->which);
3793 swaps(&rep->virtualMods);
3794 swapl(&rep->indicators);
3795 }
3796
3797 start = desc = calloc(1, length);
3798 if (!start)
3799 return BadAlloc;
3800 if (xkb->names) {
3801 if (which & XkbKeycodesNameMask) {
3802 *((CARD32 *) desc) = xkb->names->keycodes;
3803 if (client->swapped) {
3804 swapl((int *) desc);
3805 }
3806 desc += 4;
3807 }
3808 if (which & XkbGeometryNameMask) {
3809 *((CARD32 *) desc) = xkb->names->geometry;
3810 if (client->swapped) {
3811 swapl((int *) desc);
3812 }
3813 desc += 4;
3814 }
3815 if (which & XkbSymbolsNameMask) {
3816 *((CARD32 *) desc) = xkb->names->symbols;
3817 if (client->swapped) {
3818 swapl((int *) desc);
3819 }
3820 desc += 4;
3821 }
3822 if (which & XkbPhysSymbolsNameMask) {
3823 register CARD32 *atm = (CARD32 *) desc;
3824
3825 atm[0] = (CARD32) xkb->names->phys_symbols;
3826 if (client->swapped) {
3827 swapl(&atm[0]);
3828 }
3829 desc += 4;
3830 }
3831 if (which & XkbTypesNameMask) {
3832 *((CARD32 *) desc) = (CARD32) xkb->names->types;
3833 if (client->swapped) {
3834 swapl((int *) desc);
3835 }
3836 desc += 4;
3837 }
3838 if (which & XkbCompatNameMask) {
3839 *((CARD32 *) desc) = (CARD32) xkb->names->compat;
3840 if (client->swapped) {
3841 swapl((int *) desc);
3842 }
3843 desc += 4;
3844 }
3845 if (which & XkbKeyTypeNamesMask) {
3846 register CARD32 *atm = (CARD32 *) desc;
3847 register XkbKeyTypePtr type = xkb->map->types;
3848
3849 for (i = 0; i < xkb->map->num_types; i++, atm++, type++) {
3850 *atm = (CARD32) type->name;
3851 if (client->swapped) {
3852 swapl(atm);
3853 }
3854 }
3855 desc = (char *) atm;
3856 }
3857 if (which & XkbKTLevelNamesMask && xkb->map) {
3858 XkbKeyTypePtr type = xkb->map->types;
3859 register CARD32 *atm;
3860
3861 for (i = 0; i < rep->nTypes; i++, type++) {
3862 *desc++ = type->num_levels;
3863 }
3864 desc += XkbPaddedSize(rep->nTypes) - rep->nTypes;
3865
3866 atm = (CARD32 *) desc;
3867 type = xkb->map->types;
3868 for (i = 0; i < xkb->map->num_types; i++, type++) {
3869 register unsigned l;
3870
3871 if (type->level_names) {
3872 for (l = 0; l < type->num_levels; l++, atm++) {
3873 *atm = type->level_names[l];
3874 if (client->swapped) {
3875 swapl(atm);
3876 }
3877 }
3878 desc += type->num_levels * 4;
3879 }
3880 }
3881 }
3882 if (which & XkbIndicatorNamesMask) {
3883 desc =
3884 _XkbWriteAtoms(desc, xkb->names->indicators, XkbNumIndicators,
3885 client->swapped);
3886 }
3887 if (which & XkbVirtualModNamesMask) {
3888 desc = _XkbWriteAtoms(desc, xkb->names->vmods, XkbNumVirtualMods,
3889 client->swapped);
3890 }
3891 if (which & XkbGroupNamesMask) {
3892 desc = _XkbWriteAtoms(desc, xkb->names->groups, XkbNumKbdGroups,
3893 client->swapped);
3894 }
3895 if (which & XkbKeyNamesMask) {
3896 for (i = 0; i < rep->nKeys; i++, desc += sizeof(XkbKeyNameRec)) {
3897 *((XkbKeyNamePtr) desc) = xkb->names->keys[i + rep->firstKey];
3898 }
3899 }
3900 if (which & XkbKeyAliasesMask) {
3901 XkbKeyAliasPtr pAl;
3902
3903 pAl = xkb->names->key_aliases;
3904 for (i = 0; i < rep->nKeyAliases;
3905 i++, pAl++, desc += 2 * XkbKeyNameLength) {
3906 *((XkbKeyAliasPtr) desc) = *pAl;
3907 }
3908 }
3909 if ((which & XkbRGNamesMask) && (rep->nRadioGroups > 0)) {
3910 register CARD32 *atm = (CARD32 *) desc;
3911
3912 for (i = 0; i < rep->nRadioGroups; i++, atm++) {
3913 *atm = (CARD32) xkb->names->radio_groups[i];
3914 if (client->swapped) {
3915 swapl(atm);
3916 }
3917 }
3918 desc += rep->nRadioGroups * 4;
3919 }
3920 }
3921
3922 if ((desc - start) != (length)) {
3923 ErrorF("[xkb] BOGUS LENGTH in write names, expected %d, got %ld\n",
3924 length, (unsigned long) (desc - start));
3925 }
3926 WriteToClient(client, SIZEOF(xkbGetNamesReply), rep);
3927 WriteToClient(client, length, start);
3928 free((char *) start);
3929 return Success;
3930 }
3931
3932 int
ProcXkbGetNames(ClientPtr client)3933 ProcXkbGetNames(ClientPtr client)
3934 {
3935 DeviceIntPtr dev;
3936 XkbDescPtr xkb;
3937 xkbGetNamesReply rep;
3938
3939 REQUEST(xkbGetNamesReq);
3940 REQUEST_SIZE_MATCH(xkbGetNamesReq);
3941
3942 if (!(client->xkbClientFlags & _XkbClientInitialized))
3943 return BadAccess;
3944
3945 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
3946 CHK_MASK_LEGAL(0x01, stuff->which, XkbAllNamesMask);
3947
3948 xkb = dev->key->xkbInfo->desc;
3949 rep = (xkbGetNamesReply) {
3950 .type = X_Reply,
3951 .deviceID = dev->id,
3952 .sequenceNumber = client->sequence,
3953 .length = 0,
3954 .which = stuff->which,
3955 .nTypes = xkb->map->num_types,
3956 .firstKey = xkb->min_key_code,
3957 .nKeys = XkbNumKeys(xkb),
3958 .nKeyAliases = xkb->names ? xkb->names->num_key_aliases : 0,
3959 .nRadioGroups = xkb->names ? xkb->names->num_rg : 0
3960 };
3961 XkbComputeGetNamesReplySize(xkb, &rep);
3962 return XkbSendNames(client, xkb, &rep);
3963 }
3964
3965 /***====================================================================***/
3966
3967 static CARD32 *
_XkbCheckAtoms(CARD32 * wire,int nAtoms,int swapped,Atom * pError)3968 _XkbCheckAtoms(CARD32 *wire, int nAtoms, int swapped, Atom *pError)
3969 {
3970 register int i;
3971
3972 for (i = 0; i < nAtoms; i++, wire++) {
3973 if (swapped) {
3974 swapl(wire);
3975 }
3976 if ((((Atom) *wire) != None) && (!ValidAtom((Atom) *wire))) {
3977 *pError = ((Atom) *wire);
3978 return NULL;
3979 }
3980 }
3981 return wire;
3982 }
3983
3984 static CARD32 *
_XkbCheckMaskedAtoms(CARD32 * wire,int nAtoms,CARD32 present,int swapped,Atom * pError)3985 _XkbCheckMaskedAtoms(CARD32 *wire, int nAtoms, CARD32 present, int swapped,
3986 Atom *pError)
3987 {
3988 register unsigned i, bit;
3989
3990 for (i = 0, bit = 1; (i < nAtoms) && (present); i++, bit <<= 1) {
3991 if ((present & bit) == 0)
3992 continue;
3993 if (swapped) {
3994 swapl(wire);
3995 }
3996 if ((((Atom) *wire) != None) && (!ValidAtom(((Atom) *wire)))) {
3997 *pError = (Atom) *wire;
3998 return NULL;
3999 }
4000 wire++;
4001 }
4002 return wire;
4003 }
4004
4005 static Atom *
_XkbCopyMaskedAtoms(Atom * wire,Atom * dest,int nAtoms,CARD32 present)4006 _XkbCopyMaskedAtoms(Atom *wire, Atom *dest, int nAtoms, CARD32 present)
4007 {
4008 register int i, bit;
4009
4010 for (i = 0, bit = 1; (i < nAtoms) && (present); i++, bit <<= 1) {
4011 if ((present & bit) == 0)
4012 continue;
4013 dest[i] = *wire++;
4014 }
4015 return wire;
4016 }
4017
4018 static Bool
_XkbCheckTypeName(Atom name,int typeNdx)4019 _XkbCheckTypeName(Atom name, int typeNdx)
4020 {
4021 const char *str;
4022
4023 str = NameForAtom(name);
4024 if ((strcmp(str, "ONE_LEVEL") == 0) || (strcmp(str, "TWO_LEVEL") == 0) ||
4025 (strcmp(str, "ALPHABETIC") == 0) || (strcmp(str, "KEYPAD") == 0))
4026 return FALSE;
4027 return TRUE;
4028 }
4029
4030 /**
4031 * Check the device-dependent data in the request against the device. Returns
4032 * Success, or the appropriate error code.
4033 */
4034 static int
_XkbSetNamesCheck(ClientPtr client,DeviceIntPtr dev,xkbSetNamesReq * stuff,CARD32 * data)4035 _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
4036 xkbSetNamesReq * stuff, CARD32 *data)
4037 {
4038 XkbDescRec *xkb;
4039 CARD32 *tmp;
4040 Atom bad = None;
4041
4042 tmp = data;
4043 xkb = dev->key->xkbInfo->desc;
4044
4045 if (stuff->which & XkbKeyTypeNamesMask) {
4046 int i;
4047 CARD32 *old;
4048
4049 if (stuff->nTypes < 1) {
4050 client->errorValue = _XkbErrCode2(0x02, stuff->nTypes);
4051 return BadValue;
4052 }
4053 if ((unsigned) (stuff->firstType + stuff->nTypes - 1) >=
4054 xkb->map->num_types) {
4055 client->errorValue =
4056 _XkbErrCode4(0x03, stuff->firstType, stuff->nTypes,
4057 xkb->map->num_types);
4058 return BadValue;
4059 }
4060 if (((unsigned) stuff->firstType) <= XkbLastRequiredType) {
4061 client->errorValue = _XkbErrCode2(0x04, stuff->firstType);
4062 return BadAccess;
4063 }
4064 if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + stuff->nTypes))
4065 return BadLength;
4066 old = tmp;
4067 tmp = _XkbCheckAtoms(tmp, stuff->nTypes, client->swapped, &bad);
4068 if (!tmp) {
4069 client->errorValue = bad;
4070 return BadAtom;
4071 }
4072 for (i = 0; i < stuff->nTypes; i++, old++) {
4073 if (!_XkbCheckTypeName((Atom) *old, stuff->firstType + i))
4074 client->errorValue = _XkbErrCode2(0x05, i);
4075 }
4076 }
4077 if (stuff->which & XkbKTLevelNamesMask) {
4078 unsigned i;
4079 XkbKeyTypePtr type;
4080 CARD8 *width;
4081
4082 if (stuff->nKTLevels < 1) {
4083 client->errorValue = _XkbErrCode2(0x05, stuff->nKTLevels);
4084 return BadValue;
4085 }
4086 if ((unsigned) (stuff->firstKTLevel + stuff->nKTLevels - 1) >=
4087 xkb->map->num_types) {
4088 client->errorValue = _XkbErrCode4(0x06, stuff->firstKTLevel,
4089 stuff->nKTLevels,
4090 xkb->map->num_types);
4091 return BadValue;
4092 }
4093 width = (CARD8 *) tmp;
4094 tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels));
4095 if (!_XkbCheckRequestBounds(client, stuff, width, tmp))
4096 return BadLength;
4097 type = &xkb->map->types[stuff->firstKTLevel];
4098 for (i = 0; i < stuff->nKTLevels; i++, type++) {
4099 if (width[i] == 0)
4100 continue;
4101 else if (width[i] != type->num_levels) {
4102 client->errorValue = _XkbErrCode4(0x07, i + stuff->firstKTLevel,
4103 type->num_levels, width[i]);
4104 return BadMatch;
4105 }
4106 if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + width[i]))
4107 return BadLength;
4108 tmp = _XkbCheckAtoms(tmp, width[i], client->swapped, &bad);
4109 if (!tmp) {
4110 client->errorValue = bad;
4111 return BadAtom;
4112 }
4113 }
4114 }
4115 if (stuff->which & XkbIndicatorNamesMask) {
4116 if (stuff->indicators == 0) {
4117 client->errorValue = 0x08;
4118 return BadMatch;
4119 }
4120 if (!_XkbCheckRequestBounds(client, stuff, tmp,
4121 tmp + Ones(stuff->indicators)))
4122 return BadLength;
4123 tmp = _XkbCheckMaskedAtoms(tmp, XkbNumIndicators, stuff->indicators,
4124 client->swapped, &bad);
4125 if (!tmp) {
4126 client->errorValue = bad;
4127 return BadAtom;
4128 }
4129 }
4130 if (stuff->which & XkbVirtualModNamesMask) {
4131 if (stuff->virtualMods == 0) {
4132 client->errorValue = 0x09;
4133 return BadMatch;
4134 }
4135 if (!_XkbCheckRequestBounds(client, stuff, tmp,
4136 tmp + Ones(stuff->virtualMods)))
4137 return BadLength;
4138 tmp = _XkbCheckMaskedAtoms(tmp, XkbNumVirtualMods,
4139 (CARD32) stuff->virtualMods,
4140 client->swapped, &bad);
4141 if (!tmp) {
4142 client->errorValue = bad;
4143 return BadAtom;
4144 }
4145 }
4146 if (stuff->which & XkbGroupNamesMask) {
4147 if (stuff->groupNames == 0) {
4148 client->errorValue = 0x0a;
4149 return BadMatch;
4150 }
4151 if (!_XkbCheckRequestBounds(client, stuff, tmp,
4152 tmp + Ones(stuff->groupNames)))
4153 return BadLength;
4154 tmp = _XkbCheckMaskedAtoms(tmp, XkbNumKbdGroups,
4155 (CARD32) stuff->groupNames,
4156 client->swapped, &bad);
4157 if (!tmp) {
4158 client->errorValue = bad;
4159 return BadAtom;
4160 }
4161 }
4162 if (stuff->which & XkbKeyNamesMask) {
4163 if (stuff->firstKey < (unsigned) xkb->min_key_code) {
4164 client->errorValue = _XkbErrCode3(0x0b, xkb->min_key_code,
4165 stuff->firstKey);
4166 return BadValue;
4167 }
4168 if (((unsigned) (stuff->firstKey + stuff->nKeys - 1) >
4169 xkb->max_key_code) || (stuff->nKeys < 1)) {
4170 client->errorValue =
4171 _XkbErrCode4(0x0c, xkb->max_key_code, stuff->firstKey,
4172 stuff->nKeys);
4173 return BadValue;
4174 }
4175 if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + stuff->nKeys))
4176 return BadLength;
4177 tmp += stuff->nKeys;
4178 }
4179 if ((stuff->which & XkbKeyAliasesMask) && (stuff->nKeyAliases > 0)) {
4180 if (!_XkbCheckRequestBounds(client, stuff, tmp,
4181 tmp + (stuff->nKeyAliases * 2)))
4182 return BadLength;
4183 tmp += stuff->nKeyAliases * 2;
4184 }
4185 if (stuff->which & XkbRGNamesMask) {
4186 if (stuff->nRadioGroups < 1) {
4187 client->errorValue = _XkbErrCode2(0x0d, stuff->nRadioGroups);
4188 return BadValue;
4189 }
4190 if (!_XkbCheckRequestBounds(client, stuff, tmp,
4191 tmp + stuff->nRadioGroups))
4192 return BadLength;
4193 tmp = _XkbCheckAtoms(tmp, stuff->nRadioGroups, client->swapped, &bad);
4194 if (!tmp) {
4195 client->errorValue = bad;
4196 return BadAtom;
4197 }
4198 }
4199 if ((tmp - ((CARD32 *) stuff)) != stuff->length) {
4200 client->errorValue = stuff->length;
4201 return BadLength;
4202 }
4203
4204 return Success;
4205 }
4206
4207 static int
_XkbSetNames(ClientPtr client,DeviceIntPtr dev,xkbSetNamesReq * stuff)4208 _XkbSetNames(ClientPtr client, DeviceIntPtr dev, xkbSetNamesReq * stuff)
4209 {
4210 XkbDescRec *xkb;
4211 XkbNamesRec *names;
4212 CARD32 *tmp;
4213 xkbNamesNotify nn;
4214
4215 tmp = (CARD32 *) &stuff[1];
4216 xkb = dev->key->xkbInfo->desc;
4217 names = xkb->names;
4218
4219 if (XkbAllocNames(xkb, stuff->which, stuff->nRadioGroups,
4220 stuff->nKeyAliases) != Success) {
4221 return BadAlloc;
4222 }
4223
4224 memset(&nn, 0, sizeof(xkbNamesNotify));
4225 nn.changed = stuff->which;
4226 tmp = (CARD32 *) &stuff[1];
4227 if (stuff->which & XkbKeycodesNameMask)
4228 names->keycodes = *tmp++;
4229 if (stuff->which & XkbGeometryNameMask)
4230 names->geometry = *tmp++;
4231 if (stuff->which & XkbSymbolsNameMask)
4232 names->symbols = *tmp++;
4233 if (stuff->which & XkbPhysSymbolsNameMask)
4234 names->phys_symbols = *tmp++;
4235 if (stuff->which & XkbTypesNameMask)
4236 names->types = *tmp++;
4237 if (stuff->which & XkbCompatNameMask)
4238 names->compat = *tmp++;
4239 if ((stuff->which & XkbKeyTypeNamesMask) && (stuff->nTypes > 0)) {
4240 register unsigned i;
4241 register XkbKeyTypePtr type;
4242
4243 type = &xkb->map->types[stuff->firstType];
4244 for (i = 0; i < stuff->nTypes; i++, type++) {
4245 type->name = *tmp++;
4246 }
4247 nn.firstType = stuff->firstType;
4248 nn.nTypes = stuff->nTypes;
4249 }
4250 if (stuff->which & XkbKTLevelNamesMask) {
4251 register XkbKeyTypePtr type;
4252 register unsigned i;
4253 CARD8 *width;
4254
4255 width = (CARD8 *) tmp;
4256 tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels));
4257 type = &xkb->map->types[stuff->firstKTLevel];
4258 for (i = 0; i < stuff->nKTLevels; i++, type++) {
4259 if (width[i] > 0) {
4260 if (type->level_names) {
4261 register unsigned n;
4262
4263 for (n = 0; n < width[i]; n++) {
4264 type->level_names[n] = tmp[n];
4265 }
4266 }
4267 tmp += width[i];
4268 }
4269 }
4270 nn.firstLevelName = 0;
4271 nn.nLevelNames = stuff->nTypes;
4272 }
4273 if (stuff->which & XkbIndicatorNamesMask) {
4274 tmp = _XkbCopyMaskedAtoms(tmp, names->indicators, XkbNumIndicators,
4275 stuff->indicators);
4276 nn.changedIndicators = stuff->indicators;
4277 }
4278 if (stuff->which & XkbVirtualModNamesMask) {
4279 tmp = _XkbCopyMaskedAtoms(tmp, names->vmods, XkbNumVirtualMods,
4280 stuff->virtualMods);
4281 nn.changedVirtualMods = stuff->virtualMods;
4282 }
4283 if (stuff->which & XkbGroupNamesMask) {
4284 tmp = _XkbCopyMaskedAtoms(tmp, names->groups, XkbNumKbdGroups,
4285 stuff->groupNames);
4286 nn.changedVirtualMods = stuff->groupNames;
4287 }
4288 if (stuff->which & XkbKeyNamesMask) {
4289 memcpy((char *) &names->keys[stuff->firstKey], (char *) tmp,
4290 stuff->nKeys * XkbKeyNameLength);
4291 tmp += stuff->nKeys;
4292 nn.firstKey = stuff->firstKey;
4293 nn.nKeys = stuff->nKeys;
4294 }
4295 if (stuff->which & XkbKeyAliasesMask) {
4296 if (stuff->nKeyAliases > 0) {
4297 register int na = stuff->nKeyAliases;
4298
4299 if (XkbAllocNames(xkb, XkbKeyAliasesMask, 0, na) != Success)
4300 return BadAlloc;
4301 memcpy((char *) names->key_aliases, (char *) tmp,
4302 stuff->nKeyAliases * sizeof(XkbKeyAliasRec));
4303 tmp += stuff->nKeyAliases * 2;
4304 }
4305 else if (names->key_aliases != NULL) {
4306 free(names->key_aliases);
4307 names->key_aliases = NULL;
4308 names->num_key_aliases = 0;
4309 }
4310 nn.nAliases = names->num_key_aliases;
4311 }
4312 if (stuff->which & XkbRGNamesMask) {
4313 if (stuff->nRadioGroups > 0) {
4314 register unsigned i, nrg;
4315
4316 nrg = stuff->nRadioGroups;
4317 if (XkbAllocNames(xkb, XkbRGNamesMask, nrg, 0) != Success)
4318 return BadAlloc;
4319
4320 for (i = 0; i < stuff->nRadioGroups; i++) {
4321 names->radio_groups[i] = tmp[i];
4322 }
4323 tmp += stuff->nRadioGroups;
4324 }
4325 else if (names->radio_groups) {
4326 free(names->radio_groups);
4327 names->radio_groups = NULL;
4328 names->num_rg = 0;
4329 }
4330 nn.nRadioGroups = names->num_rg;
4331 }
4332 if (nn.changed) {
4333 Bool needExtEvent;
4334
4335 needExtEvent = (nn.changed & XkbIndicatorNamesMask) != 0;
4336 XkbSendNamesNotify(dev, &nn);
4337 if (needExtEvent) {
4338 XkbSrvLedInfoPtr sli;
4339 xkbExtensionDeviceNotify edev;
4340 register int i;
4341 register unsigned bit;
4342
4343 sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
4344 XkbXI_IndicatorsMask);
4345 sli->namesPresent = 0;
4346 for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
4347 if (names->indicators[i] != None)
4348 sli->namesPresent |= bit;
4349 }
4350 memset(&edev, 0, sizeof(xkbExtensionDeviceNotify));
4351 edev.reason = XkbXI_IndicatorNamesMask;
4352 edev.ledClass = KbdFeedbackClass;
4353 edev.ledID = dev->kbdfeed->ctrl.id;
4354 edev.ledsDefined = sli->namesPresent | sli->mapsPresent;
4355 edev.ledState = sli->effectiveState;
4356 edev.firstBtn = 0;
4357 edev.nBtns = 0;
4358 edev.supported = XkbXI_AllFeaturesMask;
4359 edev.unsupported = 0;
4360 XkbSendExtensionDeviceNotify(dev, client, &edev);
4361 }
4362 }
4363 return Success;
4364 }
4365
4366 int
ProcXkbSetNames(ClientPtr client)4367 ProcXkbSetNames(ClientPtr client)
4368 {
4369 DeviceIntPtr dev;
4370 CARD32 *tmp;
4371 Atom bad;
4372 int rc;
4373
4374 REQUEST(xkbSetNamesReq);
4375 REQUEST_AT_LEAST_SIZE(xkbSetNamesReq);
4376
4377 if (!(client->xkbClientFlags & _XkbClientInitialized))
4378 return BadAccess;
4379
4380 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
4381 CHK_MASK_LEGAL(0x01, stuff->which, XkbAllNamesMask);
4382
4383 /* check device-independent stuff */
4384 tmp = (CARD32 *) &stuff[1];
4385
4386 if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
4387 return BadLength;
4388 if (stuff->which & XkbKeycodesNameMask) {
4389 tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4390 if (!tmp) {
4391 client->errorValue = bad;
4392 return BadAtom;
4393 }
4394 }
4395 if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
4396 return BadLength;
4397 if (stuff->which & XkbGeometryNameMask) {
4398 tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4399 if (!tmp) {
4400 client->errorValue = bad;
4401 return BadAtom;
4402 }
4403 }
4404 if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
4405 return BadLength;
4406 if (stuff->which & XkbSymbolsNameMask) {
4407 tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4408 if (!tmp) {
4409 client->errorValue = bad;
4410 return BadAtom;
4411 }
4412 }
4413 if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
4414 return BadLength;
4415 if (stuff->which & XkbPhysSymbolsNameMask) {
4416 tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4417 if (!tmp) {
4418 client->errorValue = bad;
4419 return BadAtom;
4420 }
4421 }
4422 if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
4423 return BadLength;
4424 if (stuff->which & XkbTypesNameMask) {
4425 tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4426 if (!tmp) {
4427 client->errorValue = bad;
4428 return BadAtom;
4429 }
4430 }
4431 if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
4432 return BadLength;
4433 if (stuff->which & XkbCompatNameMask) {
4434 tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4435 if (!tmp) {
4436 client->errorValue = bad;
4437 return BadAtom;
4438 }
4439 }
4440
4441 /* start of device-dependent tests */
4442 rc = _XkbSetNamesCheck(client, dev, stuff, tmp);
4443 if (rc != Success)
4444 return rc;
4445
4446 if (stuff->deviceSpec == XkbUseCoreKbd) {
4447 DeviceIntPtr other;
4448
4449 for (other = inputInfo.devices; other; other = other->next) {
4450 if ((other != dev) && other->key && !IsMaster(other) &&
4451 GetMaster(other, MASTER_KEYBOARD) == dev) {
4452
4453 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
4454 DixManageAccess);
4455 if (rc == Success) {
4456 rc = _XkbSetNamesCheck(client, other, stuff, tmp);
4457 if (rc != Success)
4458 return rc;
4459 }
4460 }
4461 }
4462 }
4463
4464 /* everything is okay -- update names */
4465
4466 rc = _XkbSetNames(client, dev, stuff);
4467 if (rc != Success)
4468 return rc;
4469
4470 if (stuff->deviceSpec == XkbUseCoreKbd) {
4471 DeviceIntPtr other;
4472
4473 for (other = inputInfo.devices; other; other = other->next) {
4474 if ((other != dev) && other->key && !IsMaster(other) &&
4475 GetMaster(other, MASTER_KEYBOARD) == dev) {
4476
4477 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
4478 DixManageAccess);
4479 if (rc == Success)
4480 _XkbSetNames(client, other, stuff);
4481 }
4482 }
4483 }
4484
4485 /* everything is okay -- update names */
4486
4487 return Success;
4488 }
4489
4490 /***====================================================================***/
4491
4492 #include "xkbgeom.h"
4493
4494 #define XkbSizeCountedString(s) ((s)?((((2+strlen(s))+3)/4)*4):4)
4495
4496 /**
4497 * Write the zero-terminated string str into wire as a pascal string with a
4498 * 16-bit length field prefixed before the actual string.
4499 *
4500 * @param wire The destination array, usually the wire struct
4501 * @param str The source string as zero-terminated C string
4502 * @param swap If TRUE, the length field is swapped.
4503 *
4504 * @return The input string in the format <string length><string> with a
4505 * (swapped) 16 bit string length, non-zero terminated.
4506 */
4507 static char *
XkbWriteCountedString(char * wire,const char * str,Bool swap)4508 XkbWriteCountedString(char *wire, const char *str, Bool swap)
4509 {
4510 CARD16 len, *pLen, paddedLen;
4511
4512 if (!str)
4513 return wire;
4514
4515 len = strlen(str);
4516 pLen = (CARD16 *) wire;
4517 *pLen = len;
4518 if (swap) {
4519 swaps(pLen);
4520 }
4521 paddedLen = pad_to_int32(sizeof(len) + len) - sizeof(len);
4522 strncpy(&wire[sizeof(len)], str, paddedLen);
4523 wire += sizeof(len) + paddedLen;
4524 return wire;
4525 }
4526
4527 static int
XkbSizeGeomProperties(XkbGeometryPtr geom)4528 XkbSizeGeomProperties(XkbGeometryPtr geom)
4529 {
4530 register int i, size;
4531 XkbPropertyPtr prop;
4532
4533 for (size = i = 0, prop = geom->properties; i < geom->num_properties;
4534 i++, prop++) {
4535 size += XkbSizeCountedString(prop->name);
4536 size += XkbSizeCountedString(prop->value);
4537 }
4538 return size;
4539 }
4540
4541 static char *
XkbWriteGeomProperties(char * wire,XkbGeometryPtr geom,Bool swap)4542 XkbWriteGeomProperties(char *wire, XkbGeometryPtr geom, Bool swap)
4543 {
4544 register int i;
4545 register XkbPropertyPtr prop;
4546
4547 for (i = 0, prop = geom->properties; i < geom->num_properties; i++, prop++) {
4548 wire = XkbWriteCountedString(wire, prop->name, swap);
4549 wire = XkbWriteCountedString(wire, prop->value, swap);
4550 }
4551 return wire;
4552 }
4553
4554 static int
XkbSizeGeomKeyAliases(XkbGeometryPtr geom)4555 XkbSizeGeomKeyAliases(XkbGeometryPtr geom)
4556 {
4557 return geom->num_key_aliases * (2 * XkbKeyNameLength);
4558 }
4559
4560 static char *
XkbWriteGeomKeyAliases(char * wire,XkbGeometryPtr geom,Bool swap)4561 XkbWriteGeomKeyAliases(char *wire, XkbGeometryPtr geom, Bool swap)
4562 {
4563 register int sz;
4564
4565 sz = geom->num_key_aliases * (XkbKeyNameLength * 2);
4566 if (sz > 0) {
4567 memcpy(wire, (char *) geom->key_aliases, sz);
4568 wire += sz;
4569 }
4570 return wire;
4571 }
4572
4573 static int
XkbSizeGeomColors(XkbGeometryPtr geom)4574 XkbSizeGeomColors(XkbGeometryPtr geom)
4575 {
4576 register int i, size;
4577 register XkbColorPtr color;
4578
4579 for (i = size = 0, color = geom->colors; i < geom->num_colors; i++, color++) {
4580 size += XkbSizeCountedString(color->spec);
4581 }
4582 return size;
4583 }
4584
4585 static char *
XkbWriteGeomColors(char * wire,XkbGeometryPtr geom,Bool swap)4586 XkbWriteGeomColors(char *wire, XkbGeometryPtr geom, Bool swap)
4587 {
4588 register int i;
4589 register XkbColorPtr color;
4590
4591 for (i = 0, color = geom->colors; i < geom->num_colors; i++, color++) {
4592 wire = XkbWriteCountedString(wire, color->spec, swap);
4593 }
4594 return wire;
4595 }
4596
4597 static int
XkbSizeGeomShapes(XkbGeometryPtr geom)4598 XkbSizeGeomShapes(XkbGeometryPtr geom)
4599 {
4600 register int i, size;
4601 register XkbShapePtr shape;
4602
4603 for (i = size = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) {
4604 register int n;
4605 register XkbOutlinePtr ol;
4606
4607 size += SIZEOF(xkbShapeWireDesc);
4608 for (n = 0, ol = shape->outlines; n < shape->num_outlines; n++, ol++) {
4609 size += SIZEOF(xkbOutlineWireDesc);
4610 size += ol->num_points * SIZEOF(xkbPointWireDesc);
4611 }
4612 }
4613 return size;
4614 }
4615
4616 static char *
XkbWriteGeomShapes(char * wire,XkbGeometryPtr geom,Bool swap)4617 XkbWriteGeomShapes(char *wire, XkbGeometryPtr geom, Bool swap)
4618 {
4619 int i;
4620 XkbShapePtr shape;
4621 xkbShapeWireDesc *shapeWire;
4622
4623 for (i = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) {
4624 register int o;
4625 XkbOutlinePtr ol;
4626 xkbOutlineWireDesc *olWire;
4627
4628 shapeWire = (xkbShapeWireDesc *) wire;
4629 shapeWire->name = shape->name;
4630 shapeWire->nOutlines = shape->num_outlines;
4631 if (shape->primary != NULL)
4632 shapeWire->primaryNdx = XkbOutlineIndex(shape, shape->primary);
4633 else
4634 shapeWire->primaryNdx = XkbNoShape;
4635 if (shape->approx != NULL)
4636 shapeWire->approxNdx = XkbOutlineIndex(shape, shape->approx);
4637 else
4638 shapeWire->approxNdx = XkbNoShape;
4639 shapeWire->pad = 0;
4640 if (swap) {
4641 swapl(&shapeWire->name);
4642 }
4643 wire = (char *) &shapeWire[1];
4644 for (o = 0, ol = shape->outlines; o < shape->num_outlines; o++, ol++) {
4645 register int p;
4646 XkbPointPtr pt;
4647 xkbPointWireDesc *ptWire;
4648
4649 olWire = (xkbOutlineWireDesc *) wire;
4650 olWire->nPoints = ol->num_points;
4651 olWire->cornerRadius = ol->corner_radius;
4652 olWire->pad = 0;
4653 wire = (char *) &olWire[1];
4654 ptWire = (xkbPointWireDesc *) wire;
4655 for (p = 0, pt = ol->points; p < ol->num_points; p++, pt++) {
4656 ptWire[p].x = pt->x;
4657 ptWire[p].y = pt->y;
4658 if (swap) {
4659 swaps(&ptWire[p].x);
4660 swaps(&ptWire[p].y);
4661 }
4662 }
4663 wire = (char *) &ptWire[ol->num_points];
4664 }
4665 }
4666 return wire;
4667 }
4668
4669 static int
XkbSizeGeomDoodads(int num_doodads,XkbDoodadPtr doodad)4670 XkbSizeGeomDoodads(int num_doodads, XkbDoodadPtr doodad)
4671 {
4672 register int i, size;
4673
4674 for (i = size = 0; i < num_doodads; i++, doodad++) {
4675 size += SIZEOF(xkbAnyDoodadWireDesc);
4676 if (doodad->any.type == XkbTextDoodad) {
4677 size += XkbSizeCountedString(doodad->text.text);
4678 size += XkbSizeCountedString(doodad->text.font);
4679 }
4680 else if (doodad->any.type == XkbLogoDoodad) {
4681 size += XkbSizeCountedString(doodad->logo.logo_name);
4682 }
4683 }
4684 return size;
4685 }
4686
4687 static char *
XkbWriteGeomDoodads(char * wire,int num_doodads,XkbDoodadPtr doodad,Bool swap)4688 XkbWriteGeomDoodads(char *wire, int num_doodads, XkbDoodadPtr doodad, Bool swap)
4689 {
4690 register int i;
4691 xkbDoodadWireDesc *doodadWire;
4692
4693 for (i = 0; i < num_doodads; i++, doodad++) {
4694 doodadWire = (xkbDoodadWireDesc *) wire;
4695 wire = (char *) &doodadWire[1];
4696 memset(doodadWire, 0, SIZEOF(xkbDoodadWireDesc));
4697 doodadWire->any.name = doodad->any.name;
4698 doodadWire->any.type = doodad->any.type;
4699 doodadWire->any.priority = doodad->any.priority;
4700 doodadWire->any.top = doodad->any.top;
4701 doodadWire->any.left = doodad->any.left;
4702 if (swap) {
4703 swapl(&doodadWire->any.name);
4704 swaps(&doodadWire->any.top);
4705 swaps(&doodadWire->any.left);
4706 }
4707 switch (doodad->any.type) {
4708 case XkbOutlineDoodad:
4709 case XkbSolidDoodad:
4710 doodadWire->shape.angle = doodad->shape.angle;
4711 doodadWire->shape.colorNdx = doodad->shape.color_ndx;
4712 doodadWire->shape.shapeNdx = doodad->shape.shape_ndx;
4713 if (swap) {
4714 swaps(&doodadWire->shape.angle);
4715 }
4716 break;
4717 case XkbTextDoodad:
4718 doodadWire->text.angle = doodad->text.angle;
4719 doodadWire->text.width = doodad->text.width;
4720 doodadWire->text.height = doodad->text.height;
4721 doodadWire->text.colorNdx = doodad->text.color_ndx;
4722 if (swap) {
4723 swaps(&doodadWire->text.angle);
4724 swaps(&doodadWire->text.width);
4725 swaps(&doodadWire->text.height);
4726 }
4727 wire = XkbWriteCountedString(wire, doodad->text.text, swap);
4728 wire = XkbWriteCountedString(wire, doodad->text.font, swap);
4729 break;
4730 case XkbIndicatorDoodad:
4731 doodadWire->indicator.shapeNdx = doodad->indicator.shape_ndx;
4732 doodadWire->indicator.onColorNdx = doodad->indicator.on_color_ndx;
4733 doodadWire->indicator.offColorNdx = doodad->indicator.off_color_ndx;
4734 break;
4735 case XkbLogoDoodad:
4736 doodadWire->logo.angle = doodad->logo.angle;
4737 doodadWire->logo.colorNdx = doodad->logo.color_ndx;
4738 doodadWire->logo.shapeNdx = doodad->logo.shape_ndx;
4739 wire = XkbWriteCountedString(wire, doodad->logo.logo_name, swap);
4740 break;
4741 default:
4742 ErrorF("[xkb] Unknown doodad type %d in XkbWriteGeomDoodads\n",
4743 doodad->any.type);
4744 ErrorF("[xkb] Ignored\n");
4745 break;
4746 }
4747 }
4748 return wire;
4749 }
4750
4751 static char *
XkbWriteGeomOverlay(char * wire,XkbOverlayPtr ol,Bool swap)4752 XkbWriteGeomOverlay(char *wire, XkbOverlayPtr ol, Bool swap)
4753 {
4754 register int r;
4755 XkbOverlayRowPtr row;
4756 xkbOverlayWireDesc *olWire;
4757
4758 olWire = (xkbOverlayWireDesc *) wire;
4759 olWire->name = ol->name;
4760 olWire->nRows = ol->num_rows;
4761 olWire->pad1 = 0;
4762 olWire->pad2 = 0;
4763 if (swap) {
4764 swapl(&olWire->name);
4765 }
4766 wire = (char *) &olWire[1];
4767 for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) {
4768 unsigned int k;
4769 XkbOverlayKeyPtr key;
4770 xkbOverlayRowWireDesc *rowWire;
4771
4772 rowWire = (xkbOverlayRowWireDesc *) wire;
4773 rowWire->rowUnder = row->row_under;
4774 rowWire->nKeys = row->num_keys;
4775 rowWire->pad1 = 0;
4776 wire = (char *) &rowWire[1];
4777 for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
4778 xkbOverlayKeyWireDesc *keyWire;
4779
4780 keyWire = (xkbOverlayKeyWireDesc *) wire;
4781 memcpy(keyWire->over, key->over.name, XkbKeyNameLength);
4782 memcpy(keyWire->under, key->under.name, XkbKeyNameLength);
4783 wire = (char *) &keyWire[1];
4784 }
4785 }
4786 return wire;
4787 }
4788
4789 static int
XkbSizeGeomSections(XkbGeometryPtr geom)4790 XkbSizeGeomSections(XkbGeometryPtr geom)
4791 {
4792 register int i, size;
4793 XkbSectionPtr section;
4794
4795 for (i = size = 0, section = geom->sections; i < geom->num_sections;
4796 i++, section++) {
4797 size += SIZEOF(xkbSectionWireDesc);
4798 if (section->rows) {
4799 int r;
4800 XkbRowPtr row;
4801
4802 for (r = 0, row = section->rows; r < section->num_rows; row++, r++) {
4803 size += SIZEOF(xkbRowWireDesc);
4804 size += row->num_keys * SIZEOF(xkbKeyWireDesc);
4805 }
4806 }
4807 if (section->doodads)
4808 size += XkbSizeGeomDoodads(section->num_doodads, section->doodads);
4809 if (section->overlays) {
4810 int o;
4811 XkbOverlayPtr ol;
4812
4813 for (o = 0, ol = section->overlays; o < section->num_overlays;
4814 o++, ol++) {
4815 int r;
4816 XkbOverlayRowPtr row;
4817
4818 size += SIZEOF(xkbOverlayWireDesc);
4819 for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) {
4820 size += SIZEOF(xkbOverlayRowWireDesc);
4821 size += row->num_keys * SIZEOF(xkbOverlayKeyWireDesc);
4822 }
4823 }
4824 }
4825 }
4826 return size;
4827 }
4828
4829 static char *
XkbWriteGeomSections(char * wire,XkbGeometryPtr geom,Bool swap)4830 XkbWriteGeomSections(char *wire, XkbGeometryPtr geom, Bool swap)
4831 {
4832 register int i;
4833 XkbSectionPtr section;
4834 xkbSectionWireDesc *sectionWire;
4835
4836 for (i = 0, section = geom->sections; i < geom->num_sections;
4837 i++, section++) {
4838 sectionWire = (xkbSectionWireDesc *) wire;
4839 sectionWire->name = section->name;
4840 sectionWire->top = section->top;
4841 sectionWire->left = section->left;
4842 sectionWire->width = section->width;
4843 sectionWire->height = section->height;
4844 sectionWire->angle = section->angle;
4845 sectionWire->priority = section->priority;
4846 sectionWire->nRows = section->num_rows;
4847 sectionWire->nDoodads = section->num_doodads;
4848 sectionWire->nOverlays = section->num_overlays;
4849 sectionWire->pad = 0;
4850 if (swap) {
4851 swapl(§ionWire->name);
4852 swaps(§ionWire->top);
4853 swaps(§ionWire->left);
4854 swaps(§ionWire->width);
4855 swaps(§ionWire->height);
4856 swaps(§ionWire->angle);
4857 }
4858 wire = (char *) §ionWire[1];
4859 if (section->rows) {
4860 int r;
4861 XkbRowPtr row;
4862 xkbRowWireDesc *rowWire;
4863
4864 for (r = 0, row = section->rows; r < section->num_rows; r++, row++) {
4865 rowWire = (xkbRowWireDesc *) wire;
4866 rowWire->top = row->top;
4867 rowWire->left = row->left;
4868 rowWire->nKeys = row->num_keys;
4869 rowWire->vertical = row->vertical;
4870 rowWire->pad = 0;
4871 if (swap) {
4872 swaps(&rowWire->top);
4873 swaps(&rowWire->left);
4874 }
4875 wire = (char *) &rowWire[1];
4876 if (row->keys) {
4877 int k;
4878 XkbKeyPtr key;
4879 xkbKeyWireDesc *keyWire;
4880
4881 keyWire = (xkbKeyWireDesc *) wire;
4882 for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
4883 memcpy(keyWire[k].name, key->name.name,
4884 XkbKeyNameLength);
4885 keyWire[k].gap = key->gap;
4886 keyWire[k].shapeNdx = key->shape_ndx;
4887 keyWire[k].colorNdx = key->color_ndx;
4888 if (swap) {
4889 swaps(&keyWire[k].gap);
4890 }
4891 }
4892 wire = (char *) &keyWire[row->num_keys];
4893 }
4894 }
4895 }
4896 if (section->doodads) {
4897 wire = XkbWriteGeomDoodads(wire,
4898 section->num_doodads, section->doodads,
4899 swap);
4900 }
4901 if (section->overlays) {
4902 register int o;
4903
4904 for (o = 0; o < section->num_overlays; o++) {
4905 wire = XkbWriteGeomOverlay(wire, §ion->overlays[o], swap);
4906 }
4907 }
4908 }
4909 return wire;
4910 }
4911
4912 static Status
XkbComputeGetGeometryReplySize(XkbGeometryPtr geom,xkbGetGeometryReply * rep,Atom name)4913 XkbComputeGetGeometryReplySize(XkbGeometryPtr geom,
4914 xkbGetGeometryReply * rep, Atom name)
4915 {
4916 int len;
4917
4918 if (geom != NULL) {
4919 len = XkbSizeCountedString(geom->label_font);
4920 len += XkbSizeGeomProperties(geom);
4921 len += XkbSizeGeomColors(geom);
4922 len += XkbSizeGeomShapes(geom);
4923 len += XkbSizeGeomSections(geom);
4924 len += XkbSizeGeomDoodads(geom->num_doodads, geom->doodads);
4925 len += XkbSizeGeomKeyAliases(geom);
4926 rep->length = len / 4;
4927 rep->found = TRUE;
4928 rep->name = geom->name;
4929 rep->widthMM = geom->width_mm;
4930 rep->heightMM = geom->height_mm;
4931 rep->nProperties = geom->num_properties;
4932 rep->nColors = geom->num_colors;
4933 rep->nShapes = geom->num_shapes;
4934 rep->nSections = geom->num_sections;
4935 rep->nDoodads = geom->num_doodads;
4936 rep->nKeyAliases = geom->num_key_aliases;
4937 rep->baseColorNdx = XkbGeomColorIndex(geom, geom->base_color);
4938 rep->labelColorNdx = XkbGeomColorIndex(geom, geom->label_color);
4939 }
4940 else {
4941 rep->length = 0;
4942 rep->found = FALSE;
4943 rep->name = name;
4944 rep->widthMM = rep->heightMM = 0;
4945 rep->nProperties = rep->nColors = rep->nShapes = 0;
4946 rep->nSections = rep->nDoodads = 0;
4947 rep->nKeyAliases = 0;
4948 rep->labelColorNdx = rep->baseColorNdx = 0;
4949 }
4950 return Success;
4951 }
4952 static int
XkbSendGeometry(ClientPtr client,XkbGeometryPtr geom,xkbGetGeometryReply * rep,Bool freeGeom)4953 XkbSendGeometry(ClientPtr client,
4954 XkbGeometryPtr geom, xkbGetGeometryReply * rep, Bool freeGeom)
4955 {
4956 char *desc, *start;
4957 int len;
4958
4959 if (geom != NULL) {
4960 start = desc = xallocarray(rep->length, 4);
4961 if (!start)
4962 return BadAlloc;
4963 len = rep->length * 4;
4964 desc = XkbWriteCountedString(desc, geom->label_font, client->swapped);
4965 if (rep->nProperties > 0)
4966 desc = XkbWriteGeomProperties(desc, geom, client->swapped);
4967 if (rep->nColors > 0)
4968 desc = XkbWriteGeomColors(desc, geom, client->swapped);
4969 if (rep->nShapes > 0)
4970 desc = XkbWriteGeomShapes(desc, geom, client->swapped);
4971 if (rep->nSections > 0)
4972 desc = XkbWriteGeomSections(desc, geom, client->swapped);
4973 if (rep->nDoodads > 0)
4974 desc = XkbWriteGeomDoodads(desc, geom->num_doodads, geom->doodads,
4975 client->swapped);
4976 if (rep->nKeyAliases > 0)
4977 desc = XkbWriteGeomKeyAliases(desc, geom, client->swapped);
4978 if ((desc - start) != (len)) {
4979 ErrorF
4980 ("[xkb] BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n",
4981 len, (unsigned long) (desc - start));
4982 }
4983 }
4984 else {
4985 len = 0;
4986 start = NULL;
4987 }
4988 if (client->swapped) {
4989 swaps(&rep->sequenceNumber);
4990 swapl(&rep->length);
4991 swapl(&rep->name);
4992 swaps(&rep->widthMM);
4993 swaps(&rep->heightMM);
4994 swaps(&rep->nProperties);
4995 swaps(&rep->nColors);
4996 swaps(&rep->nShapes);
4997 swaps(&rep->nSections);
4998 swaps(&rep->nDoodads);
4999 swaps(&rep->nKeyAliases);
5000 }
5001 WriteToClient(client, SIZEOF(xkbGetGeometryReply), rep);
5002 if (len > 0)
5003 WriteToClient(client, len, start);
5004 if (start != NULL)
5005 free((char *) start);
5006 if (freeGeom)
5007 XkbFreeGeometry(geom, XkbGeomAllMask, TRUE);
5008 return Success;
5009 }
5010
5011 int
ProcXkbGetGeometry(ClientPtr client)5012 ProcXkbGetGeometry(ClientPtr client)
5013 {
5014 DeviceIntPtr dev;
5015 xkbGetGeometryReply rep;
5016 XkbGeometryPtr geom;
5017 Bool shouldFree;
5018 Status status;
5019
5020 REQUEST(xkbGetGeometryReq);
5021 REQUEST_SIZE_MATCH(xkbGetGeometryReq);
5022
5023 if (!(client->xkbClientFlags & _XkbClientInitialized))
5024 return BadAccess;
5025
5026 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
5027 CHK_ATOM_OR_NONE(stuff->name);
5028
5029 geom = XkbLookupNamedGeometry(dev, stuff->name, &shouldFree);
5030 rep = (xkbGetGeometryReply) {
5031 .type = X_Reply,
5032 .deviceID = dev->id,
5033 .sequenceNumber = client->sequence,
5034 .length = 0
5035 };
5036 status = XkbComputeGetGeometryReplySize(geom, &rep, stuff->name);
5037 if (status != Success)
5038 return status;
5039 else
5040 return XkbSendGeometry(client, geom, &rep, shouldFree);
5041 }
5042
5043 /***====================================================================***/
5044
5045 static Status
_GetCountedString(char ** wire_inout,ClientPtr client,char ** str)5046 _GetCountedString(char **wire_inout, ClientPtr client, char **str)
5047 {
5048 char *wire, *next;
5049 CARD16 len;
5050
5051 wire = *wire_inout;
5052 len = *(CARD16 *) wire;
5053 if (client->swapped) {
5054 swaps(&len);
5055 }
5056 next = wire + XkbPaddedSize(len + 2);
5057 /* Check we're still within the size of the request */
5058 if (client->req_len <
5059 bytes_to_int32(next - (char *) client->requestBuffer))
5060 return BadValue;
5061 *str = malloc(len + 1);
5062 if (!*str)
5063 return BadAlloc;
5064 memcpy(*str, &wire[2], len);
5065 *(*str + len) = '\0';
5066 *wire_inout = next;
5067 return Success;
5068 }
5069
5070 static Status
_CheckSetDoodad(char ** wire_inout,XkbGeometryPtr geom,XkbSectionPtr section,ClientPtr client)5071 _CheckSetDoodad(char **wire_inout,
5072 XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client)
5073 {
5074 char *wire;
5075 xkbDoodadWireDesc *dWire;
5076 xkbAnyDoodadWireDesc any;
5077 xkbTextDoodadWireDesc text;
5078 XkbDoodadPtr doodad;
5079 Status status;
5080
5081 dWire = (xkbDoodadWireDesc *) (*wire_inout);
5082 any = dWire->any;
5083 wire = (char *) &dWire[1];
5084 if (client->swapped) {
5085 swapl(&any.name);
5086 swaps(&any.top);
5087 swaps(&any.left);
5088 swaps(&any.angle);
5089 }
5090 CHK_ATOM_ONLY(dWire->any.name);
5091 doodad = XkbAddGeomDoodad(geom, section, any.name);
5092 if (!doodad)
5093 return BadAlloc;
5094 doodad->any.type = dWire->any.type;
5095 doodad->any.priority = dWire->any.priority;
5096 doodad->any.top = any.top;
5097 doodad->any.left = any.left;
5098 doodad->any.angle = any.angle;
5099 switch (doodad->any.type) {
5100 case XkbOutlineDoodad:
5101 case XkbSolidDoodad:
5102 if (dWire->shape.colorNdx >= geom->num_colors) {
5103 client->errorValue = _XkbErrCode3(0x40, geom->num_colors,
5104 dWire->shape.colorNdx);
5105 return BadMatch;
5106 }
5107 if (dWire->shape.shapeNdx >= geom->num_shapes) {
5108 client->errorValue = _XkbErrCode3(0x41, geom->num_shapes,
5109 dWire->shape.shapeNdx);
5110 return BadMatch;
5111 }
5112 doodad->shape.color_ndx = dWire->shape.colorNdx;
5113 doodad->shape.shape_ndx = dWire->shape.shapeNdx;
5114 break;
5115 case XkbTextDoodad:
5116 if (dWire->text.colorNdx >= geom->num_colors) {
5117 client->errorValue = _XkbErrCode3(0x42, geom->num_colors,
5118 dWire->text.colorNdx);
5119 return BadMatch;
5120 }
5121 text = dWire->text;
5122 if (client->swapped) {
5123 swaps(&text.width);
5124 swaps(&text.height);
5125 }
5126 doodad->text.width = text.width;
5127 doodad->text.height = text.height;
5128 doodad->text.color_ndx = dWire->text.colorNdx;
5129 status = _GetCountedString(&wire, client, &doodad->text.text);
5130 if (status != Success)
5131 return status;
5132 status = _GetCountedString(&wire, client, &doodad->text.font);
5133 if (status != Success) {
5134 free (doodad->text.text);
5135 return status;
5136 }
5137 break;
5138 case XkbIndicatorDoodad:
5139 if (dWire->indicator.onColorNdx >= geom->num_colors) {
5140 client->errorValue = _XkbErrCode3(0x43, geom->num_colors,
5141 dWire->indicator.onColorNdx);
5142 return BadMatch;
5143 }
5144 if (dWire->indicator.offColorNdx >= geom->num_colors) {
5145 client->errorValue = _XkbErrCode3(0x44, geom->num_colors,
5146 dWire->indicator.offColorNdx);
5147 return BadMatch;
5148 }
5149 if (dWire->indicator.shapeNdx >= geom->num_shapes) {
5150 client->errorValue = _XkbErrCode3(0x45, geom->num_shapes,
5151 dWire->indicator.shapeNdx);
5152 return BadMatch;
5153 }
5154 doodad->indicator.shape_ndx = dWire->indicator.shapeNdx;
5155 doodad->indicator.on_color_ndx = dWire->indicator.onColorNdx;
5156 doodad->indicator.off_color_ndx = dWire->indicator.offColorNdx;
5157 break;
5158 case XkbLogoDoodad:
5159 if (dWire->logo.colorNdx >= geom->num_colors) {
5160 client->errorValue = _XkbErrCode3(0x46, geom->num_colors,
5161 dWire->logo.colorNdx);
5162 return BadMatch;
5163 }
5164 if (dWire->logo.shapeNdx >= geom->num_shapes) {
5165 client->errorValue = _XkbErrCode3(0x47, geom->num_shapes,
5166 dWire->logo.shapeNdx);
5167 return BadMatch;
5168 }
5169 doodad->logo.color_ndx = dWire->logo.colorNdx;
5170 doodad->logo.shape_ndx = dWire->logo.shapeNdx;
5171 status = _GetCountedString(&wire, client, &doodad->logo.logo_name);
5172 if (status != Success)
5173 return status;
5174 break;
5175 default:
5176 client->errorValue = _XkbErrCode2(0x4F, dWire->any.type);
5177 return BadValue;
5178 }
5179 *wire_inout = wire;
5180 return Success;
5181 }
5182
5183 static Status
_CheckSetOverlay(char ** wire_inout,XkbGeometryPtr geom,XkbSectionPtr section,ClientPtr client)5184 _CheckSetOverlay(char **wire_inout,
5185 XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client)
5186 {
5187 register int r;
5188 char *wire;
5189 XkbOverlayPtr ol;
5190 xkbOverlayWireDesc *olWire;
5191 xkbOverlayRowWireDesc *rWire;
5192
5193 wire = *wire_inout;
5194 olWire = (xkbOverlayWireDesc *) wire;
5195 if (client->swapped) {
5196 swapl(&olWire->name);
5197 }
5198 CHK_ATOM_ONLY(olWire->name);
5199 ol = XkbAddGeomOverlay(section, olWire->name, olWire->nRows);
5200 rWire = (xkbOverlayRowWireDesc *) &olWire[1];
5201 for (r = 0; r < olWire->nRows; r++) {
5202 register int k;
5203 xkbOverlayKeyWireDesc *kWire;
5204 XkbOverlayRowPtr row;
5205
5206 if (rWire->rowUnder > section->num_rows) {
5207 client->errorValue = _XkbErrCode4(0x20, r, section->num_rows,
5208 rWire->rowUnder);
5209 return BadMatch;
5210 }
5211 row = XkbAddGeomOverlayRow(ol, rWire->rowUnder, rWire->nKeys);
5212 kWire = (xkbOverlayKeyWireDesc *) &rWire[1];
5213 for (k = 0; k < rWire->nKeys; k++, kWire++) {
5214 if (XkbAddGeomOverlayKey(ol, row,
5215 (char *) kWire->over,
5216 (char *) kWire->under) == NULL) {
5217 client->errorValue = _XkbErrCode3(0x21, r, k);
5218 return BadMatch;
5219 }
5220 }
5221 rWire = (xkbOverlayRowWireDesc *) kWire;
5222 }
5223 olWire = (xkbOverlayWireDesc *) rWire;
5224 wire = (char *) olWire;
5225 *wire_inout = wire;
5226 return Success;
5227 }
5228
5229 static Status
_CheckSetSections(XkbGeometryPtr geom,xkbSetGeometryReq * req,char ** wire_inout,ClientPtr client)5230 _CheckSetSections(XkbGeometryPtr geom,
5231 xkbSetGeometryReq * req, char **wire_inout, ClientPtr client)
5232 {
5233 Status status;
5234 register int s;
5235 char *wire;
5236 xkbSectionWireDesc *sWire;
5237 XkbSectionPtr section;
5238
5239 wire = *wire_inout;
5240 if (req->nSections < 1)
5241 return Success;
5242 sWire = (xkbSectionWireDesc *) wire;
5243 for (s = 0; s < req->nSections; s++) {
5244 register int r;
5245 xkbRowWireDesc *rWire;
5246
5247 if (client->swapped) {
5248 swapl(&sWire->name);
5249 swaps(&sWire->top);
5250 swaps(&sWire->left);
5251 swaps(&sWire->width);
5252 swaps(&sWire->height);
5253 swaps(&sWire->angle);
5254 }
5255 CHK_ATOM_ONLY(sWire->name);
5256 section = XkbAddGeomSection(geom, sWire->name, sWire->nRows,
5257 sWire->nDoodads, sWire->nOverlays);
5258 if (!section)
5259 return BadAlloc;
5260 section->priority = sWire->priority;
5261 section->top = sWire->top;
5262 section->left = sWire->left;
5263 section->width = sWire->width;
5264 section->height = sWire->height;
5265 section->angle = sWire->angle;
5266 rWire = (xkbRowWireDesc *) &sWire[1];
5267 for (r = 0; r < sWire->nRows; r++) {
5268 register int k;
5269 XkbRowPtr row;
5270 xkbKeyWireDesc *kWire;
5271
5272 if (client->swapped) {
5273 swaps(&rWire->top);
5274 swaps(&rWire->left);
5275 }
5276 row = XkbAddGeomRow(section, rWire->nKeys);
5277 if (!row)
5278 return BadAlloc;
5279 row->top = rWire->top;
5280 row->left = rWire->left;
5281 row->vertical = rWire->vertical;
5282 kWire = (xkbKeyWireDesc *) &rWire[1];
5283 for (k = 0; k < rWire->nKeys; k++) {
5284 XkbKeyPtr key;
5285
5286 key = XkbAddGeomKey(row);
5287 if (!key)
5288 return BadAlloc;
5289 memcpy(key->name.name, kWire[k].name, XkbKeyNameLength);
5290 key->gap = kWire[k].gap;
5291 key->shape_ndx = kWire[k].shapeNdx;
5292 key->color_ndx = kWire[k].colorNdx;
5293 if (key->shape_ndx >= geom->num_shapes) {
5294 client->errorValue = _XkbErrCode3(0x10, key->shape_ndx,
5295 geom->num_shapes);
5296 return BadMatch;
5297 }
5298 if (key->color_ndx >= geom->num_colors) {
5299 client->errorValue = _XkbErrCode3(0x11, key->color_ndx,
5300 geom->num_colors);
5301 return BadMatch;
5302 }
5303 }
5304 rWire = (xkbRowWireDesc *) &kWire[rWire->nKeys];
5305 }
5306 wire = (char *) rWire;
5307 if (sWire->nDoodads > 0) {
5308 register int d;
5309
5310 for (d = 0; d < sWire->nDoodads; d++) {
5311 status = _CheckSetDoodad(&wire, geom, section, client);
5312 if (status != Success)
5313 return status;
5314 }
5315 }
5316 if (sWire->nOverlays > 0) {
5317 register int o;
5318
5319 for (o = 0; o < sWire->nOverlays; o++) {
5320 status = _CheckSetOverlay(&wire, geom, section, client);
5321 if (status != Success)
5322 return status;
5323 }
5324 }
5325 sWire = (xkbSectionWireDesc *) wire;
5326 }
5327 wire = (char *) sWire;
5328 *wire_inout = wire;
5329 return Success;
5330 }
5331
5332 static Status
_CheckSetShapes(XkbGeometryPtr geom,xkbSetGeometryReq * req,char ** wire_inout,ClientPtr client)5333 _CheckSetShapes(XkbGeometryPtr geom,
5334 xkbSetGeometryReq * req, char **wire_inout, ClientPtr client)
5335 {
5336 register int i;
5337 char *wire;
5338
5339 wire = *wire_inout;
5340 if (req->nShapes < 1) {
5341 client->errorValue = _XkbErrCode2(0x06, req->nShapes);
5342 return BadValue;
5343 }
5344 else {
5345 xkbShapeWireDesc *shapeWire;
5346 XkbShapePtr shape;
5347 register int o;
5348
5349 shapeWire = (xkbShapeWireDesc *) wire;
5350 for (i = 0; i < req->nShapes; i++) {
5351 xkbOutlineWireDesc *olWire;
5352 XkbOutlinePtr ol;
5353
5354 shape =
5355 XkbAddGeomShape(geom, shapeWire->name, shapeWire->nOutlines);
5356 if (!shape)
5357 return BadAlloc;
5358 olWire = (xkbOutlineWireDesc *) (&shapeWire[1]);
5359 for (o = 0; o < shapeWire->nOutlines; o++) {
5360 register int p;
5361 XkbPointPtr pt;
5362 xkbPointWireDesc *ptWire;
5363
5364 ol = XkbAddGeomOutline(shape, olWire->nPoints);
5365 if (!ol)
5366 return BadAlloc;
5367 ol->corner_radius = olWire->cornerRadius;
5368 ptWire = (xkbPointWireDesc *) &olWire[1];
5369 for (p = 0, pt = ol->points; p < olWire->nPoints; p++, pt++) {
5370 pt->x = ptWire[p].x;
5371 pt->y = ptWire[p].y;
5372 if (client->swapped) {
5373 swaps(&pt->x);
5374 swaps(&pt->y);
5375 }
5376 }
5377 ol->num_points = olWire->nPoints;
5378 olWire = (xkbOutlineWireDesc *) (&ptWire[olWire->nPoints]);
5379 }
5380 if (shapeWire->primaryNdx != XkbNoShape)
5381 shape->primary = &shape->outlines[shapeWire->primaryNdx];
5382 if (shapeWire->approxNdx != XkbNoShape)
5383 shape->approx = &shape->outlines[shapeWire->approxNdx];
5384 shapeWire = (xkbShapeWireDesc *) olWire;
5385 }
5386 wire = (char *) shapeWire;
5387 }
5388 if (geom->num_shapes != req->nShapes) {
5389 client->errorValue = _XkbErrCode3(0x07, geom->num_shapes, req->nShapes);
5390 return BadMatch;
5391 }
5392
5393 *wire_inout = wire;
5394 return Success;
5395 }
5396
5397 static Status
_CheckSetGeom(XkbGeometryPtr geom,xkbSetGeometryReq * req,ClientPtr client)5398 _CheckSetGeom(XkbGeometryPtr geom, xkbSetGeometryReq * req, ClientPtr client)
5399 {
5400 register int i;
5401 Status status;
5402 char *wire;
5403
5404 wire = (char *) &req[1];
5405 status = _GetCountedString(&wire, client, &geom->label_font);
5406 if (status != Success)
5407 return status;
5408
5409 for (i = 0; i < req->nProperties; i++) {
5410 char *name, *val;
5411
5412 status = _GetCountedString(&wire, client, &name);
5413 if (status != Success)
5414 return status;
5415 status = _GetCountedString(&wire, client, &val);
5416 if (status != Success) {
5417 free(name);
5418 return status;
5419 }
5420 if (XkbAddGeomProperty(geom, name, val) == NULL) {
5421 free(name);
5422 free(val);
5423 return BadAlloc;
5424 }
5425 free(name);
5426 free(val);
5427 }
5428
5429 if (req->nColors < 2) {
5430 client->errorValue = _XkbErrCode3(0x01, 2, req->nColors);
5431 return BadValue;
5432 }
5433 if (req->baseColorNdx > req->nColors) {
5434 client->errorValue =
5435 _XkbErrCode3(0x03, req->nColors, req->baseColorNdx);
5436 return BadMatch;
5437 }
5438 if (req->labelColorNdx > req->nColors) {
5439 client->errorValue =
5440 _XkbErrCode3(0x03, req->nColors, req->labelColorNdx);
5441 return BadMatch;
5442 }
5443 if (req->labelColorNdx == req->baseColorNdx) {
5444 client->errorValue = _XkbErrCode3(0x04, req->baseColorNdx,
5445 req->labelColorNdx);
5446 return BadMatch;
5447 }
5448
5449 for (i = 0; i < req->nColors; i++) {
5450 char *name;
5451
5452 status = _GetCountedString(&wire, client, &name);
5453 if (status != Success)
5454 return status;
5455 if (!XkbAddGeomColor(geom, name, geom->num_colors)) {
5456 free(name);
5457 return BadAlloc;
5458 }
5459 free(name);
5460 }
5461 if (req->nColors != geom->num_colors) {
5462 client->errorValue = _XkbErrCode3(0x05, req->nColors, geom->num_colors);
5463 return BadMatch;
5464 }
5465 geom->label_color = &geom->colors[req->labelColorNdx];
5466 geom->base_color = &geom->colors[req->baseColorNdx];
5467
5468 if ((status = _CheckSetShapes(geom, req, &wire, client)) != Success)
5469 return status;
5470
5471 if ((status = _CheckSetSections(geom, req, &wire, client)) != Success)
5472 return status;
5473
5474 for (i = 0; i < req->nDoodads; i++) {
5475 status = _CheckSetDoodad(&wire, geom, NULL, client);
5476 if (status != Success)
5477 return status;
5478 }
5479
5480 for (i = 0; i < req->nKeyAliases; i++) {
5481 if (XkbAddGeomKeyAlias(geom, &wire[XkbKeyNameLength], wire) == NULL)
5482 return BadAlloc;
5483 wire += 2 * XkbKeyNameLength;
5484 }
5485 return Success;
5486 }
5487
5488 static int
_XkbSetGeometry(ClientPtr client,DeviceIntPtr dev,xkbSetGeometryReq * stuff)5489 _XkbSetGeometry(ClientPtr client, DeviceIntPtr dev, xkbSetGeometryReq * stuff)
5490 {
5491 XkbDescPtr xkb;
5492 Bool new_name;
5493 xkbNewKeyboardNotify nkn;
5494 XkbGeometryPtr geom, old;
5495 XkbGeometrySizesRec sizes;
5496 Status status;
5497
5498 xkb = dev->key->xkbInfo->desc;
5499 old = xkb->geom;
5500 xkb->geom = NULL;
5501
5502 sizes.which = XkbGeomAllMask;
5503 sizes.num_properties = stuff->nProperties;
5504 sizes.num_colors = stuff->nColors;
5505 sizes.num_shapes = stuff->nShapes;
5506 sizes.num_sections = stuff->nSections;
5507 sizes.num_doodads = stuff->nDoodads;
5508 sizes.num_key_aliases = stuff->nKeyAliases;
5509 if ((status = XkbAllocGeometry(xkb, &sizes)) != Success) {
5510 xkb->geom = old;
5511 return status;
5512 }
5513 geom = xkb->geom;
5514 geom->name = stuff->name;
5515 geom->width_mm = stuff->widthMM;
5516 geom->height_mm = stuff->heightMM;
5517 if ((status = _CheckSetGeom(geom, stuff, client)) != Success) {
5518 XkbFreeGeometry(geom, XkbGeomAllMask, TRUE);
5519 xkb->geom = old;
5520 return status;
5521 }
5522 new_name = (xkb->names->geometry != geom->name);
5523 xkb->names->geometry = geom->name;
5524 if (old)
5525 XkbFreeGeometry(old, XkbGeomAllMask, TRUE);
5526 if (new_name) {
5527 xkbNamesNotify nn;
5528
5529 memset(&nn, 0, sizeof(xkbNamesNotify));
5530 nn.changed = XkbGeometryNameMask;
5531 XkbSendNamesNotify(dev, &nn);
5532 }
5533 nkn.deviceID = nkn.oldDeviceID = dev->id;
5534 nkn.minKeyCode = nkn.oldMinKeyCode = xkb->min_key_code;
5535 nkn.maxKeyCode = nkn.oldMaxKeyCode = xkb->max_key_code;
5536 nkn.requestMajor = XkbReqCode;
5537 nkn.requestMinor = X_kbSetGeometry;
5538 nkn.changed = XkbNKN_GeometryMask;
5539 XkbSendNewKeyboardNotify(dev, &nkn);
5540 return Success;
5541 }
5542
5543 int
ProcXkbSetGeometry(ClientPtr client)5544 ProcXkbSetGeometry(ClientPtr client)
5545 {
5546 DeviceIntPtr dev;
5547 int rc;
5548
5549 REQUEST(xkbSetGeometryReq);
5550 REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq);
5551
5552 if (!(client->xkbClientFlags & _XkbClientInitialized))
5553 return BadAccess;
5554
5555 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
5556 CHK_ATOM_OR_NONE(stuff->name);
5557
5558 rc = _XkbSetGeometry(client, dev, stuff);
5559 if (rc != Success)
5560 return rc;
5561
5562 if (stuff->deviceSpec == XkbUseCoreKbd) {
5563 DeviceIntPtr other;
5564
5565 for (other = inputInfo.devices; other; other = other->next) {
5566 if ((other != dev) && other->key && !IsMaster(other) &&
5567 GetMaster(other, MASTER_KEYBOARD) == dev) {
5568 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
5569 DixManageAccess);
5570 if (rc == Success)
5571 _XkbSetGeometry(client, other, stuff);
5572 }
5573 }
5574 }
5575
5576 return Success;
5577 }
5578
5579 /***====================================================================***/
5580
5581 int
ProcXkbPerClientFlags(ClientPtr client)5582 ProcXkbPerClientFlags(ClientPtr client)
5583 {
5584 DeviceIntPtr dev;
5585 xkbPerClientFlagsReply rep;
5586 XkbInterestPtr interest;
5587 Mask access_mode = DixGetAttrAccess | DixSetAttrAccess;
5588
5589 REQUEST(xkbPerClientFlagsReq);
5590 REQUEST_SIZE_MATCH(xkbPerClientFlagsReq);
5591
5592 if (!(client->xkbClientFlags & _XkbClientInitialized))
5593 return BadAccess;
5594
5595 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
5596 CHK_MASK_LEGAL(0x01, stuff->change, XkbPCF_AllFlagsMask);
5597 CHK_MASK_MATCH(0x02, stuff->change, stuff->value);
5598
5599 interest = XkbFindClientResource((DevicePtr) dev, client);
5600 if (stuff->change) {
5601 client->xkbClientFlags &= ~stuff->change;
5602 client->xkbClientFlags |= stuff->value;
5603 }
5604 if (stuff->change & XkbPCF_AutoResetControlsMask) {
5605 Bool want;
5606
5607 want = stuff->value & XkbPCF_AutoResetControlsMask;
5608 if (interest && !want) {
5609 interest->autoCtrls = interest->autoCtrlValues = 0;
5610 }
5611 else if (want && (!interest)) {
5612 XID id = FakeClientID(client->index);
5613
5614 if (!AddResource(id, RT_XKBCLIENT, dev))
5615 return BadAlloc;
5616 interest = XkbAddClientResource((DevicePtr) dev, client, id);
5617 if (!interest)
5618 return BadAlloc;
5619 }
5620 if (interest && want) {
5621 register unsigned affect;
5622
5623 affect = stuff->ctrlsToChange;
5624
5625 CHK_MASK_LEGAL(0x03, affect, XkbAllBooleanCtrlsMask);
5626 CHK_MASK_MATCH(0x04, affect, stuff->autoCtrls);
5627 CHK_MASK_MATCH(0x05, stuff->autoCtrls, stuff->autoCtrlValues);
5628
5629 interest->autoCtrls &= ~affect;
5630 interest->autoCtrlValues &= ~affect;
5631 interest->autoCtrls |= stuff->autoCtrls & affect;
5632 interest->autoCtrlValues |= stuff->autoCtrlValues & affect;
5633 }
5634 }
5635
5636 rep = (xkbPerClientFlagsReply) {
5637 .type = X_Reply,
5638 .sequenceNumber = client->sequence,
5639 .length = 0,
5640 .supported = XkbPCF_AllFlagsMask,
5641 .value = client->xkbClientFlags & XkbPCF_AllFlagsMask,
5642 .autoCtrls = interest ? interest->autoCtrls : 0,
5643 .autoCtrlValues = interest ? interest->autoCtrlValues : 0,
5644 };
5645 if (client->swapped) {
5646 swaps(&rep.sequenceNumber);
5647 swapl(&rep.supported);
5648 swapl(&rep.value);
5649 swapl(&rep.autoCtrls);
5650 swapl(&rep.autoCtrlValues);
5651 }
5652 WriteToClient(client, SIZEOF(xkbPerClientFlagsReply), &rep);
5653 return Success;
5654 }
5655
5656 /***====================================================================***/
5657
5658 /* all latin-1 alphanumerics, plus parens, minus, underscore, slash */
5659 /* and wildcards */
5660 static unsigned char componentSpecLegal[] = {
5661 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x87,
5662 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07,
5663 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5664 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
5665 };
5666
5667 /* same as above but accepts percent, plus and bar too */
5668 static unsigned char componentExprLegal[] = {
5669 0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0xff, 0x87,
5670 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x17,
5671 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5672 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
5673 };
5674
5675 static char *
GetComponentSpec(unsigned char ** pWire,Bool allowExpr,int * errRtrn)5676 GetComponentSpec(unsigned char **pWire, Bool allowExpr, int *errRtrn)
5677 {
5678 int len;
5679 register int i;
5680 unsigned char *wire, *str, *tmp, *legal;
5681
5682 if (allowExpr)
5683 legal = &componentExprLegal[0];
5684 else
5685 legal = &componentSpecLegal[0];
5686
5687 wire = *pWire;
5688 len = (*(unsigned char *) wire++);
5689 if (len > 0) {
5690 str = calloc(1, len + 1);
5691 if (str) {
5692 tmp = str;
5693 for (i = 0; i < len; i++) {
5694 if (legal[(*wire) / 8] & (1 << ((*wire) % 8)))
5695 *tmp++ = *wire++;
5696 else
5697 wire++;
5698 }
5699 if (tmp != str)
5700 *tmp++ = '\0';
5701 else {
5702 free(str);
5703 str = NULL;
5704 }
5705 }
5706 else {
5707 *errRtrn = BadAlloc;
5708 }
5709 }
5710 else {
5711 str = NULL;
5712 }
5713 *pWire = wire;
5714 return (char *) str;
5715 }
5716
5717 /***====================================================================***/
5718
5719 int
ProcXkbListComponents(ClientPtr client)5720 ProcXkbListComponents(ClientPtr client)
5721 {
5722 DeviceIntPtr dev;
5723 xkbListComponentsReply rep;
5724 unsigned len;
5725 unsigned char *str;
5726 uint8_t size;
5727 int i;
5728
5729 REQUEST(xkbListComponentsReq);
5730 REQUEST_AT_LEAST_SIZE(xkbListComponentsReq);
5731
5732 if (!(client->xkbClientFlags & _XkbClientInitialized))
5733 return BadAccess;
5734
5735 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
5736
5737 /* The request is followed by six Pascal strings (i.e. size in characters
5738 * followed by a string pattern) describing what the client wants us to
5739 * list. We don't care, but might as well check they haven't got the
5740 * length wrong. */
5741 str = (unsigned char *) &stuff[1];
5742 for (i = 0; i < 6; i++) {
5743 size = *((uint8_t *)str);
5744 len = (str + size + 1) - ((unsigned char *) stuff);
5745 if ((XkbPaddedSize(len) / 4) > stuff->length)
5746 return BadLength;
5747 str += (size + 1);
5748 }
5749 if ((XkbPaddedSize(len) / 4) != stuff->length)
5750 return BadLength;
5751 rep = (xkbListComponentsReply) {
5752 .type = X_Reply,
5753 .deviceID = dev->id,
5754 .sequenceNumber = client->sequence,
5755 .length = 0,
5756 .nKeymaps = 0,
5757 .nKeycodes = 0,
5758 .nTypes = 0,
5759 .nCompatMaps = 0,
5760 .nSymbols = 0,
5761 .nGeometries = 0,
5762 .extra = 0
5763 };
5764 if (client->swapped) {
5765 swaps(&rep.sequenceNumber);
5766 swapl(&rep.length);
5767 swaps(&rep.nKeymaps);
5768 swaps(&rep.nKeycodes);
5769 swaps(&rep.nTypes);
5770 swaps(&rep.nCompatMaps);
5771 swaps(&rep.nSymbols);
5772 swaps(&rep.nGeometries);
5773 swaps(&rep.extra);
5774 }
5775 WriteToClient(client, SIZEOF(xkbListComponentsReply), &rep);
5776 return Success;
5777 }
5778
5779 /***====================================================================***/
5780 int
ProcXkbGetKbdByName(ClientPtr client)5781 ProcXkbGetKbdByName(ClientPtr client)
5782 {
5783 DeviceIntPtr dev;
5784 DeviceIntPtr tmpd;
5785 DeviceIntPtr master;
5786 xkbGetKbdByNameReply rep = { 0 };
5787 xkbGetMapReply mrep = { 0 };
5788 xkbGetCompatMapReply crep = { 0 };
5789 xkbGetIndicatorMapReply irep = { 0 };
5790 xkbGetNamesReply nrep = { 0 };
5791 xkbGetGeometryReply grep = { 0 };
5792 XkbComponentNamesRec names = { 0 };
5793 XkbDescPtr xkb, new;
5794 XkbEventCauseRec cause;
5795 unsigned char *str;
5796 char mapFile[PATH_MAX];
5797 unsigned len;
5798 unsigned fwant, fneed, reported;
5799 int status;
5800 Bool geom_changed;
5801 XkbSrvLedInfoPtr old_sli;
5802 XkbSrvLedInfoPtr sli;
5803 Mask access_mode = DixGetAttrAccess | DixManageAccess;
5804
5805 REQUEST(xkbGetKbdByNameReq);
5806 REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq);
5807
5808 if (!(client->xkbClientFlags & _XkbClientInitialized))
5809 return BadAccess;
5810
5811 CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
5812 master = GetMaster(dev, MASTER_KEYBOARD);
5813
5814 xkb = dev->key->xkbInfo->desc;
5815 status = Success;
5816 str = (unsigned char *) &stuff[1];
5817 if (GetComponentSpec(&str, TRUE, &status)) /* keymap, unsupported */
5818 return BadMatch;
5819 names.keycodes = GetComponentSpec(&str, TRUE, &status);
5820 names.types = GetComponentSpec(&str, TRUE, &status);
5821 names.compat = GetComponentSpec(&str, TRUE, &status);
5822 names.symbols = GetComponentSpec(&str, TRUE, &status);
5823 names.geometry = GetComponentSpec(&str, TRUE, &status);
5824 if (status != Success)
5825 return status;
5826 len = str - ((unsigned char *) stuff);
5827 if ((XkbPaddedSize(len) / 4) != stuff->length)
5828 return BadLength;
5829
5830 CHK_MASK_LEGAL(0x01, stuff->want, XkbGBN_AllComponentsMask);
5831 CHK_MASK_LEGAL(0x02, stuff->need, XkbGBN_AllComponentsMask);
5832
5833 if (stuff->load)
5834 fwant = XkbGBN_AllComponentsMask;
5835 else
5836 fwant = stuff->want | stuff->need;
5837 if ((!names.compat) &&
5838 (fwant & (XkbGBN_CompatMapMask | XkbGBN_IndicatorMapMask))) {
5839 names.compat = Xstrdup("%");
5840 }
5841 if ((!names.types) && (fwant & (XkbGBN_TypesMask))) {
5842 names.types = Xstrdup("%");
5843 }
5844 if ((!names.symbols) && (fwant & XkbGBN_SymbolsMask)) {
5845 names.symbols = Xstrdup("%");
5846 }
5847 geom_changed = ((names.geometry != NULL) &&
5848 (strcmp(names.geometry, "%") != 0));
5849 if ((!names.geometry) && (fwant & XkbGBN_GeometryMask)) {
5850 names.geometry = Xstrdup("%");
5851 geom_changed = FALSE;
5852 }
5853
5854 memset(mapFile, 0, PATH_MAX);
5855 rep.type = X_Reply;
5856 rep.deviceID = dev->id;
5857 rep.sequenceNumber = client->sequence;
5858 rep.length = 0;
5859 rep.minKeyCode = xkb->min_key_code;
5860 rep.maxKeyCode = xkb->max_key_code;
5861 rep.loaded = FALSE;
5862 fwant =
5863 XkbConvertGetByNameComponents(TRUE, stuff->want) | XkmVirtualModsMask;
5864 fneed = XkbConvertGetByNameComponents(TRUE, stuff->need);
5865 rep.reported = XkbConvertGetByNameComponents(FALSE, fwant | fneed);
5866 if (stuff->load) {
5867 fneed |= XkmKeymapRequired;
5868 fwant |= XkmKeymapLegal;
5869 }
5870 if ((fwant | fneed) & XkmSymbolsMask) {
5871 fneed |= XkmKeyNamesIndex | XkmTypesIndex;
5872 fwant |= XkmIndicatorsIndex;
5873 }
5874
5875 /* We pass dev in here so we can get the old names out if needed. */
5876 rep.found = XkbDDXLoadKeymapByNames(dev, &names, fwant, fneed, &new,
5877 mapFile, PATH_MAX);
5878 rep.newKeyboard = FALSE;
5879 rep.pad1 = rep.pad2 = rep.pad3 = rep.pad4 = 0;
5880
5881 stuff->want |= stuff->need;
5882 if (new == NULL)
5883 rep.reported = 0;
5884 else {
5885 if (stuff->load)
5886 rep.loaded = TRUE;
5887 if (stuff->load ||
5888 ((rep.reported & XkbGBN_SymbolsMask) && (new->compat))) {
5889 XkbChangesRec changes;
5890
5891 memset(&changes, 0, sizeof(changes));
5892 XkbUpdateDescActions(new,
5893 new->min_key_code, XkbNumKeys(new), &changes);
5894 }
5895
5896 if (new->map == NULL)
5897 rep.reported &= ~(XkbGBN_SymbolsMask | XkbGBN_TypesMask);
5898 else if (rep.reported & (XkbGBN_SymbolsMask | XkbGBN_TypesMask)) {
5899 mrep.type = X_Reply;
5900 mrep.deviceID = dev->id;
5901 mrep.sequenceNumber = client->sequence;
5902 mrep.length =
5903 ((SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply)) >> 2);
5904 mrep.minKeyCode = new->min_key_code;
5905 mrep.maxKeyCode = new->max_key_code;
5906 mrep.present = 0;
5907 mrep.totalSyms = mrep.totalActs =
5908 mrep.totalKeyBehaviors = mrep.totalKeyExplicit =
5909 mrep.totalModMapKeys = mrep.totalVModMapKeys = 0;
5910 if (rep.reported & (XkbGBN_TypesMask | XkbGBN_ClientSymbolsMask)) {
5911 mrep.present |= XkbKeyTypesMask;
5912 mrep.firstType = 0;
5913 mrep.nTypes = mrep.totalTypes = new->map->num_types;
5914 }
5915 else {
5916 mrep.firstType = mrep.nTypes = 0;
5917 mrep.totalTypes = 0;
5918 }
5919 if (rep.reported & XkbGBN_ClientSymbolsMask) {
5920 mrep.present |= (XkbKeySymsMask | XkbModifierMapMask);
5921 mrep.firstKeySym = mrep.firstModMapKey = new->min_key_code;
5922 mrep.nKeySyms = mrep.nModMapKeys = XkbNumKeys(new);
5923 }
5924 else {
5925 mrep.firstKeySym = mrep.firstModMapKey = 0;
5926 mrep.nKeySyms = mrep.nModMapKeys = 0;
5927 }
5928 if (rep.reported & XkbGBN_ServerSymbolsMask) {
5929 mrep.present |= XkbAllServerInfoMask;
5930 mrep.virtualMods = ~0;
5931 mrep.firstKeyAct = mrep.firstKeyBehavior =
5932 mrep.firstKeyExplicit = new->min_key_code;
5933 mrep.nKeyActs = mrep.nKeyBehaviors =
5934 mrep.nKeyExplicit = XkbNumKeys(new);
5935 mrep.firstVModMapKey = new->min_key_code;
5936 mrep.nVModMapKeys = XkbNumKeys(new);
5937 }
5938 else {
5939 mrep.virtualMods = 0;
5940 mrep.firstKeyAct = mrep.firstKeyBehavior =
5941 mrep.firstKeyExplicit = 0;
5942 mrep.nKeyActs = mrep.nKeyBehaviors = mrep.nKeyExplicit = 0;
5943 }
5944 XkbComputeGetMapReplySize(new, &mrep);
5945 rep.length += SIZEOF(xGenericReply) / 4 + mrep.length;
5946 }
5947 if (new->compat == NULL)
5948 rep.reported &= ~XkbGBN_CompatMapMask;
5949 else if (rep.reported & XkbGBN_CompatMapMask) {
5950 crep.type = X_Reply;
5951 crep.deviceID = dev->id;
5952 crep.sequenceNumber = client->sequence;
5953 crep.length = 0;
5954 crep.groups = XkbAllGroupsMask;
5955 crep.firstSI = 0;
5956 crep.nSI = crep.nTotalSI = new->compat->num_si;
5957 XkbComputeGetCompatMapReplySize(new->compat, &crep);
5958 rep.length += SIZEOF(xGenericReply) / 4 + crep.length;
5959 }
5960 if (new->indicators == NULL)
5961 rep.reported &= ~XkbGBN_IndicatorMapMask;
5962 else if (rep.reported & XkbGBN_IndicatorMapMask) {
5963 irep.type = X_Reply;
5964 irep.deviceID = dev->id;
5965 irep.sequenceNumber = client->sequence;
5966 irep.length = 0;
5967 irep.which = XkbAllIndicatorsMask;
5968 XkbComputeGetIndicatorMapReplySize(new->indicators, &irep);
5969 rep.length += SIZEOF(xGenericReply) / 4 + irep.length;
5970 }
5971 if (new->names == NULL)
5972 rep.reported &= ~(XkbGBN_OtherNamesMask | XkbGBN_KeyNamesMask);
5973 else if (rep.reported & (XkbGBN_OtherNamesMask | XkbGBN_KeyNamesMask)) {
5974 nrep.type = X_Reply;
5975 nrep.deviceID = dev->id;
5976 nrep.sequenceNumber = client->sequence;
5977 nrep.length = 0;
5978 nrep.minKeyCode = new->min_key_code;
5979 nrep.maxKeyCode = new->max_key_code;
5980 if (rep.reported & XkbGBN_OtherNamesMask) {
5981 nrep.which = XkbAllNamesMask;
5982 if (new->map != NULL)
5983 nrep.nTypes = new->map->num_types;
5984 else
5985 nrep.nTypes = 0;
5986 nrep.nKTLevels = 0;
5987 nrep.groupNames = XkbAllGroupsMask;
5988 nrep.virtualMods = XkbAllVirtualModsMask;
5989 nrep.indicators = XkbAllIndicatorsMask;
5990 nrep.nRadioGroups = new->names->num_rg;
5991 }
5992 else {
5993 nrep.which = 0;
5994 nrep.nTypes = 0;
5995 nrep.nKTLevels = 0;
5996 nrep.groupNames = 0;
5997 nrep.virtualMods = 0;
5998 nrep.indicators = 0;
5999 nrep.nRadioGroups = 0;
6000 }
6001 if (rep.reported & XkbGBN_KeyNamesMask) {
6002 nrep.which |= XkbKeyNamesMask;
6003 nrep.firstKey = new->min_key_code;
6004 nrep.nKeys = XkbNumKeys(new);
6005 nrep.nKeyAliases = new->names->num_key_aliases;
6006 if (nrep.nKeyAliases)
6007 nrep.which |= XkbKeyAliasesMask;
6008 }
6009 else {
6010 nrep.which &= ~(XkbKeyNamesMask | XkbKeyAliasesMask);
6011 nrep.firstKey = nrep.nKeys = 0;
6012 nrep.nKeyAliases = 0;
6013 }
6014 XkbComputeGetNamesReplySize(new, &nrep);
6015 rep.length += SIZEOF(xGenericReply) / 4 + nrep.length;
6016 }
6017 if (new->geom == NULL)
6018 rep.reported &= ~XkbGBN_GeometryMask;
6019 else if (rep.reported & XkbGBN_GeometryMask) {
6020 grep.type = X_Reply;
6021 grep.deviceID = dev->id;
6022 grep.sequenceNumber = client->sequence;
6023 grep.length = 0;
6024 grep.found = TRUE;
6025 grep.pad = 0;
6026 grep.widthMM = grep.heightMM = 0;
6027 grep.nProperties = grep.nColors = grep.nShapes = 0;
6028 grep.nSections = grep.nDoodads = 0;
6029 grep.baseColorNdx = grep.labelColorNdx = 0;
6030 XkbComputeGetGeometryReplySize(new->geom, &grep, None);
6031 rep.length += SIZEOF(xGenericReply) / 4 + grep.length;
6032 }
6033 }
6034
6035 reported = rep.reported;
6036 if (client->swapped) {
6037 swaps(&rep.sequenceNumber);
6038 swapl(&rep.length);
6039 swaps(&rep.found);
6040 swaps(&rep.reported);
6041 }
6042 WriteToClient(client, SIZEOF(xkbGetKbdByNameReply), &rep);
6043 if (reported & (XkbGBN_SymbolsMask | XkbGBN_TypesMask))
6044 XkbSendMap(client, new, &mrep);
6045 if (reported & XkbGBN_CompatMapMask)
6046 XkbSendCompatMap(client, new->compat, &crep);
6047 if (reported & XkbGBN_IndicatorMapMask)
6048 XkbSendIndicatorMap(client, new->indicators, &irep);
6049 if (reported & (XkbGBN_KeyNamesMask | XkbGBN_OtherNamesMask))
6050 XkbSendNames(client, new, &nrep);
6051 if (reported & XkbGBN_GeometryMask)
6052 XkbSendGeometry(client, new->geom, &grep, FALSE);
6053 if (rep.loaded) {
6054 XkbDescPtr old_xkb;
6055 xkbNewKeyboardNotify nkn;
6056
6057 old_xkb = xkb;
6058 xkb = new;
6059 dev->key->xkbInfo->desc = xkb;
6060 new = old_xkb; /* so it'll get freed automatically */
6061
6062 XkbCopyControls(xkb, old_xkb);
6063
6064 nkn.deviceID = nkn.oldDeviceID = dev->id;
6065 nkn.minKeyCode = new->min_key_code;
6066 nkn.maxKeyCode = new->max_key_code;
6067 nkn.oldMinKeyCode = xkb->min_key_code;
6068 nkn.oldMaxKeyCode = xkb->max_key_code;
6069 nkn.requestMajor = XkbReqCode;
6070 nkn.requestMinor = X_kbGetKbdByName;
6071 nkn.changed = XkbNKN_KeycodesMask;
6072 if (geom_changed)
6073 nkn.changed |= XkbNKN_GeometryMask;
6074 XkbSendNewKeyboardNotify(dev, &nkn);
6075
6076 /* Update the map and LED info on the device itself, as well as
6077 * any slaves if it's an MD, or its MD if it's an SD and was the
6078 * last device used on that MD. */
6079 for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
6080 if (tmpd != dev && GetMaster(tmpd, MASTER_KEYBOARD) != dev &&
6081 (tmpd != master || dev != master->lastSlave))
6082 continue;
6083
6084 if (tmpd != dev)
6085 XkbDeviceApplyKeymap(tmpd, xkb);
6086
6087 if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) {
6088 old_sli = tmpd->kbdfeed->xkb_sli;
6089 tmpd->kbdfeed->xkb_sli = NULL;
6090 sli = XkbAllocSrvLedInfo(tmpd, tmpd->kbdfeed, NULL, 0);
6091 if (sli) {
6092 sli->explicitState = old_sli->explicitState;
6093 sli->effectiveState = old_sli->effectiveState;
6094 }
6095 tmpd->kbdfeed->xkb_sli = sli;
6096 XkbFreeSrvLedInfo(old_sli);
6097 }
6098 }
6099 }
6100 if ((new != NULL) && (new != xkb)) {
6101 XkbFreeKeyboard(new, XkbAllComponentsMask, TRUE);
6102 new = NULL;
6103 }
6104 XkbFreeComponentNames(&names, FALSE);
6105 XkbSetCauseXkbReq(&cause, X_kbGetKbdByName, client);
6106 XkbUpdateAllDeviceIndicators(NULL, &cause);
6107
6108 return Success;
6109 }
6110
6111 /***====================================================================***/
6112
6113 static int
ComputeDeviceLedInfoSize(DeviceIntPtr dev,unsigned int what,XkbSrvLedInfoPtr sli)6114 ComputeDeviceLedInfoSize(DeviceIntPtr dev,
6115 unsigned int what, XkbSrvLedInfoPtr sli)
6116 {
6117 int nNames, nMaps;
6118 register unsigned n, bit;
6119
6120 if (sli == NULL)
6121 return 0;
6122 nNames = nMaps = 0;
6123 if ((what & XkbXI_IndicatorNamesMask) == 0)
6124 sli->namesPresent = 0;
6125 if ((what & XkbXI_IndicatorMapsMask) == 0)
6126 sli->mapsPresent = 0;
6127
6128 for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6129 if (sli->names && sli->names[n] != None) {
6130 sli->namesPresent |= bit;
6131 nNames++;
6132 }
6133 if (sli->maps && XkbIM_InUse(&sli->maps[n])) {
6134 sli->mapsPresent |= bit;
6135 nMaps++;
6136 }
6137 }
6138 return (nNames * 4) + (nMaps * SIZEOF(xkbIndicatorMapWireDesc));
6139 }
6140
6141 static int
CheckDeviceLedFBs(DeviceIntPtr dev,int class,int id,xkbGetDeviceInfoReply * rep,ClientPtr client)6142 CheckDeviceLedFBs(DeviceIntPtr dev,
6143 int class,
6144 int id, xkbGetDeviceInfoReply * rep, ClientPtr client)
6145 {
6146 int nFBs = 0;
6147 int length = 0;
6148 Bool classOk;
6149
6150 if (class == XkbDfltXIClass) {
6151 if (dev->kbdfeed)
6152 class = KbdFeedbackClass;
6153 else if (dev->leds)
6154 class = LedFeedbackClass;
6155 else {
6156 client->errorValue = _XkbErrCode2(XkbErr_BadClass, class);
6157 return XkbKeyboardErrorCode;
6158 }
6159 }
6160 classOk = FALSE;
6161 if ((dev->kbdfeed) &&
6162 ((class == KbdFeedbackClass) || (class == XkbAllXIClasses))) {
6163 KbdFeedbackPtr kf;
6164
6165 classOk = TRUE;
6166 for (kf = dev->kbdfeed; (kf); kf = kf->next) {
6167 if ((id != XkbAllXIIds) && (id != XkbDfltXIId) &&
6168 (id != kf->ctrl.id))
6169 continue;
6170 nFBs++;
6171 length += SIZEOF(xkbDeviceLedsWireDesc);
6172 if (!kf->xkb_sli)
6173 kf->xkb_sli = XkbAllocSrvLedInfo(dev, kf, NULL, 0);
6174 length += ComputeDeviceLedInfoSize(dev, rep->present, kf->xkb_sli);
6175 if (id != XkbAllXIIds)
6176 break;
6177 }
6178 }
6179 if ((dev->leds) &&
6180 ((class == LedFeedbackClass) || (class == XkbAllXIClasses))) {
6181 LedFeedbackPtr lf;
6182
6183 classOk = TRUE;
6184 for (lf = dev->leds; (lf); lf = lf->next) {
6185 if ((id != XkbAllXIIds) && (id != XkbDfltXIId) &&
6186 (id != lf->ctrl.id))
6187 continue;
6188 nFBs++;
6189 length += SIZEOF(xkbDeviceLedsWireDesc);
6190 if (!lf->xkb_sli)
6191 lf->xkb_sli = XkbAllocSrvLedInfo(dev, NULL, lf, 0);
6192 length += ComputeDeviceLedInfoSize(dev, rep->present, lf->xkb_sli);
6193 if (id != XkbAllXIIds)
6194 break;
6195 }
6196 }
6197 if (nFBs > 0) {
6198 rep->nDeviceLedFBs = nFBs;
6199 rep->length += (length / 4);
6200 return Success;
6201 }
6202 if (classOk)
6203 client->errorValue = _XkbErrCode2(XkbErr_BadId, id);
6204 else
6205 client->errorValue = _XkbErrCode2(XkbErr_BadClass, class);
6206 return XkbKeyboardErrorCode;
6207 }
6208
6209 static int
SendDeviceLedInfo(XkbSrvLedInfoPtr sli,ClientPtr client)6210 SendDeviceLedInfo(XkbSrvLedInfoPtr sli, ClientPtr client)
6211 {
6212 xkbDeviceLedsWireDesc wire;
6213 int length;
6214
6215 length = 0;
6216 wire.ledClass = sli->class;
6217 wire.ledID = sli->id;
6218 wire.namesPresent = sli->namesPresent;
6219 wire.mapsPresent = sli->mapsPresent;
6220 wire.physIndicators = sli->physIndicators;
6221 wire.state = sli->effectiveState;
6222 if (client->swapped) {
6223 swaps(&wire.ledClass);
6224 swaps(&wire.ledID);
6225 swapl(&wire.namesPresent);
6226 swapl(&wire.mapsPresent);
6227 swapl(&wire.physIndicators);
6228 swapl(&wire.state);
6229 }
6230 WriteToClient(client, SIZEOF(xkbDeviceLedsWireDesc), &wire);
6231 length += SIZEOF(xkbDeviceLedsWireDesc);
6232 if (sli->namesPresent | sli->mapsPresent) {
6233 register unsigned i, bit;
6234
6235 if (sli->namesPresent) {
6236 CARD32 awire;
6237
6238 for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
6239 if (sli->namesPresent & bit) {
6240 awire = (CARD32) sli->names[i];
6241 if (client->swapped) {
6242 swapl(&awire);
6243 }
6244 WriteToClient(client, 4, &awire);
6245 length += 4;
6246 }
6247 }
6248 }
6249 if (sli->mapsPresent) {
6250 for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
6251 xkbIndicatorMapWireDesc iwire;
6252
6253 if (sli->mapsPresent & bit) {
6254 iwire.flags = sli->maps[i].flags;
6255 iwire.whichGroups = sli->maps[i].which_groups;
6256 iwire.groups = sli->maps[i].groups;
6257 iwire.whichMods = sli->maps[i].which_mods;
6258 iwire.mods = sli->maps[i].mods.mask;
6259 iwire.realMods = sli->maps[i].mods.real_mods;
6260 iwire.virtualMods = sli->maps[i].mods.vmods;
6261 iwire.ctrls = sli->maps[i].ctrls;
6262 if (client->swapped) {
6263 swaps(&iwire.virtualMods);
6264 swapl(&iwire.ctrls);
6265 }
6266 WriteToClient(client, SIZEOF(xkbIndicatorMapWireDesc),
6267 &iwire);
6268 length += SIZEOF(xkbIndicatorMapWireDesc);
6269 }
6270 }
6271 }
6272 }
6273 return length;
6274 }
6275
6276 static int
SendDeviceLedFBs(DeviceIntPtr dev,int class,int id,unsigned wantLength,ClientPtr client)6277 SendDeviceLedFBs(DeviceIntPtr dev,
6278 int class, int id, unsigned wantLength, ClientPtr client)
6279 {
6280 int length = 0;
6281
6282 if (class == XkbDfltXIClass) {
6283 if (dev->kbdfeed)
6284 class = KbdFeedbackClass;
6285 else if (dev->leds)
6286 class = LedFeedbackClass;
6287 }
6288 if ((dev->kbdfeed) &&
6289 ((class == KbdFeedbackClass) || (class == XkbAllXIClasses))) {
6290 KbdFeedbackPtr kf;
6291
6292 for (kf = dev->kbdfeed; (kf); kf = kf->next) {
6293 if ((id == XkbAllXIIds) || (id == XkbDfltXIId) ||
6294 (id == kf->ctrl.id)) {
6295 length += SendDeviceLedInfo(kf->xkb_sli, client);
6296 if (id != XkbAllXIIds)
6297 break;
6298 }
6299 }
6300 }
6301 if ((dev->leds) &&
6302 ((class == LedFeedbackClass) || (class == XkbAllXIClasses))) {
6303 LedFeedbackPtr lf;
6304
6305 for (lf = dev->leds; (lf); lf = lf->next) {
6306 if ((id == XkbAllXIIds) || (id == XkbDfltXIId) ||
6307 (id == lf->ctrl.id)) {
6308 length += SendDeviceLedInfo(lf->xkb_sli, client);
6309 if (id != XkbAllXIIds)
6310 break;
6311 }
6312 }
6313 }
6314 if (length == wantLength)
6315 return Success;
6316 else
6317 return BadLength;
6318 }
6319
6320 int
ProcXkbGetDeviceInfo(ClientPtr client)6321 ProcXkbGetDeviceInfo(ClientPtr client)
6322 {
6323 DeviceIntPtr dev;
6324 xkbGetDeviceInfoReply rep;
6325 int status, nDeviceLedFBs;
6326 unsigned length, nameLen;
6327 CARD16 ledClass, ledID;
6328 unsigned wanted;
6329 char *str;
6330
6331 REQUEST(xkbGetDeviceInfoReq);
6332 REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq);
6333
6334 if (!(client->xkbClientFlags & _XkbClientInitialized))
6335 return BadAccess;
6336
6337 wanted = stuff->wanted;
6338
6339 CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
6340 CHK_MASK_LEGAL(0x01, wanted, XkbXI_AllDeviceFeaturesMask);
6341
6342 if ((!dev->button) || ((stuff->nBtns < 1) && (!stuff->allBtns)))
6343 wanted &= ~XkbXI_ButtonActionsMask;
6344 if ((!dev->kbdfeed) && (!dev->leds))
6345 wanted &= ~XkbXI_IndicatorsMask;
6346
6347 nameLen = XkbSizeCountedString(dev->name);
6348 rep = (xkbGetDeviceInfoReply) {
6349 .type = X_Reply,
6350 .deviceID = dev->id,
6351 .sequenceNumber = client->sequence,
6352 .length = nameLen / 4,
6353 .present = wanted,
6354 .supported = XkbXI_AllDeviceFeaturesMask,
6355 .unsupported = 0,
6356 .nDeviceLedFBs = 0,
6357 .firstBtnWanted = 0,
6358 .nBtnsWanted = 0,
6359 .firstBtnRtrn = 0,
6360 .nBtnsRtrn = 0,
6361 .totalBtns = dev->button ? dev->button->numButtons : 0,
6362 .hasOwnState = (dev->key && dev->key->xkbInfo),
6363 .dfltKbdFB = dev->kbdfeed ? dev->kbdfeed->ctrl.id : XkbXINone,
6364 .dfltLedFB = dev->leds ? dev->leds->ctrl.id : XkbXINone,
6365 .devType = dev->xinput_type
6366 };
6367
6368 ledClass = stuff->ledClass;
6369 ledID = stuff->ledID;
6370
6371 if (wanted & XkbXI_ButtonActionsMask) {
6372 if (stuff->allBtns) {
6373 stuff->firstBtn = 0;
6374 stuff->nBtns = dev->button->numButtons;
6375 }
6376
6377 if ((stuff->firstBtn + stuff->nBtns) > dev->button->numButtons) {
6378 client->errorValue = _XkbErrCode4(0x02, dev->button->numButtons,
6379 stuff->firstBtn, stuff->nBtns);
6380 return BadValue;
6381 }
6382 else {
6383 rep.firstBtnWanted = stuff->firstBtn;
6384 rep.nBtnsWanted = stuff->nBtns;
6385 if (dev->button->xkb_acts != NULL) {
6386 XkbAction *act;
6387 register int i;
6388
6389 rep.firstBtnRtrn = stuff->firstBtn;
6390 rep.nBtnsRtrn = stuff->nBtns;
6391 act = &dev->button->xkb_acts[rep.firstBtnWanted];
6392 for (i = 0; i < rep.nBtnsRtrn; i++, act++) {
6393 if (act->type != XkbSA_NoAction)
6394 break;
6395 }
6396 rep.firstBtnRtrn += i;
6397 rep.nBtnsRtrn -= i;
6398 act =
6399 &dev->button->xkb_acts[rep.firstBtnRtrn + rep.nBtnsRtrn -
6400 1];
6401 for (i = 0; i < rep.nBtnsRtrn; i++, act--) {
6402 if (act->type != XkbSA_NoAction)
6403 break;
6404 }
6405 rep.nBtnsRtrn -= i;
6406 }
6407 rep.length += (rep.nBtnsRtrn * SIZEOF(xkbActionWireDesc)) / 4;
6408 }
6409 }
6410
6411 if (wanted & XkbXI_IndicatorsMask) {
6412 status = CheckDeviceLedFBs(dev, ledClass, ledID, &rep, client);
6413 if (status != Success)
6414 return status;
6415 }
6416 length = rep.length * 4;
6417 nDeviceLedFBs = rep.nDeviceLedFBs;
6418 if (client->swapped) {
6419 swaps(&rep.sequenceNumber);
6420 swapl(&rep.length);
6421 swaps(&rep.present);
6422 swaps(&rep.supported);
6423 swaps(&rep.unsupported);
6424 swaps(&rep.nDeviceLedFBs);
6425 swaps(&rep.dfltKbdFB);
6426 swaps(&rep.dfltLedFB);
6427 swapl(&rep.devType);
6428 }
6429 WriteToClient(client, SIZEOF(xkbGetDeviceInfoReply), &rep);
6430
6431 str = malloc(nameLen);
6432 if (!str)
6433 return BadAlloc;
6434 XkbWriteCountedString(str, dev->name, client->swapped);
6435 WriteToClient(client, nameLen, str);
6436 free(str);
6437 length -= nameLen;
6438
6439 if (rep.nBtnsRtrn > 0) {
6440 int sz;
6441 xkbActionWireDesc *awire;
6442
6443 sz = rep.nBtnsRtrn * SIZEOF(xkbActionWireDesc);
6444 awire = (xkbActionWireDesc *) &dev->button->xkb_acts[rep.firstBtnRtrn];
6445 WriteToClient(client, sz, awire);
6446 length -= sz;
6447 }
6448 if (nDeviceLedFBs > 0) {
6449 status = SendDeviceLedFBs(dev, ledClass, ledID, length, client);
6450 if (status != Success)
6451 return status;
6452 }
6453 else if (length != 0) {
6454 ErrorF("[xkb] Internal Error! BadLength in ProcXkbGetDeviceInfo\n");
6455 ErrorF("[xkb] Wrote %d fewer bytes than expected\n",
6456 length);
6457 return BadLength;
6458 }
6459 return Success;
6460 }
6461
6462 static char *
CheckSetDeviceIndicators(char * wire,DeviceIntPtr dev,int num,int * status_rtrn,ClientPtr client)6463 CheckSetDeviceIndicators(char *wire,
6464 DeviceIntPtr dev,
6465 int num, int *status_rtrn, ClientPtr client)
6466 {
6467 xkbDeviceLedsWireDesc *ledWire;
6468 int i;
6469 XkbSrvLedInfoPtr sli;
6470
6471 ledWire = (xkbDeviceLedsWireDesc *) wire;
6472 for (i = 0; i < num; i++) {
6473 if (client->swapped) {
6474 swaps(&ledWire->ledClass);
6475 swaps(&ledWire->ledID);
6476 swapl(&ledWire->namesPresent);
6477 swapl(&ledWire->mapsPresent);
6478 swapl(&ledWire->physIndicators);
6479 }
6480
6481 sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID,
6482 XkbXI_IndicatorsMask);
6483 if (sli != NULL) {
6484 register int n;
6485 register unsigned bit;
6486 int nMaps, nNames;
6487 CARD32 *atomWire;
6488 xkbIndicatorMapWireDesc *mapWire;
6489
6490 nMaps = nNames = 0;
6491 for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6492 if (ledWire->namesPresent & bit)
6493 nNames++;
6494 if (ledWire->mapsPresent & bit)
6495 nMaps++;
6496 }
6497 atomWire = (CARD32 *) &ledWire[1];
6498 if (nNames > 0) {
6499 for (n = 0; n < nNames; n++) {
6500 if (client->swapped) {
6501 swapl(atomWire);
6502 }
6503 CHK_ATOM_OR_NONE3(((Atom) (*atomWire)), client->errorValue,
6504 *status_rtrn, NULL);
6505 atomWire++;
6506 }
6507 }
6508 mapWire = (xkbIndicatorMapWireDesc *) atomWire;
6509 if (nMaps > 0) {
6510 for (n = 0; n < nMaps; n++) {
6511 if (client->swapped) {
6512 swaps(&mapWire->virtualMods);
6513 swapl(&mapWire->ctrls);
6514 }
6515 CHK_MASK_LEGAL3(0x21, mapWire->whichGroups,
6516 XkbIM_UseAnyGroup,
6517 client->errorValue, *status_rtrn, NULL);
6518 CHK_MASK_LEGAL3(0x22, mapWire->whichMods, XkbIM_UseAnyMods,
6519 client->errorValue, *status_rtrn, NULL);
6520 mapWire++;
6521 }
6522 }
6523 ledWire = (xkbDeviceLedsWireDesc *) mapWire;
6524 }
6525 else {
6526 /* SHOULD NEVER HAPPEN */
6527 return (char *) ledWire;
6528 }
6529 }
6530 return (char *) ledWire;
6531 }
6532
6533 static char *
SetDeviceIndicators(char * wire,DeviceIntPtr dev,unsigned changed,int num,int * status_rtrn,ClientPtr client,xkbExtensionDeviceNotify * ev)6534 SetDeviceIndicators(char *wire,
6535 DeviceIntPtr dev,
6536 unsigned changed,
6537 int num,
6538 int *status_rtrn,
6539 ClientPtr client, xkbExtensionDeviceNotify * ev)
6540 {
6541 xkbDeviceLedsWireDesc *ledWire;
6542 int i;
6543 XkbEventCauseRec cause;
6544 unsigned namec, mapc, statec;
6545 xkbExtensionDeviceNotify ed;
6546 XkbChangesRec changes;
6547 DeviceIntPtr kbd;
6548
6549 memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify));
6550 memset((char *) &changes, 0, sizeof(XkbChangesRec));
6551 XkbSetCauseXkbReq(&cause, X_kbSetDeviceInfo, client);
6552 ledWire = (xkbDeviceLedsWireDesc *) wire;
6553 for (i = 0; i < num; i++) {
6554 register int n;
6555 register unsigned bit;
6556 CARD32 *atomWire;
6557 xkbIndicatorMapWireDesc *mapWire;
6558 XkbSrvLedInfoPtr sli;
6559
6560 namec = mapc = statec = 0;
6561 sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID,
6562 XkbXI_IndicatorMapsMask);
6563 if (!sli) {
6564 /* SHOULD NEVER HAPPEN!! */
6565 return (char *) ledWire;
6566 }
6567
6568 atomWire = (CARD32 *) &ledWire[1];
6569 if (changed & XkbXI_IndicatorNamesMask) {
6570 namec = sli->namesPresent | ledWire->namesPresent;
6571 memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom));
6572 }
6573 if (ledWire->namesPresent) {
6574 sli->namesPresent = ledWire->namesPresent;
6575 memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom));
6576 for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6577 if (ledWire->namesPresent & bit) {
6578 sli->names[n] = (Atom) *atomWire;
6579 if (sli->names[n] == None)
6580 ledWire->namesPresent &= ~bit;
6581 atomWire++;
6582 }
6583 }
6584 }
6585 mapWire = (xkbIndicatorMapWireDesc *) atomWire;
6586 if (changed & XkbXI_IndicatorMapsMask) {
6587 mapc = sli->mapsPresent | ledWire->mapsPresent;
6588 sli->mapsPresent = ledWire->mapsPresent;
6589 memset((char *) sli->maps, 0,
6590 XkbNumIndicators * sizeof(XkbIndicatorMapRec));
6591 }
6592 if (ledWire->mapsPresent) {
6593 for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6594 if (ledWire->mapsPresent & bit) {
6595 sli->maps[n].flags = mapWire->flags;
6596 sli->maps[n].which_groups = mapWire->whichGroups;
6597 sli->maps[n].groups = mapWire->groups;
6598 sli->maps[n].which_mods = mapWire->whichMods;
6599 sli->maps[n].mods.mask = mapWire->mods;
6600 sli->maps[n].mods.real_mods = mapWire->realMods;
6601 sli->maps[n].mods.vmods = mapWire->virtualMods;
6602 sli->maps[n].ctrls = mapWire->ctrls;
6603 mapWire++;
6604 }
6605 }
6606 }
6607 if (changed & XkbXI_IndicatorStateMask) {
6608 statec = sli->effectiveState ^ ledWire->state;
6609 sli->explicitState &= ~statec;
6610 sli->explicitState |= (ledWire->state & statec);
6611 }
6612 if (namec)
6613 XkbApplyLedNameChanges(dev, sli, namec, &ed, &changes, &cause);
6614 if (mapc)
6615 XkbApplyLedMapChanges(dev, sli, mapc, &ed, &changes, &cause);
6616 if (statec)
6617 XkbApplyLedStateChanges(dev, sli, statec, &ed, &changes, &cause);
6618
6619 kbd = dev;
6620 if ((sli->flags & XkbSLI_HasOwnState) == 0)
6621 kbd = inputInfo.keyboard;
6622
6623 XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause);
6624 ledWire = (xkbDeviceLedsWireDesc *) mapWire;
6625 }
6626 return (char *) ledWire;
6627 }
6628
6629 static int
_XkbSetDeviceInfo(ClientPtr client,DeviceIntPtr dev,xkbSetDeviceInfoReq * stuff)6630 _XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev,
6631 xkbSetDeviceInfoReq * stuff)
6632 {
6633 char *wire;
6634
6635 wire = (char *) &stuff[1];
6636 if (stuff->change & XkbXI_ButtonActionsMask) {
6637 if (!dev->button) {
6638 client->errorValue = _XkbErrCode2(XkbErr_BadClass, ButtonClass);
6639 return XkbKeyboardErrorCode;
6640 }
6641 if ((stuff->firstBtn + stuff->nBtns) > dev->button->numButtons) {
6642 client->errorValue =
6643 _XkbErrCode4(0x02, stuff->firstBtn, stuff->nBtns,
6644 dev->button->numButtons);
6645 return BadMatch;
6646 }
6647 wire += (stuff->nBtns * SIZEOF(xkbActionWireDesc));
6648 }
6649 if (stuff->change & XkbXI_IndicatorsMask) {
6650 int status = Success;
6651
6652 wire = CheckSetDeviceIndicators(wire, dev, stuff->nDeviceLedFBs,
6653 &status, client);
6654 if (status != Success)
6655 return status;
6656 }
6657 if (((wire - ((char *) stuff)) / 4) != stuff->length)
6658 return BadLength;
6659
6660 return Success;
6661 }
6662
6663 static int
_XkbSetDeviceInfoCheck(ClientPtr client,DeviceIntPtr dev,xkbSetDeviceInfoReq * stuff)6664 _XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev,
6665 xkbSetDeviceInfoReq * stuff)
6666 {
6667 char *wire;
6668 xkbExtensionDeviceNotify ed;
6669
6670 memset((char *) &ed, 0, SIZEOF(xkbExtensionDeviceNotify));
6671 ed.deviceID = dev->id;
6672 wire = (char *) &stuff[1];
6673 if (stuff->change & XkbXI_ButtonActionsMask) {
6674 int nBtns, sz, i;
6675 XkbAction *acts;
6676 DeviceIntPtr kbd;
6677
6678 nBtns = dev->button->numButtons;
6679 acts = dev->button->xkb_acts;
6680 if (acts == NULL) {
6681 acts = calloc(nBtns, sizeof(XkbAction));
6682 if (!acts)
6683 return BadAlloc;
6684 dev->button->xkb_acts = acts;
6685 }
6686 sz = stuff->nBtns * SIZEOF(xkbActionWireDesc);
6687 memcpy((char *) &acts[stuff->firstBtn], (char *) wire, sz);
6688 wire += sz;
6689 ed.reason |= XkbXI_ButtonActionsMask;
6690 ed.firstBtn = stuff->firstBtn;
6691 ed.nBtns = stuff->nBtns;
6692
6693 if (dev->key)
6694 kbd = dev;
6695 else
6696 kbd = inputInfo.keyboard;
6697 acts = &dev->button->xkb_acts[stuff->firstBtn];
6698 for (i = 0; i < stuff->nBtns; i++, acts++) {
6699 if (acts->type != XkbSA_NoAction)
6700 XkbSetActionKeyMods(kbd->key->xkbInfo->desc, acts, 0);
6701 }
6702 }
6703 if (stuff->change & XkbXI_IndicatorsMask) {
6704 int status = Success;
6705
6706 wire = SetDeviceIndicators(wire, dev, stuff->change,
6707 stuff->nDeviceLedFBs, &status, client, &ed);
6708 if (status != Success)
6709 return status;
6710 }
6711 if ((stuff->change) && (ed.reason))
6712 XkbSendExtensionDeviceNotify(dev, client, &ed);
6713 return Success;
6714 }
6715
6716 int
ProcXkbSetDeviceInfo(ClientPtr client)6717 ProcXkbSetDeviceInfo(ClientPtr client)
6718 {
6719 DeviceIntPtr dev;
6720 int rc;
6721
6722 REQUEST(xkbSetDeviceInfoReq);
6723 REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq);
6724
6725 if (!(client->xkbClientFlags & _XkbClientInitialized))
6726 return BadAccess;
6727
6728 CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
6729 CHK_MASK_LEGAL(0x01, stuff->change, XkbXI_AllFeaturesMask);
6730
6731 rc = _XkbSetDeviceInfoCheck(client, dev, stuff);
6732
6733 if (rc != Success)
6734 return rc;
6735
6736 if (stuff->deviceSpec == XkbUseCoreKbd ||
6737 stuff->deviceSpec == XkbUseCorePtr) {
6738 DeviceIntPtr other;
6739
6740 for (other = inputInfo.devices; other; other = other->next) {
6741 if (((other != dev) && !IsMaster(other) &&
6742 GetMaster(other, MASTER_KEYBOARD) == dev) &&
6743 ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
6744 (stuff->deviceSpec == XkbUseCorePtr && other->button))) {
6745 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
6746 DixManageAccess);
6747 if (rc == Success) {
6748 rc = _XkbSetDeviceInfoCheck(client, other, stuff);
6749 if (rc != Success)
6750 return rc;
6751 }
6752 }
6753 }
6754 }
6755
6756 /* checks done, apply */
6757 rc = _XkbSetDeviceInfo(client, dev, stuff);
6758 if (rc != Success)
6759 return rc;
6760
6761 if (stuff->deviceSpec == XkbUseCoreKbd ||
6762 stuff->deviceSpec == XkbUseCorePtr) {
6763 DeviceIntPtr other;
6764
6765 for (other = inputInfo.devices; other; other = other->next) {
6766 if (((other != dev) && !IsMaster(other) &&
6767 GetMaster(other, MASTER_KEYBOARD) == dev) &&
6768 ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
6769 (stuff->deviceSpec == XkbUseCorePtr && other->button))) {
6770 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
6771 DixManageAccess);
6772 if (rc == Success) {
6773 rc = _XkbSetDeviceInfo(client, other, stuff);
6774 if (rc != Success)
6775 return rc;
6776 }
6777 }
6778 }
6779 }
6780
6781 return Success;
6782 }
6783
6784 /***====================================================================***/
6785
6786 int
ProcXkbSetDebuggingFlags(ClientPtr client)6787 ProcXkbSetDebuggingFlags(ClientPtr client)
6788 {
6789 CARD32 newFlags, newCtrls, extraLength;
6790 xkbSetDebuggingFlagsReply rep;
6791 int rc;
6792
6793 REQUEST(xkbSetDebuggingFlagsReq);
6794 REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq);
6795
6796 rc = XaceHook(XACE_SERVER_ACCESS, client, DixDebugAccess);
6797 if (rc != Success)
6798 return rc;
6799
6800 newFlags = xkbDebugFlags & (~stuff->affectFlags);
6801 newFlags |= (stuff->flags & stuff->affectFlags);
6802 newCtrls = xkbDebugCtrls & (~stuff->affectCtrls);
6803 newCtrls |= (stuff->ctrls & stuff->affectCtrls);
6804 if (xkbDebugFlags || newFlags || stuff->msgLength) {
6805 ErrorF("[xkb] XkbDebug: Setting debug flags to 0x%lx\n",
6806 (long) newFlags);
6807 if (newCtrls != xkbDebugCtrls)
6808 ErrorF("[xkb] XkbDebug: Setting debug controls to 0x%lx\n",
6809 (long) newCtrls);
6810 }
6811 extraLength = (stuff->length << 2) - sz_xkbSetDebuggingFlagsReq;
6812 if (stuff->msgLength > 0) {
6813 char *msg;
6814
6815 if (extraLength < XkbPaddedSize(stuff->msgLength)) {
6816 ErrorF
6817 ("[xkb] XkbDebug: msgLength= %d, length= %ld (should be %d)\n",
6818 stuff->msgLength, (long) extraLength,
6819 XkbPaddedSize(stuff->msgLength));
6820 return BadLength;
6821 }
6822 msg = (char *) &stuff[1];
6823 if (msg[stuff->msgLength - 1] != '\0') {
6824 ErrorF("[xkb] XkbDebug: message not null-terminated\n");
6825 return BadValue;
6826 }
6827 ErrorF("[xkb] XkbDebug: %s\n", msg);
6828 }
6829 xkbDebugFlags = newFlags;
6830 xkbDebugCtrls = newCtrls;
6831
6832 rep = (xkbSetDebuggingFlagsReply) {
6833 .type = X_Reply,
6834 .sequenceNumber = client->sequence,
6835 .length = 0,
6836 .currentFlags = newFlags,
6837 .currentCtrls = newCtrls,
6838 .supportedFlags = ~0,
6839 .supportedCtrls = ~0
6840 };
6841 if (client->swapped) {
6842 swaps(&rep.sequenceNumber);
6843 swapl(&rep.currentFlags);
6844 swapl(&rep.currentCtrls);
6845 swapl(&rep.supportedFlags);
6846 swapl(&rep.supportedCtrls);
6847 }
6848 WriteToClient(client, SIZEOF(xkbSetDebuggingFlagsReply), &rep);
6849 return Success;
6850 }
6851
6852 /***====================================================================***/
6853
6854 static int
ProcXkbDispatch(ClientPtr client)6855 ProcXkbDispatch(ClientPtr client)
6856 {
6857 REQUEST(xReq);
6858 switch (stuff->data) {
6859 case X_kbUseExtension:
6860 return ProcXkbUseExtension(client);
6861 case X_kbSelectEvents:
6862 return ProcXkbSelectEvents(client);
6863 case X_kbBell:
6864 return ProcXkbBell(client);
6865 case X_kbGetState:
6866 return ProcXkbGetState(client);
6867 case X_kbLatchLockState:
6868 return ProcXkbLatchLockState(client);
6869 case X_kbGetControls:
6870 return ProcXkbGetControls(client);
6871 case X_kbSetControls:
6872 return ProcXkbSetControls(client);
6873 case X_kbGetMap:
6874 return ProcXkbGetMap(client);
6875 case X_kbSetMap:
6876 return ProcXkbSetMap(client);
6877 case X_kbGetCompatMap:
6878 return ProcXkbGetCompatMap(client);
6879 case X_kbSetCompatMap:
6880 return ProcXkbSetCompatMap(client);
6881 case X_kbGetIndicatorState:
6882 return ProcXkbGetIndicatorState(client);
6883 case X_kbGetIndicatorMap:
6884 return ProcXkbGetIndicatorMap(client);
6885 case X_kbSetIndicatorMap:
6886 return ProcXkbSetIndicatorMap(client);
6887 case X_kbGetNamedIndicator:
6888 return ProcXkbGetNamedIndicator(client);
6889 case X_kbSetNamedIndicator:
6890 return ProcXkbSetNamedIndicator(client);
6891 case X_kbGetNames:
6892 return ProcXkbGetNames(client);
6893 case X_kbSetNames:
6894 return ProcXkbSetNames(client);
6895 case X_kbGetGeometry:
6896 return ProcXkbGetGeometry(client);
6897 case X_kbSetGeometry:
6898 return ProcXkbSetGeometry(client);
6899 case X_kbPerClientFlags:
6900 return ProcXkbPerClientFlags(client);
6901 case X_kbListComponents:
6902 return ProcXkbListComponents(client);
6903 case X_kbGetKbdByName:
6904 return ProcXkbGetKbdByName(client);
6905 case X_kbGetDeviceInfo:
6906 return ProcXkbGetDeviceInfo(client);
6907 case X_kbSetDeviceInfo:
6908 return ProcXkbSetDeviceInfo(client);
6909 case X_kbSetDebuggingFlags:
6910 return ProcXkbSetDebuggingFlags(client);
6911 default:
6912 return BadRequest;
6913 }
6914 }
6915
6916 static int
XkbClientGone(void * data,XID id)6917 XkbClientGone(void *data, XID id)
6918 {
6919 DevicePtr pXDev = (DevicePtr) data;
6920
6921 if (!XkbRemoveResourceClient(pXDev, id)) {
6922 ErrorF
6923 ("[xkb] Internal Error! bad RemoveResourceClient in XkbClientGone\n");
6924 }
6925 return 1;
6926 }
6927
6928 void
XkbExtensionInit(void)6929 XkbExtensionInit(void)
6930 {
6931 ExtensionEntry *extEntry;
6932
6933 RT_XKBCLIENT = CreateNewResourceType(XkbClientGone, "XkbClient");
6934 if (!RT_XKBCLIENT)
6935 return;
6936
6937 if (!XkbInitPrivates())
6938 return;
6939
6940 if ((extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors,
6941 ProcXkbDispatch, SProcXkbDispatch,
6942 NULL, StandardMinorOpcode))) {
6943 XkbReqCode = (unsigned char) extEntry->base;
6944 XkbEventBase = (unsigned char) extEntry->eventBase;
6945 XkbErrorBase = (unsigned char) extEntry->errorBase;
6946 XkbKeyboardErrorCode = XkbErrorBase + XkbKeyboard;
6947 }
6948 return;
6949 }
6950