xkb.c revision 7e31ba66
105b261ecSmrg/************************************************************ 205b261ecSmrgCopyright (c) 1993 by Silicon Graphics Computer Systems, Inc. 305b261ecSmrg 405b261ecSmrgPermission to use, copy, modify, and distribute this 505b261ecSmrgsoftware and its documentation for any purpose and without 605b261ecSmrgfee is hereby granted, provided that the above copyright 705b261ecSmrgnotice appear in all copies and that both that copyright 805b261ecSmrgnotice and this permission notice appear in supporting 9f7df2e56Smrgdocumentation, and that the name of Silicon Graphics not be 10f7df2e56Smrgused in advertising or publicity pertaining to distribution 1105b261ecSmrgof the software without specific prior written permission. 12f7df2e56SmrgSilicon Graphics makes no representation about the suitability 1305b261ecSmrgof this software for any purpose. It is provided "as is" 1405b261ecSmrgwithout any express or implied warranty. 1505b261ecSmrg 16f7df2e56SmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17f7df2e56SmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 1805b261ecSmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19f7df2e56SmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20f7df2e56SmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21f7df2e56SmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 2205b261ecSmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 2305b261ecSmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE. 2405b261ecSmrg 2505b261ecSmrg********************************************************/ 2605b261ecSmrg 2705b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 2805b261ecSmrg#include <dix-config.h> 2905b261ecSmrg#endif 3005b261ecSmrg 3105b261ecSmrg#include <stdio.h> 3205b261ecSmrg#include <X11/X.h> 3305b261ecSmrg#include <X11/Xproto.h> 3405b261ecSmrg#include "misc.h" 3505b261ecSmrg#include "inputstr.h" 3605b261ecSmrg#define XKBSRV_NEED_FILE_FUNCS 3705b261ecSmrg#include <xkbsrv.h> 3805b261ecSmrg#include "extnsionst.h" 39f7df2e56Smrg#include "extinit.h" 404642e01fSmrg#include "xace.h" 4105b261ecSmrg#include "xkb.h" 426747b715Smrg#include "protocol-versions.h" 4305b261ecSmrg 4405b261ecSmrg#include <X11/extensions/XI.h> 456747b715Smrg#include <X11/extensions/XKMformat.h> 4605b261ecSmrg 47f7df2e56Smrgint XkbEventBase; 48f7df2e56Smrgstatic int XkbErrorBase; 49f7df2e56Smrgint XkbReqCode; 50f7df2e56Smrgint XkbKeyboardErrorCode; 51f7df2e56SmrgCARD32 xkbDebugFlags = 0; 52f7df2e56Smrgstatic CARD32 xkbDebugCtrls = 0; 5305b261ecSmrg 54f7df2e56Smrgstatic RESTYPE RT_XKBCLIENT; 5505b261ecSmrg 5605b261ecSmrg/***====================================================================***/ 5705b261ecSmrg 584642e01fSmrg#define CHK_DEVICE(dev, id, client, access_mode, lf) {\ 5905b261ecSmrg int why;\ 60f7df2e56Smrg int tmprc = lf(&(dev), id, client, access_mode, &why);\ 61f7df2e56Smrg if (tmprc != Success) {\ 624642e01fSmrg client->errorValue = _XkbErrCode2(why, id);\ 63f7df2e56Smrg return tmprc;\ 6405b261ecSmrg }\ 6505b261ecSmrg} 6605b261ecSmrg 674642e01fSmrg#define CHK_KBD_DEVICE(dev, id, client, mode) \ 684642e01fSmrg CHK_DEVICE(dev, id, client, mode, _XkbLookupKeyboard) 694642e01fSmrg#define CHK_LED_DEVICE(dev, id, client, mode) \ 704642e01fSmrg CHK_DEVICE(dev, id, client, mode, _XkbLookupLedDevice) 714642e01fSmrg#define CHK_BELL_DEVICE(dev, id, client, mode) \ 724642e01fSmrg CHK_DEVICE(dev, id, client, mode, _XkbLookupBellDevice) 734642e01fSmrg#define CHK_ANY_DEVICE(dev, id, client, mode) \ 744642e01fSmrg CHK_DEVICE(dev, id, client, mode, _XkbLookupAnyDevice) 7505b261ecSmrg 7605b261ecSmrg#define CHK_ATOM_ONLY2(a,ev,er) {\ 7705b261ecSmrg if (((a)==None)||(!ValidAtom((a)))) {\ 7805b261ecSmrg (ev)= (XID)(a);\ 7905b261ecSmrg return er;\ 8005b261ecSmrg }\ 8105b261ecSmrg} 8205b261ecSmrg#define CHK_ATOM_ONLY(a) \ 8305b261ecSmrg CHK_ATOM_ONLY2(a,client->errorValue,BadAtom) 8405b261ecSmrg 8505b261ecSmrg#define CHK_ATOM_OR_NONE3(a,ev,er,ret) {\ 8605b261ecSmrg if (((a)!=None)&&(!ValidAtom((a)))) {\ 8705b261ecSmrg (ev)= (XID)(a);\ 8805b261ecSmrg (er)= BadAtom;\ 8905b261ecSmrg return ret;\ 9005b261ecSmrg }\ 9105b261ecSmrg} 9205b261ecSmrg#define CHK_ATOM_OR_NONE2(a,ev,er) {\ 9305b261ecSmrg if (((a)!=None)&&(!ValidAtom((a)))) {\ 9405b261ecSmrg (ev)= (XID)(a);\ 9505b261ecSmrg return er;\ 9605b261ecSmrg }\ 9705b261ecSmrg} 9805b261ecSmrg#define CHK_ATOM_OR_NONE(a) \ 9905b261ecSmrg CHK_ATOM_OR_NONE2(a,client->errorValue,BadAtom) 10005b261ecSmrg 10105b261ecSmrg#define CHK_MASK_LEGAL3(err,mask,legal,ev,er,ret) {\ 10205b261ecSmrg if ((mask)&(~(legal))) { \ 10305b261ecSmrg (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\ 10405b261ecSmrg (er)= BadValue;\ 10505b261ecSmrg return ret;\ 10605b261ecSmrg }\ 10705b261ecSmrg} 10805b261ecSmrg#define CHK_MASK_LEGAL2(err,mask,legal,ev,er) {\ 10905b261ecSmrg if ((mask)&(~(legal))) { \ 11005b261ecSmrg (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\ 11105b261ecSmrg return er;\ 11205b261ecSmrg }\ 11305b261ecSmrg} 11405b261ecSmrg#define CHK_MASK_LEGAL(err,mask,legal) \ 11505b261ecSmrg CHK_MASK_LEGAL2(err,mask,legal,client->errorValue,BadValue) 11605b261ecSmrg 11705b261ecSmrg#define CHK_MASK_MATCH(err,affect,value) {\ 11805b261ecSmrg if ((value)&(~(affect))) { \ 11905b261ecSmrg client->errorValue= _XkbErrCode2((err),((value)&(~(affect))));\ 12005b261ecSmrg return BadMatch;\ 12105b261ecSmrg }\ 12205b261ecSmrg} 12305b261ecSmrg#define CHK_MASK_OVERLAP(err,m1,m2) {\ 12405b261ecSmrg if ((m1)&(m2)) { \ 12505b261ecSmrg client->errorValue= _XkbErrCode2((err),((m1)&(m2)));\ 12605b261ecSmrg return BadMatch;\ 12705b261ecSmrg }\ 12805b261ecSmrg} 12905b261ecSmrg#define CHK_KEY_RANGE2(err,first,num,x,ev,er) {\ 13005b261ecSmrg if (((unsigned)(first)+(num)-1)>(x)->max_key_code) {\ 13105b261ecSmrg (ev)=_XkbErrCode4(err,(first),(num),(x)->max_key_code);\ 13205b261ecSmrg return er;\ 13305b261ecSmrg }\ 13405b261ecSmrg else if ( (first)<(x)->min_key_code ) {\ 13505b261ecSmrg (ev)=_XkbErrCode3(err+1,(first),xkb->min_key_code);\ 13605b261ecSmrg return er;\ 13705b261ecSmrg }\ 13805b261ecSmrg} 13905b261ecSmrg#define CHK_KEY_RANGE(err,first,num,x) \ 14005b261ecSmrg CHK_KEY_RANGE2(err,first,num,x,client->errorValue,BadValue) 14105b261ecSmrg 14205b261ecSmrg#define CHK_REQ_KEY_RANGE2(err,first,num,r,ev,er) {\ 14305b261ecSmrg if (((unsigned)(first)+(num)-1)>(r)->maxKeyCode) {\ 14405b261ecSmrg (ev)=_XkbErrCode4(err,(first),(num),(r)->maxKeyCode);\ 14505b261ecSmrg return er;\ 14605b261ecSmrg }\ 14705b261ecSmrg else if ( (first)<(r)->minKeyCode ) {\ 14805b261ecSmrg (ev)=_XkbErrCode3(err+1,(first),(r)->minKeyCode);\ 14905b261ecSmrg return er;\ 15005b261ecSmrg }\ 15105b261ecSmrg} 15205b261ecSmrg#define CHK_REQ_KEY_RANGE(err,first,num,r) \ 15305b261ecSmrg CHK_REQ_KEY_RANGE2(err,first,num,r,client->errorValue,BadValue) 15405b261ecSmrg 15505b261ecSmrg/***====================================================================***/ 15605b261ecSmrg 15705b261ecSmrgint 15805b261ecSmrgProcXkbUseExtension(ClientPtr client) 15905b261ecSmrg{ 16005b261ecSmrg REQUEST(xkbUseExtensionReq); 161f7df2e56Smrg xkbUseExtensionReply rep; 162f7df2e56Smrg int supported; 16305b261ecSmrg 16405b261ecSmrg REQUEST_SIZE_MATCH(xkbUseExtensionReq); 1656747b715Smrg if (stuff->wantedMajor != SERVER_XKB_MAJOR_VERSION) { 166f7df2e56Smrg /* pre-release version 0.65 is compatible with 1.00 */ 167f7df2e56Smrg supported = ((SERVER_XKB_MAJOR_VERSION == 1) && 168f7df2e56Smrg (stuff->wantedMajor == 0) && (stuff->wantedMinor == 65)); 169f7df2e56Smrg } 170f7df2e56Smrg else 171f7df2e56Smrg supported = 1; 172f7df2e56Smrg 173f7df2e56Smrg if ((supported) && (!(client->xkbClientFlags & _XkbClientInitialized))) { 174f7df2e56Smrg client->xkbClientFlags = _XkbClientInitialized; 1757e31ba66Smrg if (stuff->wantedMajor == 0) 1767e31ba66Smrg client->xkbClientFlags |= _XkbClientIsAncient; 177f7df2e56Smrg } 178f7df2e56Smrg else if (xkbDebugFlags & 0x1) { 179f7df2e56Smrg ErrorF 180f7df2e56Smrg ("[xkb] Rejecting client %d (0x%lx) (wants %d.%02d, have %d.%02d)\n", 181f7df2e56Smrg client->index, (long) client->clientAsMask, stuff->wantedMajor, 182f7df2e56Smrg stuff->wantedMinor, SERVER_XKB_MAJOR_VERSION, 183f7df2e56Smrg SERVER_XKB_MINOR_VERSION); 184f7df2e56Smrg } 185f7df2e56Smrg rep = (xkbUseExtensionReply) { 186f7df2e56Smrg .type = X_Reply, 187f7df2e56Smrg .supported = supported, 188f7df2e56Smrg .sequenceNumber = client->sequence, 189f7df2e56Smrg .length = 0, 190f7df2e56Smrg .serverMajor = SERVER_XKB_MAJOR_VERSION, 191f7df2e56Smrg .serverMinor = SERVER_XKB_MINOR_VERSION 192f7df2e56Smrg }; 193f7df2e56Smrg if (client->swapped) { 194f7df2e56Smrg swaps(&rep.sequenceNumber); 195f7df2e56Smrg swaps(&rep.serverMajor); 196f7df2e56Smrg swaps(&rep.serverMinor); 19705b261ecSmrg } 198f7df2e56Smrg WriteToClient(client, SIZEOF(xkbUseExtensionReply), &rep); 1996747b715Smrg return Success; 20005b261ecSmrg} 20105b261ecSmrg 20205b261ecSmrg/***====================================================================***/ 20305b261ecSmrg 20405b261ecSmrgint 20505b261ecSmrgProcXkbSelectEvents(ClientPtr client) 20605b261ecSmrg{ 207f7df2e56Smrg unsigned legal; 208f7df2e56Smrg DeviceIntPtr dev; 209f7df2e56Smrg XkbInterestPtr masks; 210f7df2e56Smrg 21105b261ecSmrg REQUEST(xkbSelectEventsReq); 21205b261ecSmrg 21305b261ecSmrg REQUEST_AT_LEAST_SIZE(xkbSelectEventsReq); 21405b261ecSmrg 215f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 216f7df2e56Smrg return BadAccess; 21705b261ecSmrg 2184642e01fSmrg CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixUseAccess); 21905b261ecSmrg 220f7df2e56Smrg if (((stuff->affectWhich & XkbMapNotifyMask) != 0) && (stuff->affectMap)) { 221f7df2e56Smrg client->mapNotifyMask &= ~stuff->affectMap; 222f7df2e56Smrg client->mapNotifyMask |= (stuff->affectMap & stuff->map); 22305b261ecSmrg } 224f7df2e56Smrg if ((stuff->affectWhich & (~XkbMapNotifyMask)) == 0) 225f7df2e56Smrg return Success; 226f7df2e56Smrg 227f7df2e56Smrg masks = XkbFindClientResource((DevicePtr) dev, client); 228f7df2e56Smrg if (!masks) { 229f7df2e56Smrg XID id = FakeClientID(client->index); 23005b261ecSmrg 231f7df2e56Smrg if (!AddResource(id, RT_XKBCLIENT, dev)) 232f7df2e56Smrg return BadAlloc; 233f7df2e56Smrg masks = XkbAddClientResource((DevicePtr) dev, client, id); 23405b261ecSmrg } 23505b261ecSmrg if (masks) { 236f7df2e56Smrg union { 237f7df2e56Smrg CARD8 *c8; 238f7df2e56Smrg CARD16 *c16; 239f7df2e56Smrg CARD32 *c32; 240f7df2e56Smrg } from, to; 241f7df2e56Smrg register unsigned bit, ndx, maskLeft, dataLeft, size; 242f7df2e56Smrg 243f7df2e56Smrg from.c8 = (CARD8 *) &stuff[1]; 244f7df2e56Smrg dataLeft = (stuff->length * 4) - SIZEOF(xkbSelectEventsReq); 245f7df2e56Smrg maskLeft = (stuff->affectWhich & (~XkbMapNotifyMask)); 246f7df2e56Smrg for (ndx = 0, bit = 1; (maskLeft != 0); ndx++, bit <<= 1) { 247f7df2e56Smrg if ((bit & maskLeft) == 0) 248f7df2e56Smrg continue; 249f7df2e56Smrg maskLeft &= ~bit; 250f7df2e56Smrg switch (ndx) { 251f7df2e56Smrg case XkbNewKeyboardNotify: 252f7df2e56Smrg to.c16 = &client->newKeyboardNotifyMask; 253f7df2e56Smrg legal = XkbAllNewKeyboardEventsMask; 254f7df2e56Smrg size = 2; 255f7df2e56Smrg break; 256f7df2e56Smrg case XkbStateNotify: 257f7df2e56Smrg to.c16 = &masks->stateNotifyMask; 258f7df2e56Smrg legal = XkbAllStateEventsMask; 259f7df2e56Smrg size = 2; 260f7df2e56Smrg break; 261f7df2e56Smrg case XkbControlsNotify: 262f7df2e56Smrg to.c32 = &masks->ctrlsNotifyMask; 263f7df2e56Smrg legal = XkbAllControlEventsMask; 264f7df2e56Smrg size = 4; 265f7df2e56Smrg break; 266f7df2e56Smrg case XkbIndicatorStateNotify: 267f7df2e56Smrg to.c32 = &masks->iStateNotifyMask; 268f7df2e56Smrg legal = XkbAllIndicatorEventsMask; 269f7df2e56Smrg size = 4; 270f7df2e56Smrg break; 271f7df2e56Smrg case XkbIndicatorMapNotify: 272f7df2e56Smrg to.c32 = &masks->iMapNotifyMask; 273f7df2e56Smrg legal = XkbAllIndicatorEventsMask; 274f7df2e56Smrg size = 4; 275f7df2e56Smrg break; 276f7df2e56Smrg case XkbNamesNotify: 277f7df2e56Smrg to.c16 = &masks->namesNotifyMask; 278f7df2e56Smrg legal = XkbAllNameEventsMask; 279f7df2e56Smrg size = 2; 280f7df2e56Smrg break; 281f7df2e56Smrg case XkbCompatMapNotify: 282f7df2e56Smrg to.c8 = &masks->compatNotifyMask; 283f7df2e56Smrg legal = XkbAllCompatMapEventsMask; 284f7df2e56Smrg size = 1; 285f7df2e56Smrg break; 286f7df2e56Smrg case XkbBellNotify: 287f7df2e56Smrg to.c8 = &masks->bellNotifyMask; 288f7df2e56Smrg legal = XkbAllBellEventsMask; 289f7df2e56Smrg size = 1; 290f7df2e56Smrg break; 291f7df2e56Smrg case XkbActionMessage: 292f7df2e56Smrg to.c8 = &masks->actionMessageMask; 293f7df2e56Smrg legal = XkbAllActionMessagesMask; 294f7df2e56Smrg size = 1; 295f7df2e56Smrg break; 296f7df2e56Smrg case XkbAccessXNotify: 297f7df2e56Smrg to.c16 = &masks->accessXNotifyMask; 298f7df2e56Smrg legal = XkbAllAccessXEventsMask; 299f7df2e56Smrg size = 2; 300f7df2e56Smrg break; 301f7df2e56Smrg case XkbExtensionDeviceNotify: 302f7df2e56Smrg to.c16 = &masks->extDevNotifyMask; 303f7df2e56Smrg legal = XkbAllExtensionDeviceEventsMask; 304f7df2e56Smrg size = 2; 305f7df2e56Smrg break; 306f7df2e56Smrg default: 307f7df2e56Smrg client->errorValue = _XkbErrCode2(33, bit); 308f7df2e56Smrg return BadValue; 309f7df2e56Smrg } 310f7df2e56Smrg 311f7df2e56Smrg if (stuff->clear & bit) { 312f7df2e56Smrg if (size == 2) 313f7df2e56Smrg to.c16[0] = 0; 314f7df2e56Smrg else if (size == 4) 315f7df2e56Smrg to.c32[0] = 0; 316f7df2e56Smrg else 317f7df2e56Smrg to.c8[0] = 0; 318f7df2e56Smrg } 319f7df2e56Smrg else if (stuff->selectAll & bit) { 320f7df2e56Smrg if (size == 2) 321f7df2e56Smrg to.c16[0] = ~0; 322f7df2e56Smrg else if (size == 4) 323f7df2e56Smrg to.c32[0] = ~0; 324f7df2e56Smrg else 325f7df2e56Smrg to.c8[0] = ~0; 326f7df2e56Smrg } 327f7df2e56Smrg else { 328f7df2e56Smrg if (dataLeft < (size * 2)) 329f7df2e56Smrg return BadLength; 330f7df2e56Smrg if (size == 2) { 331f7df2e56Smrg CHK_MASK_MATCH(ndx, from.c16[0], from.c16[1]); 332f7df2e56Smrg CHK_MASK_LEGAL(ndx, from.c16[0], legal); 333f7df2e56Smrg to.c16[0] &= ~from.c16[0]; 334f7df2e56Smrg to.c16[0] |= (from.c16[0] & from.c16[1]); 335f7df2e56Smrg } 336f7df2e56Smrg else if (size == 4) { 337f7df2e56Smrg CHK_MASK_MATCH(ndx, from.c32[0], from.c32[1]); 338f7df2e56Smrg CHK_MASK_LEGAL(ndx, from.c32[0], legal); 339f7df2e56Smrg to.c32[0] &= ~from.c32[0]; 340f7df2e56Smrg to.c32[0] |= (from.c32[0] & from.c32[1]); 341f7df2e56Smrg } 342f7df2e56Smrg else { 343f7df2e56Smrg CHK_MASK_MATCH(ndx, from.c8[0], from.c8[1]); 344f7df2e56Smrg CHK_MASK_LEGAL(ndx, from.c8[0], legal); 345f7df2e56Smrg to.c8[0] &= ~from.c8[0]; 346f7df2e56Smrg to.c8[0] |= (from.c8[0] & from.c8[1]); 347f7df2e56Smrg size = 2; 348f7df2e56Smrg } 349f7df2e56Smrg from.c8 += (size * 2); 350f7df2e56Smrg dataLeft -= (size * 2); 351f7df2e56Smrg } 352f7df2e56Smrg } 353f7df2e56Smrg if (dataLeft > 2) { 354f7df2e56Smrg ErrorF("[xkb] Extra data (%d bytes) after SelectEvents\n", 355f7df2e56Smrg dataLeft); 356f7df2e56Smrg return BadLength; 357f7df2e56Smrg } 358f7df2e56Smrg return Success; 35905b261ecSmrg } 36005b261ecSmrg return BadAlloc; 36105b261ecSmrg} 36205b261ecSmrg 36305b261ecSmrg/***====================================================================***/ 3644642e01fSmrg/** 3654642e01fSmrg * Ring a bell on the given device for the given client. 3664642e01fSmrg */ 3674642e01fSmrgstatic int 3684642e01fSmrg_XkbBell(ClientPtr client, DeviceIntPtr dev, WindowPtr pWin, 3694642e01fSmrg int bellClass, int bellID, int pitch, int duration, 3704642e01fSmrg int percent, int forceSound, int eventOnly, Atom name) 3714642e01fSmrg{ 372f7df2e56Smrg int base; 373f7df2e56Smrg void *ctrl; 374f7df2e56Smrg int oldPitch, oldDuration; 375f7df2e56Smrg int newPercent; 3764642e01fSmrg 3774642e01fSmrg if (bellClass == KbdFeedbackClass) { 378f7df2e56Smrg KbdFeedbackPtr k; 379f7df2e56Smrg 380f7df2e56Smrg if (bellID == XkbDfltXIId) 381f7df2e56Smrg k = dev->kbdfeed; 3824642e01fSmrg else { 383f7df2e56Smrg for (k = dev->kbdfeed; k; k = k->next) { 3844642e01fSmrg if (k->ctrl.id == bellID) 3854642e01fSmrg break; 3864642e01fSmrg } 3874642e01fSmrg } 3884642e01fSmrg if (!k) { 389f7df2e56Smrg client->errorValue = _XkbErrCode2(0x5, bellID); 3904642e01fSmrg return BadValue; 3914642e01fSmrg } 3924642e01fSmrg base = k->ctrl.bell; 393f7df2e56Smrg ctrl = (void *) &(k->ctrl); 394f7df2e56Smrg oldPitch = k->ctrl.bell_pitch; 395f7df2e56Smrg oldDuration = k->ctrl.bell_duration; 396f7df2e56Smrg if (pitch != 0) { 397f7df2e56Smrg if (pitch == -1) 398f7df2e56Smrg k->ctrl.bell_pitch = defaultKeyboardControl.bell_pitch; 399f7df2e56Smrg else 400f7df2e56Smrg k->ctrl.bell_pitch = pitch; 4014642e01fSmrg } 402f7df2e56Smrg if (duration != 0) { 403f7df2e56Smrg if (duration == -1) 404f7df2e56Smrg k->ctrl.bell_duration = defaultKeyboardControl.bell_duration; 405f7df2e56Smrg else 406f7df2e56Smrg k->ctrl.bell_duration = duration; 4074642e01fSmrg } 4084642e01fSmrg } 4094642e01fSmrg else if (bellClass == BellFeedbackClass) { 410f7df2e56Smrg BellFeedbackPtr b; 411f7df2e56Smrg 412f7df2e56Smrg if (bellID == XkbDfltXIId) 413f7df2e56Smrg b = dev->bell; 4144642e01fSmrg else { 415f7df2e56Smrg for (b = dev->bell; b; b = b->next) { 4164642e01fSmrg if (b->ctrl.id == bellID) 4174642e01fSmrg break; 4184642e01fSmrg } 4194642e01fSmrg } 4204642e01fSmrg if (!b) { 421f7df2e56Smrg client->errorValue = _XkbErrCode2(0x6, bellID); 4224642e01fSmrg return BadValue; 4234642e01fSmrg } 4244642e01fSmrg base = b->ctrl.percent; 425f7df2e56Smrg ctrl = (void *) &(b->ctrl); 426f7df2e56Smrg oldPitch = b->ctrl.pitch; 427f7df2e56Smrg oldDuration = b->ctrl.duration; 428f7df2e56Smrg if (pitch != 0) { 429f7df2e56Smrg if (pitch == -1) 430f7df2e56Smrg b->ctrl.pitch = defaultKeyboardControl.bell_pitch; 431f7df2e56Smrg else 432f7df2e56Smrg b->ctrl.pitch = pitch; 4334642e01fSmrg } 434f7df2e56Smrg if (duration != 0) { 435f7df2e56Smrg if (duration == -1) 436f7df2e56Smrg b->ctrl.duration = defaultKeyboardControl.bell_duration; 437f7df2e56Smrg else 438f7df2e56Smrg b->ctrl.duration = duration; 4394642e01fSmrg } 4404642e01fSmrg } 4414642e01fSmrg else { 4424642e01fSmrg client->errorValue = _XkbErrCode2(0x7, bellClass); 4434642e01fSmrg return BadValue; 4444642e01fSmrg } 4454642e01fSmrg 446f7df2e56Smrg newPercent = (base * percent) / 100; 4474642e01fSmrg if (percent < 0) 448f7df2e56Smrg newPercent = base + newPercent; 449f7df2e56Smrg else 450f7df2e56Smrg newPercent = base - newPercent + percent; 4514642e01fSmrg 4524642e01fSmrg XkbHandleBell(forceSound, eventOnly, 453f7df2e56Smrg dev, newPercent, ctrl, bellClass, name, pWin, client); 454f7df2e56Smrg if ((pitch != 0) || (duration != 0)) { 4554642e01fSmrg if (bellClass == KbdFeedbackClass) { 456f7df2e56Smrg KbdFeedbackPtr k; 457f7df2e56Smrg 458f7df2e56Smrg k = (KbdFeedbackPtr) ctrl; 459f7df2e56Smrg if (pitch != 0) 460f7df2e56Smrg k->ctrl.bell_pitch = oldPitch; 461f7df2e56Smrg if (duration != 0) 462f7df2e56Smrg k->ctrl.bell_duration = oldDuration; 4634642e01fSmrg } 4644642e01fSmrg else { 465f7df2e56Smrg BellFeedbackPtr b; 466f7df2e56Smrg 467f7df2e56Smrg b = (BellFeedbackPtr) ctrl; 468f7df2e56Smrg if (pitch != 0) 469f7df2e56Smrg b->ctrl.pitch = oldPitch; 470f7df2e56Smrg if (duration != 0) 471f7df2e56Smrg b->ctrl.duration = oldDuration; 4724642e01fSmrg } 4734642e01fSmrg } 4744642e01fSmrg 4754642e01fSmrg return Success; 4764642e01fSmrg} 47705b261ecSmrg 47805b261ecSmrgint 47905b261ecSmrgProcXkbBell(ClientPtr client) 48005b261ecSmrg{ 48105b261ecSmrg REQUEST(xkbBellReq); 48205b261ecSmrg DeviceIntPtr dev; 483f7df2e56Smrg WindowPtr pWin; 4844642e01fSmrg int rc; 48505b261ecSmrg 48605b261ecSmrg REQUEST_SIZE_MATCH(xkbBellReq); 48705b261ecSmrg 488f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 489f7df2e56Smrg return BadAccess; 49005b261ecSmrg 4914642e01fSmrg CHK_BELL_DEVICE(dev, stuff->deviceSpec, client, DixBellAccess); 49205b261ecSmrg CHK_ATOM_OR_NONE(stuff->name); 49305b261ecSmrg 4944642e01fSmrg /* device-independent checks request for sane values */ 495f7df2e56Smrg if ((stuff->forceSound) && (stuff->eventOnly)) { 496f7df2e56Smrg client->errorValue = 497f7df2e56Smrg _XkbErrCode3(0x1, stuff->forceSound, stuff->eventOnly); 498f7df2e56Smrg return BadMatch; 49905b261ecSmrg } 50005b261ecSmrg if (stuff->percent < -100 || stuff->percent > 100) { 501f7df2e56Smrg client->errorValue = _XkbErrCode2(0x2, stuff->percent); 502f7df2e56Smrg return BadValue; 50305b261ecSmrg } 504f7df2e56Smrg if (stuff->duration < -1) { 505f7df2e56Smrg client->errorValue = _XkbErrCode2(0x3, stuff->duration); 506f7df2e56Smrg return BadValue; 50705b261ecSmrg } 508f7df2e56Smrg if (stuff->pitch < -1) { 509f7df2e56Smrg client->errorValue = _XkbErrCode2(0x4, stuff->pitch); 510f7df2e56Smrg return BadValue; 51105b261ecSmrg } 51205b261ecSmrg 51305b261ecSmrg if (stuff->bellClass == XkbDfltXIClass) { 514f7df2e56Smrg if (dev->kbdfeed != NULL) 515f7df2e56Smrg stuff->bellClass = KbdFeedbackClass; 516f7df2e56Smrg else 517f7df2e56Smrg stuff->bellClass = BellFeedbackClass; 51805b261ecSmrg } 5194642e01fSmrg 520f7df2e56Smrg if (stuff->window != None) { 521f7df2e56Smrg rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 522f7df2e56Smrg if (rc != Success) { 523f7df2e56Smrg client->errorValue = stuff->window; 524f7df2e56Smrg return rc; 525f7df2e56Smrg } 52605b261ecSmrg } 527f7df2e56Smrg else 528f7df2e56Smrg pWin = NULL; 52905b261ecSmrg 5304642e01fSmrg /* Client wants to ring a bell on the core keyboard? 5314642e01fSmrg Ring the bell on the core keyboard (which does nothing, but if that 5324642e01fSmrg fails the client is screwed anyway), and then on all extension devices. 5334642e01fSmrg Fail if the core keyboard fails but not the extension devices. this 5344642e01fSmrg may cause some keyboards to ding and others to stay silent. Fix 5354642e01fSmrg your client to use explicit keyboards to avoid this. 5364642e01fSmrg 5374642e01fSmrg dev is the device the client requested. 5384642e01fSmrg */ 5394642e01fSmrg rc = _XkbBell(client, dev, pWin, stuff->bellClass, stuff->bellID, 5404642e01fSmrg stuff->pitch, stuff->duration, stuff->percent, 5414642e01fSmrg stuff->forceSound, stuff->eventOnly, stuff->name); 5424642e01fSmrg 5434642e01fSmrg if ((rc == Success) && ((stuff->deviceSpec == XkbUseCoreKbd) || 544f7df2e56Smrg (stuff->deviceSpec == XkbUseCorePtr))) { 5454642e01fSmrg DeviceIntPtr other; 546f7df2e56Smrg 547f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 548f7df2e56Smrg if ((other != dev) && other->key && !IsMaster(other) && 549f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) { 5504642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixBellAccess); 5514642e01fSmrg if (rc == Success) 5524642e01fSmrg _XkbBell(client, other, pWin, stuff->bellClass, 5534642e01fSmrg stuff->bellID, stuff->pitch, stuff->duration, 5544642e01fSmrg stuff->percent, stuff->forceSound, 5554642e01fSmrg stuff->eventOnly, stuff->name); 5564642e01fSmrg } 5574642e01fSmrg } 558f7df2e56Smrg rc = Success; /* reset to success, that's what we got for the VCK */ 55905b261ecSmrg } 5604642e01fSmrg 5614642e01fSmrg return rc; 56205b261ecSmrg} 56305b261ecSmrg 56405b261ecSmrg/***====================================================================***/ 56505b261ecSmrg 56605b261ecSmrgint 56705b261ecSmrgProcXkbGetState(ClientPtr client) 56805b261ecSmrg{ 56905b261ecSmrg REQUEST(xkbGetStateReq); 570f7df2e56Smrg DeviceIntPtr dev; 571f7df2e56Smrg xkbGetStateReply rep; 572f7df2e56Smrg XkbStateRec *xkb; 57305b261ecSmrg 57405b261ecSmrg REQUEST_SIZE_MATCH(xkbGetStateReq); 57505b261ecSmrg 576f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 577f7df2e56Smrg return BadAccess; 57805b261ecSmrg 5796747b715Smrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); 58005b261ecSmrg 581f7df2e56Smrg xkb = &dev->key->xkbInfo->state; 582f7df2e56Smrg rep = (xkbGetStateReply) { 583f7df2e56Smrg .type = X_Reply, 584f7df2e56Smrg .deviceID = dev->id, 585f7df2e56Smrg .sequenceNumber = client->sequence, 586f7df2e56Smrg .length = 0, 587f7df2e56Smrg .mods = XkbStateFieldFromRec(xkb) & 0xff, 588f7df2e56Smrg .baseMods = xkb->base_mods, 589f7df2e56Smrg .latchedMods = xkb->latched_mods, 590f7df2e56Smrg .lockedMods = xkb->locked_mods, 591f7df2e56Smrg .group = xkb->group, 592f7df2e56Smrg .lockedGroup = xkb->locked_group, 593f7df2e56Smrg .baseGroup = xkb->base_group, 594f7df2e56Smrg .latchedGroup = xkb->latched_group, 595f7df2e56Smrg .compatState = xkb->compat_state, 596f7df2e56Smrg .ptrBtnState = xkb->ptr_buttons 597f7df2e56Smrg }; 59805b261ecSmrg if (client->swapped) { 599f7df2e56Smrg swaps(&rep.sequenceNumber); 600f7df2e56Smrg swaps(&rep.ptrBtnState); 60105b261ecSmrg } 602f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetStateReply), &rep); 6036747b715Smrg return Success; 60405b261ecSmrg} 60505b261ecSmrg 60605b261ecSmrg/***====================================================================***/ 60705b261ecSmrg 60805b261ecSmrgint 60905b261ecSmrgProcXkbLatchLockState(ClientPtr client) 61005b261ecSmrg{ 61105b261ecSmrg int status; 61205b261ecSmrg DeviceIntPtr dev, tmpd; 613f7df2e56Smrg XkbStateRec oldState, *newState; 61405b261ecSmrg CARD16 changed; 61505b261ecSmrg xkbStateNotify sn; 61605b261ecSmrg XkbEventCauseRec cause; 61705b261ecSmrg 61805b261ecSmrg REQUEST(xkbLatchLockStateReq); 61905b261ecSmrg REQUEST_SIZE_MATCH(xkbLatchLockStateReq); 62005b261ecSmrg 62105b261ecSmrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 622f7df2e56Smrg return BadAccess; 62305b261ecSmrg 6244642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess); 62505b261ecSmrg CHK_MASK_MATCH(0x01, stuff->affectModLocks, stuff->modLocks); 62605b261ecSmrg CHK_MASK_MATCH(0x01, stuff->affectModLatches, stuff->modLatches); 62705b261ecSmrg 62805b261ecSmrg status = Success; 62905b261ecSmrg 63005b261ecSmrg for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) { 631f7df2e56Smrg if ((tmpd == dev) || 632f7df2e56Smrg (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) { 6336747b715Smrg if (!tmpd->key || !tmpd->key->xkbInfo) 63405b261ecSmrg continue; 63505b261ecSmrg 63605b261ecSmrg oldState = tmpd->key->xkbInfo->state; 63705b261ecSmrg newState = &tmpd->key->xkbInfo->state; 63805b261ecSmrg if (stuff->affectModLocks) { 63905b261ecSmrg newState->locked_mods &= ~stuff->affectModLocks; 640f7df2e56Smrg newState->locked_mods |= 641f7df2e56Smrg (stuff->affectModLocks & stuff->modLocks); 64205b261ecSmrg } 64305b261ecSmrg if (status == Success && stuff->lockGroup) 64405b261ecSmrg newState->locked_group = stuff->groupLock; 64505b261ecSmrg if (status == Success && stuff->affectModLatches) 64605b261ecSmrg status = XkbLatchModifiers(tmpd, stuff->affectModLatches, 64705b261ecSmrg stuff->modLatches); 64805b261ecSmrg if (status == Success && stuff->latchGroup) 64905b261ecSmrg status = XkbLatchGroup(tmpd, stuff->groupLatch); 65005b261ecSmrg 65105b261ecSmrg if (status != Success) 65205b261ecSmrg return status; 65305b261ecSmrg 65405b261ecSmrg XkbComputeDerivedState(tmpd->key->xkbInfo); 65505b261ecSmrg 65605b261ecSmrg changed = XkbStateChangedFlags(&oldState, newState); 65705b261ecSmrg if (changed) { 65805b261ecSmrg sn.keycode = 0; 65905b261ecSmrg sn.eventType = 0; 66005b261ecSmrg sn.requestMajor = XkbReqCode; 66105b261ecSmrg sn.requestMinor = X_kbLatchLockState; 66205b261ecSmrg sn.changed = changed; 66305b261ecSmrg XkbSendStateNotify(tmpd, &sn); 6646747b715Smrg changed = XkbIndicatorsToUpdate(tmpd, changed, FALSE); 66505b261ecSmrg if (changed) { 66605b261ecSmrg XkbSetCauseXkbReq(&cause, X_kbLatchLockState, client); 6676747b715Smrg XkbUpdateIndicators(tmpd, changed, TRUE, NULL, &cause); 668f7df2e56Smrg } 66905b261ecSmrg } 67005b261ecSmrg } 67105b261ecSmrg } 67205b261ecSmrg 6736747b715Smrg return Success; 67405b261ecSmrg} 67505b261ecSmrg 67605b261ecSmrg/***====================================================================***/ 67705b261ecSmrg 67805b261ecSmrgint 67905b261ecSmrgProcXkbGetControls(ClientPtr client) 68005b261ecSmrg{ 68105b261ecSmrg xkbGetControlsReply rep; 682f7df2e56Smrg XkbControlsPtr xkb; 683f7df2e56Smrg DeviceIntPtr dev; 68405b261ecSmrg 68505b261ecSmrg REQUEST(xkbGetControlsReq); 68605b261ecSmrg REQUEST_SIZE_MATCH(xkbGetControlsReq); 68705b261ecSmrg 688f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 689f7df2e56Smrg return BadAccess; 69005b261ecSmrg 6914642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); 692f7df2e56Smrg 69305b261ecSmrg xkb = dev->key->xkbInfo->desc->ctrls; 694f7df2e56Smrg rep = (xkbGetControlsReply) { 695f7df2e56Smrg .type = X_Reply, 696f7df2e56Smrg .deviceID = ((DeviceIntPtr) dev)->id, 697f7df2e56Smrg .sequenceNumber = client->sequence, 698f7df2e56Smrg .length = bytes_to_int32(SIZEOF(xkbGetControlsReply) - 699f7df2e56Smrg SIZEOF(xGenericReply)), 700f7df2e56Smrg .mkDfltBtn = xkb->mk_dflt_btn, 701f7df2e56Smrg .numGroups = xkb->num_groups, 702f7df2e56Smrg .groupsWrap = xkb->groups_wrap, 703f7df2e56Smrg .internalMods = xkb->internal.mask, 704f7df2e56Smrg .ignoreLockMods = xkb->ignore_lock.mask, 705f7df2e56Smrg .internalRealMods = xkb->internal.real_mods, 706f7df2e56Smrg .ignoreLockRealMods = xkb->ignore_lock.real_mods, 707f7df2e56Smrg .internalVMods = xkb->internal.vmods, 708f7df2e56Smrg .ignoreLockVMods = xkb->ignore_lock.vmods, 709f7df2e56Smrg .repeatDelay = xkb->repeat_delay, 710f7df2e56Smrg .repeatInterval = xkb->repeat_interval, 711f7df2e56Smrg .slowKeysDelay = xkb->slow_keys_delay, 712f7df2e56Smrg .debounceDelay = xkb->debounce_delay, 713f7df2e56Smrg .mkDelay = xkb->mk_delay, 714f7df2e56Smrg .mkInterval = xkb->mk_interval, 715f7df2e56Smrg .mkTimeToMax = xkb->mk_time_to_max, 716f7df2e56Smrg .mkMaxSpeed = xkb->mk_max_speed, 717f7df2e56Smrg .mkCurve = xkb->mk_curve, 718f7df2e56Smrg .axOptions = xkb->ax_options, 719f7df2e56Smrg .axTimeout = xkb->ax_timeout, 720f7df2e56Smrg .axtOptsMask = xkb->axt_opts_mask, 721f7df2e56Smrg .axtOptsValues = xkb->axt_opts_values, 722f7df2e56Smrg .axtCtrlsMask = xkb->axt_ctrls_mask, 723f7df2e56Smrg .axtCtrlsValues = xkb->axt_ctrls_values, 724f7df2e56Smrg .enabledCtrls = xkb->enabled_ctrls, 725f7df2e56Smrg }; 726f7df2e56Smrg memcpy(rep.perKeyRepeat, xkb->per_key_repeat, XkbPerKeyBitArraySize); 72705b261ecSmrg if (client->swapped) { 728f7df2e56Smrg swaps(&rep.sequenceNumber); 729f7df2e56Smrg swapl(&rep.length); 730f7df2e56Smrg swaps(&rep.internalVMods); 731f7df2e56Smrg swaps(&rep.ignoreLockVMods); 732f7df2e56Smrg swapl(&rep.enabledCtrls); 733f7df2e56Smrg swaps(&rep.repeatDelay); 734f7df2e56Smrg swaps(&rep.repeatInterval); 735f7df2e56Smrg swaps(&rep.slowKeysDelay); 736f7df2e56Smrg swaps(&rep.debounceDelay); 737f7df2e56Smrg swaps(&rep.mkDelay); 738f7df2e56Smrg swaps(&rep.mkInterval); 739f7df2e56Smrg swaps(&rep.mkTimeToMax); 740f7df2e56Smrg swaps(&rep.mkMaxSpeed); 741f7df2e56Smrg swaps(&rep.mkCurve); 742f7df2e56Smrg swaps(&rep.axTimeout); 743f7df2e56Smrg swapl(&rep.axtCtrlsMask); 744f7df2e56Smrg swapl(&rep.axtCtrlsValues); 745f7df2e56Smrg swaps(&rep.axtOptsMask); 746f7df2e56Smrg swaps(&rep.axtOptsValues); 747f7df2e56Smrg swaps(&rep.axOptions); 748f7df2e56Smrg } 749f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetControlsReply), &rep); 7506747b715Smrg return Success; 75105b261ecSmrg} 75205b261ecSmrg 75305b261ecSmrgint 75405b261ecSmrgProcXkbSetControls(ClientPtr client) 75505b261ecSmrg{ 756f7df2e56Smrg DeviceIntPtr dev, tmpd; 757f7df2e56Smrg XkbSrvInfoPtr xkbi; 758f7df2e56Smrg XkbControlsPtr ctrl; 759f7df2e56Smrg XkbControlsRec new, old; 760f7df2e56Smrg xkbControlsNotify cn; 761f7df2e56Smrg XkbEventCauseRec cause; 762f7df2e56Smrg XkbSrvLedInfoPtr sli; 76305b261ecSmrg 76405b261ecSmrg REQUEST(xkbSetControlsReq); 76505b261ecSmrg REQUEST_SIZE_MATCH(xkbSetControlsReq); 76605b261ecSmrg 76705b261ecSmrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 768f7df2e56Smrg return BadAccess; 76905b261ecSmrg 7704642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); 77105b261ecSmrg CHK_MASK_LEGAL(0x01, stuff->changeCtrls, XkbAllControlsMask); 77205b261ecSmrg 7736747b715Smrg for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) { 7746747b715Smrg if (!tmpd->key || !tmpd->key->xkbInfo) 7756747b715Smrg continue; 776f7df2e56Smrg if ((tmpd == dev) || 777f7df2e56Smrg (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) { 77805b261ecSmrg xkbi = tmpd->key->xkbInfo; 77905b261ecSmrg ctrl = xkbi->desc->ctrls; 78005b261ecSmrg new = *ctrl; 78105b261ecSmrg XkbSetCauseXkbReq(&cause, X_kbSetControls, client); 78205b261ecSmrg 78305b261ecSmrg if (stuff->changeCtrls & XkbInternalModsMask) { 78405b261ecSmrg CHK_MASK_MATCH(0x02, stuff->affectInternalMods, 78505b261ecSmrg stuff->internalMods); 78605b261ecSmrg CHK_MASK_MATCH(0x03, stuff->affectInternalVMods, 78705b261ecSmrg stuff->internalVMods); 78805b261ecSmrg 78905b261ecSmrg new.internal.real_mods &= ~(stuff->affectInternalMods); 79005b261ecSmrg new.internal.real_mods |= (stuff->affectInternalMods & 79105b261ecSmrg stuff->internalMods); 79205b261ecSmrg new.internal.vmods &= ~(stuff->affectInternalVMods); 79305b261ecSmrg new.internal.vmods |= (stuff->affectInternalVMods & 79405b261ecSmrg stuff->internalVMods); 79505b261ecSmrg new.internal.mask = new.internal.real_mods | 796f7df2e56Smrg XkbMaskForVMask(xkbi->desc, new.internal.vmods); 79705b261ecSmrg } 79805b261ecSmrg 79905b261ecSmrg if (stuff->changeCtrls & XkbIgnoreLockModsMask) { 80005b261ecSmrg CHK_MASK_MATCH(0x4, stuff->affectIgnoreLockMods, 80105b261ecSmrg stuff->ignoreLockMods); 80205b261ecSmrg CHK_MASK_MATCH(0x5, stuff->affectIgnoreLockVMods, 80305b261ecSmrg stuff->ignoreLockVMods); 80405b261ecSmrg 80505b261ecSmrg new.ignore_lock.real_mods &= ~(stuff->affectIgnoreLockMods); 80605b261ecSmrg new.ignore_lock.real_mods |= (stuff->affectIgnoreLockMods & 80705b261ecSmrg stuff->ignoreLockMods); 80805b261ecSmrg new.ignore_lock.vmods &= ~(stuff->affectIgnoreLockVMods); 80905b261ecSmrg new.ignore_lock.vmods |= (stuff->affectIgnoreLockVMods & 81005b261ecSmrg stuff->ignoreLockVMods); 81105b261ecSmrg new.ignore_lock.mask = new.ignore_lock.real_mods | 812f7df2e56Smrg XkbMaskForVMask(xkbi->desc, new.ignore_lock.vmods); 81305b261ecSmrg } 81405b261ecSmrg 81505b261ecSmrg CHK_MASK_MATCH(0x06, stuff->affectEnabledCtrls, 81605b261ecSmrg stuff->enabledCtrls); 81705b261ecSmrg if (stuff->affectEnabledCtrls) { 81805b261ecSmrg CHK_MASK_LEGAL(0x07, stuff->affectEnabledCtrls, 81905b261ecSmrg XkbAllBooleanCtrlsMask); 82005b261ecSmrg 82105b261ecSmrg new.enabled_ctrls &= ~(stuff->affectEnabledCtrls); 82205b261ecSmrg new.enabled_ctrls |= (stuff->affectEnabledCtrls & 82305b261ecSmrg stuff->enabledCtrls); 82405b261ecSmrg } 82505b261ecSmrg 82605b261ecSmrg if (stuff->changeCtrls & XkbRepeatKeysMask) { 82705b261ecSmrg if (stuff->repeatDelay < 1 || stuff->repeatInterval < 1) { 82805b261ecSmrg client->errorValue = _XkbErrCode3(0x08, stuff->repeatDelay, 82905b261ecSmrg stuff->repeatInterval); 83005b261ecSmrg return BadValue; 83105b261ecSmrg } 83205b261ecSmrg 83305b261ecSmrg new.repeat_delay = stuff->repeatDelay; 83405b261ecSmrg new.repeat_interval = stuff->repeatInterval; 83505b261ecSmrg } 83605b261ecSmrg 83705b261ecSmrg if (stuff->changeCtrls & XkbSlowKeysMask) { 83805b261ecSmrg if (stuff->slowKeysDelay < 1) { 83905b261ecSmrg client->errorValue = _XkbErrCode2(0x09, 84005b261ecSmrg stuff->slowKeysDelay); 84105b261ecSmrg return BadValue; 84205b261ecSmrg } 84305b261ecSmrg 84405b261ecSmrg new.slow_keys_delay = stuff->slowKeysDelay; 84505b261ecSmrg } 84605b261ecSmrg 84705b261ecSmrg if (stuff->changeCtrls & XkbBounceKeysMask) { 84805b261ecSmrg if (stuff->debounceDelay < 1) { 84905b261ecSmrg client->errorValue = _XkbErrCode2(0x0A, 85005b261ecSmrg stuff->debounceDelay); 85105b261ecSmrg return BadValue; 85205b261ecSmrg } 85305b261ecSmrg 85405b261ecSmrg new.debounce_delay = stuff->debounceDelay; 85505b261ecSmrg } 85605b261ecSmrg 85705b261ecSmrg if (stuff->changeCtrls & XkbMouseKeysMask) { 85805b261ecSmrg if (stuff->mkDfltBtn > XkbMaxMouseKeysBtn) { 85905b261ecSmrg client->errorValue = _XkbErrCode2(0x0B, stuff->mkDfltBtn); 86005b261ecSmrg return BadValue; 86105b261ecSmrg } 86205b261ecSmrg 86305b261ecSmrg new.mk_dflt_btn = stuff->mkDfltBtn; 86405b261ecSmrg } 86505b261ecSmrg 86605b261ecSmrg if (stuff->changeCtrls & XkbMouseKeysAccelMask) { 86705b261ecSmrg if (stuff->mkDelay < 1 || stuff->mkInterval < 1 || 86805b261ecSmrg stuff->mkTimeToMax < 1 || stuff->mkMaxSpeed < 1 || 86905b261ecSmrg stuff->mkCurve < -1000) { 870f7df2e56Smrg client->errorValue = _XkbErrCode2(0x0C, 0); 87105b261ecSmrg return BadValue; 87205b261ecSmrg } 87305b261ecSmrg 87405b261ecSmrg new.mk_delay = stuff->mkDelay; 87505b261ecSmrg new.mk_interval = stuff->mkInterval; 87605b261ecSmrg new.mk_time_to_max = stuff->mkTimeToMax; 87705b261ecSmrg new.mk_max_speed = stuff->mkMaxSpeed; 87805b261ecSmrg new.mk_curve = stuff->mkCurve; 87905b261ecSmrg AccessXComputeCurveFactor(xkbi, &new); 88005b261ecSmrg } 88105b261ecSmrg 88205b261ecSmrg if (stuff->changeCtrls & XkbGroupsWrapMask) { 88305b261ecSmrg unsigned act, num; 88405b261ecSmrg 88505b261ecSmrg act = XkbOutOfRangeGroupAction(stuff->groupsWrap); 88605b261ecSmrg switch (act) { 88705b261ecSmrg case XkbRedirectIntoRange: 88805b261ecSmrg num = XkbOutOfRangeGroupNumber(stuff->groupsWrap); 88905b261ecSmrg if (num >= new.num_groups) { 89005b261ecSmrg client->errorValue = _XkbErrCode3(0x0D, new.num_groups, 89105b261ecSmrg num); 89205b261ecSmrg return BadValue; 89305b261ecSmrg } 89405b261ecSmrg case XkbWrapIntoRange: 89505b261ecSmrg case XkbClampIntoRange: 89605b261ecSmrg break; 89705b261ecSmrg default: 89805b261ecSmrg client->errorValue = _XkbErrCode2(0x0E, act); 89905b261ecSmrg return BadValue; 90005b261ecSmrg } 90105b261ecSmrg 902f7df2e56Smrg new.groups_wrap = stuff->groupsWrap; 90305b261ecSmrg } 90405b261ecSmrg 90505b261ecSmrg CHK_MASK_LEGAL(0x0F, stuff->axOptions, XkbAX_AllOptionsMask); 90605b261ecSmrg if (stuff->changeCtrls & XkbAccessXKeysMask) { 90705b261ecSmrg new.ax_options = stuff->axOptions & XkbAX_AllOptionsMask; 90805b261ecSmrg } 90905b261ecSmrg else { 91005b261ecSmrg if (stuff->changeCtrls & XkbStickyKeysMask) { 91105b261ecSmrg new.ax_options &= ~(XkbAX_SKOptionsMask); 91205b261ecSmrg new.ax_options |= (stuff->axOptions & XkbAX_SKOptionsMask); 91305b261ecSmrg } 914f7df2e56Smrg 91505b261ecSmrg if (stuff->changeCtrls & XkbAccessXFeedbackMask) { 91605b261ecSmrg new.ax_options &= ~(XkbAX_FBOptionsMask); 91705b261ecSmrg new.ax_options |= (stuff->axOptions & XkbAX_FBOptionsMask); 91805b261ecSmrg } 91905b261ecSmrg } 92005b261ecSmrg 92105b261ecSmrg if (stuff->changeCtrls & XkbAccessXTimeoutMask) { 92205b261ecSmrg if (stuff->axTimeout < 1) { 92305b261ecSmrg client->errorValue = _XkbErrCode2(0x10, stuff->axTimeout); 92405b261ecSmrg return BadValue; 92505b261ecSmrg } 92605b261ecSmrg CHK_MASK_MATCH(0x11, stuff->axtCtrlsMask, 92705b261ecSmrg stuff->axtCtrlsValues); 92805b261ecSmrg CHK_MASK_LEGAL(0x12, stuff->axtCtrlsMask, 92905b261ecSmrg XkbAllBooleanCtrlsMask); 93005b261ecSmrg CHK_MASK_MATCH(0x13, stuff->axtOptsMask, stuff->axtOptsValues); 93105b261ecSmrg CHK_MASK_LEGAL(0x14, stuff->axtOptsMask, XkbAX_AllOptionsMask); 93205b261ecSmrg new.ax_timeout = stuff->axTimeout; 93305b261ecSmrg new.axt_ctrls_mask = stuff->axtCtrlsMask; 93405b261ecSmrg new.axt_ctrls_values = (stuff->axtCtrlsValues & 93505b261ecSmrg stuff->axtCtrlsMask); 93605b261ecSmrg new.axt_opts_mask = stuff->axtOptsMask; 93705b261ecSmrg new.axt_opts_values = (stuff->axtOptsValues & 93805b261ecSmrg stuff->axtOptsMask); 93905b261ecSmrg } 94005b261ecSmrg 9419ace9065Smrg if (stuff->changeCtrls & XkbPerKeyRepeatMask) { 94205b261ecSmrg memcpy(new.per_key_repeat, stuff->perKeyRepeat, 94305b261ecSmrg XkbPerKeyBitArraySize); 9449ace9065Smrg if (xkbi->repeatKey && 9459ace9065Smrg !BitIsOn(new.per_key_repeat, xkbi->repeatKey)) { 9469ace9065Smrg AccessXCancelRepeatKey(xkbi, xkbi->repeatKey); 9479ace9065Smrg } 9489ace9065Smrg } 94905b261ecSmrg 950f7df2e56Smrg old = *ctrl; 951f7df2e56Smrg *ctrl = new; 95205b261ecSmrg XkbDDXChangeControls(tmpd, &old, ctrl); 95305b261ecSmrg 9546747b715Smrg if (XkbComputeControlsNotify(tmpd, &old, ctrl, &cn, FALSE)) { 95505b261ecSmrg cn.keycode = 0; 95605b261ecSmrg cn.eventType = 0; 95705b261ecSmrg cn.requestMajor = XkbReqCode; 95805b261ecSmrg cn.requestMinor = X_kbSetControls; 95905b261ecSmrg XkbSendControlsNotify(tmpd, &cn); 96005b261ecSmrg } 96105b261ecSmrg 96205b261ecSmrg sli = XkbFindSrvLedInfo(tmpd, XkbDfltXIClass, XkbDfltXIId, 0); 96305b261ecSmrg if (sli) 9646747b715Smrg XkbUpdateIndicators(tmpd, sli->usesControls, TRUE, NULL, 96505b261ecSmrg &cause); 96605b261ecSmrg 96705b261ecSmrg /* If sticky keys were disabled, clear all locks and latches */ 96805b261ecSmrg if ((old.enabled_ctrls & XkbStickyKeysMask) && 96905b261ecSmrg !(ctrl->enabled_ctrls & XkbStickyKeysMask)) 9706747b715Smrg XkbClearAllLatchesAndLocks(tmpd, xkbi, TRUE, &cause); 97105b261ecSmrg } 97205b261ecSmrg } 97305b261ecSmrg 9746747b715Smrg return Success; 97505b261ecSmrg} 97605b261ecSmrg 97705b261ecSmrg/***====================================================================***/ 97805b261ecSmrg 97905b261ecSmrgstatic int 980f7df2e56SmrgXkbSizeKeyTypes(XkbDescPtr xkb, xkbGetMapReply * rep) 98105b261ecSmrg{ 982f7df2e56Smrg XkbKeyTypeRec *type; 983f7df2e56Smrg unsigned i, len; 984f7df2e56Smrg 985f7df2e56Smrg len = 0; 986f7df2e56Smrg if (((rep->present & XkbKeyTypesMask) == 0) || (rep->nTypes < 1) || 987f7df2e56Smrg (!xkb) || (!xkb->map) || (!xkb->map->types)) { 988f7df2e56Smrg rep->present &= ~XkbKeyTypesMask; 989f7df2e56Smrg rep->firstType = rep->nTypes = 0; 990f7df2e56Smrg return 0; 991f7df2e56Smrg } 992f7df2e56Smrg type = &xkb->map->types[rep->firstType]; 993f7df2e56Smrg for (i = 0; i < rep->nTypes; i++, type++) { 994f7df2e56Smrg len += SIZEOF(xkbKeyTypeWireDesc); 995f7df2e56Smrg if (type->map_count > 0) { 996f7df2e56Smrg len += (type->map_count * SIZEOF(xkbKTMapEntryWireDesc)); 997f7df2e56Smrg if (type->preserve) 998f7df2e56Smrg len += (type->map_count * SIZEOF(xkbModsWireDesc)); 999f7df2e56Smrg } 100005b261ecSmrg } 100105b261ecSmrg return len; 100205b261ecSmrg} 100305b261ecSmrg 100405b261ecSmrgstatic char * 1005f7df2e56SmrgXkbWriteKeyTypes(XkbDescPtr xkb, 1006f7df2e56Smrg xkbGetMapReply * rep, char *buf, ClientPtr client) 100705b261ecSmrg{ 1008f7df2e56Smrg XkbKeyTypePtr type; 1009f7df2e56Smrg unsigned i; 101005b261ecSmrg xkbKeyTypeWireDesc *wire; 101105b261ecSmrg 1012f7df2e56Smrg type = &xkb->map->types[rep->firstType]; 1013f7df2e56Smrg for (i = 0; i < rep->nTypes; i++, type++) { 1014f7df2e56Smrg register unsigned n; 1015f7df2e56Smrg 1016f7df2e56Smrg wire = (xkbKeyTypeWireDesc *) buf; 1017f7df2e56Smrg wire->mask = type->mods.mask; 1018f7df2e56Smrg wire->realMods = type->mods.real_mods; 1019f7df2e56Smrg wire->virtualMods = type->mods.vmods; 1020f7df2e56Smrg wire->numLevels = type->num_levels; 1021f7df2e56Smrg wire->nMapEntries = type->map_count; 1022f7df2e56Smrg wire->preserve = (type->preserve != NULL); 1023f7df2e56Smrg if (client->swapped) { 1024f7df2e56Smrg swaps(&wire->virtualMods); 1025f7df2e56Smrg } 1026f7df2e56Smrg 1027f7df2e56Smrg buf = (char *) &wire[1]; 1028f7df2e56Smrg if (wire->nMapEntries > 0) { 1029f7df2e56Smrg xkbKTMapEntryWireDesc *ewire; 1030f7df2e56Smrg XkbKTMapEntryPtr entry; 1031f7df2e56Smrg 1032f7df2e56Smrg ewire = (xkbKTMapEntryWireDesc *) buf; 1033f7df2e56Smrg entry = type->map; 1034f7df2e56Smrg for (n = 0; n < type->map_count; n++, ewire++, entry++) { 1035f7df2e56Smrg ewire->active = entry->active; 1036f7df2e56Smrg ewire->mask = entry->mods.mask; 1037f7df2e56Smrg ewire->level = entry->level; 1038f7df2e56Smrg ewire->realMods = entry->mods.real_mods; 1039f7df2e56Smrg ewire->virtualMods = entry->mods.vmods; 1040f7df2e56Smrg if (client->swapped) { 1041f7df2e56Smrg swaps(&ewire->virtualMods); 1042f7df2e56Smrg } 1043f7df2e56Smrg } 1044f7df2e56Smrg buf = (char *) ewire; 1045f7df2e56Smrg if (type->preserve != NULL) { 1046f7df2e56Smrg xkbModsWireDesc *pwire; 1047f7df2e56Smrg XkbModsPtr preserve; 1048f7df2e56Smrg 1049f7df2e56Smrg pwire = (xkbModsWireDesc *) buf; 1050f7df2e56Smrg preserve = type->preserve; 1051f7df2e56Smrg for (n = 0; n < type->map_count; n++, pwire++, preserve++) { 1052f7df2e56Smrg pwire->mask = preserve->mask; 1053f7df2e56Smrg pwire->realMods = preserve->real_mods; 1054f7df2e56Smrg pwire->virtualMods = preserve->vmods; 1055f7df2e56Smrg if (client->swapped) { 1056f7df2e56Smrg swaps(&pwire->virtualMods); 1057f7df2e56Smrg } 1058f7df2e56Smrg } 1059f7df2e56Smrg buf = (char *) pwire; 1060f7df2e56Smrg } 1061f7df2e56Smrg } 106205b261ecSmrg } 106305b261ecSmrg return buf; 106405b261ecSmrg} 106505b261ecSmrg 106605b261ecSmrgstatic int 1067f7df2e56SmrgXkbSizeKeySyms(XkbDescPtr xkb, xkbGetMapReply * rep) 106805b261ecSmrg{ 1069f7df2e56Smrg XkbSymMapPtr symMap; 1070f7df2e56Smrg unsigned i, len; 1071f7df2e56Smrg unsigned nSyms, nSymsThisKey; 1072f7df2e56Smrg 1073f7df2e56Smrg if (((rep->present & XkbKeySymsMask) == 0) || (rep->nKeySyms < 1) || 1074f7df2e56Smrg (!xkb) || (!xkb->map) || (!xkb->map->key_sym_map)) { 1075f7df2e56Smrg rep->present &= ~XkbKeySymsMask; 1076f7df2e56Smrg rep->firstKeySym = rep->nKeySyms = 0; 1077f7df2e56Smrg rep->totalSyms = 0; 1078f7df2e56Smrg return 0; 1079f7df2e56Smrg } 1080f7df2e56Smrg len = rep->nKeySyms * SIZEOF(xkbSymMapWireDesc); 108105b261ecSmrg symMap = &xkb->map->key_sym_map[rep->firstKeySym]; 1082f7df2e56Smrg for (i = nSyms = 0; i < rep->nKeySyms; i++, symMap++) { 1083f7df2e56Smrg if (symMap->offset != 0) { 1084f7df2e56Smrg nSymsThisKey = XkbNumGroups(symMap->group_info) * symMap->width; 1085f7df2e56Smrg nSyms += nSymsThisKey; 1086f7df2e56Smrg } 1087f7df2e56Smrg } 1088f7df2e56Smrg len += nSyms * 4; 1089f7df2e56Smrg rep->totalSyms = nSyms; 109005b261ecSmrg return len; 109105b261ecSmrg} 109205b261ecSmrg 109305b261ecSmrgstatic int 1094f7df2e56SmrgXkbSizeVirtualMods(XkbDescPtr xkb, xkbGetMapReply * rep) 109505b261ecSmrg{ 1096f7df2e56Smrg register unsigned i, nMods, bit; 109705b261ecSmrg 1098f7df2e56Smrg if (((rep->present & XkbVirtualModsMask) == 0) || (rep->virtualMods == 0) || 1099f7df2e56Smrg (!xkb) || (!xkb->server)) { 1100f7df2e56Smrg rep->present &= ~XkbVirtualModsMask; 1101f7df2e56Smrg rep->virtualMods = 0; 1102f7df2e56Smrg return 0; 110305b261ecSmrg } 1104f7df2e56Smrg for (i = nMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) { 1105f7df2e56Smrg if (rep->virtualMods & bit) 1106f7df2e56Smrg nMods++; 110705b261ecSmrg } 110805b261ecSmrg return XkbPaddedSize(nMods); 110905b261ecSmrg} 111005b261ecSmrg 111105b261ecSmrgstatic char * 1112f7df2e56SmrgXkbWriteKeySyms(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf, 1113f7df2e56Smrg ClientPtr client) 111405b261ecSmrg{ 1115f7df2e56Smrg register KeySym *pSym; 1116f7df2e56Smrg XkbSymMapPtr symMap; 1117f7df2e56Smrg xkbSymMapWireDesc *outMap; 1118f7df2e56Smrg register unsigned i; 111905b261ecSmrg 112005b261ecSmrg symMap = &xkb->map->key_sym_map[rep->firstKeySym]; 1121f7df2e56Smrg for (i = 0; i < rep->nKeySyms; i++, symMap++) { 1122f7df2e56Smrg outMap = (xkbSymMapWireDesc *) buf; 1123f7df2e56Smrg outMap->ktIndex[0] = symMap->kt_index[0]; 1124f7df2e56Smrg outMap->ktIndex[1] = symMap->kt_index[1]; 1125f7df2e56Smrg outMap->ktIndex[2] = symMap->kt_index[2]; 1126f7df2e56Smrg outMap->ktIndex[3] = symMap->kt_index[3]; 1127f7df2e56Smrg outMap->groupInfo = symMap->group_info; 1128f7df2e56Smrg outMap->width = symMap->width; 1129f7df2e56Smrg outMap->nSyms = symMap->width * XkbNumGroups(symMap->group_info); 1130f7df2e56Smrg buf = (char *) &outMap[1]; 1131f7df2e56Smrg if (outMap->nSyms == 0) 1132f7df2e56Smrg continue; 1133f7df2e56Smrg 1134f7df2e56Smrg pSym = &xkb->map->syms[symMap->offset]; 1135f7df2e56Smrg memcpy((char *) buf, (char *) pSym, outMap->nSyms * 4); 1136f7df2e56Smrg if (client->swapped) { 1137f7df2e56Smrg register int nSyms = outMap->nSyms; 1138f7df2e56Smrg 1139f7df2e56Smrg swaps(&outMap->nSyms); 1140f7df2e56Smrg while (nSyms-- > 0) { 1141f7df2e56Smrg swapl((int *) buf); 1142f7df2e56Smrg buf += 4; 1143f7df2e56Smrg } 1144f7df2e56Smrg } 1145f7df2e56Smrg else 1146f7df2e56Smrg buf += outMap->nSyms * 4; 114705b261ecSmrg } 114805b261ecSmrg return buf; 114905b261ecSmrg} 115005b261ecSmrg 115105b261ecSmrgstatic int 1152f7df2e56SmrgXkbSizeKeyActions(XkbDescPtr xkb, xkbGetMapReply * rep) 115305b261ecSmrg{ 1154f7df2e56Smrg unsigned i, len, nActs; 1155f7df2e56Smrg register KeyCode firstKey; 1156f7df2e56Smrg 1157f7df2e56Smrg if (((rep->present & XkbKeyActionsMask) == 0) || (rep->nKeyActs < 1) || 1158f7df2e56Smrg (!xkb) || (!xkb->server) || (!xkb->server->key_acts)) { 1159f7df2e56Smrg rep->present &= ~XkbKeyActionsMask; 1160f7df2e56Smrg rep->firstKeyAct = rep->nKeyActs = 0; 1161f7df2e56Smrg rep->totalActs = 0; 1162f7df2e56Smrg return 0; 1163f7df2e56Smrg } 1164f7df2e56Smrg firstKey = rep->firstKeyAct; 1165f7df2e56Smrg for (nActs = i = 0; i < rep->nKeyActs; i++) { 1166f7df2e56Smrg if (xkb->server->key_acts[i + firstKey] != 0) 1167f7df2e56Smrg nActs += XkbKeyNumActions(xkb, i + firstKey); 1168f7df2e56Smrg } 1169f7df2e56Smrg len = XkbPaddedSize(rep->nKeyActs) + (nActs * SIZEOF(xkbActionWireDesc)); 1170f7df2e56Smrg rep->totalActs = nActs; 117105b261ecSmrg return len; 117205b261ecSmrg} 117305b261ecSmrg 117405b261ecSmrgstatic char * 1175f7df2e56SmrgXkbWriteKeyActions(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf, 1176f7df2e56Smrg ClientPtr client) 117705b261ecSmrg{ 1178f7df2e56Smrg unsigned i; 1179f7df2e56Smrg CARD8 *numDesc; 1180f7df2e56Smrg XkbAnyAction *actDesc; 1181f7df2e56Smrg 1182f7df2e56Smrg numDesc = (CARD8 *) buf; 1183f7df2e56Smrg for (i = 0; i < rep->nKeyActs; i++) { 1184f7df2e56Smrg if (xkb->server->key_acts[i + rep->firstKeyAct] == 0) 1185f7df2e56Smrg numDesc[i] = 0; 1186f7df2e56Smrg else 1187f7df2e56Smrg numDesc[i] = XkbKeyNumActions(xkb, (i + rep->firstKeyAct)); 1188f7df2e56Smrg } 1189f7df2e56Smrg buf += XkbPaddedSize(rep->nKeyActs); 1190f7df2e56Smrg 1191f7df2e56Smrg actDesc = (XkbAnyAction *) buf; 1192f7df2e56Smrg for (i = 0; i < rep->nKeyActs; i++) { 1193f7df2e56Smrg if (xkb->server->key_acts[i + rep->firstKeyAct] != 0) { 1194f7df2e56Smrg unsigned int num; 1195f7df2e56Smrg 1196f7df2e56Smrg num = XkbKeyNumActions(xkb, (i + rep->firstKeyAct)); 1197f7df2e56Smrg memcpy((char *) actDesc, 1198f7df2e56Smrg (char *) XkbKeyActionsPtr(xkb, (i + rep->firstKeyAct)), 1199f7df2e56Smrg num * SIZEOF(xkbActionWireDesc)); 1200f7df2e56Smrg actDesc += num; 1201f7df2e56Smrg } 1202f7df2e56Smrg } 1203f7df2e56Smrg buf = (char *) actDesc; 120405b261ecSmrg return buf; 120505b261ecSmrg} 120605b261ecSmrg 120705b261ecSmrgstatic int 1208f7df2e56SmrgXkbSizeKeyBehaviors(XkbDescPtr xkb, xkbGetMapReply * rep) 120905b261ecSmrg{ 1210f7df2e56Smrg unsigned i, len, nBhvr; 1211f7df2e56Smrg XkbBehavior *bhv; 1212f7df2e56Smrg 1213f7df2e56Smrg if (((rep->present & XkbKeyBehaviorsMask) == 0) || (rep->nKeyBehaviors < 1) 1214f7df2e56Smrg || (!xkb) || (!xkb->server) || (!xkb->server->behaviors)) { 1215f7df2e56Smrg rep->present &= ~XkbKeyBehaviorsMask; 1216f7df2e56Smrg rep->firstKeyBehavior = rep->nKeyBehaviors = 0; 1217f7df2e56Smrg rep->totalKeyBehaviors = 0; 1218f7df2e56Smrg return 0; 1219f7df2e56Smrg } 1220f7df2e56Smrg bhv = &xkb->server->behaviors[rep->firstKeyBehavior]; 1221f7df2e56Smrg for (nBhvr = i = 0; i < rep->nKeyBehaviors; i++, bhv++) { 1222f7df2e56Smrg if (bhv->type != XkbKB_Default) 1223f7df2e56Smrg nBhvr++; 1224f7df2e56Smrg } 1225f7df2e56Smrg len = nBhvr * SIZEOF(xkbBehaviorWireDesc); 1226f7df2e56Smrg rep->totalKeyBehaviors = nBhvr; 122705b261ecSmrg return len; 122805b261ecSmrg} 122905b261ecSmrg 123005b261ecSmrgstatic char * 1231f7df2e56SmrgXkbWriteKeyBehaviors(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf, 1232f7df2e56Smrg ClientPtr client) 123305b261ecSmrg{ 1234f7df2e56Smrg unsigned i; 1235f7df2e56Smrg xkbBehaviorWireDesc *wire; 1236f7df2e56Smrg XkbBehavior *pBhvr; 1237f7df2e56Smrg 1238f7df2e56Smrg wire = (xkbBehaviorWireDesc *) buf; 1239f7df2e56Smrg pBhvr = &xkb->server->behaviors[rep->firstKeyBehavior]; 1240f7df2e56Smrg for (i = 0; i < rep->nKeyBehaviors; i++, pBhvr++) { 1241f7df2e56Smrg if (pBhvr->type != XkbKB_Default) { 1242f7df2e56Smrg wire->key = i + rep->firstKeyBehavior; 1243f7df2e56Smrg wire->type = pBhvr->type; 1244f7df2e56Smrg wire->data = pBhvr->data; 1245f7df2e56Smrg wire++; 1246f7df2e56Smrg } 1247f7df2e56Smrg } 1248f7df2e56Smrg buf = (char *) wire; 124905b261ecSmrg return buf; 125005b261ecSmrg} 125105b261ecSmrg 125205b261ecSmrgstatic int 1253f7df2e56SmrgXkbSizeExplicit(XkbDescPtr xkb, xkbGetMapReply * rep) 125405b261ecSmrg{ 1255f7df2e56Smrg unsigned i, len, nRtrn; 1256f7df2e56Smrg 1257f7df2e56Smrg if (((rep->present & XkbExplicitComponentsMask) == 0) || 1258f7df2e56Smrg (rep->nKeyExplicit < 1) || (!xkb) || (!xkb->server) || 1259f7df2e56Smrg (!xkb->server->explicit)) { 1260f7df2e56Smrg rep->present &= ~XkbExplicitComponentsMask; 1261f7df2e56Smrg rep->firstKeyExplicit = rep->nKeyExplicit = 0; 1262f7df2e56Smrg rep->totalKeyExplicit = 0; 1263f7df2e56Smrg return 0; 1264f7df2e56Smrg } 1265f7df2e56Smrg for (nRtrn = i = 0; i < rep->nKeyExplicit; i++) { 1266f7df2e56Smrg if (xkb->server->explicit[i + rep->firstKeyExplicit] != 0) 1267f7df2e56Smrg nRtrn++; 1268f7df2e56Smrg } 1269f7df2e56Smrg rep->totalKeyExplicit = nRtrn; 1270f7df2e56Smrg len = XkbPaddedSize(nRtrn * 2); /* two bytes per non-zero explicit component */ 127105b261ecSmrg return len; 127205b261ecSmrg} 127305b261ecSmrg 127405b261ecSmrgstatic char * 1275f7df2e56SmrgXkbWriteExplicit(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf, 1276f7df2e56Smrg ClientPtr client) 127705b261ecSmrg{ 1278f7df2e56Smrg unsigned i; 1279f7df2e56Smrg char *start; 1280f7df2e56Smrg unsigned char *pExp; 1281f7df2e56Smrg 1282f7df2e56Smrg start = buf; 1283f7df2e56Smrg pExp = &xkb->server->explicit[rep->firstKeyExplicit]; 1284f7df2e56Smrg for (i = 0; i < rep->nKeyExplicit; i++, pExp++) { 1285f7df2e56Smrg if (*pExp != 0) { 1286f7df2e56Smrg *buf++ = i + rep->firstKeyExplicit; 1287f7df2e56Smrg *buf++ = *pExp; 1288f7df2e56Smrg } 1289f7df2e56Smrg } 1290f7df2e56Smrg i = XkbPaddedSize(buf - start) - (buf - start); /* pad to word boundary */ 1291f7df2e56Smrg return buf + i; 129205b261ecSmrg} 129305b261ecSmrg 129405b261ecSmrgstatic int 1295f7df2e56SmrgXkbSizeModifierMap(XkbDescPtr xkb, xkbGetMapReply * rep) 129605b261ecSmrg{ 1297f7df2e56Smrg unsigned i, len, nRtrn; 129805b261ecSmrg 1299f7df2e56Smrg if (((rep->present & XkbModifierMapMask) == 0) || (rep->nModMapKeys < 1) || 1300f7df2e56Smrg (!xkb) || (!xkb->map) || (!xkb->map->modmap)) { 1301f7df2e56Smrg rep->present &= ~XkbModifierMapMask; 1302f7df2e56Smrg rep->firstModMapKey = rep->nModMapKeys = 0; 1303f7df2e56Smrg rep->totalModMapKeys = 0; 1304f7df2e56Smrg return 0; 130505b261ecSmrg } 1306f7df2e56Smrg for (nRtrn = i = 0; i < rep->nModMapKeys; i++) { 1307f7df2e56Smrg if (xkb->map->modmap[i + rep->firstModMapKey] != 0) 1308f7df2e56Smrg nRtrn++; 130905b261ecSmrg } 1310f7df2e56Smrg rep->totalModMapKeys = nRtrn; 1311f7df2e56Smrg len = XkbPaddedSize(nRtrn * 2); /* two bytes per non-zero modmap component */ 131205b261ecSmrg return len; 131305b261ecSmrg} 131405b261ecSmrg 131505b261ecSmrgstatic char * 1316f7df2e56SmrgXkbWriteModifierMap(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf, 1317f7df2e56Smrg ClientPtr client) 131805b261ecSmrg{ 1319f7df2e56Smrg unsigned i; 1320f7df2e56Smrg char *start; 1321f7df2e56Smrg unsigned char *pMap; 1322f7df2e56Smrg 1323f7df2e56Smrg start = buf; 1324f7df2e56Smrg pMap = &xkb->map->modmap[rep->firstModMapKey]; 1325f7df2e56Smrg for (i = 0; i < rep->nModMapKeys; i++, pMap++) { 1326f7df2e56Smrg if (*pMap != 0) { 1327f7df2e56Smrg *buf++ = i + rep->firstModMapKey; 1328f7df2e56Smrg *buf++ = *pMap; 1329f7df2e56Smrg } 1330f7df2e56Smrg } 1331f7df2e56Smrg i = XkbPaddedSize(buf - start) - (buf - start); /* pad to word boundary */ 1332f7df2e56Smrg return buf + i; 133305b261ecSmrg} 133405b261ecSmrg 133505b261ecSmrgstatic int 1336f7df2e56SmrgXkbSizeVirtualModMap(XkbDescPtr xkb, xkbGetMapReply * rep) 133705b261ecSmrg{ 1338f7df2e56Smrg unsigned i, len, nRtrn; 133905b261ecSmrg 1340f7df2e56Smrg if (((rep->present & XkbVirtualModMapMask) == 0) || (rep->nVModMapKeys < 1) 1341f7df2e56Smrg || (!xkb) || (!xkb->server) || (!xkb->server->vmodmap)) { 1342f7df2e56Smrg rep->present &= ~XkbVirtualModMapMask; 1343f7df2e56Smrg rep->firstVModMapKey = rep->nVModMapKeys = 0; 1344f7df2e56Smrg rep->totalVModMapKeys = 0; 1345f7df2e56Smrg return 0; 134605b261ecSmrg } 1347f7df2e56Smrg for (nRtrn = i = 0; i < rep->nVModMapKeys; i++) { 1348f7df2e56Smrg if (xkb->server->vmodmap[i + rep->firstVModMapKey] != 0) 1349f7df2e56Smrg nRtrn++; 135005b261ecSmrg } 1351f7df2e56Smrg rep->totalVModMapKeys = nRtrn; 1352f7df2e56Smrg len = nRtrn * SIZEOF(xkbVModMapWireDesc); 135305b261ecSmrg return len; 135405b261ecSmrg} 135505b261ecSmrg 135605b261ecSmrgstatic char * 1357f7df2e56SmrgXkbWriteVirtualModMap(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf, 1358f7df2e56Smrg ClientPtr client) 135905b261ecSmrg{ 1360f7df2e56Smrg unsigned i; 1361f7df2e56Smrg xkbVModMapWireDesc *wire; 1362f7df2e56Smrg unsigned short *pMap; 1363f7df2e56Smrg 1364f7df2e56Smrg wire = (xkbVModMapWireDesc *) buf; 1365f7df2e56Smrg pMap = &xkb->server->vmodmap[rep->firstVModMapKey]; 1366f7df2e56Smrg for (i = 0; i < rep->nVModMapKeys; i++, pMap++) { 1367f7df2e56Smrg if (*pMap != 0) { 1368f7df2e56Smrg wire->key = i + rep->firstVModMapKey; 1369f7df2e56Smrg wire->vmods = *pMap; 1370f7df2e56Smrg wire++; 1371f7df2e56Smrg } 1372f7df2e56Smrg } 1373f7df2e56Smrg return (char *) wire; 137405b261ecSmrg} 137505b261ecSmrg 137605b261ecSmrgstatic Status 1377f7df2e56SmrgXkbComputeGetMapReplySize(XkbDescPtr xkb, xkbGetMapReply * rep) 137805b261ecSmrg{ 1379f7df2e56Smrg int len; 1380f7df2e56Smrg 1381f7df2e56Smrg rep->minKeyCode = xkb->min_key_code; 1382f7df2e56Smrg rep->maxKeyCode = xkb->max_key_code; 1383f7df2e56Smrg len = XkbSizeKeyTypes(xkb, rep); 1384f7df2e56Smrg len += XkbSizeKeySyms(xkb, rep); 1385f7df2e56Smrg len += XkbSizeKeyActions(xkb, rep); 1386f7df2e56Smrg len += XkbSizeKeyBehaviors(xkb, rep); 1387f7df2e56Smrg len += XkbSizeVirtualMods(xkb, rep); 1388f7df2e56Smrg len += XkbSizeExplicit(xkb, rep); 1389f7df2e56Smrg len += XkbSizeModifierMap(xkb, rep); 1390f7df2e56Smrg len += XkbSizeVirtualModMap(xkb, rep); 1391f7df2e56Smrg rep->length += (len / 4); 139205b261ecSmrg return Success; 139305b261ecSmrg} 139405b261ecSmrg 139505b261ecSmrgstatic int 1396f7df2e56SmrgXkbSendMap(ClientPtr client, XkbDescPtr xkb, xkbGetMapReply * rep) 139705b261ecSmrg{ 1398f7df2e56Smrg unsigned i, len; 1399f7df2e56Smrg char *desc, *start; 140005b261ecSmrg 1401f7df2e56Smrg len = (rep->length * 4) - (SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply)); 1402f7df2e56Smrg start = desc = calloc(1, len); 140305b261ecSmrg if (!start) 1404f7df2e56Smrg return BadAlloc; 1405f7df2e56Smrg if (rep->nTypes > 0) 1406f7df2e56Smrg desc = XkbWriteKeyTypes(xkb, rep, desc, client); 1407f7df2e56Smrg if (rep->nKeySyms > 0) 1408f7df2e56Smrg desc = XkbWriteKeySyms(xkb, rep, desc, client); 1409f7df2e56Smrg if (rep->nKeyActs > 0) 1410f7df2e56Smrg desc = XkbWriteKeyActions(xkb, rep, desc, client); 1411f7df2e56Smrg if (rep->totalKeyBehaviors > 0) 1412f7df2e56Smrg desc = XkbWriteKeyBehaviors(xkb, rep, desc, client); 1413f7df2e56Smrg if (rep->virtualMods) { 1414f7df2e56Smrg register int sz, bit; 1415f7df2e56Smrg 1416f7df2e56Smrg for (i = sz = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) { 1417f7df2e56Smrg if (rep->virtualMods & bit) { 1418f7df2e56Smrg desc[sz++] = xkb->server->vmods[i]; 1419f7df2e56Smrg } 1420f7df2e56Smrg } 1421f7df2e56Smrg desc += XkbPaddedSize(sz); 1422f7df2e56Smrg } 1423f7df2e56Smrg if (rep->totalKeyExplicit > 0) 1424f7df2e56Smrg desc = XkbWriteExplicit(xkb, rep, desc, client); 1425f7df2e56Smrg if (rep->totalModMapKeys > 0) 1426f7df2e56Smrg desc = XkbWriteModifierMap(xkb, rep, desc, client); 1427f7df2e56Smrg if (rep->totalVModMapKeys > 0) 1428f7df2e56Smrg desc = XkbWriteVirtualModMap(xkb, rep, desc, client); 1429f7df2e56Smrg if ((desc - start) != (len)) { 1430f7df2e56Smrg ErrorF 1431f7df2e56Smrg ("[xkb] BOGUS LENGTH in write keyboard desc, expected %d, got %ld\n", 1432f7df2e56Smrg len, (unsigned long) (desc - start)); 143305b261ecSmrg } 143405b261ecSmrg if (client->swapped) { 1435f7df2e56Smrg swaps(&rep->sequenceNumber); 1436f7df2e56Smrg swapl(&rep->length); 1437f7df2e56Smrg swaps(&rep->present); 1438f7df2e56Smrg swaps(&rep->totalSyms); 1439f7df2e56Smrg swaps(&rep->totalActs); 1440f7df2e56Smrg } 1441f7df2e56Smrg WriteToClient(client, (i = SIZEOF(xkbGetMapReply)), rep); 144205b261ecSmrg WriteToClient(client, len, start); 1443f7df2e56Smrg free((char *) start); 14446747b715Smrg return Success; 144505b261ecSmrg} 144605b261ecSmrg 144705b261ecSmrgint 144805b261ecSmrgProcXkbGetMap(ClientPtr client) 144905b261ecSmrg{ 1450f7df2e56Smrg DeviceIntPtr dev; 1451f7df2e56Smrg xkbGetMapReply rep; 1452f7df2e56Smrg XkbDescRec *xkb; 1453f7df2e56Smrg int n, status; 145405b261ecSmrg 145505b261ecSmrg REQUEST(xkbGetMapReq); 145605b261ecSmrg REQUEST_SIZE_MATCH(xkbGetMapReq); 1457f7df2e56Smrg 1458f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 1459f7df2e56Smrg return BadAccess; 146005b261ecSmrg 14614642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); 1462f7df2e56Smrg CHK_MASK_OVERLAP(0x01, stuff->full, stuff->partial); 1463f7df2e56Smrg CHK_MASK_LEGAL(0x02, stuff->full, XkbAllMapComponentsMask); 1464f7df2e56Smrg CHK_MASK_LEGAL(0x03, stuff->partial, XkbAllMapComponentsMask); 1465f7df2e56Smrg 1466f7df2e56Smrg xkb = dev->key->xkbInfo->desc; 1467f7df2e56Smrg rep = (xkbGetMapReply) { 1468f7df2e56Smrg .type = X_Reply, 1469f7df2e56Smrg .deviceID = dev->id, 1470f7df2e56Smrg .sequenceNumber = client->sequence, 1471f7df2e56Smrg .length = (SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply)) >> 2, 1472f7df2e56Smrg .present = stuff->partial | stuff->full, 1473f7df2e56Smrg .minKeyCode = xkb->min_key_code, 1474f7df2e56Smrg .maxKeyCode = xkb->max_key_code 1475f7df2e56Smrg }; 1476f7df2e56Smrg 1477f7df2e56Smrg if (stuff->full & XkbKeyTypesMask) { 1478f7df2e56Smrg rep.firstType = 0; 1479f7df2e56Smrg rep.nTypes = xkb->map->num_types; 1480f7df2e56Smrg } 1481f7df2e56Smrg else if (stuff->partial & XkbKeyTypesMask) { 1482f7df2e56Smrg if (((unsigned) stuff->firstType + stuff->nTypes) > xkb->map->num_types) { 1483f7df2e56Smrg client->errorValue = _XkbErrCode4(0x04, xkb->map->num_types, 1484f7df2e56Smrg stuff->firstType, stuff->nTypes); 1485f7df2e56Smrg return BadValue; 1486f7df2e56Smrg } 1487f7df2e56Smrg rep.firstType = stuff->firstType; 1488f7df2e56Smrg rep.nTypes = stuff->nTypes; 1489f7df2e56Smrg } 1490f7df2e56Smrg else 1491f7df2e56Smrg rep.nTypes = 0; 149205b261ecSmrg rep.totalTypes = xkb->map->num_types; 149305b261ecSmrg 1494f7df2e56Smrg n = XkbNumKeys(xkb); 1495f7df2e56Smrg if (stuff->full & XkbKeySymsMask) { 1496f7df2e56Smrg rep.firstKeySym = xkb->min_key_code; 1497f7df2e56Smrg rep.nKeySyms = n; 1498f7df2e56Smrg } 1499f7df2e56Smrg else if (stuff->partial & XkbKeySymsMask) { 1500f7df2e56Smrg CHK_KEY_RANGE(0x05, stuff->firstKeySym, stuff->nKeySyms, xkb); 1501f7df2e56Smrg rep.firstKeySym = stuff->firstKeySym; 1502f7df2e56Smrg rep.nKeySyms = stuff->nKeySyms; 1503f7df2e56Smrg } 1504f7df2e56Smrg else 1505f7df2e56Smrg rep.nKeySyms = 0; 1506f7df2e56Smrg rep.totalSyms = 0; 1507f7df2e56Smrg 1508f7df2e56Smrg if (stuff->full & XkbKeyActionsMask) { 1509f7df2e56Smrg rep.firstKeyAct = xkb->min_key_code; 1510f7df2e56Smrg rep.nKeyActs = n; 1511f7df2e56Smrg } 1512f7df2e56Smrg else if (stuff->partial & XkbKeyActionsMask) { 1513f7df2e56Smrg CHK_KEY_RANGE(0x07, stuff->firstKeyAct, stuff->nKeyActs, xkb); 1514f7df2e56Smrg rep.firstKeyAct = stuff->firstKeyAct; 1515f7df2e56Smrg rep.nKeyActs = stuff->nKeyActs; 1516f7df2e56Smrg } 1517f7df2e56Smrg else 1518f7df2e56Smrg rep.nKeyActs = 0; 1519f7df2e56Smrg rep.totalActs = 0; 1520f7df2e56Smrg 1521f7df2e56Smrg if (stuff->full & XkbKeyBehaviorsMask) { 1522f7df2e56Smrg rep.firstKeyBehavior = xkb->min_key_code; 1523f7df2e56Smrg rep.nKeyBehaviors = n; 1524f7df2e56Smrg } 1525f7df2e56Smrg else if (stuff->partial & XkbKeyBehaviorsMask) { 1526f7df2e56Smrg CHK_KEY_RANGE(0x09, stuff->firstKeyBehavior, stuff->nKeyBehaviors, xkb); 1527f7df2e56Smrg rep.firstKeyBehavior = stuff->firstKeyBehavior; 1528f7df2e56Smrg rep.nKeyBehaviors = stuff->nKeyBehaviors; 1529f7df2e56Smrg } 1530f7df2e56Smrg else 1531f7df2e56Smrg rep.nKeyBehaviors = 0; 1532f7df2e56Smrg rep.totalKeyBehaviors = 0; 1533f7df2e56Smrg 1534f7df2e56Smrg if (stuff->full & XkbVirtualModsMask) 1535f7df2e56Smrg rep.virtualMods = ~0; 1536f7df2e56Smrg else if (stuff->partial & XkbVirtualModsMask) 1537f7df2e56Smrg rep.virtualMods = stuff->virtualMods; 1538f7df2e56Smrg 1539f7df2e56Smrg if (stuff->full & XkbExplicitComponentsMask) { 1540f7df2e56Smrg rep.firstKeyExplicit = xkb->min_key_code; 1541f7df2e56Smrg rep.nKeyExplicit = n; 1542f7df2e56Smrg } 1543f7df2e56Smrg else if (stuff->partial & XkbExplicitComponentsMask) { 1544f7df2e56Smrg CHK_KEY_RANGE(0x0B, stuff->firstKeyExplicit, stuff->nKeyExplicit, xkb); 1545f7df2e56Smrg rep.firstKeyExplicit = stuff->firstKeyExplicit; 1546f7df2e56Smrg rep.nKeyExplicit = stuff->nKeyExplicit; 1547f7df2e56Smrg } 1548f7df2e56Smrg else 1549f7df2e56Smrg rep.nKeyExplicit = 0; 1550f7df2e56Smrg rep.totalKeyExplicit = 0; 1551f7df2e56Smrg 1552f7df2e56Smrg if (stuff->full & XkbModifierMapMask) { 1553f7df2e56Smrg rep.firstModMapKey = xkb->min_key_code; 1554f7df2e56Smrg rep.nModMapKeys = n; 1555f7df2e56Smrg } 1556f7df2e56Smrg else if (stuff->partial & XkbModifierMapMask) { 1557f7df2e56Smrg CHK_KEY_RANGE(0x0D, stuff->firstModMapKey, stuff->nModMapKeys, xkb); 1558f7df2e56Smrg rep.firstModMapKey = stuff->firstModMapKey; 1559f7df2e56Smrg rep.nModMapKeys = stuff->nModMapKeys; 1560f7df2e56Smrg } 1561f7df2e56Smrg else 1562f7df2e56Smrg rep.nModMapKeys = 0; 1563f7df2e56Smrg rep.totalModMapKeys = 0; 1564f7df2e56Smrg 1565f7df2e56Smrg if (stuff->full & XkbVirtualModMapMask) { 1566f7df2e56Smrg rep.firstVModMapKey = xkb->min_key_code; 1567f7df2e56Smrg rep.nVModMapKeys = n; 1568f7df2e56Smrg } 1569f7df2e56Smrg else if (stuff->partial & XkbVirtualModMapMask) { 1570f7df2e56Smrg CHK_KEY_RANGE(0x0F, stuff->firstVModMapKey, stuff->nVModMapKeys, xkb); 1571f7df2e56Smrg rep.firstVModMapKey = stuff->firstVModMapKey; 1572f7df2e56Smrg rep.nVModMapKeys = stuff->nVModMapKeys; 1573f7df2e56Smrg } 1574f7df2e56Smrg else 1575f7df2e56Smrg rep.nVModMapKeys = 0; 1576f7df2e56Smrg rep.totalVModMapKeys = 0; 1577f7df2e56Smrg 1578f7df2e56Smrg if ((status = XkbComputeGetMapReplySize(xkb, &rep)) != Success) 1579f7df2e56Smrg return status; 1580f7df2e56Smrg return XkbSendMap(client, xkb, &rep); 158105b261ecSmrg} 158205b261ecSmrg 158305b261ecSmrg/***====================================================================***/ 158405b261ecSmrg 158505b261ecSmrgstatic int 1586f7df2e56SmrgCheckKeyTypes(ClientPtr client, 1587f7df2e56Smrg XkbDescPtr xkb, 1588f7df2e56Smrg xkbSetMapReq * req, 1589f7df2e56Smrg xkbKeyTypeWireDesc ** wireRtrn, 1590f7df2e56Smrg int *nMapsRtrn, CARD8 *mapWidthRtrn) 159105b261ecSmrg{ 1592f7df2e56Smrg unsigned nMaps; 1593f7df2e56Smrg register unsigned i, n; 1594f7df2e56Smrg register CARD8 *map; 1595f7df2e56Smrg register xkbKeyTypeWireDesc *wire = *wireRtrn; 1596f7df2e56Smrg 1597f7df2e56Smrg if (req->firstType > ((unsigned) xkb->map->num_types)) { 1598f7df2e56Smrg *nMapsRtrn = _XkbErrCode3(0x01, req->firstType, xkb->map->num_types); 1599f7df2e56Smrg return 0; 1600f7df2e56Smrg } 1601f7df2e56Smrg if (req->flags & XkbSetMapResizeTypes) { 1602f7df2e56Smrg nMaps = req->firstType + req->nTypes; 1603f7df2e56Smrg if (nMaps < XkbNumRequiredTypes) { /* canonical types must be there */ 1604f7df2e56Smrg *nMapsRtrn = _XkbErrCode4(0x02, req->firstType, req->nTypes, 4); 1605f7df2e56Smrg return 0; 1606f7df2e56Smrg } 1607f7df2e56Smrg } 1608f7df2e56Smrg else if (req->present & XkbKeyTypesMask) { 1609f7df2e56Smrg nMaps = xkb->map->num_types; 1610f7df2e56Smrg if ((req->firstType + req->nTypes) > nMaps) { 1611f7df2e56Smrg *nMapsRtrn = req->firstType + req->nTypes; 1612f7df2e56Smrg return 0; 1613f7df2e56Smrg } 161405b261ecSmrg } 161505b261ecSmrg else { 1616f7df2e56Smrg *nMapsRtrn = xkb->map->num_types; 1617f7df2e56Smrg for (i = 0; i < xkb->map->num_types; i++) { 1618f7df2e56Smrg mapWidthRtrn[i] = xkb->map->types[i].num_levels; 1619f7df2e56Smrg } 1620f7df2e56Smrg return 1; 1621f7df2e56Smrg } 1622f7df2e56Smrg 1623f7df2e56Smrg for (i = 0; i < req->firstType; i++) { 1624f7df2e56Smrg mapWidthRtrn[i] = xkb->map->types[i].num_levels; 1625f7df2e56Smrg } 1626f7df2e56Smrg for (i = 0; i < req->nTypes; i++) { 1627f7df2e56Smrg unsigned width; 1628f7df2e56Smrg 1629f7df2e56Smrg if (client->swapped) { 1630f7df2e56Smrg swaps(&wire->virtualMods); 1631f7df2e56Smrg } 1632f7df2e56Smrg n = i + req->firstType; 1633f7df2e56Smrg width = wire->numLevels; 1634f7df2e56Smrg if (width < 1) { 1635f7df2e56Smrg *nMapsRtrn = _XkbErrCode3(0x04, n, width); 1636f7df2e56Smrg return 0; 1637f7df2e56Smrg } 1638f7df2e56Smrg else if ((n == XkbOneLevelIndex) && (width != 1)) { /* must be width 1 */ 1639f7df2e56Smrg *nMapsRtrn = _XkbErrCode3(0x05, n, width); 1640f7df2e56Smrg return 0; 1641f7df2e56Smrg } 1642f7df2e56Smrg else if ((width != 2) && 1643f7df2e56Smrg ((n == XkbTwoLevelIndex) || (n == XkbKeypadIndex) || 1644f7df2e56Smrg (n == XkbAlphabeticIndex))) { 1645f7df2e56Smrg /* TWO_LEVEL, ALPHABETIC and KEYPAD must be width 2 */ 1646f7df2e56Smrg *nMapsRtrn = _XkbErrCode3(0x05, n, width); 1647f7df2e56Smrg return 0; 1648f7df2e56Smrg } 1649f7df2e56Smrg if (wire->nMapEntries > 0) { 1650f7df2e56Smrg xkbKTSetMapEntryWireDesc *mapWire; 1651f7df2e56Smrg xkbModsWireDesc *preWire; 1652f7df2e56Smrg 1653f7df2e56Smrg mapWire = (xkbKTSetMapEntryWireDesc *) &wire[1]; 1654f7df2e56Smrg preWire = (xkbModsWireDesc *) &mapWire[wire->nMapEntries]; 1655f7df2e56Smrg for (n = 0; n < wire->nMapEntries; n++) { 1656f7df2e56Smrg if (client->swapped) { 1657f7df2e56Smrg swaps(&mapWire[n].virtualMods); 1658f7df2e56Smrg } 1659f7df2e56Smrg if (mapWire[n].realMods & (~wire->realMods)) { 1660f7df2e56Smrg *nMapsRtrn = _XkbErrCode4(0x06, n, mapWire[n].realMods, 1661f7df2e56Smrg wire->realMods); 1662f7df2e56Smrg return 0; 1663f7df2e56Smrg } 1664f7df2e56Smrg if (mapWire[n].virtualMods & (~wire->virtualMods)) { 1665f7df2e56Smrg *nMapsRtrn = _XkbErrCode3(0x07, n, mapWire[n].virtualMods); 1666f7df2e56Smrg return 0; 1667f7df2e56Smrg } 1668f7df2e56Smrg if (mapWire[n].level >= wire->numLevels) { 1669f7df2e56Smrg *nMapsRtrn = _XkbErrCode4(0x08, n, wire->numLevels, 1670f7df2e56Smrg mapWire[n].level); 1671f7df2e56Smrg return 0; 1672f7df2e56Smrg } 1673f7df2e56Smrg if (wire->preserve) { 1674f7df2e56Smrg if (client->swapped) { 1675f7df2e56Smrg swaps(&preWire[n].virtualMods); 1676f7df2e56Smrg } 1677f7df2e56Smrg if (preWire[n].realMods & (~mapWire[n].realMods)) { 1678f7df2e56Smrg *nMapsRtrn = _XkbErrCode4(0x09, n, preWire[n].realMods, 1679f7df2e56Smrg mapWire[n].realMods); 1680f7df2e56Smrg return 0; 1681f7df2e56Smrg } 1682f7df2e56Smrg if (preWire[n].virtualMods & (~mapWire[n].virtualMods)) { 1683f7df2e56Smrg *nMapsRtrn = 1684f7df2e56Smrg _XkbErrCode3(0x0a, n, preWire[n].virtualMods); 1685f7df2e56Smrg return 0; 1686f7df2e56Smrg } 1687f7df2e56Smrg } 1688f7df2e56Smrg } 1689f7df2e56Smrg if (wire->preserve) 1690f7df2e56Smrg map = (CARD8 *) &preWire[wire->nMapEntries]; 1691f7df2e56Smrg else 1692f7df2e56Smrg map = (CARD8 *) &mapWire[wire->nMapEntries]; 1693f7df2e56Smrg } 1694f7df2e56Smrg else 1695f7df2e56Smrg map = (CARD8 *) &wire[1]; 1696f7df2e56Smrg mapWidthRtrn[i + req->firstType] = wire->numLevels; 1697f7df2e56Smrg wire = (xkbKeyTypeWireDesc *) map; 1698f7df2e56Smrg } 1699f7df2e56Smrg for (i = req->firstType + req->nTypes; i < nMaps; i++) { 1700f7df2e56Smrg mapWidthRtrn[i] = xkb->map->types[i].num_levels; 170105b261ecSmrg } 170205b261ecSmrg *nMapsRtrn = nMaps; 170305b261ecSmrg *wireRtrn = wire; 170405b261ecSmrg return 1; 170505b261ecSmrg} 170605b261ecSmrg 170705b261ecSmrgstatic int 1708f7df2e56SmrgCheckKeySyms(ClientPtr client, 1709f7df2e56Smrg XkbDescPtr xkb, 1710f7df2e56Smrg xkbSetMapReq * req, 1711f7df2e56Smrg int nTypes, 1712f7df2e56Smrg CARD8 *mapWidths, 1713f7df2e56Smrg CARD16 *symsPerKey, xkbSymMapWireDesc ** wireRtrn, int *errorRtrn) 171405b261ecSmrg{ 1715f7df2e56Smrg register unsigned i; 1716f7df2e56Smrg XkbSymMapPtr map; 1717f7df2e56Smrg xkbSymMapWireDesc *wire = *wireRtrn; 1718f7df2e56Smrg 1719f7df2e56Smrg if (!(XkbKeySymsMask & req->present)) 1720f7df2e56Smrg return 1; 1721f7df2e56Smrg CHK_REQ_KEY_RANGE2(0x11, req->firstKeySym, req->nKeySyms, req, (*errorRtrn), 1722f7df2e56Smrg 0); 1723f7df2e56Smrg for (i = 0; i < req->nKeySyms; i++) { 1724f7df2e56Smrg KeySym *pSyms; 1725f7df2e56Smrg register unsigned nG; 1726f7df2e56Smrg 1727f7df2e56Smrg if (client->swapped) { 1728f7df2e56Smrg swaps(&wire->nSyms); 1729f7df2e56Smrg } 1730f7df2e56Smrg nG = XkbNumGroups(wire->groupInfo); 1731f7df2e56Smrg if (nG > XkbNumKbdGroups) { 1732f7df2e56Smrg *errorRtrn = _XkbErrCode3(0x14, i + req->firstKeySym, nG); 1733f7df2e56Smrg return 0; 1734f7df2e56Smrg } 1735f7df2e56Smrg if (nG > 0) { 1736f7df2e56Smrg register int g, w; 1737f7df2e56Smrg 1738f7df2e56Smrg for (g = w = 0; g < nG; g++) { 1739f7df2e56Smrg if (wire->ktIndex[g] >= (unsigned) nTypes) { 1740f7df2e56Smrg *errorRtrn = _XkbErrCode4(0x15, i + req->firstKeySym, g, 1741f7df2e56Smrg wire->ktIndex[g]); 1742f7df2e56Smrg return 0; 1743f7df2e56Smrg } 1744f7df2e56Smrg if (mapWidths[wire->ktIndex[g]] > w) 1745f7df2e56Smrg w = mapWidths[wire->ktIndex[g]]; 1746f7df2e56Smrg } 1747f7df2e56Smrg if (wire->width != w) { 1748f7df2e56Smrg *errorRtrn = 1749f7df2e56Smrg _XkbErrCode3(0x16, i + req->firstKeySym, wire->width); 1750f7df2e56Smrg return 0; 1751f7df2e56Smrg } 1752f7df2e56Smrg w *= nG; 1753f7df2e56Smrg symsPerKey[i + req->firstKeySym] = w; 1754f7df2e56Smrg if (w != wire->nSyms) { 1755f7df2e56Smrg *errorRtrn = 1756f7df2e56Smrg _XkbErrCode4(0x16, i + req->firstKeySym, wire->nSyms, w); 1757f7df2e56Smrg return 0; 1758f7df2e56Smrg } 1759f7df2e56Smrg } 1760f7df2e56Smrg else if (wire->nSyms != 0) { 1761f7df2e56Smrg *errorRtrn = _XkbErrCode3(0x17, i + req->firstKeySym, wire->nSyms); 1762f7df2e56Smrg return 0; 1763f7df2e56Smrg } 1764f7df2e56Smrg pSyms = (KeySym *) &wire[1]; 1765f7df2e56Smrg wire = (xkbSymMapWireDesc *) &pSyms[wire->nSyms]; 176605b261ecSmrg } 176705b261ecSmrg 176805b261ecSmrg map = &xkb->map->key_sym_map[i]; 1769f7df2e56Smrg for (; i <= (unsigned) xkb->max_key_code; i++, map++) { 1770f7df2e56Smrg register int g, nG, w; 1771f7df2e56Smrg 1772f7df2e56Smrg nG = XkbKeyNumGroups(xkb, i); 1773f7df2e56Smrg for (w = g = 0; g < nG; g++) { 1774f7df2e56Smrg if (map->kt_index[g] >= (unsigned) nTypes) { 1775f7df2e56Smrg *errorRtrn = _XkbErrCode4(0x18, i, g, map->kt_index[g]); 1776f7df2e56Smrg return 0; 1777f7df2e56Smrg } 1778f7df2e56Smrg if (mapWidths[map->kt_index[g]] > w) 1779f7df2e56Smrg w = mapWidths[map->kt_index[g]]; 1780f7df2e56Smrg } 1781f7df2e56Smrg symsPerKey[i] = w * nG; 178205b261ecSmrg } 178305b261ecSmrg *wireRtrn = wire; 178405b261ecSmrg return 1; 178505b261ecSmrg} 178605b261ecSmrg 178705b261ecSmrgstatic int 1788f7df2e56SmrgCheckKeyActions(XkbDescPtr xkb, 1789f7df2e56Smrg xkbSetMapReq * req, 1790f7df2e56Smrg int nTypes, 1791f7df2e56Smrg CARD8 *mapWidths, 1792f7df2e56Smrg CARD16 *symsPerKey, CARD8 **wireRtrn, int *nActsRtrn) 179305b261ecSmrg{ 1794f7df2e56Smrg int nActs; 1795f7df2e56Smrg CARD8 *wire = *wireRtrn; 1796f7df2e56Smrg register unsigned i; 1797f7df2e56Smrg 1798f7df2e56Smrg if (!(XkbKeyActionsMask & req->present)) 1799f7df2e56Smrg return 1; 1800f7df2e56Smrg CHK_REQ_KEY_RANGE2(0x21, req->firstKeyAct, req->nKeyActs, req, (*nActsRtrn), 1801f7df2e56Smrg 0); 1802f7df2e56Smrg for (nActs = i = 0; i < req->nKeyActs; i++) { 1803f7df2e56Smrg if (wire[0] != 0) { 1804f7df2e56Smrg if (wire[0] == symsPerKey[i + req->firstKeyAct]) 1805f7df2e56Smrg nActs += wire[0]; 1806f7df2e56Smrg else { 1807f7df2e56Smrg *nActsRtrn = _XkbErrCode3(0x23, i + req->firstKeyAct, wire[0]); 1808f7df2e56Smrg return 0; 1809f7df2e56Smrg } 1810f7df2e56Smrg } 1811f7df2e56Smrg wire++; 1812f7df2e56Smrg } 1813f7df2e56Smrg if (req->nKeyActs % 4) 1814f7df2e56Smrg wire += 4 - (req->nKeyActs % 4); 1815f7df2e56Smrg *wireRtrn = (CARD8 *) (((XkbAnyAction *) wire) + nActs); 181605b261ecSmrg *nActsRtrn = nActs; 181705b261ecSmrg return 1; 181805b261ecSmrg} 181905b261ecSmrg 182005b261ecSmrgstatic int 1821f7df2e56SmrgCheckKeyBehaviors(XkbDescPtr xkb, 1822f7df2e56Smrg xkbSetMapReq * req, 1823f7df2e56Smrg xkbBehaviorWireDesc ** wireRtrn, int *errorRtrn) 182405b261ecSmrg{ 1825f7df2e56Smrg register xkbBehaviorWireDesc *wire = *wireRtrn; 1826f7df2e56Smrg register XkbServerMapPtr server = xkb->server; 1827f7df2e56Smrg register unsigned i; 1828f7df2e56Smrg unsigned first, last; 1829f7df2e56Smrg 1830f7df2e56Smrg if (((req->present & XkbKeyBehaviorsMask) == 0) || (req->nKeyBehaviors < 1)) { 1831f7df2e56Smrg req->present &= ~XkbKeyBehaviorsMask; 1832f7df2e56Smrg req->nKeyBehaviors = 0; 1833f7df2e56Smrg return 1; 1834f7df2e56Smrg } 1835f7df2e56Smrg first = req->firstKeyBehavior; 1836f7df2e56Smrg last = req->firstKeyBehavior + req->nKeyBehaviors - 1; 1837f7df2e56Smrg if (first < req->minKeyCode) { 1838f7df2e56Smrg *errorRtrn = _XkbErrCode3(0x31, first, req->minKeyCode); 1839f7df2e56Smrg return 0; 1840f7df2e56Smrg } 1841f7df2e56Smrg if (last > req->maxKeyCode) { 1842f7df2e56Smrg *errorRtrn = _XkbErrCode3(0x32, last, req->maxKeyCode); 1843f7df2e56Smrg return 0; 1844f7df2e56Smrg } 1845f7df2e56Smrg 1846f7df2e56Smrg for (i = 0; i < req->totalKeyBehaviors; i++, wire++) { 1847f7df2e56Smrg if ((wire->key < first) || (wire->key > last)) { 1848f7df2e56Smrg *errorRtrn = _XkbErrCode4(0x33, first, last, wire->key); 1849f7df2e56Smrg return 0; 1850f7df2e56Smrg } 1851f7df2e56Smrg if ((wire->type & XkbKB_Permanent) && 1852f7df2e56Smrg ((server->behaviors[wire->key].type != wire->type) || 1853f7df2e56Smrg (server->behaviors[wire->key].data != wire->data))) { 1854f7df2e56Smrg *errorRtrn = _XkbErrCode3(0x33, wire->key, wire->type); 1855f7df2e56Smrg return 0; 1856f7df2e56Smrg } 1857f7df2e56Smrg if ((wire->type == XkbKB_RadioGroup) && 1858f7df2e56Smrg ((wire->data & (~XkbKB_RGAllowNone)) > XkbMaxRadioGroups)) { 1859f7df2e56Smrg *errorRtrn = _XkbErrCode4(0x34, wire->key, wire->data, 1860f7df2e56Smrg XkbMaxRadioGroups); 1861f7df2e56Smrg return 0; 1862f7df2e56Smrg } 1863f7df2e56Smrg if ((wire->type == XkbKB_Overlay1) || (wire->type == XkbKB_Overlay2)) { 1864f7df2e56Smrg CHK_KEY_RANGE2(0x35, wire->key, 1, xkb, *errorRtrn, 0); 1865f7df2e56Smrg } 186605b261ecSmrg } 186705b261ecSmrg *wireRtrn = wire; 186805b261ecSmrg return 1; 186905b261ecSmrg} 187005b261ecSmrg 187105b261ecSmrgstatic int 1872f7df2e56SmrgCheckVirtualMods(XkbDescRec * xkb, 1873f7df2e56Smrg xkbSetMapReq * req, CARD8 **wireRtrn, int *errorRtrn) 187405b261ecSmrg{ 1875f7df2e56Smrg register CARD8 *wire = *wireRtrn; 1876f7df2e56Smrg register unsigned i, nMods, bit; 187705b261ecSmrg 1878f7df2e56Smrg if (((req->present & XkbVirtualModsMask) == 0) || (req->virtualMods == 0)) 1879f7df2e56Smrg return 1; 1880f7df2e56Smrg for (i = nMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) { 1881f7df2e56Smrg if (req->virtualMods & bit) 1882f7df2e56Smrg nMods++; 188305b261ecSmrg } 1884f7df2e56Smrg *wireRtrn = (wire + XkbPaddedSize(nMods)); 188505b261ecSmrg return 1; 188605b261ecSmrg} 188705b261ecSmrg 188805b261ecSmrgstatic int 1889f7df2e56SmrgCheckKeyExplicit(XkbDescPtr xkb, 1890f7df2e56Smrg xkbSetMapReq * req, CARD8 **wireRtrn, int *errorRtrn) 189105b261ecSmrg{ 1892f7df2e56Smrg register CARD8 *wire = *wireRtrn; 1893f7df2e56Smrg CARD8 *start; 1894f7df2e56Smrg register unsigned i; 1895f7df2e56Smrg int first, last; 1896f7df2e56Smrg 1897f7df2e56Smrg if (((req->present & XkbExplicitComponentsMask) == 0) || 1898f7df2e56Smrg (req->nKeyExplicit < 1)) { 1899f7df2e56Smrg req->present &= ~XkbExplicitComponentsMask; 1900f7df2e56Smrg req->nKeyExplicit = 0; 1901f7df2e56Smrg return 1; 1902f7df2e56Smrg } 1903f7df2e56Smrg first = req->firstKeyExplicit; 1904f7df2e56Smrg last = first + req->nKeyExplicit - 1; 1905f7df2e56Smrg if (first < req->minKeyCode) { 1906f7df2e56Smrg *errorRtrn = _XkbErrCode3(0x51, first, req->minKeyCode); 1907f7df2e56Smrg return 0; 1908f7df2e56Smrg } 1909f7df2e56Smrg if (last > req->maxKeyCode) { 1910f7df2e56Smrg *errorRtrn = _XkbErrCode3(0x52, last, req->maxKeyCode); 1911f7df2e56Smrg return 0; 1912f7df2e56Smrg } 1913f7df2e56Smrg start = wire; 1914f7df2e56Smrg for (i = 0; i < req->totalKeyExplicit; i++, wire += 2) { 1915f7df2e56Smrg if ((wire[0] < first) || (wire[0] > last)) { 1916f7df2e56Smrg *errorRtrn = _XkbErrCode4(0x53, first, last, wire[0]); 1917f7df2e56Smrg return 0; 1918f7df2e56Smrg } 1919f7df2e56Smrg if (wire[1] & (~XkbAllExplicitMask)) { 1920f7df2e56Smrg *errorRtrn = _XkbErrCode3(0x52, ~XkbAllExplicitMask, wire[1]); 1921f7df2e56Smrg return 0; 1922f7df2e56Smrg } 1923f7df2e56Smrg } 1924f7df2e56Smrg wire += XkbPaddedSize(wire - start) - (wire - start); 1925f7df2e56Smrg *wireRtrn = wire; 192605b261ecSmrg return 1; 192705b261ecSmrg} 192805b261ecSmrg 192905b261ecSmrgstatic int 1930f7df2e56SmrgCheckModifierMap(XkbDescPtr xkb, xkbSetMapReq * req, CARD8 **wireRtrn, 1931f7df2e56Smrg int *errRtrn) 193205b261ecSmrg{ 1933f7df2e56Smrg register CARD8 *wire = *wireRtrn; 1934f7df2e56Smrg CARD8 *start; 1935f7df2e56Smrg register unsigned i; 1936f7df2e56Smrg int first, last; 1937f7df2e56Smrg 1938f7df2e56Smrg if (((req->present & XkbModifierMapMask) == 0) || (req->nModMapKeys < 1)) { 1939f7df2e56Smrg req->present &= ~XkbModifierMapMask; 1940f7df2e56Smrg req->nModMapKeys = 0; 1941f7df2e56Smrg return 1; 1942f7df2e56Smrg } 1943f7df2e56Smrg first = req->firstModMapKey; 1944f7df2e56Smrg last = first + req->nModMapKeys - 1; 1945f7df2e56Smrg if (first < req->minKeyCode) { 1946f7df2e56Smrg *errRtrn = _XkbErrCode3(0x61, first, req->minKeyCode); 1947f7df2e56Smrg return 0; 1948f7df2e56Smrg } 1949f7df2e56Smrg if (last > req->maxKeyCode) { 1950f7df2e56Smrg *errRtrn = _XkbErrCode3(0x62, last, req->maxKeyCode); 1951f7df2e56Smrg return 0; 1952f7df2e56Smrg } 1953f7df2e56Smrg start = wire; 1954f7df2e56Smrg for (i = 0; i < req->totalModMapKeys; i++, wire += 2) { 1955f7df2e56Smrg if ((wire[0] < first) || (wire[0] > last)) { 1956f7df2e56Smrg *errRtrn = _XkbErrCode4(0x63, first, last, wire[0]); 1957f7df2e56Smrg return 0; 1958f7df2e56Smrg } 1959f7df2e56Smrg } 1960f7df2e56Smrg wire += XkbPaddedSize(wire - start) - (wire - start); 1961f7df2e56Smrg *wireRtrn = wire; 196205b261ecSmrg return 1; 196305b261ecSmrg} 196405b261ecSmrg 196505b261ecSmrgstatic int 1966f7df2e56SmrgCheckVirtualModMap(XkbDescPtr xkb, 1967f7df2e56Smrg xkbSetMapReq * req, 1968f7df2e56Smrg xkbVModMapWireDesc ** wireRtrn, int *errRtrn) 196905b261ecSmrg{ 1970f7df2e56Smrg register xkbVModMapWireDesc *wire = *wireRtrn; 1971f7df2e56Smrg register unsigned i; 1972f7df2e56Smrg int first, last; 1973f7df2e56Smrg 1974f7df2e56Smrg if (((req->present & XkbVirtualModMapMask) == 0) || (req->nVModMapKeys < 1)) { 1975f7df2e56Smrg req->present &= ~XkbVirtualModMapMask; 1976f7df2e56Smrg req->nVModMapKeys = 0; 1977f7df2e56Smrg return 1; 1978f7df2e56Smrg } 1979f7df2e56Smrg first = req->firstVModMapKey; 1980f7df2e56Smrg last = first + req->nVModMapKeys - 1; 1981f7df2e56Smrg if (first < req->minKeyCode) { 1982f7df2e56Smrg *errRtrn = _XkbErrCode3(0x71, first, req->minKeyCode); 1983f7df2e56Smrg return 0; 1984f7df2e56Smrg } 1985f7df2e56Smrg if (last > req->maxKeyCode) { 1986f7df2e56Smrg *errRtrn = _XkbErrCode3(0x72, last, req->maxKeyCode); 1987f7df2e56Smrg return 0; 1988f7df2e56Smrg } 1989f7df2e56Smrg for (i = 0; i < req->totalVModMapKeys; i++, wire++) { 1990f7df2e56Smrg if ((wire->key < first) || (wire->key > last)) { 1991f7df2e56Smrg *errRtrn = _XkbErrCode4(0x73, first, last, wire->key); 1992f7df2e56Smrg return 0; 1993f7df2e56Smrg } 1994f7df2e56Smrg } 1995f7df2e56Smrg *wireRtrn = wire; 199605b261ecSmrg return 1; 199705b261ecSmrg} 199805b261ecSmrg 199905b261ecSmrgstatic char * 2000f7df2e56SmrgSetKeyTypes(XkbDescPtr xkb, 2001f7df2e56Smrg xkbSetMapReq * req, 2002f7df2e56Smrg xkbKeyTypeWireDesc * wire, XkbChangesPtr changes) 200305b261ecSmrg{ 2004f7df2e56Smrg register unsigned i; 2005f7df2e56Smrg unsigned first, last; 2006f7df2e56Smrg CARD8 *map; 2007f7df2e56Smrg 2008f7df2e56Smrg if ((unsigned) (req->firstType + req->nTypes) > xkb->map->size_types) { 2009f7df2e56Smrg i = req->firstType + req->nTypes; 2010f7df2e56Smrg if (XkbAllocClientMap(xkb, XkbKeyTypesMask, i) != Success) { 2011f7df2e56Smrg return NULL; 2012f7df2e56Smrg } 2013f7df2e56Smrg } 2014f7df2e56Smrg if ((unsigned) (req->firstType + req->nTypes) > xkb->map->num_types) 2015f7df2e56Smrg xkb->map->num_types = req->firstType + req->nTypes; 2016f7df2e56Smrg 2017f7df2e56Smrg for (i = 0; i < req->nTypes; i++) { 2018f7df2e56Smrg XkbKeyTypePtr pOld; 2019f7df2e56Smrg register unsigned n; 2020f7df2e56Smrg 2021f7df2e56Smrg if (XkbResizeKeyType(xkb, i + req->firstType, wire->nMapEntries, 2022f7df2e56Smrg wire->preserve, wire->numLevels) != Success) { 2023f7df2e56Smrg return NULL; 2024f7df2e56Smrg } 2025f7df2e56Smrg pOld = &xkb->map->types[i + req->firstType]; 2026f7df2e56Smrg map = (CARD8 *) &wire[1]; 2027f7df2e56Smrg 2028f7df2e56Smrg pOld->mods.real_mods = wire->realMods; 2029f7df2e56Smrg pOld->mods.vmods = wire->virtualMods; 2030f7df2e56Smrg pOld->num_levels = wire->numLevels; 2031f7df2e56Smrg pOld->map_count = wire->nMapEntries; 2032f7df2e56Smrg 2033f7df2e56Smrg pOld->mods.mask = pOld->mods.real_mods | 2034f7df2e56Smrg XkbMaskForVMask(xkb, pOld->mods.vmods); 2035f7df2e56Smrg 2036f7df2e56Smrg if (wire->nMapEntries) { 2037f7df2e56Smrg xkbKTSetMapEntryWireDesc *mapWire; 2038f7df2e56Smrg xkbModsWireDesc *preWire; 2039f7df2e56Smrg unsigned tmp; 2040f7df2e56Smrg 2041f7df2e56Smrg mapWire = (xkbKTSetMapEntryWireDesc *) map; 2042f7df2e56Smrg preWire = (xkbModsWireDesc *) &mapWire[wire->nMapEntries]; 2043f7df2e56Smrg for (n = 0; n < wire->nMapEntries; n++) { 2044f7df2e56Smrg pOld->map[n].active = 1; 2045f7df2e56Smrg pOld->map[n].mods.mask = mapWire[n].realMods; 2046f7df2e56Smrg pOld->map[n].mods.real_mods = mapWire[n].realMods; 2047f7df2e56Smrg pOld->map[n].mods.vmods = mapWire[n].virtualMods; 2048f7df2e56Smrg pOld->map[n].level = mapWire[n].level; 2049f7df2e56Smrg if (mapWire[n].virtualMods != 0) { 2050f7df2e56Smrg tmp = XkbMaskForVMask(xkb, mapWire[n].virtualMods); 2051f7df2e56Smrg pOld->map[n].active = (tmp != 0); 2052f7df2e56Smrg pOld->map[n].mods.mask |= tmp; 2053f7df2e56Smrg } 2054f7df2e56Smrg if (wire->preserve) { 2055f7df2e56Smrg pOld->preserve[n].real_mods = preWire[n].realMods; 2056f7df2e56Smrg pOld->preserve[n].vmods = preWire[n].virtualMods; 2057f7df2e56Smrg tmp = XkbMaskForVMask(xkb, preWire[n].virtualMods); 2058f7df2e56Smrg pOld->preserve[n].mask = preWire[n].realMods | tmp; 2059f7df2e56Smrg } 2060f7df2e56Smrg } 2061f7df2e56Smrg if (wire->preserve) 2062f7df2e56Smrg map = (CARD8 *) &preWire[wire->nMapEntries]; 2063f7df2e56Smrg else 2064f7df2e56Smrg map = (CARD8 *) &mapWire[wire->nMapEntries]; 2065f7df2e56Smrg } 2066f7df2e56Smrg else 2067f7df2e56Smrg map = (CARD8 *) &wire[1]; 2068f7df2e56Smrg wire = (xkbKeyTypeWireDesc *) map; 2069f7df2e56Smrg } 2070f7df2e56Smrg first = req->firstType; 2071f7df2e56Smrg last = first + req->nTypes - 1; /* last changed type */ 2072f7df2e56Smrg if (changes->map.changed & XkbKeyTypesMask) { 2073f7df2e56Smrg int oldLast; 2074f7df2e56Smrg 2075f7df2e56Smrg oldLast = changes->map.first_type + changes->map.num_types - 1; 2076f7df2e56Smrg if (changes->map.first_type < first) 2077f7df2e56Smrg first = changes->map.first_type; 2078f7df2e56Smrg if (oldLast > last) 2079f7df2e56Smrg last = oldLast; 2080f7df2e56Smrg } 2081f7df2e56Smrg changes->map.changed |= XkbKeyTypesMask; 208205b261ecSmrg changes->map.first_type = first; 2083f7df2e56Smrg changes->map.num_types = (last - first) + 1; 2084f7df2e56Smrg return (char *) wire; 208505b261ecSmrg} 208605b261ecSmrg 208705b261ecSmrgstatic char * 2088f7df2e56SmrgSetKeySyms(ClientPtr client, 2089f7df2e56Smrg XkbDescPtr xkb, 2090f7df2e56Smrg xkbSetMapReq * req, 2091f7df2e56Smrg xkbSymMapWireDesc * wire, XkbChangesPtr changes, DeviceIntPtr dev) 209205b261ecSmrg{ 2093f7df2e56Smrg register unsigned i, s; 2094f7df2e56Smrg XkbSymMapPtr oldMap; 2095f7df2e56Smrg KeySym *newSyms; 2096f7df2e56Smrg KeySym *pSyms; 2097f7df2e56Smrg unsigned first, last; 209805b261ecSmrg 209905b261ecSmrg oldMap = &xkb->map->key_sym_map[req->firstKeySym]; 2100f7df2e56Smrg for (i = 0; i < req->nKeySyms; i++, oldMap++) { 2101f7df2e56Smrg pSyms = (KeySym *) &wire[1]; 2102f7df2e56Smrg if (wire->nSyms > 0) { 2103f7df2e56Smrg newSyms = XkbResizeKeySyms(xkb, i + req->firstKeySym, wire->nSyms); 2104f7df2e56Smrg for (s = 0; s < wire->nSyms; s++) { 2105f7df2e56Smrg newSyms[s] = pSyms[s]; 2106f7df2e56Smrg } 2107f7df2e56Smrg if (client->swapped) { 2108f7df2e56Smrg for (s = 0; s < wire->nSyms; s++) { 2109f7df2e56Smrg swapl(&newSyms[s]); 2110f7df2e56Smrg } 2111f7df2e56Smrg } 2112f7df2e56Smrg } 2113f7df2e56Smrg oldMap->kt_index[0] = wire->ktIndex[0]; 2114f7df2e56Smrg oldMap->kt_index[1] = wire->ktIndex[1]; 2115f7df2e56Smrg oldMap->kt_index[2] = wire->ktIndex[2]; 2116f7df2e56Smrg oldMap->kt_index[3] = wire->ktIndex[3]; 2117f7df2e56Smrg oldMap->group_info = wire->groupInfo; 2118f7df2e56Smrg oldMap->width = wire->width; 2119f7df2e56Smrg wire = (xkbSymMapWireDesc *) &pSyms[wire->nSyms]; 2120f7df2e56Smrg } 2121f7df2e56Smrg first = req->firstKeySym; 2122f7df2e56Smrg last = first + req->nKeySyms - 1; 2123f7df2e56Smrg if (changes->map.changed & XkbKeySymsMask) { 2124f7df2e56Smrg int oldLast = 2125f7df2e56Smrg (changes->map.first_key_sym + changes->map.num_key_syms - 1); 2126f7df2e56Smrg if (changes->map.first_key_sym < first) 2127f7df2e56Smrg first = changes->map.first_key_sym; 2128f7df2e56Smrg if (oldLast > last) 2129f7df2e56Smrg last = oldLast; 2130f7df2e56Smrg } 2131f7df2e56Smrg changes->map.changed |= XkbKeySymsMask; 213205b261ecSmrg changes->map.first_key_sym = first; 2133f7df2e56Smrg changes->map.num_key_syms = (last - first + 1); 2134f7df2e56Smrg 2135f7df2e56Smrg s = 0; 2136f7df2e56Smrg for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) { 2137f7df2e56Smrg if (XkbKeyNumGroups(xkb, i) > s) 2138f7df2e56Smrg s = XkbKeyNumGroups(xkb, i); 2139f7df2e56Smrg } 2140f7df2e56Smrg if (s != xkb->ctrls->num_groups) { 2141f7df2e56Smrg xkbControlsNotify cn; 2142f7df2e56Smrg XkbControlsRec old; 2143f7df2e56Smrg 2144f7df2e56Smrg cn.keycode = 0; 2145f7df2e56Smrg cn.eventType = 0; 2146f7df2e56Smrg cn.requestMajor = XkbReqCode; 2147f7df2e56Smrg cn.requestMinor = X_kbSetMap; 2148f7df2e56Smrg old = *xkb->ctrls; 2149f7df2e56Smrg xkb->ctrls->num_groups = s; 2150f7df2e56Smrg if (XkbComputeControlsNotify(dev, &old, xkb->ctrls, &cn, FALSE)) 2151f7df2e56Smrg XkbSendControlsNotify(dev, &cn); 2152f7df2e56Smrg } 2153f7df2e56Smrg return (char *) wire; 215405b261ecSmrg} 215505b261ecSmrg 215605b261ecSmrgstatic char * 2157f7df2e56SmrgSetKeyActions(XkbDescPtr xkb, 2158f7df2e56Smrg xkbSetMapReq * req, CARD8 *wire, XkbChangesPtr changes) 215905b261ecSmrg{ 2160f7df2e56Smrg register unsigned i, first, last; 2161f7df2e56Smrg CARD8 *nActs = wire; 2162f7df2e56Smrg XkbAction *newActs; 2163f7df2e56Smrg 2164f7df2e56Smrg wire += XkbPaddedSize(req->nKeyActs); 2165f7df2e56Smrg for (i = 0; i < req->nKeyActs; i++) { 2166f7df2e56Smrg if (nActs[i] == 0) 2167f7df2e56Smrg xkb->server->key_acts[i + req->firstKeyAct] = 0; 2168f7df2e56Smrg else { 2169f7df2e56Smrg newActs = XkbResizeKeyActions(xkb, i + req->firstKeyAct, nActs[i]); 2170f7df2e56Smrg memcpy((char *) newActs, (char *) wire, 2171f7df2e56Smrg nActs[i] * SIZEOF(xkbActionWireDesc)); 2172f7df2e56Smrg wire += nActs[i] * SIZEOF(xkbActionWireDesc); 2173f7df2e56Smrg } 2174f7df2e56Smrg } 2175f7df2e56Smrg first = req->firstKeyAct; 2176f7df2e56Smrg last = (first + req->nKeyActs - 1); 2177f7df2e56Smrg if (changes->map.changed & XkbKeyActionsMask) { 2178f7df2e56Smrg int oldLast; 2179f7df2e56Smrg 2180f7df2e56Smrg oldLast = changes->map.first_key_act + changes->map.num_key_acts - 1; 2181f7df2e56Smrg if (changes->map.first_key_act < first) 2182f7df2e56Smrg first = changes->map.first_key_act; 2183f7df2e56Smrg if (oldLast > last) 2184f7df2e56Smrg last = oldLast; 2185f7df2e56Smrg } 2186f7df2e56Smrg changes->map.changed |= XkbKeyActionsMask; 2187f7df2e56Smrg changes->map.first_key_act = first; 2188f7df2e56Smrg changes->map.num_key_acts = (last - first + 1); 2189f7df2e56Smrg return (char *) wire; 219005b261ecSmrg} 219105b261ecSmrg 219205b261ecSmrgstatic char * 2193f7df2e56SmrgSetKeyBehaviors(XkbSrvInfoPtr xkbi, 2194f7df2e56Smrg xkbSetMapReq * req, 2195f7df2e56Smrg xkbBehaviorWireDesc * wire, XkbChangesPtr changes) 219605b261ecSmrg{ 2197f7df2e56Smrg register unsigned i; 2198f7df2e56Smrg int maxRG = -1; 2199f7df2e56Smrg XkbDescPtr xkb = xkbi->desc; 2200f7df2e56Smrg XkbServerMapPtr server = xkb->server; 2201f7df2e56Smrg unsigned first, last; 2202f7df2e56Smrg 2203f7df2e56Smrg first = req->firstKeyBehavior; 2204f7df2e56Smrg last = req->firstKeyBehavior + req->nKeyBehaviors - 1; 2205f7df2e56Smrg memset(&server->behaviors[first], 0, 2206f7df2e56Smrg req->nKeyBehaviors * sizeof(XkbBehavior)); 2207f7df2e56Smrg for (i = 0; i < req->totalKeyBehaviors; i++) { 2208f7df2e56Smrg if ((server->behaviors[wire->key].type & XkbKB_Permanent) == 0) { 2209f7df2e56Smrg server->behaviors[wire->key].type = wire->type; 2210f7df2e56Smrg server->behaviors[wire->key].data = wire->data; 2211f7df2e56Smrg if ((wire->type == XkbKB_RadioGroup) && 2212f7df2e56Smrg (((int) wire->data) > maxRG)) 2213f7df2e56Smrg maxRG = wire->data + 1; 2214f7df2e56Smrg } 2215f7df2e56Smrg wire++; 2216f7df2e56Smrg } 2217f7df2e56Smrg 2218f7df2e56Smrg if (maxRG > (int) xkbi->nRadioGroups) { 221905b261ecSmrg if (xkbi->radioGroups) 2220f7df2e56Smrg xkbi->radioGroups = reallocarray(xkbi->radioGroups, maxRG, 2221f7df2e56Smrg sizeof(XkbRadioGroupRec)); 2222f7df2e56Smrg else 2223f7df2e56Smrg xkbi->radioGroups = calloc(maxRG, sizeof(XkbRadioGroupRec)); 222405b261ecSmrg if (xkbi->radioGroups) { 2225f7df2e56Smrg if (xkbi->nRadioGroups) 2226f7df2e56Smrg memset(&xkbi->radioGroups[xkbi->nRadioGroups], 0, 2227f7df2e56Smrg (maxRG - xkbi->nRadioGroups) * sizeof(XkbRadioGroupRec)); 2228f7df2e56Smrg xkbi->nRadioGroups = maxRG; 222905b261ecSmrg } 2230f7df2e56Smrg else 2231f7df2e56Smrg xkbi->nRadioGroups = 0; 223205b261ecSmrg /* should compute members here */ 223305b261ecSmrg } 2234f7df2e56Smrg if (changes->map.changed & XkbKeyBehaviorsMask) { 2235f7df2e56Smrg unsigned oldLast; 2236f7df2e56Smrg 2237f7df2e56Smrg oldLast = changes->map.first_key_behavior + 2238f7df2e56Smrg changes->map.num_key_behaviors - 1; 2239f7df2e56Smrg if (changes->map.first_key_behavior < req->firstKeyBehavior) 2240f7df2e56Smrg first = changes->map.first_key_behavior; 2241f7df2e56Smrg if (oldLast > last) 2242f7df2e56Smrg last = oldLast; 224305b261ecSmrg } 2244f7df2e56Smrg changes->map.changed |= XkbKeyBehaviorsMask; 224505b261ecSmrg changes->map.first_key_behavior = first; 2246f7df2e56Smrg changes->map.num_key_behaviors = (last - first + 1); 2247f7df2e56Smrg return (char *) wire; 224805b261ecSmrg} 224905b261ecSmrg 225005b261ecSmrgstatic char * 2251f7df2e56SmrgSetVirtualMods(XkbSrvInfoPtr xkbi, xkbSetMapReq * req, CARD8 *wire, 2252f7df2e56Smrg XkbChangesPtr changes) 225305b261ecSmrg{ 2254f7df2e56Smrg register int i, bit, nMods; 2255f7df2e56Smrg XkbServerMapPtr srv = xkbi->desc->server; 2256f7df2e56Smrg 2257f7df2e56Smrg if (((req->present & XkbVirtualModsMask) == 0) || (req->virtualMods == 0)) 2258f7df2e56Smrg return (char *) wire; 2259f7df2e56Smrg for (i = nMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) { 2260f7df2e56Smrg if (req->virtualMods & bit) { 2261f7df2e56Smrg if (srv->vmods[i] != wire[nMods]) { 2262f7df2e56Smrg changes->map.changed |= XkbVirtualModsMask; 2263f7df2e56Smrg changes->map.vmods |= bit; 2264f7df2e56Smrg srv->vmods[i] = wire[nMods]; 2265f7df2e56Smrg } 2266f7df2e56Smrg nMods++; 2267f7df2e56Smrg } 2268f7df2e56Smrg } 2269f7df2e56Smrg return (char *) (wire + XkbPaddedSize(nMods)); 227005b261ecSmrg} 227105b261ecSmrg 227205b261ecSmrgstatic char * 2273f7df2e56SmrgSetKeyExplicit(XkbSrvInfoPtr xkbi, xkbSetMapReq * req, CARD8 *wire, 2274f7df2e56Smrg XkbChangesPtr changes) 227505b261ecSmrg{ 2276f7df2e56Smrg register unsigned i, first, last; 2277f7df2e56Smrg XkbServerMapPtr xkb = xkbi->desc->server; 2278f7df2e56Smrg CARD8 *start; 227905b261ecSmrg 2280f7df2e56Smrg start = wire; 2281f7df2e56Smrg first = req->firstKeyExplicit; 2282f7df2e56Smrg last = req->firstKeyExplicit + req->nKeyExplicit - 1; 22836747b715Smrg memset(&xkb->explicit[first], 0, req->nKeyExplicit); 2284f7df2e56Smrg for (i = 0; i < req->totalKeyExplicit; i++, wire += 2) { 2285f7df2e56Smrg xkb->explicit[wire[0]] = wire[1]; 2286f7df2e56Smrg } 2287f7df2e56Smrg if (first > 0) { 2288f7df2e56Smrg if (changes->map.changed & XkbExplicitComponentsMask) { 2289f7df2e56Smrg int oldLast; 2290f7df2e56Smrg 2291f7df2e56Smrg oldLast = changes->map.first_key_explicit + 2292f7df2e56Smrg changes->map.num_key_explicit - 1; 2293f7df2e56Smrg if (changes->map.first_key_explicit < first) 2294f7df2e56Smrg first = changes->map.first_key_explicit; 2295f7df2e56Smrg if (oldLast > last) 2296f7df2e56Smrg last = oldLast; 2297f7df2e56Smrg } 2298f7df2e56Smrg changes->map.first_key_explicit = first; 2299f7df2e56Smrg changes->map.num_key_explicit = (last - first) + 1; 2300f7df2e56Smrg } 2301f7df2e56Smrg wire += XkbPaddedSize(wire - start) - (wire - start); 2302f7df2e56Smrg return (char *) wire; 230305b261ecSmrg} 230405b261ecSmrg 230505b261ecSmrgstatic char * 2306f7df2e56SmrgSetModifierMap(XkbSrvInfoPtr xkbi, 2307f7df2e56Smrg xkbSetMapReq * req, CARD8 *wire, XkbChangesPtr changes) 230805b261ecSmrg{ 2309f7df2e56Smrg register unsigned i, first, last; 2310f7df2e56Smrg XkbClientMapPtr xkb = xkbi->desc->map; 2311f7df2e56Smrg CARD8 *start; 231205b261ecSmrg 2313f7df2e56Smrg start = wire; 2314f7df2e56Smrg first = req->firstModMapKey; 2315f7df2e56Smrg last = req->firstModMapKey + req->nModMapKeys - 1; 23166747b715Smrg memset(&xkb->modmap[first], 0, req->nModMapKeys); 2317f7df2e56Smrg for (i = 0; i < req->totalModMapKeys; i++, wire += 2) { 2318f7df2e56Smrg xkb->modmap[wire[0]] = wire[1]; 2319f7df2e56Smrg } 2320f7df2e56Smrg if (first > 0) { 2321f7df2e56Smrg if (changes->map.changed & XkbModifierMapMask) { 2322f7df2e56Smrg int oldLast; 2323f7df2e56Smrg 2324f7df2e56Smrg oldLast = changes->map.first_modmap_key + 2325f7df2e56Smrg changes->map.num_modmap_keys - 1; 2326f7df2e56Smrg if (changes->map.first_modmap_key < first) 2327f7df2e56Smrg first = changes->map.first_modmap_key; 2328f7df2e56Smrg if (oldLast > last) 2329f7df2e56Smrg last = oldLast; 2330f7df2e56Smrg } 2331f7df2e56Smrg changes->map.first_modmap_key = first; 2332f7df2e56Smrg changes->map.num_modmap_keys = (last - first) + 1; 2333f7df2e56Smrg } 2334f7df2e56Smrg wire += XkbPaddedSize(wire - start) - (wire - start); 2335f7df2e56Smrg return (char *) wire; 233605b261ecSmrg} 233705b261ecSmrg 233805b261ecSmrgstatic char * 2339f7df2e56SmrgSetVirtualModMap(XkbSrvInfoPtr xkbi, 2340f7df2e56Smrg xkbSetMapReq * req, 2341f7df2e56Smrg xkbVModMapWireDesc * wire, XkbChangesPtr changes) 234205b261ecSmrg{ 2343f7df2e56Smrg register unsigned i, first, last; 2344f7df2e56Smrg XkbServerMapPtr srv = xkbi->desc->server; 2345f7df2e56Smrg 2346f7df2e56Smrg first = req->firstVModMapKey; 2347f7df2e56Smrg last = req->firstVModMapKey + req->nVModMapKeys - 1; 2348f7df2e56Smrg memset(&srv->vmodmap[first], 0, req->nVModMapKeys * sizeof(unsigned short)); 2349f7df2e56Smrg for (i = 0; i < req->totalVModMapKeys; i++, wire++) { 2350f7df2e56Smrg srv->vmodmap[wire->key] = wire->vmods; 2351f7df2e56Smrg } 2352f7df2e56Smrg if (first > 0) { 2353f7df2e56Smrg if (changes->map.changed & XkbVirtualModMapMask) { 2354f7df2e56Smrg int oldLast; 2355f7df2e56Smrg 2356f7df2e56Smrg oldLast = changes->map.first_vmodmap_key + 2357f7df2e56Smrg changes->map.num_vmodmap_keys - 1; 2358f7df2e56Smrg if (changes->map.first_vmodmap_key < first) 2359f7df2e56Smrg first = changes->map.first_vmodmap_key; 2360f7df2e56Smrg if (oldLast > last) 2361f7df2e56Smrg last = oldLast; 2362f7df2e56Smrg } 2363f7df2e56Smrg changes->map.first_vmodmap_key = first; 2364f7df2e56Smrg changes->map.num_vmodmap_keys = (last - first) + 1; 2365f7df2e56Smrg } 2366f7df2e56Smrg return (char *) wire; 236705b261ecSmrg} 236805b261ecSmrg 23694642e01fSmrg/** 23704642e01fSmrg * Check if the given request can be applied to the given device but don't 23714642e01fSmrg * actually do anything.. 23724642e01fSmrg */ 23734642e01fSmrgstatic int 2374f7df2e56Smrg_XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq * req, 2375f7df2e56Smrg char *values) 237605b261ecSmrg{ 2377f7df2e56Smrg XkbSrvInfoPtr xkbi; 2378f7df2e56Smrg XkbDescPtr xkb; 2379f7df2e56Smrg int error; 2380f7df2e56Smrg int nTypes = 0, nActions; 2381f7df2e56Smrg CARD8 mapWidths[XkbMaxLegalKeyCode + 1] = { 0 }; 2382f7df2e56Smrg CARD16 symsPerKey[XkbMaxLegalKeyCode + 1] = { 0 }; 2383f7df2e56Smrg XkbSymMapPtr map; 2384f7df2e56Smrg int i; 2385f7df2e56Smrg 2386f7df2e56Smrg xkbi = dev->key->xkbInfo; 238705b261ecSmrg xkb = xkbi->desc; 238805b261ecSmrg 2389f7df2e56Smrg if ((xkb->min_key_code != req->minKeyCode) || 23904642e01fSmrg (xkb->max_key_code != req->maxKeyCode)) { 23917e31ba66Smrg if (client->xkbClientFlags & _XkbClientIsAncient) { 23927e31ba66Smrg /* pre 1.0 versions of Xlib have a bug */ 2393f7df2e56Smrg req->minKeyCode = xkb->min_key_code; 2394f7df2e56Smrg req->maxKeyCode = xkb->max_key_code; 2395f7df2e56Smrg } 2396f7df2e56Smrg else { 2397f7df2e56Smrg if (!XkbIsLegalKeycode(req->minKeyCode)) { 2398f7df2e56Smrg client->errorValue = 2399f7df2e56Smrg _XkbErrCode3(2, req->minKeyCode, req->maxKeyCode); 2400f7df2e56Smrg return BadValue; 2401f7df2e56Smrg } 2402f7df2e56Smrg if (req->minKeyCode > req->maxKeyCode) { 2403f7df2e56Smrg client->errorValue = 2404f7df2e56Smrg _XkbErrCode3(3, req->minKeyCode, req->maxKeyCode); 2405f7df2e56Smrg return BadMatch; 2406f7df2e56Smrg } 2407f7df2e56Smrg } 240805b261ecSmrg } 240905b261ecSmrg 24104642e01fSmrg if ((req->present & XkbKeyTypesMask) && 2411f7df2e56Smrg (!CheckKeyTypes(client, xkb, req, (xkbKeyTypeWireDesc **) &values, 2412f7df2e56Smrg &nTypes, mapWidths))) { 2413f7df2e56Smrg client->errorValue = nTypes; 2414f7df2e56Smrg return BadValue; 241505b261ecSmrg } 24169ace9065Smrg 24179ace9065Smrg /* symsPerKey/mapWidths must be filled regardless of client-side flags */ 24189ace9065Smrg map = &xkb->map->key_sym_map[xkb->min_key_code]; 2419f7df2e56Smrg for (i = xkb->min_key_code; i < xkb->max_key_code; i++, map++) { 2420f7df2e56Smrg register int g, ng, w; 2421f7df2e56Smrg 2422f7df2e56Smrg ng = XkbNumGroups(map->group_info); 2423f7df2e56Smrg for (w = g = 0; g < ng; g++) { 2424f7df2e56Smrg if (map->kt_index[g] >= (unsigned) nTypes) { 2425f7df2e56Smrg client->errorValue = _XkbErrCode4(0x13, i, g, map->kt_index[g]); 2426f7df2e56Smrg return 0; 2427f7df2e56Smrg } 2428f7df2e56Smrg if (mapWidths[map->kt_index[g]] > w) 2429f7df2e56Smrg w = mapWidths[map->kt_index[g]]; 2430f7df2e56Smrg } 2431f7df2e56Smrg symsPerKey[i] = w * ng; 24329ace9065Smrg } 24339ace9065Smrg 24344642e01fSmrg if ((req->present & XkbKeySymsMask) && 2435f7df2e56Smrg (!CheckKeySyms(client, xkb, req, nTypes, mapWidths, symsPerKey, 2436f7df2e56Smrg (xkbSymMapWireDesc **) &values, &error))) { 2437f7df2e56Smrg client->errorValue = error; 2438f7df2e56Smrg return BadValue; 243905b261ecSmrg } 244005b261ecSmrg 24414642e01fSmrg if ((req->present & XkbKeyActionsMask) && 2442f7df2e56Smrg (!CheckKeyActions(xkb, req, nTypes, mapWidths, symsPerKey, 2443f7df2e56Smrg (CARD8 **) &values, &nActions))) { 2444f7df2e56Smrg client->errorValue = nActions; 2445f7df2e56Smrg return BadValue; 244605b261ecSmrg } 244705b261ecSmrg 24484642e01fSmrg if ((req->present & XkbKeyBehaviorsMask) && 2449f7df2e56Smrg (!CheckKeyBehaviors 2450f7df2e56Smrg (xkb, req, (xkbBehaviorWireDesc **) &values, &error))) { 2451f7df2e56Smrg client->errorValue = error; 2452f7df2e56Smrg return BadValue; 245305b261ecSmrg } 245405b261ecSmrg 24554642e01fSmrg if ((req->present & XkbVirtualModsMask) && 2456f7df2e56Smrg (!CheckVirtualMods(xkb, req, (CARD8 **) &values, &error))) { 2457f7df2e56Smrg client->errorValue = error; 2458f7df2e56Smrg return BadValue; 245905b261ecSmrg } 2460f7df2e56Smrg if ((req->present & XkbExplicitComponentsMask) && 2461f7df2e56Smrg (!CheckKeyExplicit(xkb, req, (CARD8 **) &values, &error))) { 2462f7df2e56Smrg client->errorValue = error; 2463f7df2e56Smrg return BadValue; 246405b261ecSmrg } 2465f7df2e56Smrg if ((req->present & XkbModifierMapMask) && 2466f7df2e56Smrg (!CheckModifierMap(xkb, req, (CARD8 **) &values, &error))) { 2467f7df2e56Smrg client->errorValue = error; 2468f7df2e56Smrg return BadValue; 246905b261ecSmrg } 2470f7df2e56Smrg if ((req->present & XkbVirtualModMapMask) && 2471f7df2e56Smrg (!CheckVirtualModMap 2472f7df2e56Smrg (xkb, req, (xkbVModMapWireDesc **) &values, &error))) { 2473f7df2e56Smrg client->errorValue = error; 2474f7df2e56Smrg return BadValue; 247505b261ecSmrg } 24764642e01fSmrg 2477f7df2e56Smrg if (((values - ((char *) req)) / 4) != req->length) { 2478f7df2e56Smrg ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after check)\n"); 2479f7df2e56Smrg client->errorValue = values - ((char *) &req[1]); 2480f7df2e56Smrg return BadLength; 248105b261ecSmrg } 24824642e01fSmrg 24834642e01fSmrg return Success; 24844642e01fSmrg} 24854642e01fSmrg 24864642e01fSmrg/** 24874642e01fSmrg * Apply the given request on the given device. 24884642e01fSmrg */ 24894642e01fSmrgstatic int 2490f7df2e56Smrg_XkbSetMap(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq * req, char *values) 24914642e01fSmrg{ 2492f7df2e56Smrg XkbEventCauseRec cause; 2493f7df2e56Smrg XkbChangesRec change; 2494f7df2e56Smrg Bool sentNKN; 2495f7df2e56Smrg XkbSrvInfoPtr xkbi; 2496f7df2e56Smrg XkbDescPtr xkb; 24974642e01fSmrg 2498f7df2e56Smrg xkbi = dev->key->xkbInfo; 24994642e01fSmrg xkb = xkbi->desc; 25004642e01fSmrg 2501f7df2e56Smrg XkbSetCauseXkbReq(&cause, X_kbSetMap, client); 25026747b715Smrg memset(&change, 0, sizeof(change)); 25036747b715Smrg sentNKN = FALSE; 2504f7df2e56Smrg if ((xkb->min_key_code != req->minKeyCode) || 2505f7df2e56Smrg (xkb->max_key_code != req->maxKeyCode)) { 2506f7df2e56Smrg Status status; 2507f7df2e56Smrg xkbNewKeyboardNotify nkn; 2508f7df2e56Smrg 2509f7df2e56Smrg nkn.deviceID = nkn.oldDeviceID = dev->id; 2510f7df2e56Smrg nkn.oldMinKeyCode = xkb->min_key_code; 2511f7df2e56Smrg nkn.oldMaxKeyCode = xkb->max_key_code; 2512f7df2e56Smrg status = XkbChangeKeycodeRange(xkb, req->minKeyCode, 2513f7df2e56Smrg req->maxKeyCode, &change); 2514f7df2e56Smrg if (status != Success) 2515f7df2e56Smrg return status; /* oh-oh. what about the other keyboards? */ 2516f7df2e56Smrg nkn.minKeyCode = xkb->min_key_code; 2517f7df2e56Smrg nkn.maxKeyCode = xkb->max_key_code; 2518f7df2e56Smrg nkn.requestMajor = XkbReqCode; 2519f7df2e56Smrg nkn.requestMinor = X_kbSetMap; 2520f7df2e56Smrg nkn.changed = XkbNKN_KeycodesMask; 2521f7df2e56Smrg XkbSendNewKeyboardNotify(dev, &nkn); 2522f7df2e56Smrg sentNKN = TRUE; 2523f7df2e56Smrg } 2524f7df2e56Smrg 2525f7df2e56Smrg if (req->present & XkbKeyTypesMask) { 2526f7df2e56Smrg values = SetKeyTypes(xkb, req, (xkbKeyTypeWireDesc *) values, &change); 2527f7df2e56Smrg if (!values) 2528f7df2e56Smrg goto allocFailure; 2529f7df2e56Smrg } 2530f7df2e56Smrg if (req->present & XkbKeySymsMask) { 2531f7df2e56Smrg values = 2532f7df2e56Smrg SetKeySyms(client, xkb, req, (xkbSymMapWireDesc *) values, &change, 2533f7df2e56Smrg dev); 2534f7df2e56Smrg if (!values) 2535f7df2e56Smrg goto allocFailure; 2536f7df2e56Smrg } 2537f7df2e56Smrg if (req->present & XkbKeyActionsMask) { 2538f7df2e56Smrg values = SetKeyActions(xkb, req, (CARD8 *) values, &change); 2539f7df2e56Smrg if (!values) 2540f7df2e56Smrg goto allocFailure; 2541f7df2e56Smrg } 2542f7df2e56Smrg if (req->present & XkbKeyBehaviorsMask) { 2543f7df2e56Smrg values = 2544f7df2e56Smrg SetKeyBehaviors(xkbi, req, (xkbBehaviorWireDesc *) values, &change); 2545f7df2e56Smrg if (!values) 2546f7df2e56Smrg goto allocFailure; 2547f7df2e56Smrg } 2548f7df2e56Smrg if (req->present & XkbVirtualModsMask) 2549f7df2e56Smrg values = SetVirtualMods(xkbi, req, (CARD8 *) values, &change); 2550f7df2e56Smrg if (req->present & XkbExplicitComponentsMask) 2551f7df2e56Smrg values = SetKeyExplicit(xkbi, req, (CARD8 *) values, &change); 2552f7df2e56Smrg if (req->present & XkbModifierMapMask) 2553f7df2e56Smrg values = SetModifierMap(xkbi, req, (CARD8 *) values, &change); 2554f7df2e56Smrg if (req->present & XkbVirtualModMapMask) 2555f7df2e56Smrg values = 2556f7df2e56Smrg SetVirtualModMap(xkbi, req, (xkbVModMapWireDesc *) values, &change); 2557f7df2e56Smrg if (((values - ((char *) req)) / 4) != req->length) { 2558f7df2e56Smrg ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after set)\n"); 2559f7df2e56Smrg client->errorValue = values - ((char *) &req[1]); 2560f7df2e56Smrg return BadLength; 2561f7df2e56Smrg } 2562f7df2e56Smrg if (req->flags & XkbSetMapRecomputeActions) { 2563f7df2e56Smrg KeyCode first, last, firstMM, lastMM; 2564f7df2e56Smrg 2565f7df2e56Smrg if (change.map.num_key_syms > 0) { 2566f7df2e56Smrg first = change.map.first_key_sym; 2567f7df2e56Smrg last = first + change.map.num_key_syms - 1; 2568f7df2e56Smrg } 2569f7df2e56Smrg else 2570f7df2e56Smrg first = last = 0; 2571f7df2e56Smrg if (change.map.num_modmap_keys > 0) { 2572f7df2e56Smrg firstMM = change.map.first_modmap_key; 25737e31ba66Smrg lastMM = firstMM + change.map.num_modmap_keys - 1; 2574f7df2e56Smrg } 2575f7df2e56Smrg else 2576f7df2e56Smrg firstMM = lastMM = 0; 2577f7df2e56Smrg if ((last > 0) && (lastMM > 0)) { 2578f7df2e56Smrg if (firstMM < first) 2579f7df2e56Smrg first = firstMM; 2580f7df2e56Smrg if (lastMM > last) 2581f7df2e56Smrg last = lastMM; 2582f7df2e56Smrg } 2583f7df2e56Smrg else if (lastMM > 0) { 2584f7df2e56Smrg first = firstMM; 2585f7df2e56Smrg last = lastMM; 2586f7df2e56Smrg } 2587f7df2e56Smrg if (last > 0) { 2588f7df2e56Smrg unsigned check = 0; 2589f7df2e56Smrg 2590f7df2e56Smrg XkbUpdateActions(dev, first, (last - first + 1), &change, &check, 2591f7df2e56Smrg &cause); 2592f7df2e56Smrg if (check) 2593f7df2e56Smrg XkbCheckSecondaryEffects(xkbi, check, &change, &cause); 2594f7df2e56Smrg } 259505b261ecSmrg } 259605b261ecSmrg if (!sentNKN) 2597f7df2e56Smrg XkbSendNotification(dev, &change, &cause); 259805b261ecSmrg 25994642e01fSmrg return Success; 2600f7df2e56Smrg allocFailure: 260105b261ecSmrg return BadAlloc; 260205b261ecSmrg} 260305b261ecSmrg 26044642e01fSmrgint 26054642e01fSmrgProcXkbSetMap(ClientPtr client) 26064642e01fSmrg{ 2607f7df2e56Smrg DeviceIntPtr dev; 2608f7df2e56Smrg char *tmp; 2609f7df2e56Smrg int rc; 26104642e01fSmrg 26114642e01fSmrg REQUEST(xkbSetMapReq); 26124642e01fSmrg REQUEST_AT_LEAST_SIZE(xkbSetMapReq); 26134642e01fSmrg 2614f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 2615f7df2e56Smrg return BadAccess; 26164642e01fSmrg 26174642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); 2618f7df2e56Smrg CHK_MASK_LEGAL(0x01, stuff->present, XkbAllMapComponentsMask); 26194642e01fSmrg 2620f7df2e56Smrg tmp = (char *) &stuff[1]; 26214642e01fSmrg 26224642e01fSmrg /* Check if we can to the SetMap on the requested device. If this 26234642e01fSmrg succeeds, do the same thing for all extension devices (if needed). 26244642e01fSmrg If any of them fails, fail. */ 26254642e01fSmrg rc = _XkbSetMapChecks(client, dev, stuff, tmp); 26264642e01fSmrg 26274642e01fSmrg if (rc != Success) 26284642e01fSmrg return rc; 26294642e01fSmrg 26307e31ba66Smrg DeviceIntPtr master = GetMaster(dev, MASTER_KEYBOARD); 26317e31ba66Smrg 2632f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd) { 26334642e01fSmrg DeviceIntPtr other; 2634f7df2e56Smrg 2635f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 2636f7df2e56Smrg if ((other != dev) && other->key && !IsMaster(other) && 2637f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) { 2638f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 2639f7df2e56Smrg DixManageAccess); 2640f7df2e56Smrg if (rc == Success) { 26414642e01fSmrg rc = _XkbSetMapChecks(client, other, stuff, tmp); 26424642e01fSmrg if (rc != Success) 26434642e01fSmrg return rc; 26444642e01fSmrg } 26454642e01fSmrg } 26464642e01fSmrg } 26477e31ba66Smrg } else { 26487e31ba66Smrg DeviceIntPtr other; 26497e31ba66Smrg 26507e31ba66Smrg for (other = inputInfo.devices; other; other = other->next) { 26517e31ba66Smrg if (other != dev && GetMaster(other, MASTER_KEYBOARD) != dev && 26527e31ba66Smrg (other != master || dev != master->lastSlave)) 26537e31ba66Smrg continue; 26547e31ba66Smrg 26557e31ba66Smrg rc = _XkbSetMapChecks(client, other, stuff, tmp); 26567e31ba66Smrg if (rc != Success) 26577e31ba66Smrg return rc; 26587e31ba66Smrg } 26594642e01fSmrg } 26604642e01fSmrg 26617e31ba66Smrg /* We know now that we will succeed with the SetMap. In theory anyway. */ 26624642e01fSmrg rc = _XkbSetMap(client, dev, stuff, tmp); 26634642e01fSmrg if (rc != Success) 26644642e01fSmrg return rc; 26654642e01fSmrg 2666f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd) { 26674642e01fSmrg DeviceIntPtr other; 2668f7df2e56Smrg 2669f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 2670f7df2e56Smrg if ((other != dev) && other->key && !IsMaster(other) && 2671f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) { 2672f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 2673f7df2e56Smrg DixManageAccess); 26744642e01fSmrg if (rc == Success) 26754642e01fSmrg _XkbSetMap(client, other, stuff, tmp); 26764642e01fSmrg /* ignore rc. if the SetMap failed although the check above 26774642e01fSmrg reported true there isn't much we can do. we still need to 26784642e01fSmrg set all other devices, hoping that at least they stay in 26794642e01fSmrg sync. */ 26804642e01fSmrg } 26814642e01fSmrg } 26827e31ba66Smrg } else { 26837e31ba66Smrg DeviceIntPtr other; 26847e31ba66Smrg 26857e31ba66Smrg for (other = inputInfo.devices; other; other = other->next) { 26867e31ba66Smrg if (other != dev && GetMaster(other, MASTER_KEYBOARD) != dev && 26877e31ba66Smrg (other != master || dev != master->lastSlave)) 26887e31ba66Smrg continue; 26897e31ba66Smrg 26907e31ba66Smrg _XkbSetMap(client, other, stuff, tmp); //ignore rc 26917e31ba66Smrg } 26924642e01fSmrg } 26934642e01fSmrg 26946747b715Smrg return Success; 26954642e01fSmrg} 26964642e01fSmrg 269705b261ecSmrg/***====================================================================***/ 269805b261ecSmrg 269905b261ecSmrgstatic Status 2700f7df2e56SmrgXkbComputeGetCompatMapReplySize(XkbCompatMapPtr compat, 2701f7df2e56Smrg xkbGetCompatMapReply * rep) 270205b261ecSmrg{ 2703f7df2e56Smrg unsigned size, nGroups; 2704f7df2e56Smrg 2705f7df2e56Smrg nGroups = 0; 2706f7df2e56Smrg if (rep->groups != 0) { 2707f7df2e56Smrg register int i, bit; 2708f7df2e56Smrg 2709f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) { 2710f7df2e56Smrg if (rep->groups & bit) 2711f7df2e56Smrg nGroups++; 2712f7df2e56Smrg } 2713f7df2e56Smrg } 2714f7df2e56Smrg size = nGroups * SIZEOF(xkbModsWireDesc); 2715f7df2e56Smrg size += (rep->nSI * SIZEOF(xkbSymInterpretWireDesc)); 2716f7df2e56Smrg rep->length = size / 4; 271705b261ecSmrg return Success; 271805b261ecSmrg} 271905b261ecSmrg 272005b261ecSmrgstatic int 2721f7df2e56SmrgXkbSendCompatMap(ClientPtr client, 2722f7df2e56Smrg XkbCompatMapPtr compat, xkbGetCompatMapReply * rep) 272305b261ecSmrg{ 2724f7df2e56Smrg char *data; 2725f7df2e56Smrg int size; 2726f7df2e56Smrg 2727f7df2e56Smrg if (rep->length > 0) { 2728f7df2e56Smrg data = xallocarray(rep->length, 4); 2729f7df2e56Smrg if (data) { 2730f7df2e56Smrg register unsigned i, bit; 2731f7df2e56Smrg xkbModsWireDesc *grp; 2732f7df2e56Smrg XkbSymInterpretPtr sym = &compat->sym_interpret[rep->firstSI]; 2733f7df2e56Smrg xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *) data; 2734f7df2e56Smrg 2735f7df2e56Smrg size = rep->length * 4; 2736f7df2e56Smrg 2737f7df2e56Smrg for (i = 0; i < rep->nSI; i++, sym++, wire++) { 2738f7df2e56Smrg wire->sym = sym->sym; 2739f7df2e56Smrg wire->mods = sym->mods; 2740f7df2e56Smrg wire->match = sym->match; 2741f7df2e56Smrg wire->virtualMod = sym->virtual_mod; 2742f7df2e56Smrg wire->flags = sym->flags; 2743f7df2e56Smrg memcpy((char *) &wire->act, (char *) &sym->act, 2744f7df2e56Smrg sz_xkbActionWireDesc); 2745f7df2e56Smrg if (client->swapped) { 2746f7df2e56Smrg swapl(&wire->sym); 2747f7df2e56Smrg } 2748f7df2e56Smrg } 2749f7df2e56Smrg if (rep->groups) { 2750f7df2e56Smrg grp = (xkbModsWireDesc *) wire; 2751f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) { 2752f7df2e56Smrg if (rep->groups & bit) { 2753f7df2e56Smrg grp->mask = compat->groups[i].mask; 2754f7df2e56Smrg grp->realMods = compat->groups[i].real_mods; 2755f7df2e56Smrg grp->virtualMods = compat->groups[i].vmods; 2756f7df2e56Smrg if (client->swapped) { 2757f7df2e56Smrg swaps(&grp->virtualMods); 2758f7df2e56Smrg } 2759f7df2e56Smrg grp++; 2760f7df2e56Smrg } 2761f7df2e56Smrg } 2762f7df2e56Smrg wire = (xkbSymInterpretWireDesc *) grp; 2763f7df2e56Smrg } 2764f7df2e56Smrg } 2765f7df2e56Smrg else 2766f7df2e56Smrg return BadAlloc; 2767f7df2e56Smrg } 2768f7df2e56Smrg else 2769f7df2e56Smrg data = NULL; 277005b261ecSmrg 277105b261ecSmrg if (client->swapped) { 2772f7df2e56Smrg swaps(&rep->sequenceNumber); 2773f7df2e56Smrg swapl(&rep->length); 2774f7df2e56Smrg swaps(&rep->firstSI); 2775f7df2e56Smrg swaps(&rep->nSI); 2776f7df2e56Smrg swaps(&rep->nTotalSI); 277705b261ecSmrg } 277805b261ecSmrg 2779f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetCompatMapReply), rep); 278005b261ecSmrg if (data) { 2781f7df2e56Smrg WriteToClient(client, size, data); 2782f7df2e56Smrg free((char *) data); 278305b261ecSmrg } 27846747b715Smrg return Success; 278505b261ecSmrg} 278605b261ecSmrg 278705b261ecSmrgint 278805b261ecSmrgProcXkbGetCompatMap(ClientPtr client) 278905b261ecSmrg{ 2790f7df2e56Smrg xkbGetCompatMapReply rep; 2791f7df2e56Smrg DeviceIntPtr dev; 2792f7df2e56Smrg XkbDescPtr xkb; 2793f7df2e56Smrg XkbCompatMapPtr compat; 279405b261ecSmrg 279505b261ecSmrg REQUEST(xkbGetCompatMapReq); 279605b261ecSmrg REQUEST_SIZE_MATCH(xkbGetCompatMapReq); 279705b261ecSmrg 2798f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 2799f7df2e56Smrg return BadAccess; 280005b261ecSmrg 28014642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); 280205b261ecSmrg 280305b261ecSmrg xkb = dev->key->xkbInfo->desc; 2804f7df2e56Smrg compat = xkb->compat; 280505b261ecSmrg 2806f7df2e56Smrg rep = (xkbGetCompatMapReply) { 2807f7df2e56Smrg .type = X_Reply, 2808f7df2e56Smrg .sequenceNumber = client->sequence, 2809f7df2e56Smrg .length = 0, 2810f7df2e56Smrg .deviceID = dev->id, 2811f7df2e56Smrg .firstSI = stuff->firstSI, 2812f7df2e56Smrg .nSI = stuff->nSI 2813f7df2e56Smrg }; 281405b261ecSmrg if (stuff->getAllSI) { 2815f7df2e56Smrg rep.firstSI = 0; 2816f7df2e56Smrg rep.nSI = compat->num_si; 281705b261ecSmrg } 2818f7df2e56Smrg else if ((((unsigned) stuff->nSI) > 0) && 2819f7df2e56Smrg ((unsigned) (stuff->firstSI + stuff->nSI - 1) >= compat->num_si)) { 2820f7df2e56Smrg client->errorValue = _XkbErrCode2(0x05, compat->num_si); 2821f7df2e56Smrg return BadValue; 282205b261ecSmrg } 282305b261ecSmrg rep.nTotalSI = compat->num_si; 2824f7df2e56Smrg rep.groups = stuff->groups; 2825f7df2e56Smrg XkbComputeGetCompatMapReplySize(compat, &rep); 2826f7df2e56Smrg return XkbSendCompatMap(client, compat, &rep); 282705b261ecSmrg} 282805b261ecSmrg 28294642e01fSmrg/** 28304642e01fSmrg * Apply the given request on the given device. 28316747b715Smrg * If dryRun is TRUE, then value checks are performed, but the device isn't 28324642e01fSmrg * modified. 28334642e01fSmrg */ 28344642e01fSmrgstatic int 28354642e01fSmrg_XkbSetCompatMap(ClientPtr client, DeviceIntPtr dev, 2836f7df2e56Smrg xkbSetCompatMapReq * req, char *data, BOOL dryRun) 283705b261ecSmrg{ 2838f7df2e56Smrg XkbSrvInfoPtr xkbi; 2839f7df2e56Smrg XkbDescPtr xkb; 2840f7df2e56Smrg XkbCompatMapPtr compat; 2841f7df2e56Smrg int nGroups; 2842f7df2e56Smrg unsigned i, bit; 284305b261ecSmrg 284405b261ecSmrg xkbi = dev->key->xkbInfo; 28454642e01fSmrg xkb = xkbi->desc; 28464642e01fSmrg compat = xkb->compat; 28474642e01fSmrg 2848f7df2e56Smrg if ((req->nSI > 0) || (req->truncateSI)) { 2849f7df2e56Smrg xkbSymInterpretWireDesc *wire; 2850f7df2e56Smrg 2851f7df2e56Smrg if (req->firstSI > compat->num_si) { 2852f7df2e56Smrg client->errorValue = _XkbErrCode2(0x02, compat->num_si); 2853f7df2e56Smrg return BadValue; 2854f7df2e56Smrg } 2855f7df2e56Smrg wire = (xkbSymInterpretWireDesc *) data; 2856f7df2e56Smrg wire += req->nSI; 2857f7df2e56Smrg data = (char *) wire; 285805b261ecSmrg } 28594642e01fSmrg 2860f7df2e56Smrg nGroups = 0; 2861f7df2e56Smrg if (req->groups != 0) { 2862f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) { 2863f7df2e56Smrg if (req->groups & bit) 2864f7df2e56Smrg nGroups++; 2865f7df2e56Smrg } 286605b261ecSmrg } 2867f7df2e56Smrg data += nGroups * SIZEOF(xkbModsWireDesc); 2868f7df2e56Smrg if (((data - ((char *) req)) / 4) != req->length) { 2869f7df2e56Smrg return BadLength; 287005b261ecSmrg } 28714642e01fSmrg 28724642e01fSmrg /* Done all the checks we can do */ 28734642e01fSmrg if (dryRun) 28744642e01fSmrg return Success; 28754642e01fSmrg 2876f7df2e56Smrg data = (char *) &req[1]; 2877f7df2e56Smrg if (req->nSI > 0) { 2878f7df2e56Smrg xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *) data; 2879f7df2e56Smrg XkbSymInterpretPtr sym; 2880f7df2e56Smrg unsigned int skipped = 0; 2881f7df2e56Smrg 2882f7df2e56Smrg if ((unsigned) (req->firstSI + req->nSI) > compat->num_si) { 2883f7df2e56Smrg compat->num_si = req->firstSI + req->nSI; 2884f7df2e56Smrg compat->sym_interpret = reallocarray(compat->sym_interpret, 2885f7df2e56Smrg compat->num_si, 2886f7df2e56Smrg sizeof(XkbSymInterpretRec)); 2887f7df2e56Smrg if (!compat->sym_interpret) { 2888f7df2e56Smrg compat->num_si = 0; 2889f7df2e56Smrg return BadAlloc; 2890f7df2e56Smrg } 2891f7df2e56Smrg } 2892f7df2e56Smrg else if (req->truncateSI) { 2893f7df2e56Smrg compat->num_si = req->firstSI + req->nSI; 2894f7df2e56Smrg } 2895f7df2e56Smrg sym = &compat->sym_interpret[req->firstSI]; 2896f7df2e56Smrg for (i = 0; i < req->nSI; i++, wire++) { 2897f7df2e56Smrg if (client->swapped) { 2898f7df2e56Smrg swapl(&wire->sym); 2899f7df2e56Smrg } 2900f7df2e56Smrg if (wire->sym == NoSymbol && wire->match == XkbSI_AnyOfOrNone && 2901f7df2e56Smrg (wire->mods & 0xff) == 0xff && 2902f7df2e56Smrg wire->act.type == XkbSA_XFree86Private) { 2903f7df2e56Smrg ErrorF("XKB: Skipping broken Any+AnyOfOrNone(All) -> Private " 2904f7df2e56Smrg "action from client\n"); 2905f7df2e56Smrg skipped++; 2906f7df2e56Smrg continue; 2907f7df2e56Smrg } 2908f7df2e56Smrg sym->sym = wire->sym; 2909f7df2e56Smrg sym->mods = wire->mods; 2910f7df2e56Smrg sym->match = wire->match; 2911f7df2e56Smrg sym->flags = wire->flags; 2912f7df2e56Smrg sym->virtual_mod = wire->virtualMod; 2913f7df2e56Smrg memcpy((char *) &sym->act, (char *) &wire->act, 2914f7df2e56Smrg SIZEOF(xkbActionWireDesc)); 2915f7df2e56Smrg sym++; 2916f7df2e56Smrg } 2917f7df2e56Smrg if (skipped) { 2918f7df2e56Smrg if (req->firstSI + req->nSI < compat->num_si) 2919f7df2e56Smrg memmove(sym, sym + skipped, 2920f7df2e56Smrg (compat->num_si - req->firstSI - req->nSI) * 2921f7df2e56Smrg sizeof(*sym)); 2922f7df2e56Smrg compat->num_si -= skipped; 2923f7df2e56Smrg } 2924f7df2e56Smrg data = (char *) wire; 292505b261ecSmrg } 29264642e01fSmrg else if (req->truncateSI) { 2927f7df2e56Smrg compat->num_si = req->firstSI; 2928f7df2e56Smrg } 2929f7df2e56Smrg 2930f7df2e56Smrg if (req->groups != 0) { 2931f7df2e56Smrg xkbModsWireDesc *wire = (xkbModsWireDesc *) data; 2932f7df2e56Smrg 2933f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) { 2934f7df2e56Smrg if (req->groups & bit) { 2935f7df2e56Smrg if (client->swapped) { 2936f7df2e56Smrg swaps(&wire->virtualMods); 2937f7df2e56Smrg } 2938f7df2e56Smrg compat->groups[i].mask = wire->realMods; 2939f7df2e56Smrg compat->groups[i].real_mods = wire->realMods; 2940f7df2e56Smrg compat->groups[i].vmods = wire->virtualMods; 2941f7df2e56Smrg if (wire->virtualMods != 0) { 2942f7df2e56Smrg unsigned tmp; 2943f7df2e56Smrg 2944f7df2e56Smrg tmp = XkbMaskForVMask(xkb, wire->virtualMods); 2945f7df2e56Smrg compat->groups[i].mask |= tmp; 2946f7df2e56Smrg } 2947f7df2e56Smrg data += SIZEOF(xkbModsWireDesc); 2948f7df2e56Smrg wire = (xkbModsWireDesc *) data; 2949f7df2e56Smrg } 2950f7df2e56Smrg } 2951f7df2e56Smrg } 2952f7df2e56Smrg i = XkbPaddedSize((data - ((char *) req))); 2953f7df2e56Smrg if ((i / 4) != req->length) { 2954f7df2e56Smrg ErrorF("[xkb] Internal length error on read in _XkbSetCompatMap\n"); 2955f7df2e56Smrg return BadLength; 295605b261ecSmrg } 29574642e01fSmrg 295805b261ecSmrg if (dev->xkb_interest) { 2959f7df2e56Smrg xkbCompatMapNotify ev; 2960f7df2e56Smrg 2961f7df2e56Smrg ev.deviceID = dev->id; 2962f7df2e56Smrg ev.changedGroups = req->groups; 2963f7df2e56Smrg ev.firstSI = req->firstSI; 2964f7df2e56Smrg ev.nSI = req->nSI; 2965f7df2e56Smrg ev.nTotalSI = compat->num_si; 2966f7df2e56Smrg XkbSendCompatMapNotify(dev, &ev); 296705b261ecSmrg } 296805b261ecSmrg 29694642e01fSmrg if (req->recomputeActions) { 2970f7df2e56Smrg XkbChangesRec change; 2971f7df2e56Smrg unsigned check; 2972f7df2e56Smrg XkbEventCauseRec cause; 2973f7df2e56Smrg 2974f7df2e56Smrg XkbSetCauseXkbReq(&cause, X_kbSetCompatMap, client); 2975f7df2e56Smrg memset(&change, 0, sizeof(XkbChangesRec)); 2976f7df2e56Smrg XkbUpdateActions(dev, xkb->min_key_code, XkbNumKeys(xkb), &change, 2977f7df2e56Smrg &check, &cause); 2978f7df2e56Smrg if (check) 2979f7df2e56Smrg XkbCheckSecondaryEffects(xkbi, check, &change, &cause); 2980f7df2e56Smrg XkbSendNotification(dev, &change, &cause); 298105b261ecSmrg } 29824642e01fSmrg return Success; 29834642e01fSmrg} 29844642e01fSmrg 29854642e01fSmrgint 29864642e01fSmrgProcXkbSetCompatMap(ClientPtr client) 29874642e01fSmrg{ 2988f7df2e56Smrg DeviceIntPtr dev; 2989f7df2e56Smrg char *data; 2990f7df2e56Smrg int rc; 29914642e01fSmrg 29924642e01fSmrg REQUEST(xkbSetCompatMapReq); 29934642e01fSmrg REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq); 29944642e01fSmrg 2995f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 2996f7df2e56Smrg return BadAccess; 29974642e01fSmrg 29984642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); 29994642e01fSmrg 3000f7df2e56Smrg data = (char *) &stuff[1]; 30014642e01fSmrg 30024642e01fSmrg /* check first using a dry-run */ 30034642e01fSmrg rc = _XkbSetCompatMap(client, dev, stuff, data, TRUE); 30044642e01fSmrg if (rc != Success) 30054642e01fSmrg return rc; 3006f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd) { 30074642e01fSmrg DeviceIntPtr other; 3008f7df2e56Smrg 3009f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 3010f7df2e56Smrg if ((other != dev) && other->key && !IsMaster(other) && 3011f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) { 3012f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 3013f7df2e56Smrg DixManageAccess); 3014f7df2e56Smrg if (rc == Success) { 30154642e01fSmrg /* dry-run */ 30164642e01fSmrg rc = _XkbSetCompatMap(client, other, stuff, data, TRUE); 30174642e01fSmrg if (rc != Success) 30184642e01fSmrg return rc; 30194642e01fSmrg } 30204642e01fSmrg } 30214642e01fSmrg } 30224642e01fSmrg } 30234642e01fSmrg 30244642e01fSmrg /* Yay, the dry-runs succeed. Let's apply */ 30254642e01fSmrg rc = _XkbSetCompatMap(client, dev, stuff, data, FALSE); 30264642e01fSmrg if (rc != Success) 30274642e01fSmrg return rc; 3028f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd) { 30294642e01fSmrg DeviceIntPtr other; 3030f7df2e56Smrg 3031f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 3032f7df2e56Smrg if ((other != dev) && other->key && !IsMaster(other) && 3033f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) { 3034f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 3035f7df2e56Smrg DixManageAccess); 3036f7df2e56Smrg if (rc == Success) { 30374642e01fSmrg rc = _XkbSetCompatMap(client, other, stuff, data, FALSE); 30384642e01fSmrg if (rc != Success) 30394642e01fSmrg return rc; 30404642e01fSmrg } 30414642e01fSmrg } 30424642e01fSmrg } 30434642e01fSmrg } 30444642e01fSmrg 30456747b715Smrg return Success; 304605b261ecSmrg} 304705b261ecSmrg 304805b261ecSmrg/***====================================================================***/ 304905b261ecSmrg 305005b261ecSmrgint 305105b261ecSmrgProcXkbGetIndicatorState(ClientPtr client) 305205b261ecSmrg{ 3053f7df2e56Smrg xkbGetIndicatorStateReply rep; 3054f7df2e56Smrg XkbSrvLedInfoPtr sli; 3055f7df2e56Smrg DeviceIntPtr dev; 305605b261ecSmrg 305705b261ecSmrg REQUEST(xkbGetIndicatorStateReq); 305805b261ecSmrg REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq); 305905b261ecSmrg 3060f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 3061f7df2e56Smrg return BadAccess; 306205b261ecSmrg 30634642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess); 306405b261ecSmrg 3065f7df2e56Smrg sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 3066f7df2e56Smrg XkbXI_IndicatorStateMask); 306705b261ecSmrg if (!sli) 3068f7df2e56Smrg return BadAlloc; 306905b261ecSmrg 3070f7df2e56Smrg rep = (xkbGetIndicatorStateReply) { 3071f7df2e56Smrg .type = X_Reply, 3072f7df2e56Smrg .deviceID = dev->id, 3073f7df2e56Smrg .sequenceNumber = client->sequence, 3074f7df2e56Smrg .length = 0, 3075f7df2e56Smrg .state = sli->effectiveState 3076f7df2e56Smrg }; 307705b261ecSmrg 307805b261ecSmrg if (client->swapped) { 3079f7df2e56Smrg swaps(&rep.sequenceNumber); 3080f7df2e56Smrg swapl(&rep.state); 308105b261ecSmrg } 3082f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetIndicatorStateReply), &rep); 30836747b715Smrg return Success; 308405b261ecSmrg} 308505b261ecSmrg 308605b261ecSmrg/***====================================================================***/ 308705b261ecSmrg 308805b261ecSmrgstatic Status 3089f7df2e56SmrgXkbComputeGetIndicatorMapReplySize(XkbIndicatorPtr indicators, 3090f7df2e56Smrg xkbGetIndicatorMapReply * rep) 309105b261ecSmrg{ 3092f7df2e56Smrg register int i, bit; 3093f7df2e56Smrg int nIndicators; 309405b261ecSmrg 309505b261ecSmrg rep->realIndicators = indicators->phys_indicators; 3096f7df2e56Smrg for (i = nIndicators = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 3097f7df2e56Smrg if (rep->which & bit) 3098f7df2e56Smrg nIndicators++; 309905b261ecSmrg } 3100f7df2e56Smrg rep->length = (nIndicators * SIZEOF(xkbIndicatorMapWireDesc)) / 4; 3101f7df2e56Smrg rep->nIndicators = nIndicators; 310205b261ecSmrg return Success; 310305b261ecSmrg} 310405b261ecSmrg 310505b261ecSmrgstatic int 3106f7df2e56SmrgXkbSendIndicatorMap(ClientPtr client, 3107f7df2e56Smrg XkbIndicatorPtr indicators, xkbGetIndicatorMapReply * rep) 310805b261ecSmrg{ 3109f7df2e56Smrg int length; 3110f7df2e56Smrg CARD8 *map; 3111f7df2e56Smrg register int i; 3112f7df2e56Smrg register unsigned bit; 3113f7df2e56Smrg 3114f7df2e56Smrg if (rep->length > 0) { 3115f7df2e56Smrg CARD8 *to; 3116f7df2e56Smrg 3117f7df2e56Smrg to = map = xallocarray(rep->length, 4); 3118f7df2e56Smrg if (map) { 3119f7df2e56Smrg xkbIndicatorMapWireDesc *wire = (xkbIndicatorMapWireDesc *) to; 3120f7df2e56Smrg 3121f7df2e56Smrg length = rep->length * 4; 3122f7df2e56Smrg 3123f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 3124f7df2e56Smrg if (rep->which & bit) { 3125f7df2e56Smrg wire->flags = indicators->maps[i].flags; 3126f7df2e56Smrg wire->whichGroups = indicators->maps[i].which_groups; 3127f7df2e56Smrg wire->groups = indicators->maps[i].groups; 3128f7df2e56Smrg wire->whichMods = indicators->maps[i].which_mods; 3129f7df2e56Smrg wire->mods = indicators->maps[i].mods.mask; 3130f7df2e56Smrg wire->realMods = indicators->maps[i].mods.real_mods; 3131f7df2e56Smrg wire->virtualMods = indicators->maps[i].mods.vmods; 3132f7df2e56Smrg wire->ctrls = indicators->maps[i].ctrls; 3133f7df2e56Smrg if (client->swapped) { 3134f7df2e56Smrg swaps(&wire->virtualMods); 3135f7df2e56Smrg swapl(&wire->ctrls); 3136f7df2e56Smrg } 3137f7df2e56Smrg wire++; 3138f7df2e56Smrg } 3139f7df2e56Smrg } 3140f7df2e56Smrg to = (CARD8 *) wire; 3141f7df2e56Smrg if ((to - map) != length) { 3142f7df2e56Smrg client->errorValue = _XkbErrCode2(0xff, length); 3143f7df2e56Smrg free(map); 3144f7df2e56Smrg return BadLength; 3145f7df2e56Smrg } 3146f7df2e56Smrg } 3147f7df2e56Smrg else 3148f7df2e56Smrg return BadAlloc; 3149f7df2e56Smrg } 3150f7df2e56Smrg else 3151f7df2e56Smrg map = NULL; 315205b261ecSmrg if (client->swapped) { 3153f7df2e56Smrg swaps(&rep->sequenceNumber); 3154f7df2e56Smrg swapl(&rep->length); 3155f7df2e56Smrg swapl(&rep->which); 3156f7df2e56Smrg swapl(&rep->realIndicators); 315705b261ecSmrg } 3158f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetIndicatorMapReply), rep); 315905b261ecSmrg if (map) { 3160f7df2e56Smrg WriteToClient(client, length, map); 3161f7df2e56Smrg free((char *) map); 316205b261ecSmrg } 31636747b715Smrg return Success; 316405b261ecSmrg} 316505b261ecSmrg 316605b261ecSmrgint 316705b261ecSmrgProcXkbGetIndicatorMap(ClientPtr client) 316805b261ecSmrg{ 3169f7df2e56Smrg xkbGetIndicatorMapReply rep; 3170f7df2e56Smrg DeviceIntPtr dev; 3171f7df2e56Smrg XkbDescPtr xkb; 3172f7df2e56Smrg XkbIndicatorPtr leds; 317305b261ecSmrg 317405b261ecSmrg REQUEST(xkbGetIndicatorMapReq); 317505b261ecSmrg REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq); 317605b261ecSmrg 3177f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 3178f7df2e56Smrg return BadAccess; 317905b261ecSmrg 31804642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); 318105b261ecSmrg 3182f7df2e56Smrg xkb = dev->key->xkbInfo->desc; 3183f7df2e56Smrg leds = xkb->indicators; 3184f7df2e56Smrg 3185f7df2e56Smrg rep = (xkbGetIndicatorMapReply) { 3186f7df2e56Smrg .type = X_Reply, 3187f7df2e56Smrg .deviceID = dev->id, 3188f7df2e56Smrg .sequenceNumber = client->sequence, 3189f7df2e56Smrg .length = 0, 3190f7df2e56Smrg .which = stuff->which 3191f7df2e56Smrg }; 3192f7df2e56Smrg XkbComputeGetIndicatorMapReplySize(leds, &rep); 3193f7df2e56Smrg return XkbSendIndicatorMap(client, leds, &rep); 319405b261ecSmrg} 319505b261ecSmrg 31964642e01fSmrg/** 31974642e01fSmrg * Apply the given map to the given device. Which specifies which components 31984642e01fSmrg * to apply. 31994642e01fSmrg */ 32004642e01fSmrgstatic int 32014642e01fSmrg_XkbSetIndicatorMap(ClientPtr client, DeviceIntPtr dev, 3202f7df2e56Smrg int which, xkbIndicatorMapWireDesc * desc) 32034642e01fSmrg{ 3204f7df2e56Smrg XkbSrvInfoPtr xkbi; 3205f7df2e56Smrg XkbSrvLedInfoPtr sli; 3206f7df2e56Smrg XkbEventCauseRec cause; 3207f7df2e56Smrg int i, bit; 32084642e01fSmrg 32094642e01fSmrg xkbi = dev->key->xkbInfo; 32104642e01fSmrg 3211f7df2e56Smrg sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 3212f7df2e56Smrg XkbXI_IndicatorMapsMask); 32134642e01fSmrg if (!sli) 3214f7df2e56Smrg return BadAlloc; 32154642e01fSmrg 32164642e01fSmrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 3217f7df2e56Smrg if (which & bit) { 3218f7df2e56Smrg sli->maps[i].flags = desc->flags; 3219f7df2e56Smrg sli->maps[i].which_groups = desc->whichGroups; 3220f7df2e56Smrg sli->maps[i].groups = desc->groups; 3221f7df2e56Smrg sli->maps[i].which_mods = desc->whichMods; 3222f7df2e56Smrg sli->maps[i].mods.mask = desc->mods; 3223f7df2e56Smrg sli->maps[i].mods.real_mods = desc->mods; 3224f7df2e56Smrg sli->maps[i].mods.vmods = desc->virtualMods; 3225f7df2e56Smrg sli->maps[i].ctrls = desc->ctrls; 3226f7df2e56Smrg if (desc->virtualMods != 0) { 3227f7df2e56Smrg unsigned tmp; 3228f7df2e56Smrg 3229f7df2e56Smrg tmp = XkbMaskForVMask(xkbi->desc, desc->virtualMods); 3230f7df2e56Smrg sli->maps[i].mods.mask = desc->mods | tmp; 3231f7df2e56Smrg } 3232f7df2e56Smrg desc++; 3233f7df2e56Smrg } 3234f7df2e56Smrg } 3235f7df2e56Smrg 3236f7df2e56Smrg XkbSetCauseXkbReq(&cause, X_kbSetIndicatorMap, client); 3237f7df2e56Smrg XkbApplyLedMapChanges(dev, sli, which, NULL, NULL, &cause); 32384642e01fSmrg 32394642e01fSmrg return Success; 32404642e01fSmrg} 32414642e01fSmrg 324205b261ecSmrgint 324305b261ecSmrgProcXkbSetIndicatorMap(ClientPtr client) 324405b261ecSmrg{ 3245f7df2e56Smrg int i, bit; 3246f7df2e56Smrg int nIndicators; 3247f7df2e56Smrg DeviceIntPtr dev; 3248f7df2e56Smrg xkbIndicatorMapWireDesc *from; 3249f7df2e56Smrg int rc; 325005b261ecSmrg 325105b261ecSmrg REQUEST(xkbSetIndicatorMapReq); 325205b261ecSmrg REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq); 325305b261ecSmrg 3254f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 3255f7df2e56Smrg return BadAccess; 325605b261ecSmrg 32574642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess); 325805b261ecSmrg 3259f7df2e56Smrg if (stuff->which == 0) 3260f7df2e56Smrg return Success; 326105b261ecSmrg 3262f7df2e56Smrg for (nIndicators = i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 3263f7df2e56Smrg if (stuff->which & bit) 3264f7df2e56Smrg nIndicators++; 326505b261ecSmrg } 3266f7df2e56Smrg if (stuff->length != ((SIZEOF(xkbSetIndicatorMapReq) + 3267f7df2e56Smrg (nIndicators * SIZEOF(xkbIndicatorMapWireDesc))) / 3268f7df2e56Smrg 4)) { 3269f7df2e56Smrg return BadLength; 327005b261ecSmrg } 327105b261ecSmrg 3272f7df2e56Smrg from = (xkbIndicatorMapWireDesc *) &stuff[1]; 3273f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 3274f7df2e56Smrg if (stuff->which & bit) { 3275f7df2e56Smrg if (client->swapped) { 3276f7df2e56Smrg swaps(&from->virtualMods); 3277f7df2e56Smrg swapl(&from->ctrls); 3278f7df2e56Smrg } 3279f7df2e56Smrg CHK_MASK_LEGAL(i, from->whichGroups, XkbIM_UseAnyGroup); 3280f7df2e56Smrg CHK_MASK_LEGAL(i, from->whichMods, XkbIM_UseAnyMods); 3281f7df2e56Smrg from++; 3282f7df2e56Smrg } 328305b261ecSmrg } 328405b261ecSmrg 3285f7df2e56Smrg from = (xkbIndicatorMapWireDesc *) &stuff[1]; 32864642e01fSmrg rc = _XkbSetIndicatorMap(client, dev, stuff->which, from); 32874642e01fSmrg if (rc != Success) 32884642e01fSmrg return rc; 32894642e01fSmrg 3290f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd) { 32914642e01fSmrg DeviceIntPtr other; 3292f7df2e56Smrg 3293f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 3294f7df2e56Smrg if ((other != dev) && other->key && !IsMaster(other) && 3295f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) { 3296f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 3297f7df2e56Smrg DixSetAttrAccess); 32984642e01fSmrg if (rc == Success) 32994642e01fSmrg _XkbSetIndicatorMap(client, other, stuff->which, from); 33004642e01fSmrg } 33014642e01fSmrg } 330205b261ecSmrg } 330305b261ecSmrg 33044642e01fSmrg return Success; 330505b261ecSmrg} 330605b261ecSmrg 330705b261ecSmrg/***====================================================================***/ 330805b261ecSmrg 330905b261ecSmrgint 331005b261ecSmrgProcXkbGetNamedIndicator(ClientPtr client) 331105b261ecSmrg{ 3312f7df2e56Smrg DeviceIntPtr dev; 3313f7df2e56Smrg xkbGetNamedIndicatorReply rep; 3314f7df2e56Smrg register int i = 0; 3315f7df2e56Smrg XkbSrvLedInfoPtr sli; 3316f7df2e56Smrg XkbIndicatorMapPtr map = NULL; 331705b261ecSmrg 331805b261ecSmrg REQUEST(xkbGetNamedIndicatorReq); 331905b261ecSmrg REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq); 332005b261ecSmrg 3321f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 3322f7df2e56Smrg return BadAccess; 332305b261ecSmrg 33244642e01fSmrg CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess); 332505b261ecSmrg CHK_ATOM_ONLY(stuff->indicator); 332605b261ecSmrg 3327f7df2e56Smrg sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID, 0); 332805b261ecSmrg if (!sli) 3329f7df2e56Smrg return BadAlloc; 3330f7df2e56Smrg 3331f7df2e56Smrg i = 0; 3332f7df2e56Smrg map = NULL; 3333f7df2e56Smrg if ((sli->names) && (sli->maps)) { 3334f7df2e56Smrg for (i = 0; i < XkbNumIndicators; i++) { 3335f7df2e56Smrg if (stuff->indicator == sli->names[i]) { 3336f7df2e56Smrg map = &sli->maps[i]; 333705b261ecSmrg break; 333805b261ecSmrg } 333905b261ecSmrg } 334005b261ecSmrg } 334105b261ecSmrg 3342f7df2e56Smrg rep = (xkbGetNamedIndicatorReply) { 3343f7df2e56Smrg .type = X_Reply, 3344f7df2e56Smrg .sequenceNumber = client->sequence, 3345f7df2e56Smrg .length = 0, 3346f7df2e56Smrg .deviceID = dev->id, 3347f7df2e56Smrg .indicator = stuff->indicator 3348f7df2e56Smrg }; 3349f7df2e56Smrg if (map != NULL) { 3350f7df2e56Smrg rep.found = TRUE; 3351f7df2e56Smrg rep.on = ((sli->effectiveState & (1 << i)) != 0); 3352f7df2e56Smrg rep.realIndicator = ((sli->physIndicators & (1 << i)) != 0); 3353f7df2e56Smrg rep.ndx = i; 3354f7df2e56Smrg rep.flags = map->flags; 3355f7df2e56Smrg rep.whichGroups = map->which_groups; 3356f7df2e56Smrg rep.groups = map->groups; 3357f7df2e56Smrg rep.whichMods = map->which_mods; 3358f7df2e56Smrg rep.mods = map->mods.mask; 3359f7df2e56Smrg rep.realMods = map->mods.real_mods; 3360f7df2e56Smrg rep.virtualMods = map->mods.vmods; 3361f7df2e56Smrg rep.ctrls = map->ctrls; 3362f7df2e56Smrg rep.supported = TRUE; 3363f7df2e56Smrg } 3364f7df2e56Smrg else { 3365f7df2e56Smrg rep.found = FALSE; 3366f7df2e56Smrg rep.on = FALSE; 3367f7df2e56Smrg rep.realIndicator = FALSE; 3368f7df2e56Smrg rep.ndx = XkbNoIndicator; 3369f7df2e56Smrg rep.flags = 0; 3370f7df2e56Smrg rep.whichGroups = 0; 3371f7df2e56Smrg rep.groups = 0; 3372f7df2e56Smrg rep.whichMods = 0; 3373f7df2e56Smrg rep.mods = 0; 3374f7df2e56Smrg rep.realMods = 0; 3375f7df2e56Smrg rep.virtualMods = 0; 3376f7df2e56Smrg rep.ctrls = 0; 3377f7df2e56Smrg rep.supported = TRUE; 3378f7df2e56Smrg } 3379f7df2e56Smrg if (client->swapped) { 3380f7df2e56Smrg swapl(&rep.length); 3381f7df2e56Smrg swaps(&rep.sequenceNumber); 3382f7df2e56Smrg swapl(&rep.indicator); 3383f7df2e56Smrg swaps(&rep.virtualMods); 3384f7df2e56Smrg swapl(&rep.ctrls); 3385f7df2e56Smrg } 3386f7df2e56Smrg 3387f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetNamedIndicatorReply), &rep); 33886747b715Smrg return Success; 338905b261ecSmrg} 339005b261ecSmrg 33914642e01fSmrg/** 33924642e01fSmrg * Find the IM on the device. 33934642e01fSmrg * Returns the map, or NULL if the map doesn't exist. 33944642e01fSmrg * If the return value is NULL, led_return is undefined. Otherwise, led_return 33954642e01fSmrg * is set to the led index of the map. 33964642e01fSmrg */ 33974642e01fSmrgstatic XkbIndicatorMapPtr 3398f7df2e56Smrg_XkbFindNamedIndicatorMap(XkbSrvLedInfoPtr sli, Atom indicator, int *led_return) 33994642e01fSmrg{ 3400f7df2e56Smrg XkbIndicatorMapPtr map; 340105b261ecSmrg 34024642e01fSmrg /* search for the right indicator */ 34034642e01fSmrg map = NULL; 340405b261ecSmrg if (sli->names && sli->maps) { 3405f7df2e56Smrg int led; 34066747b715Smrg 3407f7df2e56Smrg for (led = 0; (led < XkbNumIndicators) && (map == NULL); led++) { 3408f7df2e56Smrg if (sli->names[led] == indicator) { 3409f7df2e56Smrg map = &sli->maps[led]; 3410f7df2e56Smrg *led_return = led; 3411f7df2e56Smrg break; 3412f7df2e56Smrg } 3413f7df2e56Smrg } 341405b261ecSmrg } 341505b261ecSmrg 34164642e01fSmrg return map; 34174642e01fSmrg} 34184642e01fSmrg 34194642e01fSmrg/** 34206747b715Smrg * Creates an indicator map on the device. If dryRun is TRUE, it only checks 34214642e01fSmrg * if creation is possible, but doesn't actually create it. 34224642e01fSmrg */ 34234642e01fSmrgstatic int 34244642e01fSmrg_XkbCreateIndicatorMap(DeviceIntPtr dev, Atom indicator, 34254642e01fSmrg int ledClass, int ledID, 3426f7df2e56Smrg XkbIndicatorMapPtr * map_return, int *led_return, 34274642e01fSmrg Bool dryRun) 34284642e01fSmrg{ 3429f7df2e56Smrg XkbSrvLedInfoPtr sli; 3430f7df2e56Smrg XkbIndicatorMapPtr map; 3431f7df2e56Smrg int led; 34324642e01fSmrg 34334642e01fSmrg sli = XkbFindSrvLedInfo(dev, ledClass, ledID, XkbXI_IndicatorsMask); 34344642e01fSmrg if (!sli) 34354642e01fSmrg return BadAlloc; 34364642e01fSmrg 34374642e01fSmrg map = _XkbFindNamedIndicatorMap(sli, indicator, &led); 34384642e01fSmrg 3439f7df2e56Smrg if (!map) { 34404642e01fSmrg /* find first unused indicator maps and assign the name to it */ 3441f7df2e56Smrg for (led = 0, map = NULL; (led < XkbNumIndicators) && (map == NULL); 3442f7df2e56Smrg led++) { 34434642e01fSmrg if ((sli->names) && (sli->maps) && (sli->names[led] == None) && 3444f7df2e56Smrg (!XkbIM_InUse(&sli->maps[led]))) { 34454642e01fSmrg map = &sli->maps[led]; 34464642e01fSmrg if (!dryRun) 34474642e01fSmrg sli->names[led] = indicator; 34484642e01fSmrg break; 34494642e01fSmrg } 34504642e01fSmrg } 34514642e01fSmrg } 34524642e01fSmrg 34534642e01fSmrg if (!map) 34544642e01fSmrg return BadAlloc; 34554642e01fSmrg 34564642e01fSmrg *led_return = led; 34574642e01fSmrg *map_return = map; 34584642e01fSmrg return Success; 34594642e01fSmrg} 34604642e01fSmrg 34614642e01fSmrgstatic int 34624642e01fSmrg_XkbSetNamedIndicator(ClientPtr client, DeviceIntPtr dev, 3463f7df2e56Smrg xkbSetNamedIndicatorReq * stuff) 34644642e01fSmrg{ 3465f7df2e56Smrg unsigned int extDevReason; 3466f7df2e56Smrg unsigned int statec, namec, mapc; 3467f7df2e56Smrg XkbSrvLedInfoPtr sli; 3468f7df2e56Smrg int led = 0; 3469f7df2e56Smrg XkbIndicatorMapPtr map; 3470f7df2e56Smrg DeviceIntPtr kbd; 3471f7df2e56Smrg XkbEventCauseRec cause; 3472f7df2e56Smrg xkbExtensionDeviceNotify ed; 3473f7df2e56Smrg XkbChangesRec changes; 3474f7df2e56Smrg int rc; 34754642e01fSmrg 34764642e01fSmrg rc = _XkbCreateIndicatorMap(dev, stuff->indicator, stuff->ledClass, 34774642e01fSmrg stuff->ledID, &map, &led, FALSE); 3478f7df2e56Smrg if (rc != Success || !map) /* oh-oh */ 34794642e01fSmrg return rc; 34804642e01fSmrg 34814642e01fSmrg sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID, 34824642e01fSmrg XkbXI_IndicatorsMask); 34834642e01fSmrg if (!sli) 34844642e01fSmrg return BadAlloc; 34854642e01fSmrg 34864642e01fSmrg namec = mapc = statec = 0; 34874642e01fSmrg extDevReason = 0; 34884642e01fSmrg 3489f7df2e56Smrg namec |= (1 << led); 34904642e01fSmrg sli->namesPresent |= ((stuff->indicator != None) ? (1 << led) : 0); 34914642e01fSmrg extDevReason |= XkbXI_IndicatorNamesMask; 34924642e01fSmrg 34934642e01fSmrg if (stuff->setMap) { 34944642e01fSmrg map->flags = stuff->flags; 34954642e01fSmrg map->which_groups = stuff->whichGroups; 34964642e01fSmrg map->groups = stuff->groups; 34974642e01fSmrg map->which_mods = stuff->whichMods; 34984642e01fSmrg map->mods.mask = stuff->realMods; 34994642e01fSmrg map->mods.real_mods = stuff->realMods; 3500f7df2e56Smrg map->mods.vmods = stuff->virtualMods; 35014642e01fSmrg map->ctrls = stuff->ctrls; 3502f7df2e56Smrg mapc |= (1 << led); 35034642e01fSmrg } 35044642e01fSmrg 3505f7df2e56Smrg if ((stuff->setState) && ((map->flags & XkbIM_NoExplicit) == 0)) { 3506f7df2e56Smrg if (stuff->on) 3507f7df2e56Smrg sli->explicitState |= (1 << led); 3508f7df2e56Smrg else 3509f7df2e56Smrg sli->explicitState &= ~(1 << led); 35104642e01fSmrg statec |= ((sli->effectiveState ^ sli->explicitState) & (1 << led)); 351105b261ecSmrg } 35124642e01fSmrg 3513f7df2e56Smrg memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify)); 3514f7df2e56Smrg memset((char *) &changes, 0, sizeof(XkbChangesRec)); 3515f7df2e56Smrg XkbSetCauseXkbReq(&cause, X_kbSetNamedIndicator, client); 351605b261ecSmrg if (namec) 3517f7df2e56Smrg XkbApplyLedNameChanges(dev, sli, namec, &ed, &changes, &cause); 351805b261ecSmrg if (mapc) 3519f7df2e56Smrg XkbApplyLedMapChanges(dev, sli, mapc, &ed, &changes, &cause); 352005b261ecSmrg if (statec) 3521f7df2e56Smrg XkbApplyLedStateChanges(dev, sli, statec, &ed, &changes, &cause); 352205b261ecSmrg 35234642e01fSmrg kbd = dev; 3524f7df2e56Smrg if ((sli->flags & XkbSLI_HasOwnState) == 0) 35254642e01fSmrg kbd = inputInfo.keyboard; 35264642e01fSmrg XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause); 35274642e01fSmrg 35284642e01fSmrg return Success; 35294642e01fSmrg} 35304642e01fSmrg 35314642e01fSmrgint 35324642e01fSmrgProcXkbSetNamedIndicator(ClientPtr client) 35334642e01fSmrg{ 3534f7df2e56Smrg int rc; 3535f7df2e56Smrg DeviceIntPtr dev; 3536f7df2e56Smrg int led = 0; 3537f7df2e56Smrg XkbIndicatorMapPtr map; 35384642e01fSmrg 35394642e01fSmrg REQUEST(xkbSetNamedIndicatorReq); 35404642e01fSmrg REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq); 35414642e01fSmrg 3542f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 3543f7df2e56Smrg return BadAccess; 35444642e01fSmrg 35454642e01fSmrg CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess); 35464642e01fSmrg CHK_ATOM_ONLY(stuff->indicator); 3547f7df2e56Smrg CHK_MASK_LEGAL(0x10, stuff->whichGroups, XkbIM_UseAnyGroup); 3548f7df2e56Smrg CHK_MASK_LEGAL(0x11, stuff->whichMods, XkbIM_UseAnyMods); 35494642e01fSmrg 35504642e01fSmrg /* Dry-run for checks */ 35514642e01fSmrg rc = _XkbCreateIndicatorMap(dev, stuff->indicator, 35524642e01fSmrg stuff->ledClass, stuff->ledID, 35534642e01fSmrg &map, &led, TRUE); 3554f7df2e56Smrg if (rc != Success || !map) /* couldn't be created or didn't exist */ 35554642e01fSmrg return rc; 35564642e01fSmrg 35574642e01fSmrg if (stuff->deviceSpec == XkbUseCoreKbd || 3558f7df2e56Smrg stuff->deviceSpec == XkbUseCorePtr) { 35594642e01fSmrg DeviceIntPtr other; 3560f7df2e56Smrg 3561f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 3562f7df2e56Smrg if ((other != dev) && !IsMaster(other) && 3563f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev && (other->kbdfeed || 3564f7df2e56Smrg other->leds) && 3565f7df2e56Smrg (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) 3566f7df2e56Smrg == Success)) { 35674642e01fSmrg rc = _XkbCreateIndicatorMap(other, stuff->indicator, 3568f7df2e56Smrg stuff->ledClass, stuff->ledID, &map, 3569f7df2e56Smrg &led, TRUE); 35704642e01fSmrg if (rc != Success || !map) 35714642e01fSmrg return rc; 35724642e01fSmrg } 35734642e01fSmrg } 35744642e01fSmrg } 35754642e01fSmrg 35764642e01fSmrg /* All checks passed, let's do it */ 35774642e01fSmrg rc = _XkbSetNamedIndicator(client, dev, stuff); 35784642e01fSmrg if (rc != Success) 35794642e01fSmrg return rc; 35804642e01fSmrg 35814642e01fSmrg if (stuff->deviceSpec == XkbUseCoreKbd || 3582f7df2e56Smrg stuff->deviceSpec == XkbUseCorePtr) { 35834642e01fSmrg DeviceIntPtr other; 3584f7df2e56Smrg 3585f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 3586f7df2e56Smrg if ((other != dev) && !IsMaster(other) && 3587f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev && (other->kbdfeed || 3588f7df2e56Smrg other->leds) && 3589f7df2e56Smrg (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) 3590f7df2e56Smrg == Success)) { 35914642e01fSmrg _XkbSetNamedIndicator(client, other, stuff); 35924642e01fSmrg } 35934642e01fSmrg } 35944642e01fSmrg } 35954642e01fSmrg 35966747b715Smrg return Success; 359705b261ecSmrg} 359805b261ecSmrg 359905b261ecSmrg/***====================================================================***/ 360005b261ecSmrg 360105b261ecSmrgstatic CARD32 3602f7df2e56Smrg_XkbCountAtoms(Atom *atoms, int maxAtoms, int *count) 360305b261ecSmrg{ 3604f7df2e56Smrg register unsigned int i, bit, nAtoms; 3605f7df2e56Smrg register CARD32 atomsPresent; 360605b261ecSmrg 3607f7df2e56Smrg for (i = nAtoms = atomsPresent = 0, bit = 1; i < maxAtoms; i++, bit <<= 1) { 3608f7df2e56Smrg if (atoms[i] != None) { 3609f7df2e56Smrg atomsPresent |= bit; 3610f7df2e56Smrg nAtoms++; 3611f7df2e56Smrg } 361205b261ecSmrg } 361305b261ecSmrg if (count) 3614f7df2e56Smrg *count = nAtoms; 361505b261ecSmrg return atomsPresent; 361605b261ecSmrg} 361705b261ecSmrg 361805b261ecSmrgstatic char * 3619f7df2e56Smrg_XkbWriteAtoms(char *wire, Atom *atoms, int maxAtoms, int swap) 362005b261ecSmrg{ 3621f7df2e56Smrg register unsigned int i; 3622f7df2e56Smrg Atom *atm; 3623f7df2e56Smrg 3624f7df2e56Smrg atm = (Atom *) wire; 3625f7df2e56Smrg for (i = 0; i < maxAtoms; i++) { 3626f7df2e56Smrg if (atoms[i] != None) { 3627f7df2e56Smrg *atm = atoms[i]; 3628f7df2e56Smrg if (swap) { 3629f7df2e56Smrg swapl(atm); 3630f7df2e56Smrg } 3631f7df2e56Smrg atm++; 3632f7df2e56Smrg } 3633f7df2e56Smrg } 3634f7df2e56Smrg return (char *) atm; 363505b261ecSmrg} 363605b261ecSmrg 363705b261ecSmrgstatic Status 3638f7df2e56SmrgXkbComputeGetNamesReplySize(XkbDescPtr xkb, xkbGetNamesReply * rep) 363905b261ecSmrg{ 3640f7df2e56Smrg register unsigned which, length; 3641f7df2e56Smrg register int i; 3642f7df2e56Smrg 3643f7df2e56Smrg rep->minKeyCode = xkb->min_key_code; 3644f7df2e56Smrg rep->maxKeyCode = xkb->max_key_code; 3645f7df2e56Smrg which = rep->which; 3646f7df2e56Smrg length = 0; 3647f7df2e56Smrg if (xkb->names != NULL) { 3648f7df2e56Smrg if (which & XkbKeycodesNameMask) 3649f7df2e56Smrg length++; 3650f7df2e56Smrg if (which & XkbGeometryNameMask) 3651f7df2e56Smrg length++; 3652f7df2e56Smrg if (which & XkbSymbolsNameMask) 3653f7df2e56Smrg length++; 3654f7df2e56Smrg if (which & XkbPhysSymbolsNameMask) 3655f7df2e56Smrg length++; 3656f7df2e56Smrg if (which & XkbTypesNameMask) 3657f7df2e56Smrg length++; 3658f7df2e56Smrg if (which & XkbCompatNameMask) 3659f7df2e56Smrg length++; 3660f7df2e56Smrg } 3661f7df2e56Smrg else 3662f7df2e56Smrg which &= ~XkbComponentNamesMask; 3663f7df2e56Smrg 3664f7df2e56Smrg if (xkb->map != NULL) { 3665f7df2e56Smrg if (which & XkbKeyTypeNamesMask) 3666f7df2e56Smrg length += xkb->map->num_types; 3667f7df2e56Smrg rep->nTypes = xkb->map->num_types; 3668f7df2e56Smrg if (which & XkbKTLevelNamesMask) { 3669f7df2e56Smrg XkbKeyTypePtr pType = xkb->map->types; 3670f7df2e56Smrg int nKTLevels = 0; 3671f7df2e56Smrg 3672f7df2e56Smrg length += XkbPaddedSize(xkb->map->num_types) / 4; 3673f7df2e56Smrg for (i = 0; i < xkb->map->num_types; i++, pType++) { 3674f7df2e56Smrg if (pType->level_names != NULL) 3675f7df2e56Smrg nKTLevels += pType->num_levels; 3676f7df2e56Smrg } 3677f7df2e56Smrg rep->nKTLevels = nKTLevels; 3678f7df2e56Smrg length += nKTLevels; 3679f7df2e56Smrg } 368005b261ecSmrg } 368105b261ecSmrg else { 3682f7df2e56Smrg rep->nTypes = 0; 3683f7df2e56Smrg rep->nKTLevels = 0; 3684f7df2e56Smrg which &= ~(XkbKeyTypeNamesMask | XkbKTLevelNamesMask); 3685f7df2e56Smrg } 3686f7df2e56Smrg 3687f7df2e56Smrg rep->minKeyCode = xkb->min_key_code; 3688f7df2e56Smrg rep->maxKeyCode = xkb->max_key_code; 3689f7df2e56Smrg rep->indicators = 0; 3690f7df2e56Smrg rep->virtualMods = 0; 3691f7df2e56Smrg rep->groupNames = 0; 3692f7df2e56Smrg if (xkb->names != NULL) { 3693f7df2e56Smrg if (which & XkbIndicatorNamesMask) { 3694f7df2e56Smrg int nLeds; 3695f7df2e56Smrg 3696f7df2e56Smrg rep->indicators = 3697f7df2e56Smrg _XkbCountAtoms(xkb->names->indicators, XkbNumIndicators, 3698f7df2e56Smrg &nLeds); 3699f7df2e56Smrg length += nLeds; 3700f7df2e56Smrg if (nLeds == 0) 3701f7df2e56Smrg which &= ~XkbIndicatorNamesMask; 3702f7df2e56Smrg } 3703f7df2e56Smrg 3704f7df2e56Smrg if (which & XkbVirtualModNamesMask) { 3705f7df2e56Smrg int nVMods; 3706f7df2e56Smrg 3707f7df2e56Smrg rep->virtualMods = 3708f7df2e56Smrg _XkbCountAtoms(xkb->names->vmods, XkbNumVirtualMods, &nVMods); 3709f7df2e56Smrg length += nVMods; 3710f7df2e56Smrg if (nVMods == 0) 3711f7df2e56Smrg which &= ~XkbVirtualModNamesMask; 3712f7df2e56Smrg } 3713f7df2e56Smrg 3714f7df2e56Smrg if (which & XkbGroupNamesMask) { 3715f7df2e56Smrg int nGroups; 3716f7df2e56Smrg 3717f7df2e56Smrg rep->groupNames = 3718f7df2e56Smrg _XkbCountAtoms(xkb->names->groups, XkbNumKbdGroups, &nGroups); 3719f7df2e56Smrg length += nGroups; 3720f7df2e56Smrg if (nGroups == 0) 3721f7df2e56Smrg which &= ~XkbGroupNamesMask; 3722f7df2e56Smrg } 3723f7df2e56Smrg 3724f7df2e56Smrg if ((which & XkbKeyNamesMask) && (xkb->names->keys)) 3725f7df2e56Smrg length += rep->nKeys; 3726f7df2e56Smrg else 3727f7df2e56Smrg which &= ~XkbKeyNamesMask; 3728f7df2e56Smrg 3729f7df2e56Smrg if ((which & XkbKeyAliasesMask) && 3730f7df2e56Smrg (xkb->names->key_aliases) && (xkb->names->num_key_aliases > 0)) { 3731f7df2e56Smrg rep->nKeyAliases = xkb->names->num_key_aliases; 3732f7df2e56Smrg length += rep->nKeyAliases * 2; 3733f7df2e56Smrg } 3734f7df2e56Smrg else { 3735f7df2e56Smrg which &= ~XkbKeyAliasesMask; 3736f7df2e56Smrg rep->nKeyAliases = 0; 3737f7df2e56Smrg } 3738f7df2e56Smrg 3739f7df2e56Smrg if ((which & XkbRGNamesMask) && (xkb->names->num_rg > 0)) 3740f7df2e56Smrg length += xkb->names->num_rg; 3741f7df2e56Smrg else 3742f7df2e56Smrg which &= ~XkbRGNamesMask; 374305b261ecSmrg } 374405b261ecSmrg else { 3745f7df2e56Smrg which &= ~(XkbIndicatorNamesMask | XkbVirtualModNamesMask); 3746f7df2e56Smrg which &= ~(XkbGroupNamesMask | XkbKeyNamesMask | XkbKeyAliasesMask); 3747f7df2e56Smrg which &= ~XkbRGNamesMask; 374805b261ecSmrg } 374905b261ecSmrg 3750f7df2e56Smrg rep->length = length; 3751f7df2e56Smrg rep->which = which; 375205b261ecSmrg return Success; 375305b261ecSmrg} 375405b261ecSmrg 375505b261ecSmrgstatic int 3756f7df2e56SmrgXkbSendNames(ClientPtr client, XkbDescPtr xkb, xkbGetNamesReply * rep) 375705b261ecSmrg{ 3758f7df2e56Smrg register unsigned i, length, which; 3759f7df2e56Smrg char *start; 3760f7df2e56Smrg char *desc; 376105b261ecSmrg 3762f7df2e56Smrg length = rep->length * 4; 3763f7df2e56Smrg which = rep->which; 376405b261ecSmrg if (client->swapped) { 3765f7df2e56Smrg swaps(&rep->sequenceNumber); 3766f7df2e56Smrg swapl(&rep->length); 3767f7df2e56Smrg swapl(&rep->which); 3768f7df2e56Smrg swaps(&rep->virtualMods); 3769f7df2e56Smrg swapl(&rep->indicators); 377005b261ecSmrg } 377105b261ecSmrg 37729ace9065Smrg start = desc = calloc(1, length); 3773f7df2e56Smrg if (!start) 3774f7df2e56Smrg return BadAlloc; 377505b261ecSmrg if (xkb->names) { 3776f7df2e56Smrg if (which & XkbKeycodesNameMask) { 3777f7df2e56Smrg *((CARD32 *) desc) = xkb->names->keycodes; 377805b261ecSmrg if (client->swapped) { 3779f7df2e56Smrg swapl((int *) desc); 378005b261ecSmrg } 3781f7df2e56Smrg desc += 4; 378205b261ecSmrg } 3783f7df2e56Smrg if (which & XkbGeometryNameMask) { 3784f7df2e56Smrg *((CARD32 *) desc) = xkb->names->geometry; 378505b261ecSmrg if (client->swapped) { 3786f7df2e56Smrg swapl((int *) desc); 378705b261ecSmrg } 3788f7df2e56Smrg desc += 4; 378905b261ecSmrg } 3790f7df2e56Smrg if (which & XkbSymbolsNameMask) { 3791f7df2e56Smrg *((CARD32 *) desc) = xkb->names->symbols; 379205b261ecSmrg if (client->swapped) { 3793f7df2e56Smrg swapl((int *) desc); 379405b261ecSmrg } 3795f7df2e56Smrg desc += 4; 379605b261ecSmrg } 3797f7df2e56Smrg if (which & XkbPhysSymbolsNameMask) { 3798f7df2e56Smrg register CARD32 *atm = (CARD32 *) desc; 3799f7df2e56Smrg 3800f7df2e56Smrg atm[0] = (CARD32) xkb->names->phys_symbols; 380105b261ecSmrg if (client->swapped) { 3802f7df2e56Smrg swapl(&atm[0]); 380305b261ecSmrg } 3804f7df2e56Smrg desc += 4; 380505b261ecSmrg } 3806f7df2e56Smrg if (which & XkbTypesNameMask) { 3807f7df2e56Smrg *((CARD32 *) desc) = (CARD32) xkb->names->types; 380805b261ecSmrg if (client->swapped) { 3809f7df2e56Smrg swapl((int *) desc); 381005b261ecSmrg } 3811f7df2e56Smrg desc += 4; 381205b261ecSmrg } 3813f7df2e56Smrg if (which & XkbCompatNameMask) { 3814f7df2e56Smrg *((CARD32 *) desc) = (CARD32) xkb->names->compat; 381505b261ecSmrg if (client->swapped) { 3816f7df2e56Smrg swapl((int *) desc); 381705b261ecSmrg } 3818f7df2e56Smrg desc += 4; 381905b261ecSmrg } 3820f7df2e56Smrg if (which & XkbKeyTypeNamesMask) { 3821f7df2e56Smrg register CARD32 *atm = (CARD32 *) desc; 3822f7df2e56Smrg register XkbKeyTypePtr type = xkb->map->types; 382305b261ecSmrg 3824f7df2e56Smrg for (i = 0; i < xkb->map->num_types; i++, atm++, type++) { 3825f7df2e56Smrg *atm = (CARD32) type->name; 382605b261ecSmrg if (client->swapped) { 3827f7df2e56Smrg swapl(atm); 382805b261ecSmrg } 382905b261ecSmrg } 3830f7df2e56Smrg desc = (char *) atm; 383105b261ecSmrg } 3832f7df2e56Smrg if (which & XkbKTLevelNamesMask && xkb->map) { 383305b261ecSmrg XkbKeyTypePtr type = xkb->map->types; 383405b261ecSmrg register CARD32 *atm; 3835f7df2e56Smrg 3836f7df2e56Smrg for (i = 0; i < rep->nTypes; i++, type++) { 383705b261ecSmrg *desc++ = type->num_levels; 383805b261ecSmrg } 3839f7df2e56Smrg desc += XkbPaddedSize(rep->nTypes) - rep->nTypes; 384005b261ecSmrg 3841f7df2e56Smrg atm = (CARD32 *) desc; 384205b261ecSmrg type = xkb->map->types; 3843f7df2e56Smrg for (i = 0; i < xkb->map->num_types; i++, type++) { 384405b261ecSmrg register unsigned l; 3845f7df2e56Smrg 384605b261ecSmrg if (type->level_names) { 3847f7df2e56Smrg for (l = 0; l < type->num_levels; l++, atm++) { 3848f7df2e56Smrg *atm = type->level_names[l]; 384905b261ecSmrg if (client->swapped) { 3850f7df2e56Smrg swapl(atm); 385105b261ecSmrg } 385205b261ecSmrg } 3853f7df2e56Smrg desc += type->num_levels * 4; 385405b261ecSmrg } 385505b261ecSmrg } 385605b261ecSmrg } 3857f7df2e56Smrg if (which & XkbIndicatorNamesMask) { 3858f7df2e56Smrg desc = 3859f7df2e56Smrg _XkbWriteAtoms(desc, xkb->names->indicators, XkbNumIndicators, 3860f7df2e56Smrg client->swapped); 386105b261ecSmrg } 3862f7df2e56Smrg if (which & XkbVirtualModNamesMask) { 3863f7df2e56Smrg desc = _XkbWriteAtoms(desc, xkb->names->vmods, XkbNumVirtualMods, 3864f7df2e56Smrg client->swapped); 386505b261ecSmrg } 3866f7df2e56Smrg if (which & XkbGroupNamesMask) { 3867f7df2e56Smrg desc = _XkbWriteAtoms(desc, xkb->names->groups, XkbNumKbdGroups, 3868f7df2e56Smrg client->swapped); 386905b261ecSmrg } 3870f7df2e56Smrg if (which & XkbKeyNamesMask) { 3871f7df2e56Smrg for (i = 0; i < rep->nKeys; i++, desc += sizeof(XkbKeyNameRec)) { 3872f7df2e56Smrg *((XkbKeyNamePtr) desc) = xkb->names->keys[i + rep->firstKey]; 387305b261ecSmrg } 387405b261ecSmrg } 3875f7df2e56Smrg if (which & XkbKeyAliasesMask) { 3876f7df2e56Smrg XkbKeyAliasPtr pAl; 3877f7df2e56Smrg 3878f7df2e56Smrg pAl = xkb->names->key_aliases; 3879f7df2e56Smrg for (i = 0; i < rep->nKeyAliases; 3880f7df2e56Smrg i++, pAl++, desc += 2 * XkbKeyNameLength) { 3881f7df2e56Smrg *((XkbKeyAliasPtr) desc) = *pAl; 388205b261ecSmrg } 388305b261ecSmrg } 3884f7df2e56Smrg if ((which & XkbRGNamesMask) && (rep->nRadioGroups > 0)) { 3885f7df2e56Smrg register CARD32 *atm = (CARD32 *) desc; 3886f7df2e56Smrg 3887f7df2e56Smrg for (i = 0; i < rep->nRadioGroups; i++, atm++) { 3888f7df2e56Smrg *atm = (CARD32) xkb->names->radio_groups[i]; 388905b261ecSmrg if (client->swapped) { 3890f7df2e56Smrg swapl(atm); 389105b261ecSmrg } 389205b261ecSmrg } 3893f7df2e56Smrg desc += rep->nRadioGroups * 4; 389405b261ecSmrg } 389505b261ecSmrg } 389605b261ecSmrg 3897f7df2e56Smrg if ((desc - start) != (length)) { 3898f7df2e56Smrg ErrorF("[xkb] BOGUS LENGTH in write names, expected %d, got %ld\n", 3899f7df2e56Smrg length, (unsigned long) (desc - start)); 390005b261ecSmrg } 3901f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetNamesReply), rep); 390205b261ecSmrg WriteToClient(client, length, start); 3903f7df2e56Smrg free((char *) start); 39046747b715Smrg return Success; 390505b261ecSmrg} 390605b261ecSmrg 390705b261ecSmrgint 390805b261ecSmrgProcXkbGetNames(ClientPtr client) 390905b261ecSmrg{ 3910f7df2e56Smrg DeviceIntPtr dev; 3911f7df2e56Smrg XkbDescPtr xkb; 3912f7df2e56Smrg xkbGetNamesReply rep; 391305b261ecSmrg 391405b261ecSmrg REQUEST(xkbGetNamesReq); 391505b261ecSmrg REQUEST_SIZE_MATCH(xkbGetNamesReq); 391605b261ecSmrg 3917f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 3918f7df2e56Smrg return BadAccess; 391905b261ecSmrg 39204642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); 3921f7df2e56Smrg CHK_MASK_LEGAL(0x01, stuff->which, XkbAllNamesMask); 392205b261ecSmrg 392305b261ecSmrg xkb = dev->key->xkbInfo->desc; 3924f7df2e56Smrg rep = (xkbGetNamesReply) { 3925f7df2e56Smrg .type = X_Reply, 3926f7df2e56Smrg .deviceID = dev->id, 3927f7df2e56Smrg .sequenceNumber = client->sequence, 3928f7df2e56Smrg .length = 0, 3929f7df2e56Smrg .which = stuff->which, 3930f7df2e56Smrg .nTypes = xkb->map->num_types, 3931f7df2e56Smrg .firstKey = xkb->min_key_code, 3932f7df2e56Smrg .nKeys = XkbNumKeys(xkb), 3933f7df2e56Smrg .nKeyAliases = xkb->names ? xkb->names->num_key_aliases : 0, 3934f7df2e56Smrg .nRadioGroups = xkb->names ? xkb->names->num_rg : 0 3935f7df2e56Smrg }; 3936f7df2e56Smrg XkbComputeGetNamesReplySize(xkb, &rep); 3937f7df2e56Smrg return XkbSendNames(client, xkb, &rep); 393805b261ecSmrg} 393905b261ecSmrg 394005b261ecSmrg/***====================================================================***/ 394105b261ecSmrg 394205b261ecSmrgstatic CARD32 * 3943f7df2e56Smrg_XkbCheckAtoms(CARD32 *wire, int nAtoms, int swapped, Atom *pError) 394405b261ecSmrg{ 3945f7df2e56Smrg register int i; 3946f7df2e56Smrg 3947f7df2e56Smrg for (i = 0; i < nAtoms; i++, wire++) { 3948f7df2e56Smrg if (swapped) { 3949f7df2e56Smrg swapl(wire); 3950f7df2e56Smrg } 3951f7df2e56Smrg if ((((Atom) *wire) != None) && (!ValidAtom((Atom) *wire))) { 3952f7df2e56Smrg *pError = ((Atom) *wire); 3953f7df2e56Smrg return NULL; 3954f7df2e56Smrg } 395505b261ecSmrg } 395605b261ecSmrg return wire; 395705b261ecSmrg} 395805b261ecSmrg 395905b261ecSmrgstatic CARD32 * 3960f7df2e56Smrg_XkbCheckMaskedAtoms(CARD32 *wire, int nAtoms, CARD32 present, int swapped, 3961f7df2e56Smrg Atom *pError) 396205b261ecSmrg{ 3963f7df2e56Smrg register unsigned i, bit; 3964f7df2e56Smrg 3965f7df2e56Smrg for (i = 0, bit = 1; (i < nAtoms) && (present); i++, bit <<= 1) { 3966f7df2e56Smrg if ((present & bit) == 0) 3967f7df2e56Smrg continue; 3968f7df2e56Smrg if (swapped) { 3969f7df2e56Smrg swapl(wire); 3970f7df2e56Smrg } 3971f7df2e56Smrg if ((((Atom) *wire) != None) && (!ValidAtom(((Atom) *wire)))) { 3972f7df2e56Smrg *pError = (Atom) *wire; 3973f7df2e56Smrg return NULL; 3974f7df2e56Smrg } 3975f7df2e56Smrg wire++; 397605b261ecSmrg } 397705b261ecSmrg return wire; 397805b261ecSmrg} 397905b261ecSmrg 398005b261ecSmrgstatic Atom * 3981f7df2e56Smrg_XkbCopyMaskedAtoms(Atom *wire, Atom *dest, int nAtoms, CARD32 present) 398205b261ecSmrg{ 3983f7df2e56Smrg register int i, bit; 398405b261ecSmrg 3985f7df2e56Smrg for (i = 0, bit = 1; (i < nAtoms) && (present); i++, bit <<= 1) { 3986f7df2e56Smrg if ((present & bit) == 0) 3987f7df2e56Smrg continue; 3988f7df2e56Smrg dest[i] = *wire++; 398905b261ecSmrg } 399005b261ecSmrg return wire; 399105b261ecSmrg} 399205b261ecSmrg 399305b261ecSmrgstatic Bool 3994f7df2e56Smrg_XkbCheckTypeName(Atom name, int typeNdx) 399505b261ecSmrg{ 3996f7df2e56Smrg const char *str; 399705b261ecSmrg 3998f7df2e56Smrg str = NameForAtom(name); 3999f7df2e56Smrg if ((strcmp(str, "ONE_LEVEL") == 0) || (strcmp(str, "TWO_LEVEL") == 0) || 4000f7df2e56Smrg (strcmp(str, "ALPHABETIC") == 0) || (strcmp(str, "KEYPAD") == 0)) 4001f7df2e56Smrg return FALSE; 40026747b715Smrg return TRUE; 400305b261ecSmrg} 400405b261ecSmrg 40054642e01fSmrg/** 40064642e01fSmrg * Check the device-dependent data in the request against the device. Returns 40074642e01fSmrg * Success, or the appropriate error code. 40084642e01fSmrg */ 40094642e01fSmrgstatic int 40104642e01fSmrg_XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev, 4011f7df2e56Smrg xkbSetNamesReq * stuff, CARD32 *data) 401205b261ecSmrg{ 4013f7df2e56Smrg XkbDescRec *xkb; 4014f7df2e56Smrg CARD32 *tmp; 4015f7df2e56Smrg Atom bad = None; 401605b261ecSmrg 40174642e01fSmrg tmp = data; 40184642e01fSmrg xkb = dev->key->xkbInfo->desc; 40194642e01fSmrg 40204642e01fSmrg if (stuff->which & XkbKeyTypeNamesMask) { 40214642e01fSmrg int i; 4022f7df2e56Smrg CARD32 *old; 4023f7df2e56Smrg 4024f7df2e56Smrg if (stuff->nTypes < 1) { 4025f7df2e56Smrg client->errorValue = _XkbErrCode2(0x02, stuff->nTypes); 40264642e01fSmrg return BadValue; 40274642e01fSmrg } 4028f7df2e56Smrg if ((unsigned) (stuff->firstType + stuff->nTypes - 1) >= 4029f7df2e56Smrg xkb->map->num_types) { 4030f7df2e56Smrg client->errorValue = 4031f7df2e56Smrg _XkbErrCode4(0x03, stuff->firstType, stuff->nTypes, 4032f7df2e56Smrg xkb->map->num_types); 40334642e01fSmrg return BadValue; 40344642e01fSmrg } 4035f7df2e56Smrg if (((unsigned) stuff->firstType) <= XkbLastRequiredType) { 4036f7df2e56Smrg client->errorValue = _XkbErrCode2(0x04, stuff->firstType); 40374642e01fSmrg return BadAccess; 40384642e01fSmrg } 4039f7df2e56Smrg old = tmp; 4040f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, stuff->nTypes, client->swapped, &bad); 40414642e01fSmrg if (!tmp) { 4042f7df2e56Smrg client->errorValue = bad; 40434642e01fSmrg return BadAtom; 40444642e01fSmrg } 4045f7df2e56Smrg for (i = 0; i < stuff->nTypes; i++, old++) { 4046f7df2e56Smrg if (!_XkbCheckTypeName((Atom) *old, stuff->firstType + i)) 4047f7df2e56Smrg client->errorValue = _XkbErrCode2(0x05, i); 40484642e01fSmrg } 40494642e01fSmrg } 4050f7df2e56Smrg if (stuff->which & XkbKTLevelNamesMask) { 40514642e01fSmrg unsigned i; 4052f7df2e56Smrg XkbKeyTypePtr type; 4053f7df2e56Smrg CARD8 *width; 4054f7df2e56Smrg 4055f7df2e56Smrg if (stuff->nKTLevels < 1) { 4056f7df2e56Smrg client->errorValue = _XkbErrCode2(0x05, stuff->nKTLevels); 40574642e01fSmrg return BadValue; 40584642e01fSmrg } 4059f7df2e56Smrg if ((unsigned) (stuff->firstKTLevel + stuff->nKTLevels - 1) >= 4060f7df2e56Smrg xkb->map->num_types) { 4061f7df2e56Smrg client->errorValue = _XkbErrCode4(0x06, stuff->firstKTLevel, 4062f7df2e56Smrg stuff->nKTLevels, 4063f7df2e56Smrg xkb->map->num_types); 40644642e01fSmrg return BadValue; 40654642e01fSmrg } 4066f7df2e56Smrg width = (CARD8 *) tmp; 4067f7df2e56Smrg tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels)); 40684642e01fSmrg type = &xkb->map->types[stuff->firstKTLevel]; 4069f7df2e56Smrg for (i = 0; i < stuff->nKTLevels; i++, type++) { 4070f7df2e56Smrg if (width[i] == 0) 40714642e01fSmrg continue; 4072f7df2e56Smrg else if (width[i] != type->num_levels) { 4073f7df2e56Smrg client->errorValue = _XkbErrCode4(0x07, i + stuff->firstKTLevel, 4074f7df2e56Smrg type->num_levels, width[i]); 40754642e01fSmrg return BadMatch; 40764642e01fSmrg } 4077f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, width[i], client->swapped, &bad); 40784642e01fSmrg if (!tmp) { 4079f7df2e56Smrg client->errorValue = bad; 40804642e01fSmrg return BadAtom; 40814642e01fSmrg } 40824642e01fSmrg } 40834642e01fSmrg } 4084f7df2e56Smrg if (stuff->which & XkbIndicatorNamesMask) { 4085f7df2e56Smrg if (stuff->indicators == 0) { 4086f7df2e56Smrg client->errorValue = 0x08; 40874642e01fSmrg return BadMatch; 40884642e01fSmrg } 4089f7df2e56Smrg tmp = _XkbCheckMaskedAtoms(tmp, XkbNumIndicators, stuff->indicators, 4090f7df2e56Smrg client->swapped, &bad); 40914642e01fSmrg if (!tmp) { 4092f7df2e56Smrg client->errorValue = bad; 40934642e01fSmrg return BadAtom; 40944642e01fSmrg } 40954642e01fSmrg } 4096f7df2e56Smrg if (stuff->which & XkbVirtualModNamesMask) { 4097f7df2e56Smrg if (stuff->virtualMods == 0) { 4098f7df2e56Smrg client->errorValue = 0x09; 40994642e01fSmrg return BadMatch; 41004642e01fSmrg } 4101f7df2e56Smrg tmp = _XkbCheckMaskedAtoms(tmp, XkbNumVirtualMods, 4102f7df2e56Smrg (CARD32) stuff->virtualMods, 4103f7df2e56Smrg client->swapped, &bad); 41044642e01fSmrg if (!tmp) { 41054642e01fSmrg client->errorValue = bad; 41064642e01fSmrg return BadAtom; 41074642e01fSmrg } 41084642e01fSmrg } 4109f7df2e56Smrg if (stuff->which & XkbGroupNamesMask) { 4110f7df2e56Smrg if (stuff->groupNames == 0) { 4111f7df2e56Smrg client->errorValue = 0x0a; 41124642e01fSmrg return BadMatch; 41134642e01fSmrg } 4114f7df2e56Smrg tmp = _XkbCheckMaskedAtoms(tmp, XkbNumKbdGroups, 4115f7df2e56Smrg (CARD32) stuff->groupNames, 4116f7df2e56Smrg client->swapped, &bad); 41174642e01fSmrg if (!tmp) { 41184642e01fSmrg client->errorValue = bad; 41194642e01fSmrg return BadAtom; 41204642e01fSmrg } 41214642e01fSmrg } 4122f7df2e56Smrg if (stuff->which & XkbKeyNamesMask) { 4123f7df2e56Smrg if (stuff->firstKey < (unsigned) xkb->min_key_code) { 4124f7df2e56Smrg client->errorValue = _XkbErrCode3(0x0b, xkb->min_key_code, 4125f7df2e56Smrg stuff->firstKey); 41264642e01fSmrg return BadValue; 41274642e01fSmrg } 4128f7df2e56Smrg if (((unsigned) (stuff->firstKey + stuff->nKeys - 1) > 4129f7df2e56Smrg xkb->max_key_code) || (stuff->nKeys < 1)) { 4130f7df2e56Smrg client->errorValue = 4131f7df2e56Smrg _XkbErrCode4(0x0c, xkb->max_key_code, stuff->firstKey, 4132f7df2e56Smrg stuff->nKeys); 41334642e01fSmrg return BadValue; 41344642e01fSmrg } 4135f7df2e56Smrg tmp += stuff->nKeys; 41364642e01fSmrg } 4137f7df2e56Smrg if ((stuff->which & XkbKeyAliasesMask) && (stuff->nKeyAliases > 0)) { 4138f7df2e56Smrg tmp += stuff->nKeyAliases * 2; 41394642e01fSmrg } 4140f7df2e56Smrg if (stuff->which & XkbRGNamesMask) { 4141f7df2e56Smrg if (stuff->nRadioGroups < 1) { 4142f7df2e56Smrg client->errorValue = _XkbErrCode2(0x0d, stuff->nRadioGroups); 41434642e01fSmrg return BadValue; 41444642e01fSmrg } 4145f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, stuff->nRadioGroups, client->swapped, &bad); 41464642e01fSmrg if (!tmp) { 4147f7df2e56Smrg client->errorValue = bad; 41484642e01fSmrg return BadAtom; 41494642e01fSmrg } 41504642e01fSmrg } 4151f7df2e56Smrg if ((tmp - ((CARD32 *) stuff)) != stuff->length) { 41524642e01fSmrg client->errorValue = stuff->length; 41534642e01fSmrg return BadLength; 41544642e01fSmrg } 41554642e01fSmrg 41564642e01fSmrg return Success; 41574642e01fSmrg} 41584642e01fSmrg 41594642e01fSmrgstatic int 4160f7df2e56Smrg_XkbSetNames(ClientPtr client, DeviceIntPtr dev, xkbSetNamesReq * stuff) 41614642e01fSmrg{ 4162f7df2e56Smrg XkbDescRec *xkb; 4163f7df2e56Smrg XkbNamesRec *names; 4164f7df2e56Smrg CARD32 *tmp; 4165f7df2e56Smrg xkbNamesNotify nn; 41664642e01fSmrg 4167f7df2e56Smrg tmp = (CARD32 *) &stuff[1]; 41684642e01fSmrg xkb = dev->key->xkbInfo->desc; 41694642e01fSmrg names = xkb->names; 41704642e01fSmrg 4171f7df2e56Smrg if (XkbAllocNames(xkb, stuff->which, stuff->nRadioGroups, 4172f7df2e56Smrg stuff->nKeyAliases) != Success) { 41734642e01fSmrg return BadAlloc; 41744642e01fSmrg } 41754642e01fSmrg 41766747b715Smrg memset(&nn, 0, sizeof(xkbNamesNotify)); 4177f7df2e56Smrg nn.changed = stuff->which; 4178f7df2e56Smrg tmp = (CARD32 *) &stuff[1]; 4179f7df2e56Smrg if (stuff->which & XkbKeycodesNameMask) 4180f7df2e56Smrg names->keycodes = *tmp++; 4181f7df2e56Smrg if (stuff->which & XkbGeometryNameMask) 4182f7df2e56Smrg names->geometry = *tmp++; 4183f7df2e56Smrg if (stuff->which & XkbSymbolsNameMask) 4184f7df2e56Smrg names->symbols = *tmp++; 4185f7df2e56Smrg if (stuff->which & XkbPhysSymbolsNameMask) 4186f7df2e56Smrg names->phys_symbols = *tmp++; 4187f7df2e56Smrg if (stuff->which & XkbTypesNameMask) 4188f7df2e56Smrg names->types = *tmp++; 4189f7df2e56Smrg if (stuff->which & XkbCompatNameMask) 4190f7df2e56Smrg names->compat = *tmp++; 4191f7df2e56Smrg if ((stuff->which & XkbKeyTypeNamesMask) && (stuff->nTypes > 0)) { 41924642e01fSmrg register unsigned i; 41934642e01fSmrg register XkbKeyTypePtr type; 41944642e01fSmrg 4195f7df2e56Smrg type = &xkb->map->types[stuff->firstType]; 4196f7df2e56Smrg for (i = 0; i < stuff->nTypes; i++, type++) { 4197f7df2e56Smrg type->name = *tmp++; 41984642e01fSmrg } 4199f7df2e56Smrg nn.firstType = stuff->firstType; 4200f7df2e56Smrg nn.nTypes = stuff->nTypes; 42014642e01fSmrg } 4202f7df2e56Smrg if (stuff->which & XkbKTLevelNamesMask) { 4203f7df2e56Smrg register XkbKeyTypePtr type; 42044642e01fSmrg register unsigned i; 42054642e01fSmrg CARD8 *width; 42064642e01fSmrg 4207f7df2e56Smrg width = (CARD8 *) tmp; 4208f7df2e56Smrg tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels)); 4209f7df2e56Smrg type = &xkb->map->types[stuff->firstKTLevel]; 4210f7df2e56Smrg for (i = 0; i < stuff->nKTLevels; i++, type++) { 4211f7df2e56Smrg if (width[i] > 0) { 42124642e01fSmrg if (type->level_names) { 42134642e01fSmrg register unsigned n; 4214f7df2e56Smrg 4215f7df2e56Smrg for (n = 0; n < width[i]; n++) { 4216f7df2e56Smrg type->level_names[n] = tmp[n]; 42174642e01fSmrg } 42184642e01fSmrg } 4219f7df2e56Smrg tmp += width[i]; 42204642e01fSmrg } 42214642e01fSmrg } 4222f7df2e56Smrg nn.firstLevelName = 0; 4223f7df2e56Smrg nn.nLevelNames = stuff->nTypes; 4224f7df2e56Smrg } 4225f7df2e56Smrg if (stuff->which & XkbIndicatorNamesMask) { 4226f7df2e56Smrg tmp = _XkbCopyMaskedAtoms(tmp, names->indicators, XkbNumIndicators, 4227f7df2e56Smrg stuff->indicators); 4228f7df2e56Smrg nn.changedIndicators = stuff->indicators; 4229f7df2e56Smrg } 4230f7df2e56Smrg if (stuff->which & XkbVirtualModNamesMask) { 4231f7df2e56Smrg tmp = _XkbCopyMaskedAtoms(tmp, names->vmods, XkbNumVirtualMods, 4232f7df2e56Smrg stuff->virtualMods); 4233f7df2e56Smrg nn.changedVirtualMods = stuff->virtualMods; 4234f7df2e56Smrg } 4235f7df2e56Smrg if (stuff->which & XkbGroupNamesMask) { 4236f7df2e56Smrg tmp = _XkbCopyMaskedAtoms(tmp, names->groups, XkbNumKbdGroups, 4237f7df2e56Smrg stuff->groupNames); 4238f7df2e56Smrg nn.changedVirtualMods = stuff->groupNames; 4239f7df2e56Smrg } 4240f7df2e56Smrg if (stuff->which & XkbKeyNamesMask) { 4241f7df2e56Smrg memcpy((char *) &names->keys[stuff->firstKey], (char *) tmp, 4242f7df2e56Smrg stuff->nKeys * XkbKeyNameLength); 4243f7df2e56Smrg tmp += stuff->nKeys; 4244f7df2e56Smrg nn.firstKey = stuff->firstKey; 4245f7df2e56Smrg nn.nKeys = stuff->nKeys; 4246f7df2e56Smrg } 4247f7df2e56Smrg if (stuff->which & XkbKeyAliasesMask) { 4248f7df2e56Smrg if (stuff->nKeyAliases > 0) { 4249f7df2e56Smrg register int na = stuff->nKeyAliases; 4250f7df2e56Smrg 4251f7df2e56Smrg if (XkbAllocNames(xkb, XkbKeyAliasesMask, 0, na) != Success) 42524642e01fSmrg return BadAlloc; 4253f7df2e56Smrg memcpy((char *) names->key_aliases, (char *) tmp, 4254f7df2e56Smrg stuff->nKeyAliases * sizeof(XkbKeyAliasRec)); 4255f7df2e56Smrg tmp += stuff->nKeyAliases * 2; 42564642e01fSmrg } 4257f7df2e56Smrg else if (names->key_aliases != NULL) { 42586747b715Smrg free(names->key_aliases); 4259f7df2e56Smrg names->key_aliases = NULL; 4260f7df2e56Smrg names->num_key_aliases = 0; 42614642e01fSmrg } 4262f7df2e56Smrg nn.nAliases = names->num_key_aliases; 42634642e01fSmrg } 4264f7df2e56Smrg if (stuff->which & XkbRGNamesMask) { 4265f7df2e56Smrg if (stuff->nRadioGroups > 0) { 4266f7df2e56Smrg register unsigned i, nrg; 4267f7df2e56Smrg 4268f7df2e56Smrg nrg = stuff->nRadioGroups; 4269f7df2e56Smrg if (XkbAllocNames(xkb, XkbRGNamesMask, nrg, 0) != Success) 42704642e01fSmrg return BadAlloc; 42714642e01fSmrg 4272f7df2e56Smrg for (i = 0; i < stuff->nRadioGroups; i++) { 4273f7df2e56Smrg names->radio_groups[i] = tmp[i]; 42744642e01fSmrg } 4275f7df2e56Smrg tmp += stuff->nRadioGroups; 42764642e01fSmrg } 42774642e01fSmrg else if (names->radio_groups) { 42786747b715Smrg free(names->radio_groups); 4279f7df2e56Smrg names->radio_groups = NULL; 4280f7df2e56Smrg names->num_rg = 0; 42814642e01fSmrg } 4282f7df2e56Smrg nn.nRadioGroups = names->num_rg; 42834642e01fSmrg } 42844642e01fSmrg if (nn.changed) { 42854642e01fSmrg Bool needExtEvent; 4286f7df2e56Smrg 4287f7df2e56Smrg needExtEvent = (nn.changed & XkbIndicatorNamesMask) != 0; 4288f7df2e56Smrg XkbSendNamesNotify(dev, &nn); 42894642e01fSmrg if (needExtEvent) { 4290f7df2e56Smrg XkbSrvLedInfoPtr sli; 4291f7df2e56Smrg xkbExtensionDeviceNotify edev; 4292f7df2e56Smrg register int i; 4293f7df2e56Smrg register unsigned bit; 4294f7df2e56Smrg 4295f7df2e56Smrg sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 4296f7df2e56Smrg XkbXI_IndicatorsMask); 4297f7df2e56Smrg sli->namesPresent = 0; 4298f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 4299f7df2e56Smrg if (names->indicators[i] != None) 4300f7df2e56Smrg sli->namesPresent |= bit; 43014642e01fSmrg } 43026747b715Smrg memset(&edev, 0, sizeof(xkbExtensionDeviceNotify)); 4303f7df2e56Smrg edev.reason = XkbXI_IndicatorNamesMask; 4304f7df2e56Smrg edev.ledClass = KbdFeedbackClass; 4305f7df2e56Smrg edev.ledID = dev->kbdfeed->ctrl.id; 4306f7df2e56Smrg edev.ledsDefined = sli->namesPresent | sli->mapsPresent; 4307f7df2e56Smrg edev.ledState = sli->effectiveState; 4308f7df2e56Smrg edev.firstBtn = 0; 4309f7df2e56Smrg edev.nBtns = 0; 4310f7df2e56Smrg edev.supported = XkbXI_AllFeaturesMask; 4311f7df2e56Smrg edev.unsupported = 0; 4312f7df2e56Smrg XkbSendExtensionDeviceNotify(dev, client, &edev); 43134642e01fSmrg } 43144642e01fSmrg } 43154642e01fSmrg return Success; 43164642e01fSmrg} 43174642e01fSmrg 43184642e01fSmrgint 43194642e01fSmrgProcXkbSetNames(ClientPtr client) 43204642e01fSmrg{ 4321f7df2e56Smrg DeviceIntPtr dev; 4322f7df2e56Smrg CARD32 *tmp; 4323f7df2e56Smrg Atom bad; 4324f7df2e56Smrg int rc; 43254642e01fSmrg 432605b261ecSmrg REQUEST(xkbSetNamesReq); 432705b261ecSmrg REQUEST_AT_LEAST_SIZE(xkbSetNamesReq); 432805b261ecSmrg 4329f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 4330f7df2e56Smrg return BadAccess; 433105b261ecSmrg 43324642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); 4333f7df2e56Smrg CHK_MASK_LEGAL(0x01, stuff->which, XkbAllNamesMask); 433405b261ecSmrg 43354642e01fSmrg /* check device-independent stuff */ 4336f7df2e56Smrg tmp = (CARD32 *) &stuff[1]; 4337f7df2e56Smrg 4338f7df2e56Smrg if (stuff->which & XkbKeycodesNameMask) { 4339f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad); 4340f7df2e56Smrg if (!tmp) { 4341f7df2e56Smrg client->errorValue = bad; 4342f7df2e56Smrg return BadAtom; 4343f7df2e56Smrg } 4344f7df2e56Smrg } 4345f7df2e56Smrg if (stuff->which & XkbGeometryNameMask) { 4346f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad); 4347f7df2e56Smrg if (!tmp) { 4348f7df2e56Smrg client->errorValue = bad; 4349f7df2e56Smrg return BadAtom; 4350f7df2e56Smrg } 4351f7df2e56Smrg } 4352f7df2e56Smrg if (stuff->which & XkbSymbolsNameMask) { 4353f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad); 4354f7df2e56Smrg if (!tmp) { 4355f7df2e56Smrg client->errorValue = bad; 4356f7df2e56Smrg return BadAtom; 4357f7df2e56Smrg } 4358f7df2e56Smrg } 4359f7df2e56Smrg if (stuff->which & XkbPhysSymbolsNameMask) { 4360f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad); 4361f7df2e56Smrg if (!tmp) { 4362f7df2e56Smrg client->errorValue = bad; 4363f7df2e56Smrg return BadAtom; 4364f7df2e56Smrg } 4365f7df2e56Smrg } 4366f7df2e56Smrg if (stuff->which & XkbTypesNameMask) { 4367f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad); 4368f7df2e56Smrg if (!tmp) { 4369f7df2e56Smrg client->errorValue = bad; 4370f7df2e56Smrg return BadAtom; 4371f7df2e56Smrg } 4372f7df2e56Smrg } 4373f7df2e56Smrg if (stuff->which & XkbCompatNameMask) { 4374f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad); 4375f7df2e56Smrg if (!tmp) { 4376f7df2e56Smrg client->errorValue = bad; 4377f7df2e56Smrg return BadAtom; 4378f7df2e56Smrg } 437905b261ecSmrg } 43804642e01fSmrg 43814642e01fSmrg /* start of device-dependent tests */ 43824642e01fSmrg rc = _XkbSetNamesCheck(client, dev, stuff, tmp); 43834642e01fSmrg if (rc != Success) 43844642e01fSmrg return rc; 43854642e01fSmrg 4386f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd) { 43874642e01fSmrg DeviceIntPtr other; 43884642e01fSmrg 4389f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 4390f7df2e56Smrg if ((other != dev) && other->key && !IsMaster(other) && 4391f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) { 4392f7df2e56Smrg 4393f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 4394f7df2e56Smrg DixManageAccess); 4395f7df2e56Smrg if (rc == Success) { 43964642e01fSmrg rc = _XkbSetNamesCheck(client, other, stuff, tmp); 43974642e01fSmrg if (rc != Success) 43984642e01fSmrg return rc; 43994642e01fSmrg } 44004642e01fSmrg } 44014642e01fSmrg } 440205b261ecSmrg } 440305b261ecSmrg 440405b261ecSmrg /* everything is okay -- update names */ 440505b261ecSmrg 44064642e01fSmrg rc = _XkbSetNames(client, dev, stuff); 44074642e01fSmrg if (rc != Success) 44084642e01fSmrg return rc; 440905b261ecSmrg 4410f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd) { 44114642e01fSmrg DeviceIntPtr other; 44124642e01fSmrg 4413f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 4414f7df2e56Smrg if ((other != dev) && other->key && !IsMaster(other) && 4415f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) { 4416f7df2e56Smrg 4417f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 4418f7df2e56Smrg DixManageAccess); 44194642e01fSmrg if (rc == Success) 44204642e01fSmrg _XkbSetNames(client, other, stuff); 44214642e01fSmrg } 44224642e01fSmrg } 442305b261ecSmrg } 44244642e01fSmrg 44254642e01fSmrg /* everything is okay -- update names */ 44264642e01fSmrg 44276747b715Smrg return Success; 442805b261ecSmrg} 442905b261ecSmrg 443005b261ecSmrg/***====================================================================***/ 443105b261ecSmrg 44324642e01fSmrg#include "xkbgeom.h" 443305b261ecSmrg 443405b261ecSmrg#define XkbSizeCountedString(s) ((s)?((((2+strlen(s))+3)/4)*4):4) 443505b261ecSmrg 4436f7df2e56Smrg/** 4437f7df2e56Smrg * Write the zero-terminated string str into wire as a pascal string with a 4438f7df2e56Smrg * 16-bit length field prefixed before the actual string. 4439f7df2e56Smrg * 4440f7df2e56Smrg * @param wire The destination array, usually the wire struct 4441f7df2e56Smrg * @param str The source string as zero-terminated C string 4442f7df2e56Smrg * @param swap If TRUE, the length field is swapped. 4443f7df2e56Smrg * 4444f7df2e56Smrg * @return The input string in the format <string length><string> with a 4445f7df2e56Smrg * (swapped) 16 bit string length, non-zero terminated. 4446f7df2e56Smrg */ 444705b261ecSmrgstatic char * 4448f7df2e56SmrgXkbWriteCountedString(char *wire, const char *str, Bool swap) 444905b261ecSmrg{ 4450f7df2e56Smrg CARD16 len, *pLen, paddedLen; 445105b261ecSmrg 44526747b715Smrg if (!str) 44536747b715Smrg return wire; 44546747b715Smrg 4455f7df2e56Smrg len = strlen(str); 4456f7df2e56Smrg pLen = (CARD16 *) wire; 4457f7df2e56Smrg *pLen = len; 445805b261ecSmrg if (swap) { 4459f7df2e56Smrg swaps(pLen); 446005b261ecSmrg } 4461f7df2e56Smrg paddedLen = pad_to_int32(sizeof(len) + len) - sizeof(len); 4462f7df2e56Smrg strncpy(&wire[sizeof(len)], str, paddedLen); 4463f7df2e56Smrg wire += sizeof(len) + paddedLen; 446405b261ecSmrg return wire; 446505b261ecSmrg} 446605b261ecSmrg 446705b261ecSmrgstatic int 446805b261ecSmrgXkbSizeGeomProperties(XkbGeometryPtr geom) 446905b261ecSmrg{ 4470f7df2e56Smrg register int i, size; 4471f7df2e56Smrg XkbPropertyPtr prop; 4472f7df2e56Smrg 4473f7df2e56Smrg for (size = i = 0, prop = geom->properties; i < geom->num_properties; 4474f7df2e56Smrg i++, prop++) { 4475f7df2e56Smrg size += XkbSizeCountedString(prop->name); 4476f7df2e56Smrg size += XkbSizeCountedString(prop->value); 447705b261ecSmrg } 447805b261ecSmrg return size; 447905b261ecSmrg} 448005b261ecSmrg 448105b261ecSmrgstatic char * 4482f7df2e56SmrgXkbWriteGeomProperties(char *wire, XkbGeometryPtr geom, Bool swap) 448305b261ecSmrg{ 4484f7df2e56Smrg register int i; 4485f7df2e56Smrg register XkbPropertyPtr prop; 4486f7df2e56Smrg 4487f7df2e56Smrg for (i = 0, prop = geom->properties; i < geom->num_properties; i++, prop++) { 4488f7df2e56Smrg wire = XkbWriteCountedString(wire, prop->name, swap); 4489f7df2e56Smrg wire = XkbWriteCountedString(wire, prop->value, swap); 449005b261ecSmrg } 449105b261ecSmrg return wire; 449205b261ecSmrg} 449305b261ecSmrg 449405b261ecSmrgstatic int 449505b261ecSmrgXkbSizeGeomKeyAliases(XkbGeometryPtr geom) 449605b261ecSmrg{ 4497f7df2e56Smrg return geom->num_key_aliases * (2 * XkbKeyNameLength); 449805b261ecSmrg} 449905b261ecSmrg 450005b261ecSmrgstatic char * 4501f7df2e56SmrgXkbWriteGeomKeyAliases(char *wire, XkbGeometryPtr geom, Bool swap) 450205b261ecSmrg{ 4503f7df2e56Smrg register int sz; 4504f7df2e56Smrg 4505f7df2e56Smrg sz = geom->num_key_aliases * (XkbKeyNameLength * 2); 4506f7df2e56Smrg if (sz > 0) { 4507f7df2e56Smrg memcpy(wire, (char *) geom->key_aliases, sz); 4508f7df2e56Smrg wire += sz; 450905b261ecSmrg } 451005b261ecSmrg return wire; 451105b261ecSmrg} 451205b261ecSmrg 451305b261ecSmrgstatic int 451405b261ecSmrgXkbSizeGeomColors(XkbGeometryPtr geom) 451505b261ecSmrg{ 4516f7df2e56Smrg register int i, size; 4517f7df2e56Smrg register XkbColorPtr color; 451805b261ecSmrg 4519f7df2e56Smrg for (i = size = 0, color = geom->colors; i < geom->num_colors; i++, color++) { 4520f7df2e56Smrg size += XkbSizeCountedString(color->spec); 452105b261ecSmrg } 452205b261ecSmrg return size; 452305b261ecSmrg} 452405b261ecSmrg 452505b261ecSmrgstatic char * 4526f7df2e56SmrgXkbWriteGeomColors(char *wire, XkbGeometryPtr geom, Bool swap) 452705b261ecSmrg{ 4528f7df2e56Smrg register int i; 4529f7df2e56Smrg register XkbColorPtr color; 453005b261ecSmrg 4531f7df2e56Smrg for (i = 0, color = geom->colors; i < geom->num_colors; i++, color++) { 4532f7df2e56Smrg wire = XkbWriteCountedString(wire, color->spec, swap); 453305b261ecSmrg } 453405b261ecSmrg return wire; 453505b261ecSmrg} 453605b261ecSmrg 453705b261ecSmrgstatic int 453805b261ecSmrgXkbSizeGeomShapes(XkbGeometryPtr geom) 453905b261ecSmrg{ 4540f7df2e56Smrg register int i, size; 4541f7df2e56Smrg register XkbShapePtr shape; 4542f7df2e56Smrg 4543f7df2e56Smrg for (i = size = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) { 4544f7df2e56Smrg register int n; 4545f7df2e56Smrg register XkbOutlinePtr ol; 4546f7df2e56Smrg 4547f7df2e56Smrg size += SIZEOF(xkbShapeWireDesc); 4548f7df2e56Smrg for (n = 0, ol = shape->outlines; n < shape->num_outlines; n++, ol++) { 4549f7df2e56Smrg size += SIZEOF(xkbOutlineWireDesc); 4550f7df2e56Smrg size += ol->num_points * SIZEOF(xkbPointWireDesc); 4551f7df2e56Smrg } 455205b261ecSmrg } 455305b261ecSmrg return size; 455405b261ecSmrg} 455505b261ecSmrg 455605b261ecSmrgstatic char * 4557f7df2e56SmrgXkbWriteGeomShapes(char *wire, XkbGeometryPtr geom, Bool swap) 455805b261ecSmrg{ 4559f7df2e56Smrg int i; 4560f7df2e56Smrg XkbShapePtr shape; 4561f7df2e56Smrg xkbShapeWireDesc *shapeWire; 4562f7df2e56Smrg 4563f7df2e56Smrg for (i = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) { 4564f7df2e56Smrg register int o; 4565f7df2e56Smrg XkbOutlinePtr ol; 4566f7df2e56Smrg xkbOutlineWireDesc *olWire; 4567f7df2e56Smrg 4568f7df2e56Smrg shapeWire = (xkbShapeWireDesc *) wire; 4569f7df2e56Smrg shapeWire->name = shape->name; 4570f7df2e56Smrg shapeWire->nOutlines = shape->num_outlines; 4571f7df2e56Smrg if (shape->primary != NULL) 4572f7df2e56Smrg shapeWire->primaryNdx = XkbOutlineIndex(shape, shape->primary); 4573f7df2e56Smrg else 4574f7df2e56Smrg shapeWire->primaryNdx = XkbNoShape; 4575f7df2e56Smrg if (shape->approx != NULL) 4576f7df2e56Smrg shapeWire->approxNdx = XkbOutlineIndex(shape, shape->approx); 4577f7df2e56Smrg else 4578f7df2e56Smrg shapeWire->approxNdx = XkbNoShape; 4579f7df2e56Smrg shapeWire->pad = 0; 4580f7df2e56Smrg if (swap) { 4581f7df2e56Smrg swapl(&shapeWire->name); 4582f7df2e56Smrg } 4583f7df2e56Smrg wire = (char *) &shapeWire[1]; 4584f7df2e56Smrg for (o = 0, ol = shape->outlines; o < shape->num_outlines; o++, ol++) { 4585f7df2e56Smrg register int p; 4586f7df2e56Smrg XkbPointPtr pt; 4587f7df2e56Smrg xkbPointWireDesc *ptWire; 4588f7df2e56Smrg 4589f7df2e56Smrg olWire = (xkbOutlineWireDesc *) wire; 4590f7df2e56Smrg olWire->nPoints = ol->num_points; 4591f7df2e56Smrg olWire->cornerRadius = ol->corner_radius; 4592f7df2e56Smrg olWire->pad = 0; 4593f7df2e56Smrg wire = (char *) &olWire[1]; 4594f7df2e56Smrg ptWire = (xkbPointWireDesc *) wire; 4595f7df2e56Smrg for (p = 0, pt = ol->points; p < ol->num_points; p++, pt++) { 4596f7df2e56Smrg ptWire[p].x = pt->x; 4597f7df2e56Smrg ptWire[p].y = pt->y; 4598f7df2e56Smrg if (swap) { 4599f7df2e56Smrg swaps(&ptWire[p].x); 4600f7df2e56Smrg swaps(&ptWire[p].y); 4601f7df2e56Smrg } 4602f7df2e56Smrg } 4603f7df2e56Smrg wire = (char *) &ptWire[ol->num_points]; 4604f7df2e56Smrg } 460505b261ecSmrg } 460605b261ecSmrg return wire; 460705b261ecSmrg} 460805b261ecSmrg 460905b261ecSmrgstatic int 4610f7df2e56SmrgXkbSizeGeomDoodads(int num_doodads, XkbDoodadPtr doodad) 461105b261ecSmrg{ 4612f7df2e56Smrg register int i, size; 4613f7df2e56Smrg 4614f7df2e56Smrg for (i = size = 0; i < num_doodads; i++, doodad++) { 4615f7df2e56Smrg size += SIZEOF(xkbAnyDoodadWireDesc); 4616f7df2e56Smrg if (doodad->any.type == XkbTextDoodad) { 4617f7df2e56Smrg size += XkbSizeCountedString(doodad->text.text); 4618f7df2e56Smrg size += XkbSizeCountedString(doodad->text.font); 4619f7df2e56Smrg } 4620f7df2e56Smrg else if (doodad->any.type == XkbLogoDoodad) { 4621f7df2e56Smrg size += XkbSizeCountedString(doodad->logo.logo_name); 4622f7df2e56Smrg } 462305b261ecSmrg } 462405b261ecSmrg return size; 462505b261ecSmrg} 462605b261ecSmrg 462705b261ecSmrgstatic char * 4628f7df2e56SmrgXkbWriteGeomDoodads(char *wire, int num_doodads, XkbDoodadPtr doodad, Bool swap) 462905b261ecSmrg{ 4630f7df2e56Smrg register int i; 4631f7df2e56Smrg xkbDoodadWireDesc *doodadWire; 4632f7df2e56Smrg 4633f7df2e56Smrg for (i = 0; i < num_doodads; i++, doodad++) { 4634f7df2e56Smrg doodadWire = (xkbDoodadWireDesc *) wire; 4635f7df2e56Smrg wire = (char *) &doodadWire[1]; 4636f7df2e56Smrg memset(doodadWire, 0, SIZEOF(xkbDoodadWireDesc)); 4637f7df2e56Smrg doodadWire->any.name = doodad->any.name; 4638f7df2e56Smrg doodadWire->any.type = doodad->any.type; 4639f7df2e56Smrg doodadWire->any.priority = doodad->any.priority; 4640f7df2e56Smrg doodadWire->any.top = doodad->any.top; 4641f7df2e56Smrg doodadWire->any.left = doodad->any.left; 4642f7df2e56Smrg if (swap) { 4643f7df2e56Smrg swapl(&doodadWire->any.name); 4644f7df2e56Smrg swaps(&doodadWire->any.top); 4645f7df2e56Smrg swaps(&doodadWire->any.left); 4646f7df2e56Smrg } 4647f7df2e56Smrg switch (doodad->any.type) { 4648f7df2e56Smrg case XkbOutlineDoodad: 4649f7df2e56Smrg case XkbSolidDoodad: 4650f7df2e56Smrg doodadWire->shape.angle = doodad->shape.angle; 4651f7df2e56Smrg doodadWire->shape.colorNdx = doodad->shape.color_ndx; 4652f7df2e56Smrg doodadWire->shape.shapeNdx = doodad->shape.shape_ndx; 4653f7df2e56Smrg if (swap) { 4654f7df2e56Smrg swaps(&doodadWire->shape.angle); 4655f7df2e56Smrg } 4656f7df2e56Smrg break; 4657f7df2e56Smrg case XkbTextDoodad: 4658f7df2e56Smrg doodadWire->text.angle = doodad->text.angle; 4659f7df2e56Smrg doodadWire->text.width = doodad->text.width; 4660f7df2e56Smrg doodadWire->text.height = doodad->text.height; 4661f7df2e56Smrg doodadWire->text.colorNdx = doodad->text.color_ndx; 4662f7df2e56Smrg if (swap) { 4663f7df2e56Smrg swaps(&doodadWire->text.angle); 4664f7df2e56Smrg swaps(&doodadWire->text.width); 4665f7df2e56Smrg swaps(&doodadWire->text.height); 4666f7df2e56Smrg } 4667f7df2e56Smrg wire = XkbWriteCountedString(wire, doodad->text.text, swap); 4668f7df2e56Smrg wire = XkbWriteCountedString(wire, doodad->text.font, swap); 4669f7df2e56Smrg break; 4670f7df2e56Smrg case XkbIndicatorDoodad: 4671f7df2e56Smrg doodadWire->indicator.shapeNdx = doodad->indicator.shape_ndx; 4672f7df2e56Smrg doodadWire->indicator.onColorNdx = doodad->indicator.on_color_ndx; 4673f7df2e56Smrg doodadWire->indicator.offColorNdx = doodad->indicator.off_color_ndx; 4674f7df2e56Smrg break; 4675f7df2e56Smrg case XkbLogoDoodad: 4676f7df2e56Smrg doodadWire->logo.angle = doodad->logo.angle; 4677f7df2e56Smrg doodadWire->logo.colorNdx = doodad->logo.color_ndx; 4678f7df2e56Smrg doodadWire->logo.shapeNdx = doodad->logo.shape_ndx; 4679f7df2e56Smrg wire = XkbWriteCountedString(wire, doodad->logo.logo_name, swap); 4680f7df2e56Smrg break; 4681f7df2e56Smrg default: 4682f7df2e56Smrg ErrorF("[xkb] Unknown doodad type %d in XkbWriteGeomDoodads\n", 4683f7df2e56Smrg doodad->any.type); 4684f7df2e56Smrg ErrorF("[xkb] Ignored\n"); 4685f7df2e56Smrg break; 4686f7df2e56Smrg } 468705b261ecSmrg } 468805b261ecSmrg return wire; 468905b261ecSmrg} 469005b261ecSmrg 469105b261ecSmrgstatic char * 4692f7df2e56SmrgXkbWriteGeomOverlay(char *wire, XkbOverlayPtr ol, Bool swap) 469305b261ecSmrg{ 4694f7df2e56Smrg register int r; 4695f7df2e56Smrg XkbOverlayRowPtr row; 4696f7df2e56Smrg xkbOverlayWireDesc *olWire; 4697f7df2e56Smrg 4698f7df2e56Smrg olWire = (xkbOverlayWireDesc *) wire; 4699f7df2e56Smrg olWire->name = ol->name; 4700f7df2e56Smrg olWire->nRows = ol->num_rows; 4701f7df2e56Smrg olWire->pad1 = 0; 4702f7df2e56Smrg olWire->pad2 = 0; 4703f7df2e56Smrg if (swap) { 4704f7df2e56Smrg swapl(&olWire->name); 4705f7df2e56Smrg } 4706f7df2e56Smrg wire = (char *) &olWire[1]; 4707f7df2e56Smrg for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) { 4708f7df2e56Smrg unsigned int k; 4709f7df2e56Smrg XkbOverlayKeyPtr key; 4710f7df2e56Smrg xkbOverlayRowWireDesc *rowWire; 4711f7df2e56Smrg 4712f7df2e56Smrg rowWire = (xkbOverlayRowWireDesc *) wire; 4713f7df2e56Smrg rowWire->rowUnder = row->row_under; 4714f7df2e56Smrg rowWire->nKeys = row->num_keys; 4715f7df2e56Smrg rowWire->pad1 = 0; 4716f7df2e56Smrg wire = (char *) &rowWire[1]; 4717f7df2e56Smrg for (k = 0, key = row->keys; k < row->num_keys; k++, key++) { 4718f7df2e56Smrg xkbOverlayKeyWireDesc *keyWire; 4719f7df2e56Smrg 4720f7df2e56Smrg keyWire = (xkbOverlayKeyWireDesc *) wire; 4721f7df2e56Smrg memcpy(keyWire->over, key->over.name, XkbKeyNameLength); 4722f7df2e56Smrg memcpy(keyWire->under, key->under.name, XkbKeyNameLength); 4723f7df2e56Smrg wire = (char *) &keyWire[1]; 4724f7df2e56Smrg } 4725f7df2e56Smrg } 4726f7df2e56Smrg return wire; 472705b261ecSmrg} 472805b261ecSmrg 472905b261ecSmrgstatic int 473005b261ecSmrgXkbSizeGeomSections(XkbGeometryPtr geom) 473105b261ecSmrg{ 4732f7df2e56Smrg register int i, size; 4733f7df2e56Smrg XkbSectionPtr section; 4734f7df2e56Smrg 4735f7df2e56Smrg for (i = size = 0, section = geom->sections; i < geom->num_sections; 4736f7df2e56Smrg i++, section++) { 4737f7df2e56Smrg size += SIZEOF(xkbSectionWireDesc); 4738f7df2e56Smrg if (section->rows) { 4739f7df2e56Smrg int r; 4740f7df2e56Smrg XkbRowPtr row; 4741f7df2e56Smrg 4742f7df2e56Smrg for (r = 0, row = section->rows; r < section->num_rows; row++, r++) { 4743f7df2e56Smrg size += SIZEOF(xkbRowWireDesc); 4744f7df2e56Smrg size += row->num_keys * SIZEOF(xkbKeyWireDesc); 4745f7df2e56Smrg } 4746f7df2e56Smrg } 4747f7df2e56Smrg if (section->doodads) 4748f7df2e56Smrg size += XkbSizeGeomDoodads(section->num_doodads, section->doodads); 4749f7df2e56Smrg if (section->overlays) { 4750f7df2e56Smrg int o; 4751f7df2e56Smrg XkbOverlayPtr ol; 4752f7df2e56Smrg 4753f7df2e56Smrg for (o = 0, ol = section->overlays; o < section->num_overlays; 4754f7df2e56Smrg o++, ol++) { 4755f7df2e56Smrg int r; 4756f7df2e56Smrg XkbOverlayRowPtr row; 4757f7df2e56Smrg 4758f7df2e56Smrg size += SIZEOF(xkbOverlayWireDesc); 4759f7df2e56Smrg for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) { 4760f7df2e56Smrg size += SIZEOF(xkbOverlayRowWireDesc); 4761f7df2e56Smrg size += row->num_keys * SIZEOF(xkbOverlayKeyWireDesc); 4762f7df2e56Smrg } 4763f7df2e56Smrg } 4764f7df2e56Smrg } 476505b261ecSmrg } 476605b261ecSmrg return size; 476705b261ecSmrg} 476805b261ecSmrg 476905b261ecSmrgstatic char * 4770f7df2e56SmrgXkbWriteGeomSections(char *wire, XkbGeometryPtr geom, Bool swap) 477105b261ecSmrg{ 4772f7df2e56Smrg register int i; 4773f7df2e56Smrg XkbSectionPtr section; 4774f7df2e56Smrg xkbSectionWireDesc *sectionWire; 4775f7df2e56Smrg 4776f7df2e56Smrg for (i = 0, section = geom->sections; i < geom->num_sections; 4777f7df2e56Smrg i++, section++) { 4778f7df2e56Smrg sectionWire = (xkbSectionWireDesc *) wire; 4779f7df2e56Smrg sectionWire->name = section->name; 4780f7df2e56Smrg sectionWire->top = section->top; 4781f7df2e56Smrg sectionWire->left = section->left; 4782f7df2e56Smrg sectionWire->width = section->width; 4783f7df2e56Smrg sectionWire->height = section->height; 4784f7df2e56Smrg sectionWire->angle = section->angle; 4785f7df2e56Smrg sectionWire->priority = section->priority; 4786f7df2e56Smrg sectionWire->nRows = section->num_rows; 4787f7df2e56Smrg sectionWire->nDoodads = section->num_doodads; 4788f7df2e56Smrg sectionWire->nOverlays = section->num_overlays; 4789f7df2e56Smrg sectionWire->pad = 0; 4790f7df2e56Smrg if (swap) { 4791f7df2e56Smrg swapl(§ionWire->name); 4792f7df2e56Smrg swaps(§ionWire->top); 4793f7df2e56Smrg swaps(§ionWire->left); 4794f7df2e56Smrg swaps(§ionWire->width); 4795f7df2e56Smrg swaps(§ionWire->height); 4796f7df2e56Smrg swaps(§ionWire->angle); 4797f7df2e56Smrg } 4798f7df2e56Smrg wire = (char *) §ionWire[1]; 4799f7df2e56Smrg if (section->rows) { 4800f7df2e56Smrg int r; 4801f7df2e56Smrg XkbRowPtr row; 4802f7df2e56Smrg xkbRowWireDesc *rowWire; 4803f7df2e56Smrg 4804f7df2e56Smrg for (r = 0, row = section->rows; r < section->num_rows; r++, row++) { 4805f7df2e56Smrg rowWire = (xkbRowWireDesc *) wire; 4806f7df2e56Smrg rowWire->top = row->top; 4807f7df2e56Smrg rowWire->left = row->left; 4808f7df2e56Smrg rowWire->nKeys = row->num_keys; 4809f7df2e56Smrg rowWire->vertical = row->vertical; 4810f7df2e56Smrg rowWire->pad = 0; 4811f7df2e56Smrg if (swap) { 4812f7df2e56Smrg swaps(&rowWire->top); 4813f7df2e56Smrg swaps(&rowWire->left); 4814f7df2e56Smrg } 4815f7df2e56Smrg wire = (char *) &rowWire[1]; 4816f7df2e56Smrg if (row->keys) { 4817f7df2e56Smrg int k; 4818f7df2e56Smrg XkbKeyPtr key; 4819f7df2e56Smrg xkbKeyWireDesc *keyWire; 4820f7df2e56Smrg 4821f7df2e56Smrg keyWire = (xkbKeyWireDesc *) wire; 4822f7df2e56Smrg for (k = 0, key = row->keys; k < row->num_keys; k++, key++) { 4823f7df2e56Smrg memcpy(keyWire[k].name, key->name.name, 4824f7df2e56Smrg XkbKeyNameLength); 4825f7df2e56Smrg keyWire[k].gap = key->gap; 4826f7df2e56Smrg keyWire[k].shapeNdx = key->shape_ndx; 4827f7df2e56Smrg keyWire[k].colorNdx = key->color_ndx; 4828f7df2e56Smrg if (swap) { 4829f7df2e56Smrg swaps(&keyWire[k].gap); 4830f7df2e56Smrg } 4831f7df2e56Smrg } 4832f7df2e56Smrg wire = (char *) &keyWire[row->num_keys]; 4833f7df2e56Smrg } 4834f7df2e56Smrg } 4835f7df2e56Smrg } 4836f7df2e56Smrg if (section->doodads) { 4837f7df2e56Smrg wire = XkbWriteGeomDoodads(wire, 4838f7df2e56Smrg section->num_doodads, section->doodads, 4839f7df2e56Smrg swap); 4840f7df2e56Smrg } 4841f7df2e56Smrg if (section->overlays) { 4842f7df2e56Smrg register int o; 4843f7df2e56Smrg 4844f7df2e56Smrg for (o = 0; o < section->num_overlays; o++) { 4845f7df2e56Smrg wire = XkbWriteGeomOverlay(wire, §ion->overlays[o], swap); 4846f7df2e56Smrg } 4847f7df2e56Smrg } 484805b261ecSmrg } 484905b261ecSmrg return wire; 485005b261ecSmrg} 485105b261ecSmrg 485205b261ecSmrgstatic Status 4853f7df2e56SmrgXkbComputeGetGeometryReplySize(XkbGeometryPtr geom, 4854f7df2e56Smrg xkbGetGeometryReply * rep, Atom name) 485505b261ecSmrg{ 4856f7df2e56Smrg int len; 4857f7df2e56Smrg 4858f7df2e56Smrg if (geom != NULL) { 4859f7df2e56Smrg len = XkbSizeCountedString(geom->label_font); 4860f7df2e56Smrg len += XkbSizeGeomProperties(geom); 4861f7df2e56Smrg len += XkbSizeGeomColors(geom); 4862f7df2e56Smrg len += XkbSizeGeomShapes(geom); 4863f7df2e56Smrg len += XkbSizeGeomSections(geom); 4864f7df2e56Smrg len += XkbSizeGeomDoodads(geom->num_doodads, geom->doodads); 4865f7df2e56Smrg len += XkbSizeGeomKeyAliases(geom); 4866f7df2e56Smrg rep->length = len / 4; 4867f7df2e56Smrg rep->found = TRUE; 4868f7df2e56Smrg rep->name = geom->name; 4869f7df2e56Smrg rep->widthMM = geom->width_mm; 4870f7df2e56Smrg rep->heightMM = geom->height_mm; 4871f7df2e56Smrg rep->nProperties = geom->num_properties; 4872f7df2e56Smrg rep->nColors = geom->num_colors; 4873f7df2e56Smrg rep->nShapes = geom->num_shapes; 4874f7df2e56Smrg rep->nSections = geom->num_sections; 4875f7df2e56Smrg rep->nDoodads = geom->num_doodads; 4876f7df2e56Smrg rep->nKeyAliases = geom->num_key_aliases; 4877f7df2e56Smrg rep->baseColorNdx = XkbGeomColorIndex(geom, geom->base_color); 4878f7df2e56Smrg rep->labelColorNdx = XkbGeomColorIndex(geom, geom->label_color); 487905b261ecSmrg } 488005b261ecSmrg else { 4881f7df2e56Smrg rep->length = 0; 4882f7df2e56Smrg rep->found = FALSE; 4883f7df2e56Smrg rep->name = name; 4884f7df2e56Smrg rep->widthMM = rep->heightMM = 0; 4885f7df2e56Smrg rep->nProperties = rep->nColors = rep->nShapes = 0; 4886f7df2e56Smrg rep->nSections = rep->nDoodads = 0; 4887f7df2e56Smrg rep->nKeyAliases = 0; 4888f7df2e56Smrg rep->labelColorNdx = rep->baseColorNdx = 0; 488905b261ecSmrg } 489005b261ecSmrg return Success; 489105b261ecSmrg} 489205b261ecSmrgstatic int 4893f7df2e56SmrgXkbSendGeometry(ClientPtr client, 4894f7df2e56Smrg XkbGeometryPtr geom, xkbGetGeometryReply * rep, Bool freeGeom) 489505b261ecSmrg{ 4896f7df2e56Smrg char *desc, *start; 4897f7df2e56Smrg int len; 4898f7df2e56Smrg 4899f7df2e56Smrg if (geom != NULL) { 4900f7df2e56Smrg start = desc = xallocarray(rep->length, 4); 4901f7df2e56Smrg if (!start) 4902f7df2e56Smrg return BadAlloc; 4903f7df2e56Smrg len = rep->length * 4; 4904f7df2e56Smrg desc = XkbWriteCountedString(desc, geom->label_font, client->swapped); 4905f7df2e56Smrg if (rep->nProperties > 0) 4906f7df2e56Smrg desc = XkbWriteGeomProperties(desc, geom, client->swapped); 4907f7df2e56Smrg if (rep->nColors > 0) 4908f7df2e56Smrg desc = XkbWriteGeomColors(desc, geom, client->swapped); 4909f7df2e56Smrg if (rep->nShapes > 0) 4910f7df2e56Smrg desc = XkbWriteGeomShapes(desc, geom, client->swapped); 4911f7df2e56Smrg if (rep->nSections > 0) 4912f7df2e56Smrg desc = XkbWriteGeomSections(desc, geom, client->swapped); 4913f7df2e56Smrg if (rep->nDoodads > 0) 4914f7df2e56Smrg desc = XkbWriteGeomDoodads(desc, geom->num_doodads, geom->doodads, 4915f7df2e56Smrg client->swapped); 4916f7df2e56Smrg if (rep->nKeyAliases > 0) 4917f7df2e56Smrg desc = XkbWriteGeomKeyAliases(desc, geom, client->swapped); 4918f7df2e56Smrg if ((desc - start) != (len)) { 4919f7df2e56Smrg ErrorF 4920f7df2e56Smrg ("[xkb] BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n", 4921f7df2e56Smrg len, (unsigned long) (desc - start)); 4922f7df2e56Smrg } 492305b261ecSmrg } 492405b261ecSmrg else { 4925f7df2e56Smrg len = 0; 4926f7df2e56Smrg start = NULL; 492705b261ecSmrg } 492805b261ecSmrg if (client->swapped) { 4929f7df2e56Smrg swaps(&rep->sequenceNumber); 4930f7df2e56Smrg swapl(&rep->length); 4931f7df2e56Smrg swapl(&rep->name); 4932f7df2e56Smrg swaps(&rep->widthMM); 4933f7df2e56Smrg swaps(&rep->heightMM); 4934f7df2e56Smrg swaps(&rep->nProperties); 4935f7df2e56Smrg swaps(&rep->nColors); 4936f7df2e56Smrg swaps(&rep->nShapes); 4937f7df2e56Smrg swaps(&rep->nSections); 4938f7df2e56Smrg swaps(&rep->nDoodads); 4939f7df2e56Smrg swaps(&rep->nKeyAliases); 4940f7df2e56Smrg } 4941f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetGeometryReply), rep); 4942f7df2e56Smrg if (len > 0) 4943f7df2e56Smrg WriteToClient(client, len, start); 4944f7df2e56Smrg if (start != NULL) 4945f7df2e56Smrg free((char *) start); 494605b261ecSmrg if (freeGeom) 4947f7df2e56Smrg XkbFreeGeometry(geom, XkbGeomAllMask, TRUE); 49486747b715Smrg return Success; 494905b261ecSmrg} 495005b261ecSmrg 495105b261ecSmrgint 495205b261ecSmrgProcXkbGetGeometry(ClientPtr client) 495305b261ecSmrg{ 4954f7df2e56Smrg DeviceIntPtr dev; 495505b261ecSmrg xkbGetGeometryReply rep; 4956f7df2e56Smrg XkbGeometryPtr geom; 4957f7df2e56Smrg Bool shouldFree; 4958f7df2e56Smrg Status status; 495905b261ecSmrg 496005b261ecSmrg REQUEST(xkbGetGeometryReq); 496105b261ecSmrg REQUEST_SIZE_MATCH(xkbGetGeometryReq); 496205b261ecSmrg 4963f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 4964f7df2e56Smrg return BadAccess; 496505b261ecSmrg 49664642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); 496705b261ecSmrg CHK_ATOM_OR_NONE(stuff->name); 496805b261ecSmrg 4969f7df2e56Smrg geom = XkbLookupNamedGeometry(dev, stuff->name, &shouldFree); 4970f7df2e56Smrg rep = (xkbGetGeometryReply) { 4971f7df2e56Smrg .type = X_Reply, 4972f7df2e56Smrg .deviceID = dev->id, 4973f7df2e56Smrg .sequenceNumber = client->sequence, 4974f7df2e56Smrg .length = 0 4975f7df2e56Smrg }; 4976f7df2e56Smrg status = XkbComputeGetGeometryReplySize(geom, &rep, stuff->name); 4977f7df2e56Smrg if (status != Success) 4978f7df2e56Smrg return status; 4979f7df2e56Smrg else 4980f7df2e56Smrg return XkbSendGeometry(client, geom, &rep, shouldFree); 498105b261ecSmrg} 498205b261ecSmrg 498305b261ecSmrg/***====================================================================***/ 498405b261ecSmrg 49851e26616aSmrgstatic Status 49861e26616aSmrg_GetCountedString(char **wire_inout, ClientPtr client, char **str) 498705b261ecSmrg{ 49881e26616aSmrg char *wire, *next; 49891e26616aSmrg CARD16 len; 499005b261ecSmrg 49911e26616aSmrg wire = *wire_inout; 49921e26616aSmrg len = *(CARD16 *) wire; 49931e26616aSmrg if (client->swapped) { 4994f7df2e56Smrg swaps(&len); 499505b261ecSmrg } 49961e26616aSmrg next = wire + XkbPaddedSize(len + 2); 49971e26616aSmrg /* Check we're still within the size of the request */ 49981e26616aSmrg if (client->req_len < 49991e26616aSmrg bytes_to_int32(next - (char *) client->requestBuffer)) 50001e26616aSmrg return BadValue; 50011e26616aSmrg *str = malloc(len + 1); 50021e26616aSmrg if (!*str) 50031e26616aSmrg return BadAlloc; 50041e26616aSmrg memcpy(*str, &wire[2], len); 50051e26616aSmrg *(*str + len) = '\0'; 50061e26616aSmrg *wire_inout = next; 50071e26616aSmrg return Success; 500805b261ecSmrg} 500905b261ecSmrg 501005b261ecSmrgstatic Status 5011f7df2e56Smrg_CheckSetDoodad(char **wire_inout, 5012f7df2e56Smrg XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client) 501305b261ecSmrg{ 5014f7df2e56Smrg char *wire; 5015f7df2e56Smrg xkbDoodadWireDesc *dWire; 5016f7df2e56Smrg xkbAnyDoodadWireDesc any; 5017f7df2e56Smrg xkbTextDoodadWireDesc text; 5018f7df2e56Smrg XkbDoodadPtr doodad; 50191e26616aSmrg Status status; 502005b261ecSmrg 5021f7df2e56Smrg dWire = (xkbDoodadWireDesc *) (*wire_inout); 5022f7df2e56Smrg any = dWire->any; 5023f7df2e56Smrg wire = (char *) &dWire[1]; 502405b261ecSmrg if (client->swapped) { 5025f7df2e56Smrg swapl(&any.name); 5026f7df2e56Smrg swaps(&any.top); 5027f7df2e56Smrg swaps(&any.left); 5028f7df2e56Smrg swaps(&any.angle); 502905b261ecSmrg } 503005b261ecSmrg CHK_ATOM_ONLY(dWire->any.name); 5031f7df2e56Smrg doodad = XkbAddGeomDoodad(geom, section, any.name); 503205b261ecSmrg if (!doodad) 5033f7df2e56Smrg return BadAlloc; 5034f7df2e56Smrg doodad->any.type = dWire->any.type; 5035f7df2e56Smrg doodad->any.priority = dWire->any.priority; 5036f7df2e56Smrg doodad->any.top = any.top; 5037f7df2e56Smrg doodad->any.left = any.left; 5038f7df2e56Smrg doodad->any.angle = any.angle; 503905b261ecSmrg switch (doodad->any.type) { 5040f7df2e56Smrg case XkbOutlineDoodad: 5041f7df2e56Smrg case XkbSolidDoodad: 5042f7df2e56Smrg if (dWire->shape.colorNdx >= geom->num_colors) { 5043f7df2e56Smrg client->errorValue = _XkbErrCode3(0x40, geom->num_colors, 5044f7df2e56Smrg dWire->shape.colorNdx); 5045f7df2e56Smrg return BadMatch; 5046f7df2e56Smrg } 5047f7df2e56Smrg if (dWire->shape.shapeNdx >= geom->num_shapes) { 5048f7df2e56Smrg client->errorValue = _XkbErrCode3(0x41, geom->num_shapes, 5049f7df2e56Smrg dWire->shape.shapeNdx); 5050f7df2e56Smrg return BadMatch; 5051f7df2e56Smrg } 5052f7df2e56Smrg doodad->shape.color_ndx = dWire->shape.colorNdx; 5053f7df2e56Smrg doodad->shape.shape_ndx = dWire->shape.shapeNdx; 5054f7df2e56Smrg break; 5055f7df2e56Smrg case XkbTextDoodad: 5056f7df2e56Smrg if (dWire->text.colorNdx >= geom->num_colors) { 5057f7df2e56Smrg client->errorValue = _XkbErrCode3(0x42, geom->num_colors, 5058f7df2e56Smrg dWire->text.colorNdx); 5059f7df2e56Smrg return BadMatch; 5060f7df2e56Smrg } 5061f7df2e56Smrg text = dWire->text; 5062f7df2e56Smrg if (client->swapped) { 5063f7df2e56Smrg swaps(&text.width); 5064f7df2e56Smrg swaps(&text.height); 5065f7df2e56Smrg } 5066f7df2e56Smrg doodad->text.width = text.width; 5067f7df2e56Smrg doodad->text.height = text.height; 5068f7df2e56Smrg doodad->text.color_ndx = dWire->text.colorNdx; 5069f7df2e56Smrg status = _GetCountedString(&wire, client, &doodad->text.text); 5070f7df2e56Smrg if (status != Success) 5071f7df2e56Smrg return status; 5072f7df2e56Smrg status = _GetCountedString(&wire, client, &doodad->text.font); 5073f7df2e56Smrg if (status != Success) { 5074f7df2e56Smrg free (doodad->text.text); 5075f7df2e56Smrg return status; 5076f7df2e56Smrg } 5077f7df2e56Smrg break; 5078f7df2e56Smrg case XkbIndicatorDoodad: 5079f7df2e56Smrg if (dWire->indicator.onColorNdx >= geom->num_colors) { 5080f7df2e56Smrg client->errorValue = _XkbErrCode3(0x43, geom->num_colors, 5081f7df2e56Smrg dWire->indicator.onColorNdx); 5082f7df2e56Smrg return BadMatch; 5083f7df2e56Smrg } 5084f7df2e56Smrg if (dWire->indicator.offColorNdx >= geom->num_colors) { 5085f7df2e56Smrg client->errorValue = _XkbErrCode3(0x44, geom->num_colors, 5086f7df2e56Smrg dWire->indicator.offColorNdx); 5087f7df2e56Smrg return BadMatch; 5088f7df2e56Smrg } 5089f7df2e56Smrg if (dWire->indicator.shapeNdx >= geom->num_shapes) { 5090f7df2e56Smrg client->errorValue = _XkbErrCode3(0x45, geom->num_shapes, 5091f7df2e56Smrg dWire->indicator.shapeNdx); 5092f7df2e56Smrg return BadMatch; 5093f7df2e56Smrg } 5094f7df2e56Smrg doodad->indicator.shape_ndx = dWire->indicator.shapeNdx; 5095f7df2e56Smrg doodad->indicator.on_color_ndx = dWire->indicator.onColorNdx; 5096f7df2e56Smrg doodad->indicator.off_color_ndx = dWire->indicator.offColorNdx; 5097f7df2e56Smrg break; 5098f7df2e56Smrg case XkbLogoDoodad: 5099f7df2e56Smrg if (dWire->logo.colorNdx >= geom->num_colors) { 5100f7df2e56Smrg client->errorValue = _XkbErrCode3(0x46, geom->num_colors, 5101f7df2e56Smrg dWire->logo.colorNdx); 5102f7df2e56Smrg return BadMatch; 5103f7df2e56Smrg } 5104f7df2e56Smrg if (dWire->logo.shapeNdx >= geom->num_shapes) { 5105f7df2e56Smrg client->errorValue = _XkbErrCode3(0x47, geom->num_shapes, 5106f7df2e56Smrg dWire->logo.shapeNdx); 5107f7df2e56Smrg return BadMatch; 5108f7df2e56Smrg } 5109f7df2e56Smrg doodad->logo.color_ndx = dWire->logo.colorNdx; 5110f7df2e56Smrg doodad->logo.shape_ndx = dWire->logo.shapeNdx; 5111f7df2e56Smrg status = _GetCountedString(&wire, client, &doodad->logo.logo_name); 5112f7df2e56Smrg if (status != Success) 5113f7df2e56Smrg return status; 5114f7df2e56Smrg break; 5115f7df2e56Smrg default: 5116f7df2e56Smrg client->errorValue = _XkbErrCode2(0x4F, dWire->any.type); 5117f7df2e56Smrg return BadValue; 5118f7df2e56Smrg } 5119f7df2e56Smrg *wire_inout = wire; 5120f7df2e56Smrg return Success; 5121f7df2e56Smrg} 5122f7df2e56Smrg 5123f7df2e56Smrgstatic Status 5124f7df2e56Smrg_CheckSetOverlay(char **wire_inout, 5125f7df2e56Smrg XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client) 512605b261ecSmrg{ 5127f7df2e56Smrg register int r; 5128f7df2e56Smrg char *wire; 5129f7df2e56Smrg XkbOverlayPtr ol; 5130f7df2e56Smrg xkbOverlayWireDesc *olWire; 5131f7df2e56Smrg xkbOverlayRowWireDesc *rWire; 513205b261ecSmrg 5133f7df2e56Smrg wire = *wire_inout; 5134f7df2e56Smrg olWire = (xkbOverlayWireDesc *) wire; 5135f7df2e56Smrg if (client->swapped) { 5136f7df2e56Smrg swapl(&olWire->name); 5137f7df2e56Smrg } 5138f7df2e56Smrg CHK_ATOM_ONLY(olWire->name); 5139f7df2e56Smrg ol = XkbAddGeomOverlay(section, olWire->name, olWire->nRows); 5140f7df2e56Smrg rWire = (xkbOverlayRowWireDesc *) &olWire[1]; 5141f7df2e56Smrg for (r = 0; r < olWire->nRows; r++) { 5142f7df2e56Smrg register int k; 5143f7df2e56Smrg xkbOverlayKeyWireDesc *kWire; 5144f7df2e56Smrg XkbOverlayRowPtr row; 5145f7df2e56Smrg 5146f7df2e56Smrg if (rWire->rowUnder > section->num_rows) { 5147f7df2e56Smrg client->errorValue = _XkbErrCode4(0x20, r, section->num_rows, 5148f7df2e56Smrg rWire->rowUnder); 5149f7df2e56Smrg return BadMatch; 5150f7df2e56Smrg } 5151f7df2e56Smrg row = XkbAddGeomOverlayRow(ol, rWire->rowUnder, rWire->nKeys); 5152f7df2e56Smrg kWire = (xkbOverlayKeyWireDesc *) &rWire[1]; 5153f7df2e56Smrg for (k = 0; k < rWire->nKeys; k++, kWire++) { 5154f7df2e56Smrg if (XkbAddGeomOverlayKey(ol, row, 5155f7df2e56Smrg (char *) kWire->over, 5156f7df2e56Smrg (char *) kWire->under) == NULL) { 5157f7df2e56Smrg client->errorValue = _XkbErrCode3(0x21, r, k); 5158f7df2e56Smrg return BadMatch; 5159f7df2e56Smrg } 5160f7df2e56Smrg } 5161f7df2e56Smrg rWire = (xkbOverlayRowWireDesc *) kWire; 5162f7df2e56Smrg } 5163f7df2e56Smrg olWire = (xkbOverlayWireDesc *) rWire; 5164f7df2e56Smrg wire = (char *) olWire; 5165f7df2e56Smrg *wire_inout = wire; 5166f7df2e56Smrg return Success; 5167f7df2e56Smrg} 5168f7df2e56Smrg 5169f7df2e56Smrgstatic Status 5170f7df2e56Smrg_CheckSetSections(XkbGeometryPtr geom, 5171f7df2e56Smrg xkbSetGeometryReq * req, char **wire_inout, ClientPtr client) 5172f7df2e56Smrg{ 5173f7df2e56Smrg Status status; 5174f7df2e56Smrg register int s; 5175f7df2e56Smrg char *wire; 5176f7df2e56Smrg xkbSectionWireDesc *sWire; 5177f7df2e56Smrg XkbSectionPtr section; 5178f7df2e56Smrg 5179f7df2e56Smrg wire = *wire_inout; 5180f7df2e56Smrg if (req->nSections < 1) 5181f7df2e56Smrg return Success; 5182f7df2e56Smrg sWire = (xkbSectionWireDesc *) wire; 5183f7df2e56Smrg for (s = 0; s < req->nSections; s++) { 5184f7df2e56Smrg register int r; 5185f7df2e56Smrg xkbRowWireDesc *rWire; 5186f7df2e56Smrg 5187f7df2e56Smrg if (client->swapped) { 5188f7df2e56Smrg swapl(&sWire->name); 5189f7df2e56Smrg swaps(&sWire->top); 5190f7df2e56Smrg swaps(&sWire->left); 5191f7df2e56Smrg swaps(&sWire->width); 5192f7df2e56Smrg swaps(&sWire->height); 5193f7df2e56Smrg swaps(&sWire->angle); 5194f7df2e56Smrg } 5195f7df2e56Smrg CHK_ATOM_ONLY(sWire->name); 5196f7df2e56Smrg section = XkbAddGeomSection(geom, sWire->name, sWire->nRows, 5197f7df2e56Smrg sWire->nDoodads, sWire->nOverlays); 5198f7df2e56Smrg if (!section) 5199f7df2e56Smrg return BadAlloc; 5200f7df2e56Smrg section->priority = sWire->priority; 5201f7df2e56Smrg section->top = sWire->top; 5202f7df2e56Smrg section->left = sWire->left; 5203f7df2e56Smrg section->width = sWire->width; 5204f7df2e56Smrg section->height = sWire->height; 5205f7df2e56Smrg section->angle = sWire->angle; 5206f7df2e56Smrg rWire = (xkbRowWireDesc *) &sWire[1]; 5207f7df2e56Smrg for (r = 0; r < sWire->nRows; r++) { 5208f7df2e56Smrg register int k; 5209f7df2e56Smrg XkbRowPtr row; 5210f7df2e56Smrg xkbKeyWireDesc *kWire; 5211f7df2e56Smrg 5212f7df2e56Smrg if (client->swapped) { 5213f7df2e56Smrg swaps(&rWire->top); 5214f7df2e56Smrg swaps(&rWire->left); 5215f7df2e56Smrg } 5216f7df2e56Smrg row = XkbAddGeomRow(section, rWire->nKeys); 5217f7df2e56Smrg if (!row) 5218f7df2e56Smrg return BadAlloc; 5219f7df2e56Smrg row->top = rWire->top; 5220f7df2e56Smrg row->left = rWire->left; 5221f7df2e56Smrg row->vertical = rWire->vertical; 5222f7df2e56Smrg kWire = (xkbKeyWireDesc *) &rWire[1]; 5223f7df2e56Smrg for (k = 0; k < rWire->nKeys; k++) { 5224f7df2e56Smrg XkbKeyPtr key; 5225f7df2e56Smrg 5226f7df2e56Smrg key = XkbAddGeomKey(row); 5227f7df2e56Smrg if (!key) 5228f7df2e56Smrg return BadAlloc; 5229f7df2e56Smrg memcpy(key->name.name, kWire[k].name, XkbKeyNameLength); 5230f7df2e56Smrg key->gap = kWire[k].gap; 5231f7df2e56Smrg key->shape_ndx = kWire[k].shapeNdx; 5232f7df2e56Smrg key->color_ndx = kWire[k].colorNdx; 5233f7df2e56Smrg if (key->shape_ndx >= geom->num_shapes) { 5234f7df2e56Smrg client->errorValue = _XkbErrCode3(0x10, key->shape_ndx, 5235f7df2e56Smrg geom->num_shapes); 5236f7df2e56Smrg return BadMatch; 5237f7df2e56Smrg } 5238f7df2e56Smrg if (key->color_ndx >= geom->num_colors) { 5239f7df2e56Smrg client->errorValue = _XkbErrCode3(0x11, key->color_ndx, 5240f7df2e56Smrg geom->num_colors); 5241f7df2e56Smrg return BadMatch; 5242f7df2e56Smrg } 5243f7df2e56Smrg } 5244f7df2e56Smrg rWire = (xkbRowWireDesc *) &kWire[rWire->nKeys]; 5245f7df2e56Smrg } 5246f7df2e56Smrg wire = (char *) rWire; 5247f7df2e56Smrg if (sWire->nDoodads > 0) { 5248f7df2e56Smrg register int d; 5249f7df2e56Smrg 5250f7df2e56Smrg for (d = 0; d < sWire->nDoodads; d++) { 5251f7df2e56Smrg status = _CheckSetDoodad(&wire, geom, section, client); 5252f7df2e56Smrg if (status != Success) 5253f7df2e56Smrg return status; 5254f7df2e56Smrg } 5255f7df2e56Smrg } 5256f7df2e56Smrg if (sWire->nOverlays > 0) { 5257f7df2e56Smrg register int o; 5258f7df2e56Smrg 5259f7df2e56Smrg for (o = 0; o < sWire->nOverlays; o++) { 5260f7df2e56Smrg status = _CheckSetOverlay(&wire, geom, section, client); 5261f7df2e56Smrg if (status != Success) 5262f7df2e56Smrg return status; 5263f7df2e56Smrg } 5264f7df2e56Smrg } 5265f7df2e56Smrg sWire = (xkbSectionWireDesc *) wire; 5266f7df2e56Smrg } 5267f7df2e56Smrg wire = (char *) sWire; 5268f7df2e56Smrg *wire_inout = wire; 5269f7df2e56Smrg return Success; 5270f7df2e56Smrg} 5271f7df2e56Smrg 5272f7df2e56Smrgstatic Status 5273f7df2e56Smrg_CheckSetShapes(XkbGeometryPtr geom, 5274f7df2e56Smrg xkbSetGeometryReq * req, char **wire_inout, ClientPtr client) 5275f7df2e56Smrg{ 5276f7df2e56Smrg register int i; 5277f7df2e56Smrg char *wire; 5278f7df2e56Smrg 5279f7df2e56Smrg wire = *wire_inout; 5280f7df2e56Smrg if (req->nShapes < 1) { 5281f7df2e56Smrg client->errorValue = _XkbErrCode2(0x06, req->nShapes); 5282f7df2e56Smrg return BadValue; 528305b261ecSmrg } 528405b261ecSmrg else { 5285f7df2e56Smrg xkbShapeWireDesc *shapeWire; 5286f7df2e56Smrg XkbShapePtr shape; 5287f7df2e56Smrg register int o; 5288f7df2e56Smrg 5289f7df2e56Smrg shapeWire = (xkbShapeWireDesc *) wire; 5290f7df2e56Smrg for (i = 0; i < req->nShapes; i++) { 5291f7df2e56Smrg xkbOutlineWireDesc *olWire; 5292f7df2e56Smrg XkbOutlinePtr ol; 5293f7df2e56Smrg 5294f7df2e56Smrg shape = 5295f7df2e56Smrg XkbAddGeomShape(geom, shapeWire->name, shapeWire->nOutlines); 5296f7df2e56Smrg if (!shape) 5297f7df2e56Smrg return BadAlloc; 5298f7df2e56Smrg olWire = (xkbOutlineWireDesc *) (&shapeWire[1]); 5299f7df2e56Smrg for (o = 0; o < shapeWire->nOutlines; o++) { 5300f7df2e56Smrg register int p; 5301f7df2e56Smrg XkbPointPtr pt; 5302f7df2e56Smrg xkbPointWireDesc *ptWire; 5303f7df2e56Smrg 5304f7df2e56Smrg ol = XkbAddGeomOutline(shape, olWire->nPoints); 5305f7df2e56Smrg if (!ol) 5306f7df2e56Smrg return BadAlloc; 5307f7df2e56Smrg ol->corner_radius = olWire->cornerRadius; 5308f7df2e56Smrg ptWire = (xkbPointWireDesc *) &olWire[1]; 5309f7df2e56Smrg for (p = 0, pt = ol->points; p < olWire->nPoints; p++, pt++) { 5310f7df2e56Smrg pt->x = ptWire[p].x; 5311f7df2e56Smrg pt->y = ptWire[p].y; 5312f7df2e56Smrg if (client->swapped) { 5313f7df2e56Smrg swaps(&pt->x); 5314f7df2e56Smrg swaps(&pt->y); 5315f7df2e56Smrg } 5316f7df2e56Smrg } 5317f7df2e56Smrg ol->num_points = olWire->nPoints; 5318f7df2e56Smrg olWire = (xkbOutlineWireDesc *) (&ptWire[olWire->nPoints]); 5319f7df2e56Smrg } 5320f7df2e56Smrg if (shapeWire->primaryNdx != XkbNoShape) 5321f7df2e56Smrg shape->primary = &shape->outlines[shapeWire->primaryNdx]; 5322f7df2e56Smrg if (shapeWire->approxNdx != XkbNoShape) 5323f7df2e56Smrg shape->approx = &shape->outlines[shapeWire->approxNdx]; 5324f7df2e56Smrg shapeWire = (xkbShapeWireDesc *) olWire; 5325f7df2e56Smrg } 5326f7df2e56Smrg wire = (char *) shapeWire; 5327f7df2e56Smrg } 5328f7df2e56Smrg if (geom->num_shapes != req->nShapes) { 5329f7df2e56Smrg client->errorValue = _XkbErrCode3(0x07, geom->num_shapes, req->nShapes); 5330f7df2e56Smrg return BadMatch; 5331f7df2e56Smrg } 5332f7df2e56Smrg 5333f7df2e56Smrg *wire_inout = wire; 533405b261ecSmrg return Success; 533505b261ecSmrg} 533605b261ecSmrg 533705b261ecSmrgstatic Status 5338f7df2e56Smrg_CheckSetGeom(XkbGeometryPtr geom, xkbSetGeometryReq * req, ClientPtr client) 533905b261ecSmrg{ 5340f7df2e56Smrg register int i; 5341f7df2e56Smrg Status status; 5342f7df2e56Smrg char *wire; 534305b261ecSmrg 5344f7df2e56Smrg wire = (char *) &req[1]; 53451e26616aSmrg status = _GetCountedString(&wire, client, &geom->label_font); 53461e26616aSmrg if (status != Success) 53471e26616aSmrg return status; 53481e26616aSmrg 53491e26616aSmrg for (i = 0; i < req->nProperties; i++) { 5350f7df2e56Smrg char *name, *val; 53511e26616aSmrg 53521e26616aSmrg status = _GetCountedString(&wire, client, &name); 53531e26616aSmrg if (status != Success) 53541e26616aSmrg return status; 53551e26616aSmrg status = _GetCountedString(&wire, client, &val); 53561e26616aSmrg if (status != Success) { 53576747b715Smrg free(name); 53581e26616aSmrg return status; 535905b261ecSmrg } 5360f7df2e56Smrg if (XkbAddGeomProperty(geom, name, val) == NULL) { 53616747b715Smrg free(name); 53626747b715Smrg free(val); 5363f7df2e56Smrg return BadAlloc; 536405b261ecSmrg } 53656747b715Smrg free(name); 53666747b715Smrg free(val); 536705b261ecSmrg } 536805b261ecSmrg 5369f7df2e56Smrg if (req->nColors < 2) { 5370f7df2e56Smrg client->errorValue = _XkbErrCode3(0x01, 2, req->nColors); 5371f7df2e56Smrg return BadValue; 537205b261ecSmrg } 5373f7df2e56Smrg if (req->baseColorNdx > req->nColors) { 5374f7df2e56Smrg client->errorValue = 5375f7df2e56Smrg _XkbErrCode3(0x03, req->nColors, req->baseColorNdx); 5376f7df2e56Smrg return BadMatch; 537705b261ecSmrg } 5378f7df2e56Smrg if (req->labelColorNdx > req->nColors) { 5379f7df2e56Smrg client->errorValue = 5380f7df2e56Smrg _XkbErrCode3(0x03, req->nColors, req->labelColorNdx); 5381f7df2e56Smrg return BadMatch; 538205b261ecSmrg } 5383f7df2e56Smrg if (req->labelColorNdx == req->baseColorNdx) { 5384f7df2e56Smrg client->errorValue = _XkbErrCode3(0x04, req->baseColorNdx, 5385f7df2e56Smrg req->labelColorNdx); 5386f7df2e56Smrg return BadMatch; 538705b261ecSmrg } 538805b261ecSmrg 53891e26616aSmrg for (i = 0; i < req->nColors; i++) { 5390f7df2e56Smrg char *name; 5391f7df2e56Smrg 53921e26616aSmrg status = _GetCountedString(&wire, client, &name); 53931e26616aSmrg if (status != Success) 53941e26616aSmrg return status; 5395f7df2e56Smrg if (!XkbAddGeomColor(geom, name, geom->num_colors)) { 53966747b715Smrg free(name); 5397f7df2e56Smrg return BadAlloc; 539805b261ecSmrg } 53996747b715Smrg free(name); 540005b261ecSmrg } 5401f7df2e56Smrg if (req->nColors != geom->num_colors) { 5402f7df2e56Smrg client->errorValue = _XkbErrCode3(0x05, req->nColors, geom->num_colors); 5403f7df2e56Smrg return BadMatch; 540405b261ecSmrg } 5405f7df2e56Smrg geom->label_color = &geom->colors[req->labelColorNdx]; 5406f7df2e56Smrg geom->base_color = &geom->colors[req->baseColorNdx]; 540705b261ecSmrg 5408f7df2e56Smrg if ((status = _CheckSetShapes(geom, req, &wire, client)) != Success) 5409f7df2e56Smrg return status; 541005b261ecSmrg 5411f7df2e56Smrg if ((status = _CheckSetSections(geom, req, &wire, client)) != Success) 5412f7df2e56Smrg return status; 541305b261ecSmrg 5414f7df2e56Smrg for (i = 0; i < req->nDoodads; i++) { 5415f7df2e56Smrg status = _CheckSetDoodad(&wire, geom, NULL, client); 5416f7df2e56Smrg if (status != Success) 5417f7df2e56Smrg return status; 541805b261ecSmrg } 541905b261ecSmrg 5420f7df2e56Smrg for (i = 0; i < req->nKeyAliases; i++) { 5421f7df2e56Smrg if (XkbAddGeomKeyAlias(geom, &wire[XkbKeyNameLength], wire) == NULL) 5422f7df2e56Smrg return BadAlloc; 5423f7df2e56Smrg wire += 2 * XkbKeyNameLength; 542405b261ecSmrg } 542505b261ecSmrg return Success; 542605b261ecSmrg} 542705b261ecSmrg 54284642e01fSmrgstatic int 5429f7df2e56Smrg_XkbSetGeometry(ClientPtr client, DeviceIntPtr dev, xkbSetGeometryReq * stuff) 543005b261ecSmrg{ 5431f7df2e56Smrg XkbDescPtr xkb; 5432f7df2e56Smrg Bool new_name; 5433f7df2e56Smrg xkbNewKeyboardNotify nkn; 5434f7df2e56Smrg XkbGeometryPtr geom, old; 5435f7df2e56Smrg XkbGeometrySizesRec sizes; 5436f7df2e56Smrg Status status; 5437f7df2e56Smrg 5438f7df2e56Smrg xkb = dev->key->xkbInfo->desc; 5439f7df2e56Smrg old = xkb->geom; 5440f7df2e56Smrg xkb->geom = NULL; 5441f7df2e56Smrg 5442f7df2e56Smrg sizes.which = XkbGeomAllMask; 5443f7df2e56Smrg sizes.num_properties = stuff->nProperties; 5444f7df2e56Smrg sizes.num_colors = stuff->nColors; 5445f7df2e56Smrg sizes.num_shapes = stuff->nShapes; 5446f7df2e56Smrg sizes.num_sections = stuff->nSections; 5447f7df2e56Smrg sizes.num_doodads = stuff->nDoodads; 5448f7df2e56Smrg sizes.num_key_aliases = stuff->nKeyAliases; 5449f7df2e56Smrg if ((status = XkbAllocGeometry(xkb, &sizes)) != Success) { 5450f7df2e56Smrg xkb->geom = old; 54514642e01fSmrg return status; 545205b261ecSmrg } 5453f7df2e56Smrg geom = xkb->geom; 5454f7df2e56Smrg geom->name = stuff->name; 5455f7df2e56Smrg geom->width_mm = stuff->widthMM; 5456f7df2e56Smrg geom->height_mm = stuff->heightMM; 5457f7df2e56Smrg if ((status = _CheckSetGeom(geom, stuff, client)) != Success) { 5458f7df2e56Smrg XkbFreeGeometry(geom, XkbGeomAllMask, TRUE); 5459f7df2e56Smrg xkb->geom = old; 54604642e01fSmrg return status; 546105b261ecSmrg } 5462f7df2e56Smrg new_name = (xkb->names->geometry != geom->name); 5463f7df2e56Smrg xkb->names->geometry = geom->name; 546405b261ecSmrg if (old) 5465f7df2e56Smrg XkbFreeGeometry(old, XkbGeomAllMask, TRUE); 546605b261ecSmrg if (new_name) { 5467f7df2e56Smrg xkbNamesNotify nn; 5468f7df2e56Smrg 54696747b715Smrg memset(&nn, 0, sizeof(xkbNamesNotify)); 5470f7df2e56Smrg nn.changed = XkbGeometryNameMask; 5471f7df2e56Smrg XkbSendNamesNotify(dev, &nn); 5472f7df2e56Smrg } 5473f7df2e56Smrg nkn.deviceID = nkn.oldDeviceID = dev->id; 5474f7df2e56Smrg nkn.minKeyCode = nkn.oldMinKeyCode = xkb->min_key_code; 5475f7df2e56Smrg nkn.maxKeyCode = nkn.oldMaxKeyCode = xkb->max_key_code; 5476f7df2e56Smrg nkn.requestMajor = XkbReqCode; 5477f7df2e56Smrg nkn.requestMinor = X_kbSetGeometry; 5478f7df2e56Smrg nkn.changed = XkbNKN_GeometryMask; 5479f7df2e56Smrg XkbSendNewKeyboardNotify(dev, &nkn); 548005b261ecSmrg return Success; 548105b261ecSmrg} 548205b261ecSmrg 54834642e01fSmrgint 54844642e01fSmrgProcXkbSetGeometry(ClientPtr client) 54854642e01fSmrg{ 5486f7df2e56Smrg DeviceIntPtr dev; 5487f7df2e56Smrg int rc; 54884642e01fSmrg 54894642e01fSmrg REQUEST(xkbSetGeometryReq); 54904642e01fSmrg REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq); 54914642e01fSmrg 5492f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 5493f7df2e56Smrg return BadAccess; 54944642e01fSmrg 54954642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); 54964642e01fSmrg CHK_ATOM_OR_NONE(stuff->name); 54974642e01fSmrg 54984642e01fSmrg rc = _XkbSetGeometry(client, dev, stuff); 54994642e01fSmrg if (rc != Success) 55004642e01fSmrg return rc; 55014642e01fSmrg 5502f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd) { 55034642e01fSmrg DeviceIntPtr other; 5504f7df2e56Smrg 5505f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 5506f7df2e56Smrg if ((other != dev) && other->key && !IsMaster(other) && 5507f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) { 5508f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 5509f7df2e56Smrg DixManageAccess); 55104642e01fSmrg if (rc == Success) 55114642e01fSmrg _XkbSetGeometry(client, other, stuff); 55124642e01fSmrg } 55134642e01fSmrg } 55144642e01fSmrg } 55154642e01fSmrg 55164642e01fSmrg return Success; 55174642e01fSmrg} 55184642e01fSmrg 551905b261ecSmrg/***====================================================================***/ 552005b261ecSmrg 552105b261ecSmrgint 552205b261ecSmrgProcXkbPerClientFlags(ClientPtr client) 552305b261ecSmrg{ 5524f7df2e56Smrg DeviceIntPtr dev; 5525f7df2e56Smrg xkbPerClientFlagsReply rep; 5526f7df2e56Smrg XkbInterestPtr interest; 55274642e01fSmrg Mask access_mode = DixGetAttrAccess | DixSetAttrAccess; 552805b261ecSmrg 552905b261ecSmrg REQUEST(xkbPerClientFlagsReq); 553005b261ecSmrg REQUEST_SIZE_MATCH(xkbPerClientFlagsReq); 553105b261ecSmrg 5532f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 5533f7df2e56Smrg return BadAccess; 553405b261ecSmrg 55354642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode); 5536f7df2e56Smrg CHK_MASK_LEGAL(0x01, stuff->change, XkbPCF_AllFlagsMask); 5537f7df2e56Smrg CHK_MASK_MATCH(0x02, stuff->change, stuff->value); 553805b261ecSmrg 5539f7df2e56Smrg interest = XkbFindClientResource((DevicePtr) dev, client); 554005b261ecSmrg if (stuff->change) { 5541f7df2e56Smrg client->xkbClientFlags &= ~stuff->change; 5542f7df2e56Smrg client->xkbClientFlags |= stuff->value; 554305b261ecSmrg } 5544f7df2e56Smrg if (stuff->change & XkbPCF_AutoResetControlsMask) { 5545f7df2e56Smrg Bool want; 5546f7df2e56Smrg 5547f7df2e56Smrg want = stuff->value & XkbPCF_AutoResetControlsMask; 5548f7df2e56Smrg if (interest && !want) { 5549f7df2e56Smrg interest->autoCtrls = interest->autoCtrlValues = 0; 5550f7df2e56Smrg } 5551f7df2e56Smrg else if (want && (!interest)) { 5552f7df2e56Smrg XID id = FakeClientID(client->index); 5553f7df2e56Smrg 5554f7df2e56Smrg if (!AddResource(id, RT_XKBCLIENT, dev)) 5555f7df2e56Smrg return BadAlloc; 5556f7df2e56Smrg interest = XkbAddClientResource((DevicePtr) dev, client, id); 5557f7df2e56Smrg if (!interest) 5558f7df2e56Smrg return BadAlloc; 5559f7df2e56Smrg } 5560f7df2e56Smrg if (interest && want) { 5561f7df2e56Smrg register unsigned affect; 5562f7df2e56Smrg 5563f7df2e56Smrg affect = stuff->ctrlsToChange; 5564f7df2e56Smrg 5565f7df2e56Smrg CHK_MASK_LEGAL(0x03, affect, XkbAllBooleanCtrlsMask); 5566f7df2e56Smrg CHK_MASK_MATCH(0x04, affect, stuff->autoCtrls); 5567f7df2e56Smrg CHK_MASK_MATCH(0x05, stuff->autoCtrls, stuff->autoCtrlValues); 5568f7df2e56Smrg 5569f7df2e56Smrg interest->autoCtrls &= ~affect; 5570f7df2e56Smrg interest->autoCtrlValues &= ~affect; 5571f7df2e56Smrg interest->autoCtrls |= stuff->autoCtrls & affect; 5572f7df2e56Smrg interest->autoCtrlValues |= stuff->autoCtrlValues & affect; 5573f7df2e56Smrg } 557405b261ecSmrg } 5575f7df2e56Smrg 5576f7df2e56Smrg rep = (xkbPerClientFlagsReply) { 5577f7df2e56Smrg .type = X_Reply, 5578f7df2e56Smrg .sequenceNumber = client->sequence, 5579f7df2e56Smrg .length = 0, 5580f7df2e56Smrg .supported = XkbPCF_AllFlagsMask, 5581f7df2e56Smrg .value = client->xkbClientFlags & XkbPCF_AllFlagsMask, 5582f7df2e56Smrg .autoCtrls = interest ? interest->autoCtrls : 0, 5583f7df2e56Smrg .autoCtrlValues = interest ? interest->autoCtrlValues : 0, 5584f7df2e56Smrg }; 5585f7df2e56Smrg if (client->swapped) { 5586f7df2e56Smrg swaps(&rep.sequenceNumber); 5587f7df2e56Smrg swapl(&rep.supported); 5588f7df2e56Smrg swapl(&rep.value); 5589f7df2e56Smrg swapl(&rep.autoCtrls); 5590f7df2e56Smrg swapl(&rep.autoCtrlValues); 559105b261ecSmrg } 5592f7df2e56Smrg WriteToClient(client, SIZEOF(xkbPerClientFlagsReply), &rep); 55936747b715Smrg return Success; 559405b261ecSmrg} 559505b261ecSmrg 559605b261ecSmrg/***====================================================================***/ 559705b261ecSmrg 559805b261ecSmrg/* all latin-1 alphanumerics, plus parens, minus, underscore, slash */ 559905b261ecSmrg/* and wildcards */ 560005b261ecSmrgstatic unsigned char componentSpecLegal[] = { 5601f7df2e56Smrg 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x87, 5602f7df2e56Smrg 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07, 5603f7df2e56Smrg 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 5604f7df2e56Smrg 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff 560505b261ecSmrg}; 560605b261ecSmrg 560705b261ecSmrg/* same as above but accepts percent, plus and bar too */ 560805b261ecSmrgstatic unsigned char componentExprLegal[] = { 5609f7df2e56Smrg 0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0xff, 0x87, 5610f7df2e56Smrg 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x17, 5611f7df2e56Smrg 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 5612f7df2e56Smrg 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff 561305b261ecSmrg}; 561405b261ecSmrg 561505b261ecSmrgstatic char * 5616f7df2e56SmrgGetComponentSpec(unsigned char **pWire, Bool allowExpr, int *errRtrn) 561705b261ecSmrg{ 5618f7df2e56Smrg int len; 5619f7df2e56Smrg register int i; 5620f7df2e56Smrg unsigned char *wire, *str, *tmp, *legal; 5621f7df2e56Smrg 5622f7df2e56Smrg if (allowExpr) 5623f7df2e56Smrg legal = &componentExprLegal[0]; 5624f7df2e56Smrg else 5625f7df2e56Smrg legal = &componentSpecLegal[0]; 5626f7df2e56Smrg 5627f7df2e56Smrg wire = *pWire; 5628f7df2e56Smrg len = (*(unsigned char *) wire++); 5629f7df2e56Smrg if (len > 0) { 5630f7df2e56Smrg str = calloc(1, len + 1); 5631f7df2e56Smrg if (str) { 5632f7df2e56Smrg tmp = str; 5633f7df2e56Smrg for (i = 0; i < len; i++) { 5634f7df2e56Smrg if (legal[(*wire) / 8] & (1 << ((*wire) % 8))) 5635f7df2e56Smrg *tmp++ = *wire++; 5636f7df2e56Smrg else 5637f7df2e56Smrg wire++; 5638f7df2e56Smrg } 5639f7df2e56Smrg if (tmp != str) 5640f7df2e56Smrg *tmp++ = '\0'; 5641f7df2e56Smrg else { 5642f7df2e56Smrg free(str); 5643f7df2e56Smrg str = NULL; 5644f7df2e56Smrg } 5645f7df2e56Smrg } 5646f7df2e56Smrg else { 5647f7df2e56Smrg *errRtrn = BadAlloc; 5648f7df2e56Smrg } 564905b261ecSmrg } 565005b261ecSmrg else { 5651f7df2e56Smrg str = NULL; 565205b261ecSmrg } 5653f7df2e56Smrg *pWire = wire; 5654f7df2e56Smrg return (char *) str; 565505b261ecSmrg} 565605b261ecSmrg 565705b261ecSmrg/***====================================================================***/ 565805b261ecSmrg 565905b261ecSmrgint 566005b261ecSmrgProcXkbListComponents(ClientPtr client) 566105b261ecSmrg{ 5662f7df2e56Smrg DeviceIntPtr dev; 5663f7df2e56Smrg xkbListComponentsReply rep; 5664f7df2e56Smrg unsigned len; 5665f7df2e56Smrg unsigned char *str; 5666f7df2e56Smrg uint8_t size; 5667f7df2e56Smrg int i; 566805b261ecSmrg 566905b261ecSmrg REQUEST(xkbListComponentsReq); 567005b261ecSmrg REQUEST_AT_LEAST_SIZE(xkbListComponentsReq); 567105b261ecSmrg 5672f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 5673f7df2e56Smrg return BadAccess; 567405b261ecSmrg 56754642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); 567605b261ecSmrg 5677f7df2e56Smrg /* The request is followed by six Pascal strings (i.e. size in characters 5678f7df2e56Smrg * followed by a string pattern) describing what the client wants us to 5679f7df2e56Smrg * list. We don't care, but might as well check they haven't got the 5680f7df2e56Smrg * length wrong. */ 5681f7df2e56Smrg str = (unsigned char *) &stuff[1]; 5682f7df2e56Smrg for (i = 0; i < 6; i++) { 5683f7df2e56Smrg size = *((uint8_t *)str); 5684f7df2e56Smrg len = (str + size + 1) - ((unsigned char *) stuff); 5685f7df2e56Smrg if ((XkbPaddedSize(len) / 4) > stuff->length) 5686f7df2e56Smrg return BadLength; 5687f7df2e56Smrg str += (size + 1); 5688f7df2e56Smrg } 5689f7df2e56Smrg if ((XkbPaddedSize(len) / 4) != stuff->length) 5690f7df2e56Smrg return BadLength; 5691f7df2e56Smrg rep = (xkbListComponentsReply) { 5692f7df2e56Smrg .type = X_Reply, 5693f7df2e56Smrg .deviceID = dev->id, 5694f7df2e56Smrg .sequenceNumber = client->sequence, 5695f7df2e56Smrg .length = 0, 5696f7df2e56Smrg .nKeymaps = 0, 5697f7df2e56Smrg .nKeycodes = 0, 5698f7df2e56Smrg .nTypes = 0, 5699f7df2e56Smrg .nCompatMaps = 0, 5700f7df2e56Smrg .nSymbols = 0, 5701f7df2e56Smrg .nGeometries = 0, 5702f7df2e56Smrg .extra = 0 5703f7df2e56Smrg }; 570405b261ecSmrg if (client->swapped) { 5705f7df2e56Smrg swaps(&rep.sequenceNumber); 5706f7df2e56Smrg swapl(&rep.length); 5707f7df2e56Smrg swaps(&rep.nKeymaps); 5708f7df2e56Smrg swaps(&rep.nKeycodes); 5709f7df2e56Smrg swaps(&rep.nTypes); 5710f7df2e56Smrg swaps(&rep.nCompatMaps); 5711f7df2e56Smrg swaps(&rep.nSymbols); 5712f7df2e56Smrg swaps(&rep.nGeometries); 5713f7df2e56Smrg swaps(&rep.extra); 5714f7df2e56Smrg } 5715f7df2e56Smrg WriteToClient(client, SIZEOF(xkbListComponentsReply), &rep); 57166747b715Smrg return Success; 571705b261ecSmrg} 571805b261ecSmrg 571905b261ecSmrg/***====================================================================***/ 572005b261ecSmrgint 572105b261ecSmrgProcXkbGetKbdByName(ClientPtr client) 572205b261ecSmrg{ 5723f7df2e56Smrg DeviceIntPtr dev; 5724f7df2e56Smrg DeviceIntPtr tmpd; 5725f7df2e56Smrg DeviceIntPtr master; 5726f7df2e56Smrg xkbGetKbdByNameReply rep = { 0 }; 5727f7df2e56Smrg xkbGetMapReply mrep = { 0 }; 5728f7df2e56Smrg xkbGetCompatMapReply crep = { 0 }; 5729f7df2e56Smrg xkbGetIndicatorMapReply irep = { 0 }; 5730f7df2e56Smrg xkbGetNamesReply nrep = { 0 }; 5731f7df2e56Smrg xkbGetGeometryReply grep = { 0 }; 5732f7df2e56Smrg XkbComponentNamesRec names = { 0 }; 5733f7df2e56Smrg XkbDescPtr xkb, new; 5734f7df2e56Smrg XkbEventCauseRec cause; 5735f7df2e56Smrg unsigned char *str; 5736f7df2e56Smrg char mapFile[PATH_MAX]; 5737f7df2e56Smrg unsigned len; 5738f7df2e56Smrg unsigned fwant, fneed, reported; 5739f7df2e56Smrg int status; 5740f7df2e56Smrg Bool geom_changed; 5741f7df2e56Smrg XkbSrvLedInfoPtr old_sli; 5742f7df2e56Smrg XkbSrvLedInfoPtr sli; 57434642e01fSmrg Mask access_mode = DixGetAttrAccess | DixManageAccess; 574405b261ecSmrg 574505b261ecSmrg REQUEST(xkbGetKbdByNameReq); 574605b261ecSmrg REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq); 574705b261ecSmrg 5748f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 5749f7df2e56Smrg return BadAccess; 575005b261ecSmrg 57514642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode); 5752f7df2e56Smrg master = GetMaster(dev, MASTER_KEYBOARD); 575305b261ecSmrg 575405b261ecSmrg xkb = dev->key->xkbInfo->desc; 5755f7df2e56Smrg status = Success; 5756f7df2e56Smrg str = (unsigned char *) &stuff[1]; 5757f7df2e56Smrg if (GetComponentSpec(&str, TRUE, &status)) /* keymap, unsupported */ 57586747b715Smrg return BadMatch; 5759f7df2e56Smrg names.keycodes = GetComponentSpec(&str, TRUE, &status); 5760f7df2e56Smrg names.types = GetComponentSpec(&str, TRUE, &status); 5761f7df2e56Smrg names.compat = GetComponentSpec(&str, TRUE, &status); 5762f7df2e56Smrg names.symbols = GetComponentSpec(&str, TRUE, &status); 5763f7df2e56Smrg names.geometry = GetComponentSpec(&str, TRUE, &status); 5764f7df2e56Smrg if (status != Success) 5765f7df2e56Smrg return status; 5766f7df2e56Smrg len = str - ((unsigned char *) stuff); 5767f7df2e56Smrg if ((XkbPaddedSize(len) / 4) != stuff->length) 5768f7df2e56Smrg return BadLength; 5769f7df2e56Smrg 5770f7df2e56Smrg CHK_MASK_LEGAL(0x01, stuff->want, XkbGBN_AllComponentsMask); 5771f7df2e56Smrg CHK_MASK_LEGAL(0x02, stuff->need, XkbGBN_AllComponentsMask); 5772f7df2e56Smrg 577305b261ecSmrg if (stuff->load) 5774f7df2e56Smrg fwant = XkbGBN_AllComponentsMask; 5775f7df2e56Smrg else 5776f7df2e56Smrg fwant = stuff->want | stuff->need; 5777f7df2e56Smrg if ((!names.compat) && 5778f7df2e56Smrg (fwant & (XkbGBN_CompatMapMask | XkbGBN_IndicatorMapMask))) { 5779f7df2e56Smrg names.compat = Xstrdup("%"); 578005b261ecSmrg } 5781f7df2e56Smrg if ((!names.types) && (fwant & (XkbGBN_TypesMask))) { 5782f7df2e56Smrg names.types = Xstrdup("%"); 57834642e01fSmrg } 5784f7df2e56Smrg if ((!names.symbols) && (fwant & XkbGBN_SymbolsMask)) { 5785f7df2e56Smrg names.symbols = Xstrdup("%"); 57864642e01fSmrg } 5787f7df2e56Smrg geom_changed = ((names.geometry != NULL) && 5788f7df2e56Smrg (strcmp(names.geometry, "%") != 0)); 5789f7df2e56Smrg if ((!names.geometry) && (fwant & XkbGBN_GeometryMask)) { 5790f7df2e56Smrg names.geometry = Xstrdup("%"); 5791f7df2e56Smrg geom_changed = FALSE; 579205b261ecSmrg } 579305b261ecSmrg 57946747b715Smrg memset(mapFile, 0, PATH_MAX); 5795f7df2e56Smrg rep.type = X_Reply; 579605b261ecSmrg rep.deviceID = dev->id; 579705b261ecSmrg rep.sequenceNumber = client->sequence; 579805b261ecSmrg rep.length = 0; 579905b261ecSmrg rep.minKeyCode = xkb->min_key_code; 580005b261ecSmrg rep.maxKeyCode = xkb->max_key_code; 5801f7df2e56Smrg rep.loaded = FALSE; 5802f7df2e56Smrg fwant = 5803f7df2e56Smrg XkbConvertGetByNameComponents(TRUE, stuff->want) | XkmVirtualModsMask; 5804f7df2e56Smrg fneed = XkbConvertGetByNameComponents(TRUE, stuff->need); 5805f7df2e56Smrg rep.reported = XkbConvertGetByNameComponents(FALSE, fwant | fneed); 580605b261ecSmrg if (stuff->load) { 5807f7df2e56Smrg fneed |= XkmKeymapRequired; 5808f7df2e56Smrg fwant |= XkmKeymapLegal; 580905b261ecSmrg } 5810f7df2e56Smrg if ((fwant | fneed) & XkmSymbolsMask) { 5811f7df2e56Smrg fneed |= XkmKeyNamesIndex | XkmTypesIndex; 5812f7df2e56Smrg fwant |= XkmIndicatorsIndex; 581305b261ecSmrg } 581405b261ecSmrg 581505b261ecSmrg /* We pass dev in here so we can get the old names out if needed. */ 5816f7df2e56Smrg rep.found = XkbDDXLoadKeymapByNames(dev, &names, fwant, fneed, &new, 5817f7df2e56Smrg mapFile, PATH_MAX); 5818f7df2e56Smrg rep.newKeyboard = FALSE; 5819f7df2e56Smrg rep.pad1 = rep.pad2 = rep.pad3 = rep.pad4 = 0; 5820f7df2e56Smrg 5821f7df2e56Smrg stuff->want |= stuff->need; 5822f7df2e56Smrg if (new == NULL) 5823f7df2e56Smrg rep.reported = 0; 582405b261ecSmrg else { 5825f7df2e56Smrg if (stuff->load) 5826f7df2e56Smrg rep.loaded = TRUE; 5827f7df2e56Smrg if (stuff->load || 5828f7df2e56Smrg ((rep.reported & XkbGBN_SymbolsMask) && (new->compat))) { 5829f7df2e56Smrg XkbChangesRec changes; 5830f7df2e56Smrg 5831f7df2e56Smrg memset(&changes, 0, sizeof(changes)); 5832f7df2e56Smrg XkbUpdateDescActions(new, 5833f7df2e56Smrg new->min_key_code, XkbNumKeys(new), &changes); 5834f7df2e56Smrg } 583505b261ecSmrg 5836f7df2e56Smrg if (new->map == NULL) 5837f7df2e56Smrg rep.reported &= ~(XkbGBN_SymbolsMask | XkbGBN_TypesMask); 5838f7df2e56Smrg else if (rep.reported & (XkbGBN_SymbolsMask | XkbGBN_TypesMask)) { 5839f7df2e56Smrg mrep.type = X_Reply; 5840f7df2e56Smrg mrep.deviceID = dev->id; 5841f7df2e56Smrg mrep.sequenceNumber = client->sequence; 5842f7df2e56Smrg mrep.length = 5843f7df2e56Smrg ((SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply)) >> 2); 5844f7df2e56Smrg mrep.minKeyCode = new->min_key_code; 5845f7df2e56Smrg mrep.maxKeyCode = new->max_key_code; 5846f7df2e56Smrg mrep.present = 0; 5847f7df2e56Smrg mrep.totalSyms = mrep.totalActs = 5848f7df2e56Smrg mrep.totalKeyBehaviors = mrep.totalKeyExplicit = 5849f7df2e56Smrg mrep.totalModMapKeys = mrep.totalVModMapKeys = 0; 5850f7df2e56Smrg if (rep.reported & (XkbGBN_TypesMask | XkbGBN_ClientSymbolsMask)) { 5851f7df2e56Smrg mrep.present |= XkbKeyTypesMask; 5852f7df2e56Smrg mrep.firstType = 0; 5853f7df2e56Smrg mrep.nTypes = mrep.totalTypes = new->map->num_types; 5854f7df2e56Smrg } 5855f7df2e56Smrg else { 5856f7df2e56Smrg mrep.firstType = mrep.nTypes = 0; 5857f7df2e56Smrg mrep.totalTypes = 0; 5858f7df2e56Smrg } 5859f7df2e56Smrg if (rep.reported & XkbGBN_ClientSymbolsMask) { 5860f7df2e56Smrg mrep.present |= (XkbKeySymsMask | XkbModifierMapMask); 5861f7df2e56Smrg mrep.firstKeySym = mrep.firstModMapKey = new->min_key_code; 5862f7df2e56Smrg mrep.nKeySyms = mrep.nModMapKeys = XkbNumKeys(new); 5863f7df2e56Smrg } 5864f7df2e56Smrg else { 5865f7df2e56Smrg mrep.firstKeySym = mrep.firstModMapKey = 0; 5866f7df2e56Smrg mrep.nKeySyms = mrep.nModMapKeys = 0; 5867f7df2e56Smrg } 5868f7df2e56Smrg if (rep.reported & XkbGBN_ServerSymbolsMask) { 5869f7df2e56Smrg mrep.present |= XkbAllServerInfoMask; 5870f7df2e56Smrg mrep.virtualMods = ~0; 5871f7df2e56Smrg mrep.firstKeyAct = mrep.firstKeyBehavior = 5872f7df2e56Smrg mrep.firstKeyExplicit = new->min_key_code; 5873f7df2e56Smrg mrep.nKeyActs = mrep.nKeyBehaviors = 5874f7df2e56Smrg mrep.nKeyExplicit = XkbNumKeys(new); 5875f7df2e56Smrg mrep.firstVModMapKey = new->min_key_code; 5876f7df2e56Smrg mrep.nVModMapKeys = XkbNumKeys(new); 5877f7df2e56Smrg } 5878f7df2e56Smrg else { 5879f7df2e56Smrg mrep.virtualMods = 0; 5880f7df2e56Smrg mrep.firstKeyAct = mrep.firstKeyBehavior = 5881f7df2e56Smrg mrep.firstKeyExplicit = 0; 5882f7df2e56Smrg mrep.nKeyActs = mrep.nKeyBehaviors = mrep.nKeyExplicit = 0; 5883f7df2e56Smrg } 5884f7df2e56Smrg XkbComputeGetMapReplySize(new, &mrep); 5885f7df2e56Smrg rep.length += SIZEOF(xGenericReply) / 4 + mrep.length; 5886f7df2e56Smrg } 5887f7df2e56Smrg if (new->compat == NULL) 5888f7df2e56Smrg rep.reported &= ~XkbGBN_CompatMapMask; 5889f7df2e56Smrg else if (rep.reported & XkbGBN_CompatMapMask) { 5890f7df2e56Smrg crep.type = X_Reply; 5891f7df2e56Smrg crep.deviceID = dev->id; 5892f7df2e56Smrg crep.sequenceNumber = client->sequence; 5893f7df2e56Smrg crep.length = 0; 5894f7df2e56Smrg crep.groups = XkbAllGroupsMask; 5895f7df2e56Smrg crep.firstSI = 0; 5896f7df2e56Smrg crep.nSI = crep.nTotalSI = new->compat->num_si; 5897f7df2e56Smrg XkbComputeGetCompatMapReplySize(new->compat, &crep); 5898f7df2e56Smrg rep.length += SIZEOF(xGenericReply) / 4 + crep.length; 5899f7df2e56Smrg } 5900f7df2e56Smrg if (new->indicators == NULL) 5901f7df2e56Smrg rep.reported &= ~XkbGBN_IndicatorMapMask; 5902f7df2e56Smrg else if (rep.reported & XkbGBN_IndicatorMapMask) { 5903f7df2e56Smrg irep.type = X_Reply; 5904f7df2e56Smrg irep.deviceID = dev->id; 5905f7df2e56Smrg irep.sequenceNumber = client->sequence; 5906f7df2e56Smrg irep.length = 0; 5907f7df2e56Smrg irep.which = XkbAllIndicatorsMask; 5908f7df2e56Smrg XkbComputeGetIndicatorMapReplySize(new->indicators, &irep); 5909f7df2e56Smrg rep.length += SIZEOF(xGenericReply) / 4 + irep.length; 5910f7df2e56Smrg } 5911f7df2e56Smrg if (new->names == NULL) 5912f7df2e56Smrg rep.reported &= ~(XkbGBN_OtherNamesMask | XkbGBN_KeyNamesMask); 5913f7df2e56Smrg else if (rep.reported & (XkbGBN_OtherNamesMask | XkbGBN_KeyNamesMask)) { 5914f7df2e56Smrg nrep.type = X_Reply; 5915f7df2e56Smrg nrep.deviceID = dev->id; 5916f7df2e56Smrg nrep.sequenceNumber = client->sequence; 5917f7df2e56Smrg nrep.length = 0; 5918f7df2e56Smrg nrep.minKeyCode = new->min_key_code; 5919f7df2e56Smrg nrep.maxKeyCode = new->max_key_code; 5920f7df2e56Smrg if (rep.reported & XkbGBN_OtherNamesMask) { 5921f7df2e56Smrg nrep.which = XkbAllNamesMask; 5922f7df2e56Smrg if (new->map != NULL) 5923f7df2e56Smrg nrep.nTypes = new->map->num_types; 5924f7df2e56Smrg else 5925f7df2e56Smrg nrep.nTypes = 0; 5926f7df2e56Smrg nrep.nKTLevels = 0; 5927f7df2e56Smrg nrep.groupNames = XkbAllGroupsMask; 5928f7df2e56Smrg nrep.virtualMods = XkbAllVirtualModsMask; 5929f7df2e56Smrg nrep.indicators = XkbAllIndicatorsMask; 5930f7df2e56Smrg nrep.nRadioGroups = new->names->num_rg; 5931f7df2e56Smrg } 5932f7df2e56Smrg else { 5933f7df2e56Smrg nrep.which = 0; 5934f7df2e56Smrg nrep.nTypes = 0; 5935f7df2e56Smrg nrep.nKTLevels = 0; 5936f7df2e56Smrg nrep.groupNames = 0; 5937f7df2e56Smrg nrep.virtualMods = 0; 5938f7df2e56Smrg nrep.indicators = 0; 5939f7df2e56Smrg nrep.nRadioGroups = 0; 5940f7df2e56Smrg } 5941f7df2e56Smrg if (rep.reported & XkbGBN_KeyNamesMask) { 5942f7df2e56Smrg nrep.which |= XkbKeyNamesMask; 5943f7df2e56Smrg nrep.firstKey = new->min_key_code; 5944f7df2e56Smrg nrep.nKeys = XkbNumKeys(new); 5945f7df2e56Smrg nrep.nKeyAliases = new->names->num_key_aliases; 5946f7df2e56Smrg if (nrep.nKeyAliases) 5947f7df2e56Smrg nrep.which |= XkbKeyAliasesMask; 5948f7df2e56Smrg } 5949f7df2e56Smrg else { 5950f7df2e56Smrg nrep.which &= ~(XkbKeyNamesMask | XkbKeyAliasesMask); 5951f7df2e56Smrg nrep.firstKey = nrep.nKeys = 0; 5952f7df2e56Smrg nrep.nKeyAliases = 0; 5953f7df2e56Smrg } 5954f7df2e56Smrg XkbComputeGetNamesReplySize(new, &nrep); 5955f7df2e56Smrg rep.length += SIZEOF(xGenericReply) / 4 + nrep.length; 5956f7df2e56Smrg } 5957f7df2e56Smrg if (new->geom == NULL) 5958f7df2e56Smrg rep.reported &= ~XkbGBN_GeometryMask; 5959f7df2e56Smrg else if (rep.reported & XkbGBN_GeometryMask) { 5960f7df2e56Smrg grep.type = X_Reply; 5961f7df2e56Smrg grep.deviceID = dev->id; 5962f7df2e56Smrg grep.sequenceNumber = client->sequence; 5963f7df2e56Smrg grep.length = 0; 5964f7df2e56Smrg grep.found = TRUE; 5965f7df2e56Smrg grep.pad = 0; 5966f7df2e56Smrg grep.widthMM = grep.heightMM = 0; 5967f7df2e56Smrg grep.nProperties = grep.nColors = grep.nShapes = 0; 5968f7df2e56Smrg grep.nSections = grep.nDoodads = 0; 5969f7df2e56Smrg grep.baseColorNdx = grep.labelColorNdx = 0; 5970f7df2e56Smrg XkbComputeGetGeometryReplySize(new->geom, &grep, None); 5971f7df2e56Smrg rep.length += SIZEOF(xGenericReply) / 4 + grep.length; 5972f7df2e56Smrg } 5973f7df2e56Smrg } 5974f7df2e56Smrg 5975f7df2e56Smrg reported = rep.reported; 5976f7df2e56Smrg if (client->swapped) { 5977f7df2e56Smrg swaps(&rep.sequenceNumber); 5978f7df2e56Smrg swapl(&rep.length); 5979f7df2e56Smrg swaps(&rep.found); 5980f7df2e56Smrg swaps(&rep.reported); 5981f7df2e56Smrg } 5982f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetKbdByNameReply), &rep); 5983f7df2e56Smrg if (reported & (XkbGBN_SymbolsMask | XkbGBN_TypesMask)) 5984f7df2e56Smrg XkbSendMap(client, new, &mrep); 5985f7df2e56Smrg if (reported & XkbGBN_CompatMapMask) 5986f7df2e56Smrg XkbSendCompatMap(client, new->compat, &crep); 5987f7df2e56Smrg if (reported & XkbGBN_IndicatorMapMask) 5988f7df2e56Smrg XkbSendIndicatorMap(client, new->indicators, &irep); 5989f7df2e56Smrg if (reported & (XkbGBN_KeyNamesMask | XkbGBN_OtherNamesMask)) 5990f7df2e56Smrg XkbSendNames(client, new, &nrep); 5991f7df2e56Smrg if (reported & XkbGBN_GeometryMask) 5992f7df2e56Smrg XkbSendGeometry(client, new->geom, &grep, FALSE); 5993f7df2e56Smrg if (rep.loaded) { 5994f7df2e56Smrg XkbDescPtr old_xkb; 5995f7df2e56Smrg xkbNewKeyboardNotify nkn; 5996f7df2e56Smrg 5997f7df2e56Smrg old_xkb = xkb; 5998f7df2e56Smrg xkb = new; 5999f7df2e56Smrg dev->key->xkbInfo->desc = xkb; 6000f7df2e56Smrg new = old_xkb; /* so it'll get freed automatically */ 6001f7df2e56Smrg 6002f7df2e56Smrg XkbCopyControls(xkb, old_xkb); 6003f7df2e56Smrg 6004f7df2e56Smrg nkn.deviceID = nkn.oldDeviceID = dev->id; 6005f7df2e56Smrg nkn.minKeyCode = new->min_key_code; 6006f7df2e56Smrg nkn.maxKeyCode = new->max_key_code; 6007f7df2e56Smrg nkn.oldMinKeyCode = xkb->min_key_code; 6008f7df2e56Smrg nkn.oldMaxKeyCode = xkb->max_key_code; 6009f7df2e56Smrg nkn.requestMajor = XkbReqCode; 6010f7df2e56Smrg nkn.requestMinor = X_kbGetKbdByName; 6011f7df2e56Smrg nkn.changed = XkbNKN_KeycodesMask; 6012f7df2e56Smrg if (geom_changed) 6013f7df2e56Smrg nkn.changed |= XkbNKN_GeometryMask; 6014f7df2e56Smrg XkbSendNewKeyboardNotify(dev, &nkn); 6015f7df2e56Smrg 6016f7df2e56Smrg /* Update the map and LED info on the device itself, as well as 6017f7df2e56Smrg * any slaves if it's an MD, or its MD if it's an SD and was the 6018f7df2e56Smrg * last device used on that MD. */ 601905b261ecSmrg for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) { 6020f7df2e56Smrg if (tmpd != dev && GetMaster(tmpd, MASTER_KEYBOARD) != dev && 6021f7df2e56Smrg (tmpd != master || dev != master->lastSlave)) 6022f7df2e56Smrg continue; 6023f7df2e56Smrg 6024f7df2e56Smrg if (tmpd != dev) 6025f7df2e56Smrg XkbDeviceApplyKeymap(tmpd, xkb); 6026f7df2e56Smrg 6027f7df2e56Smrg if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) { 6028f7df2e56Smrg old_sli = tmpd->kbdfeed->xkb_sli; 6029f7df2e56Smrg tmpd->kbdfeed->xkb_sli = NULL; 6030f7df2e56Smrg sli = XkbAllocSrvLedInfo(tmpd, tmpd->kbdfeed, NULL, 0); 6031f7df2e56Smrg if (sli) { 6032f7df2e56Smrg sli->explicitState = old_sli->explicitState; 6033f7df2e56Smrg sli->effectiveState = old_sli->effectiveState; 603405b261ecSmrg } 6035f7df2e56Smrg tmpd->kbdfeed->xkb_sli = sli; 6036f7df2e56Smrg XkbFreeSrvLedInfo(old_sli); 603705b261ecSmrg } 603805b261ecSmrg } 6039f7df2e56Smrg } 6040f7df2e56Smrg if ((new != NULL) && (new != xkb)) { 6041f7df2e56Smrg XkbFreeKeyboard(new, XkbAllComponentsMask, TRUE); 6042f7df2e56Smrg new = NULL; 604305b261ecSmrg } 60449ace9065Smrg XkbFreeComponentNames(&names, FALSE); 6045f7df2e56Smrg XkbSetCauseXkbReq(&cause, X_kbGetKbdByName, client); 6046f7df2e56Smrg XkbUpdateAllDeviceIndicators(NULL, &cause); 6047f7df2e56Smrg 60486747b715Smrg return Success; 604905b261ecSmrg} 605005b261ecSmrg 605105b261ecSmrg/***====================================================================***/ 605205b261ecSmrg 605305b261ecSmrgstatic int 6054f7df2e56SmrgComputeDeviceLedInfoSize(DeviceIntPtr dev, 6055f7df2e56Smrg unsigned int what, XkbSrvLedInfoPtr sli) 605605b261ecSmrg{ 6057f7df2e56Smrg int nNames, nMaps; 6058f7df2e56Smrg register unsigned n, bit; 6059f7df2e56Smrg 6060f7df2e56Smrg if (sli == NULL) 6061f7df2e56Smrg return 0; 6062f7df2e56Smrg nNames = nMaps = 0; 6063f7df2e56Smrg if ((what & XkbXI_IndicatorNamesMask) == 0) 6064f7df2e56Smrg sli->namesPresent = 0; 6065f7df2e56Smrg if ((what & XkbXI_IndicatorMapsMask) == 0) 6066f7df2e56Smrg sli->mapsPresent = 0; 6067f7df2e56Smrg 6068f7df2e56Smrg for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) { 6069f7df2e56Smrg if (sli->names && sli->names[n] != None) { 6070f7df2e56Smrg sli->namesPresent |= bit; 6071f7df2e56Smrg nNames++; 6072f7df2e56Smrg } 6073f7df2e56Smrg if (sli->maps && XkbIM_InUse(&sli->maps[n])) { 6074f7df2e56Smrg sli->mapsPresent |= bit; 6075f7df2e56Smrg nMaps++; 6076f7df2e56Smrg } 6077f7df2e56Smrg } 6078f7df2e56Smrg return (nNames * 4) + (nMaps * SIZEOF(xkbIndicatorMapWireDesc)); 607905b261ecSmrg} 608005b261ecSmrg 6081f7df2e56Smrgstatic int 6082f7df2e56SmrgCheckDeviceLedFBs(DeviceIntPtr dev, 6083f7df2e56Smrg int class, 6084f7df2e56Smrg int id, xkbGetDeviceInfoReply * rep, ClientPtr client) 608505b261ecSmrg{ 6086f7df2e56Smrg int nFBs = 0; 6087f7df2e56Smrg int length = 0; 6088f7df2e56Smrg Bool classOk; 6089f7df2e56Smrg 6090f7df2e56Smrg if (class == XkbDfltXIClass) { 6091f7df2e56Smrg if (dev->kbdfeed) 6092f7df2e56Smrg class = KbdFeedbackClass; 6093f7df2e56Smrg else if (dev->leds) 6094f7df2e56Smrg class = LedFeedbackClass; 6095f7df2e56Smrg else { 6096f7df2e56Smrg client->errorValue = _XkbErrCode2(XkbErr_BadClass, class); 6097f7df2e56Smrg return XkbKeyboardErrorCode; 6098f7df2e56Smrg } 6099f7df2e56Smrg } 6100f7df2e56Smrg classOk = FALSE; 6101f7df2e56Smrg if ((dev->kbdfeed) && 6102f7df2e56Smrg ((class == KbdFeedbackClass) || (class == XkbAllXIClasses))) { 6103f7df2e56Smrg KbdFeedbackPtr kf; 6104f7df2e56Smrg 6105f7df2e56Smrg classOk = TRUE; 6106f7df2e56Smrg for (kf = dev->kbdfeed; (kf); kf = kf->next) { 6107f7df2e56Smrg if ((id != XkbAllXIIds) && (id != XkbDfltXIId) && 6108f7df2e56Smrg (id != kf->ctrl.id)) 6109f7df2e56Smrg continue; 6110f7df2e56Smrg nFBs++; 6111f7df2e56Smrg length += SIZEOF(xkbDeviceLedsWireDesc); 6112f7df2e56Smrg if (!kf->xkb_sli) 6113f7df2e56Smrg kf->xkb_sli = XkbAllocSrvLedInfo(dev, kf, NULL, 0); 6114f7df2e56Smrg length += ComputeDeviceLedInfoSize(dev, rep->present, kf->xkb_sli); 6115f7df2e56Smrg if (id != XkbAllXIIds) 6116f7df2e56Smrg break; 6117f7df2e56Smrg } 6118f7df2e56Smrg } 6119f7df2e56Smrg if ((dev->leds) && 6120f7df2e56Smrg ((class == LedFeedbackClass) || (class == XkbAllXIClasses))) { 6121f7df2e56Smrg LedFeedbackPtr lf; 6122f7df2e56Smrg 6123f7df2e56Smrg classOk = TRUE; 6124f7df2e56Smrg for (lf = dev->leds; (lf); lf = lf->next) { 6125f7df2e56Smrg if ((id != XkbAllXIIds) && (id != XkbDfltXIId) && 6126f7df2e56Smrg (id != lf->ctrl.id)) 6127f7df2e56Smrg continue; 6128f7df2e56Smrg nFBs++; 6129f7df2e56Smrg length += SIZEOF(xkbDeviceLedsWireDesc); 6130f7df2e56Smrg if (!lf->xkb_sli) 6131f7df2e56Smrg lf->xkb_sli = XkbAllocSrvLedInfo(dev, NULL, lf, 0); 6132f7df2e56Smrg length += ComputeDeviceLedInfoSize(dev, rep->present, lf->xkb_sli); 6133f7df2e56Smrg if (id != XkbAllXIIds) 6134f7df2e56Smrg break; 6135f7df2e56Smrg } 6136f7df2e56Smrg } 6137f7df2e56Smrg if (nFBs > 0) { 6138f7df2e56Smrg rep->nDeviceLedFBs = nFBs; 6139f7df2e56Smrg rep->length += (length / 4); 6140f7df2e56Smrg return Success; 6141f7df2e56Smrg } 6142f7df2e56Smrg if (classOk) 6143f7df2e56Smrg client->errorValue = _XkbErrCode2(XkbErr_BadId, id); 6144f7df2e56Smrg else 6145f7df2e56Smrg client->errorValue = _XkbErrCode2(XkbErr_BadClass, class); 614605b261ecSmrg return XkbKeyboardErrorCode; 614705b261ecSmrg} 614805b261ecSmrg 614905b261ecSmrgstatic int 6150f7df2e56SmrgSendDeviceLedInfo(XkbSrvLedInfoPtr sli, ClientPtr client) 615105b261ecSmrg{ 6152f7df2e56Smrg xkbDeviceLedsWireDesc wire; 6153f7df2e56Smrg int length; 6154f7df2e56Smrg 6155f7df2e56Smrg length = 0; 6156f7df2e56Smrg wire.ledClass = sli->class; 6157f7df2e56Smrg wire.ledID = sli->id; 6158f7df2e56Smrg wire.namesPresent = sli->namesPresent; 6159f7df2e56Smrg wire.mapsPresent = sli->mapsPresent; 6160f7df2e56Smrg wire.physIndicators = sli->physIndicators; 6161f7df2e56Smrg wire.state = sli->effectiveState; 616205b261ecSmrg if (client->swapped) { 6163f7df2e56Smrg swaps(&wire.ledClass); 6164f7df2e56Smrg swaps(&wire.ledID); 6165f7df2e56Smrg swapl(&wire.namesPresent); 6166f7df2e56Smrg swapl(&wire.mapsPresent); 6167f7df2e56Smrg swapl(&wire.physIndicators); 6168f7df2e56Smrg swapl(&wire.state); 6169f7df2e56Smrg } 6170f7df2e56Smrg WriteToClient(client, SIZEOF(xkbDeviceLedsWireDesc), &wire); 6171f7df2e56Smrg length += SIZEOF(xkbDeviceLedsWireDesc); 6172f7df2e56Smrg if (sli->namesPresent | sli->mapsPresent) { 6173f7df2e56Smrg register unsigned i, bit; 6174f7df2e56Smrg 6175f7df2e56Smrg if (sli->namesPresent) { 6176f7df2e56Smrg CARD32 awire; 6177f7df2e56Smrg 6178f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 6179f7df2e56Smrg if (sli->namesPresent & bit) { 6180f7df2e56Smrg awire = (CARD32) sli->names[i]; 6181f7df2e56Smrg if (client->swapped) { 6182f7df2e56Smrg swapl(&awire); 6183f7df2e56Smrg } 6184f7df2e56Smrg WriteToClient(client, 4, &awire); 6185f7df2e56Smrg length += 4; 6186f7df2e56Smrg } 6187f7df2e56Smrg } 6188f7df2e56Smrg } 6189f7df2e56Smrg if (sli->mapsPresent) { 6190f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 6191f7df2e56Smrg xkbIndicatorMapWireDesc iwire; 6192f7df2e56Smrg 6193f7df2e56Smrg if (sli->mapsPresent & bit) { 6194f7df2e56Smrg iwire.flags = sli->maps[i].flags; 6195f7df2e56Smrg iwire.whichGroups = sli->maps[i].which_groups; 6196f7df2e56Smrg iwire.groups = sli->maps[i].groups; 6197f7df2e56Smrg iwire.whichMods = sli->maps[i].which_mods; 6198f7df2e56Smrg iwire.mods = sli->maps[i].mods.mask; 6199f7df2e56Smrg iwire.realMods = sli->maps[i].mods.real_mods; 6200f7df2e56Smrg iwire.virtualMods = sli->maps[i].mods.vmods; 6201f7df2e56Smrg iwire.ctrls = sli->maps[i].ctrls; 6202f7df2e56Smrg if (client->swapped) { 6203f7df2e56Smrg swaps(&iwire.virtualMods); 6204f7df2e56Smrg swapl(&iwire.ctrls); 6205f7df2e56Smrg } 6206f7df2e56Smrg WriteToClient(client, SIZEOF(xkbIndicatorMapWireDesc), 6207f7df2e56Smrg &iwire); 6208f7df2e56Smrg length += SIZEOF(xkbIndicatorMapWireDesc); 6209f7df2e56Smrg } 6210f7df2e56Smrg } 6211f7df2e56Smrg } 621205b261ecSmrg } 621305b261ecSmrg return length; 621405b261ecSmrg} 621505b261ecSmrg 621605b261ecSmrgstatic int 6217f7df2e56SmrgSendDeviceLedFBs(DeviceIntPtr dev, 6218f7df2e56Smrg int class, int id, unsigned wantLength, ClientPtr client) 621905b261ecSmrg{ 6220f7df2e56Smrg int length = 0; 6221f7df2e56Smrg 6222f7df2e56Smrg if (class == XkbDfltXIClass) { 6223f7df2e56Smrg if (dev->kbdfeed) 6224f7df2e56Smrg class = KbdFeedbackClass; 6225f7df2e56Smrg else if (dev->leds) 6226f7df2e56Smrg class = LedFeedbackClass; 6227f7df2e56Smrg } 6228f7df2e56Smrg if ((dev->kbdfeed) && 6229f7df2e56Smrg ((class == KbdFeedbackClass) || (class == XkbAllXIClasses))) { 6230f7df2e56Smrg KbdFeedbackPtr kf; 6231f7df2e56Smrg 6232f7df2e56Smrg for (kf = dev->kbdfeed; (kf); kf = kf->next) { 6233f7df2e56Smrg if ((id == XkbAllXIIds) || (id == XkbDfltXIId) || 6234f7df2e56Smrg (id == kf->ctrl.id)) { 6235f7df2e56Smrg length += SendDeviceLedInfo(kf->xkb_sli, client); 6236f7df2e56Smrg if (id != XkbAllXIIds) 6237f7df2e56Smrg break; 6238f7df2e56Smrg } 6239f7df2e56Smrg } 6240f7df2e56Smrg } 6241f7df2e56Smrg if ((dev->leds) && 6242f7df2e56Smrg ((class == LedFeedbackClass) || (class == XkbAllXIClasses))) { 6243f7df2e56Smrg LedFeedbackPtr lf; 6244f7df2e56Smrg 6245f7df2e56Smrg for (lf = dev->leds; (lf); lf = lf->next) { 6246f7df2e56Smrg if ((id == XkbAllXIIds) || (id == XkbDfltXIId) || 6247f7df2e56Smrg (id == lf->ctrl.id)) { 6248f7df2e56Smrg length += SendDeviceLedInfo(lf->xkb_sli, client); 6249f7df2e56Smrg if (id != XkbAllXIIds) 6250f7df2e56Smrg break; 6251f7df2e56Smrg } 6252f7df2e56Smrg } 6253f7df2e56Smrg } 6254f7df2e56Smrg if (length == wantLength) 6255f7df2e56Smrg return Success; 6256f7df2e56Smrg else 6257f7df2e56Smrg return BadLength; 625805b261ecSmrg} 625905b261ecSmrg 626005b261ecSmrgint 626105b261ecSmrgProcXkbGetDeviceInfo(ClientPtr client) 626205b261ecSmrg{ 6263f7df2e56Smrg DeviceIntPtr dev; 6264f7df2e56Smrg xkbGetDeviceInfoReply rep; 6265f7df2e56Smrg int status, nDeviceLedFBs; 6266f7df2e56Smrg unsigned length, nameLen; 6267f7df2e56Smrg CARD16 ledClass, ledID; 6268f7df2e56Smrg unsigned wanted; 6269f7df2e56Smrg char *str; 627005b261ecSmrg 627105b261ecSmrg REQUEST(xkbGetDeviceInfoReq); 627205b261ecSmrg REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq); 627305b261ecSmrg 6274f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 6275f7df2e56Smrg return BadAccess; 627605b261ecSmrg 6277f7df2e56Smrg wanted = stuff->wanted; 627805b261ecSmrg 62794642e01fSmrg CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); 6280f7df2e56Smrg CHK_MASK_LEGAL(0x01, wanted, XkbXI_AllDeviceFeaturesMask); 6281f7df2e56Smrg 6282f7df2e56Smrg if ((!dev->button) || ((stuff->nBtns < 1) && (!stuff->allBtns))) 6283f7df2e56Smrg wanted &= ~XkbXI_ButtonActionsMask; 6284f7df2e56Smrg if ((!dev->kbdfeed) && (!dev->leds)) 6285f7df2e56Smrg wanted &= ~XkbXI_IndicatorsMask; 6286f7df2e56Smrg 6287f7df2e56Smrg nameLen = XkbSizeCountedString(dev->name); 6288f7df2e56Smrg rep = (xkbGetDeviceInfoReply) { 6289f7df2e56Smrg .type = X_Reply, 6290f7df2e56Smrg .deviceID = dev->id, 6291f7df2e56Smrg .sequenceNumber = client->sequence, 6292f7df2e56Smrg .length = nameLen / 4, 6293f7df2e56Smrg .present = wanted, 6294f7df2e56Smrg .supported = XkbXI_AllDeviceFeaturesMask, 6295f7df2e56Smrg .unsupported = 0, 6296f7df2e56Smrg .nDeviceLedFBs = 0, 6297f7df2e56Smrg .firstBtnWanted = 0, 6298f7df2e56Smrg .nBtnsWanted = 0, 6299f7df2e56Smrg .firstBtnRtrn = 0, 6300f7df2e56Smrg .nBtnsRtrn = 0, 6301f7df2e56Smrg .totalBtns = dev->button ? dev->button->numButtons : 0, 6302f7df2e56Smrg .hasOwnState = (dev->key && dev->key->xkbInfo), 6303f7df2e56Smrg .dfltKbdFB = dev->kbdfeed ? dev->kbdfeed->ctrl.id : XkbXINone, 6304f7df2e56Smrg .dfltLedFB = dev->leds ? dev->leds->ctrl.id : XkbXINone, 6305f7df2e56Smrg .devType = dev->xinput_type 6306f7df2e56Smrg }; 6307f7df2e56Smrg 6308f7df2e56Smrg ledClass = stuff->ledClass; 6309f7df2e56Smrg ledID = stuff->ledID; 6310f7df2e56Smrg 6311f7df2e56Smrg if (wanted & XkbXI_ButtonActionsMask) { 6312f7df2e56Smrg if (stuff->allBtns) { 6313f7df2e56Smrg stuff->firstBtn = 0; 6314f7df2e56Smrg stuff->nBtns = dev->button->numButtons; 6315f7df2e56Smrg } 631605b261ecSmrg 6317f7df2e56Smrg if ((stuff->firstBtn + stuff->nBtns) > dev->button->numButtons) { 6318f7df2e56Smrg client->errorValue = _XkbErrCode4(0x02, dev->button->numButtons, 6319f7df2e56Smrg stuff->firstBtn, stuff->nBtns); 6320f7df2e56Smrg return BadValue; 6321f7df2e56Smrg } 6322f7df2e56Smrg else { 6323f7df2e56Smrg rep.firstBtnWanted = stuff->firstBtn; 6324f7df2e56Smrg rep.nBtnsWanted = stuff->nBtns; 6325f7df2e56Smrg if (dev->button->xkb_acts != NULL) { 6326f7df2e56Smrg XkbAction *act; 6327f7df2e56Smrg register int i; 6328f7df2e56Smrg 6329f7df2e56Smrg rep.firstBtnRtrn = stuff->firstBtn; 6330f7df2e56Smrg rep.nBtnsRtrn = stuff->nBtns; 6331f7df2e56Smrg act = &dev->button->xkb_acts[rep.firstBtnWanted]; 6332f7df2e56Smrg for (i = 0; i < rep.nBtnsRtrn; i++, act++) { 6333f7df2e56Smrg if (act->type != XkbSA_NoAction) 6334f7df2e56Smrg break; 6335f7df2e56Smrg } 6336f7df2e56Smrg rep.firstBtnRtrn += i; 6337f7df2e56Smrg rep.nBtnsRtrn -= i; 6338f7df2e56Smrg act = 6339f7df2e56Smrg &dev->button->xkb_acts[rep.firstBtnRtrn + rep.nBtnsRtrn - 6340f7df2e56Smrg 1]; 6341f7df2e56Smrg for (i = 0; i < rep.nBtnsRtrn; i++, act--) { 6342f7df2e56Smrg if (act->type != XkbSA_NoAction) 6343f7df2e56Smrg break; 6344f7df2e56Smrg } 6345f7df2e56Smrg rep.nBtnsRtrn -= i; 6346f7df2e56Smrg } 6347f7df2e56Smrg rep.length += (rep.nBtnsRtrn * SIZEOF(xkbActionWireDesc)) / 4; 6348f7df2e56Smrg } 6349f7df2e56Smrg } 635005b261ecSmrg 6351f7df2e56Smrg if (wanted & XkbXI_IndicatorsMask) { 6352f7df2e56Smrg status = CheckDeviceLedFBs(dev, ledClass, ledID, &rep, client); 6353f7df2e56Smrg if (status != Success) 6354f7df2e56Smrg return status; 6355f7df2e56Smrg } 6356f7df2e56Smrg length = rep.length * 4; 635705b261ecSmrg nDeviceLedFBs = rep.nDeviceLedFBs; 635805b261ecSmrg if (client->swapped) { 6359f7df2e56Smrg swaps(&rep.sequenceNumber); 6360f7df2e56Smrg swapl(&rep.length); 6361f7df2e56Smrg swaps(&rep.present); 6362f7df2e56Smrg swaps(&rep.supported); 6363f7df2e56Smrg swaps(&rep.unsupported); 6364f7df2e56Smrg swaps(&rep.nDeviceLedFBs); 6365f7df2e56Smrg swaps(&rep.dfltKbdFB); 6366f7df2e56Smrg swaps(&rep.dfltLedFB); 6367f7df2e56Smrg swapl(&rep.devType); 6368f7df2e56Smrg } 6369f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetDeviceInfoReply), &rep); 6370f7df2e56Smrg 6371f7df2e56Smrg str = malloc(nameLen); 6372f7df2e56Smrg if (!str) 6373f7df2e56Smrg return BadAlloc; 6374f7df2e56Smrg XkbWriteCountedString(str, dev->name, client->swapped); 6375f7df2e56Smrg WriteToClient(client, nameLen, str); 63766747b715Smrg free(str); 6377f7df2e56Smrg length -= nameLen; 6378f7df2e56Smrg 6379f7df2e56Smrg if (rep.nBtnsRtrn > 0) { 6380f7df2e56Smrg int sz; 6381f7df2e56Smrg xkbActionWireDesc *awire; 6382f7df2e56Smrg 6383f7df2e56Smrg sz = rep.nBtnsRtrn * SIZEOF(xkbActionWireDesc); 6384f7df2e56Smrg awire = (xkbActionWireDesc *) &dev->button->xkb_acts[rep.firstBtnRtrn]; 6385f7df2e56Smrg WriteToClient(client, sz, awire); 6386f7df2e56Smrg length -= sz; 6387f7df2e56Smrg } 6388f7df2e56Smrg if (nDeviceLedFBs > 0) { 6389f7df2e56Smrg status = SendDeviceLedFBs(dev, ledClass, ledID, length, client); 6390f7df2e56Smrg if (status != Success) 6391f7df2e56Smrg return status; 6392f7df2e56Smrg } 6393f7df2e56Smrg else if (length != 0) { 6394f7df2e56Smrg ErrorF("[xkb] Internal Error! BadLength in ProcXkbGetDeviceInfo\n"); 6395f7df2e56Smrg ErrorF("[xkb] Wrote %d fewer bytes than expected\n", 6396f7df2e56Smrg length); 6397f7df2e56Smrg return BadLength; 639805b261ecSmrg } 63996747b715Smrg return Success; 640005b261ecSmrg} 640105b261ecSmrg 640205b261ecSmrgstatic char * 6403f7df2e56SmrgCheckSetDeviceIndicators(char *wire, 6404f7df2e56Smrg DeviceIntPtr dev, 6405f7df2e56Smrg int num, int *status_rtrn, ClientPtr client) 640605b261ecSmrg{ 6407f7df2e56Smrg xkbDeviceLedsWireDesc *ledWire; 6408f7df2e56Smrg int i; 6409f7df2e56Smrg XkbSrvLedInfoPtr sli; 6410f7df2e56Smrg 6411f7df2e56Smrg ledWire = (xkbDeviceLedsWireDesc *) wire; 6412f7df2e56Smrg for (i = 0; i < num; i++) { 6413f7df2e56Smrg if (client->swapped) { 6414f7df2e56Smrg swaps(&ledWire->ledClass); 6415f7df2e56Smrg swaps(&ledWire->ledID); 6416f7df2e56Smrg swapl(&ledWire->namesPresent); 6417f7df2e56Smrg swapl(&ledWire->mapsPresent); 6418f7df2e56Smrg swapl(&ledWire->physIndicators); 6419f7df2e56Smrg } 6420f7df2e56Smrg 6421f7df2e56Smrg sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID, 6422f7df2e56Smrg XkbXI_IndicatorsMask); 6423f7df2e56Smrg if (sli != NULL) { 6424f7df2e56Smrg register int n; 6425f7df2e56Smrg register unsigned bit; 6426f7df2e56Smrg int nMaps, nNames; 6427f7df2e56Smrg CARD32 *atomWire; 6428f7df2e56Smrg xkbIndicatorMapWireDesc *mapWire; 6429f7df2e56Smrg 6430f7df2e56Smrg nMaps = nNames = 0; 6431f7df2e56Smrg for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) { 6432f7df2e56Smrg if (ledWire->namesPresent & bit) 6433f7df2e56Smrg nNames++; 6434f7df2e56Smrg if (ledWire->mapsPresent & bit) 6435f7df2e56Smrg nMaps++; 6436f7df2e56Smrg } 6437f7df2e56Smrg atomWire = (CARD32 *) &ledWire[1]; 6438f7df2e56Smrg if (nNames > 0) { 6439f7df2e56Smrg for (n = 0; n < nNames; n++) { 6440f7df2e56Smrg if (client->swapped) { 6441f7df2e56Smrg swapl(atomWire); 6442f7df2e56Smrg } 6443f7df2e56Smrg CHK_ATOM_OR_NONE3(((Atom) (*atomWire)), client->errorValue, 6444f7df2e56Smrg *status_rtrn, NULL); 6445f7df2e56Smrg atomWire++; 6446f7df2e56Smrg } 6447f7df2e56Smrg } 6448f7df2e56Smrg mapWire = (xkbIndicatorMapWireDesc *) atomWire; 6449f7df2e56Smrg if (nMaps > 0) { 6450f7df2e56Smrg for (n = 0; n < nMaps; n++) { 6451f7df2e56Smrg if (client->swapped) { 6452f7df2e56Smrg swaps(&mapWire->virtualMods); 6453f7df2e56Smrg swapl(&mapWire->ctrls); 6454f7df2e56Smrg } 6455f7df2e56Smrg CHK_MASK_LEGAL3(0x21, mapWire->whichGroups, 6456f7df2e56Smrg XkbIM_UseAnyGroup, 6457f7df2e56Smrg client->errorValue, *status_rtrn, NULL); 6458f7df2e56Smrg CHK_MASK_LEGAL3(0x22, mapWire->whichMods, XkbIM_UseAnyMods, 6459f7df2e56Smrg client->errorValue, *status_rtrn, NULL); 6460f7df2e56Smrg mapWire++; 6461f7df2e56Smrg } 6462f7df2e56Smrg } 6463f7df2e56Smrg ledWire = (xkbDeviceLedsWireDesc *) mapWire; 6464f7df2e56Smrg } 6465f7df2e56Smrg else { 6466f7df2e56Smrg /* SHOULD NEVER HAPPEN */ 6467f7df2e56Smrg return (char *) ledWire; 6468f7df2e56Smrg } 6469f7df2e56Smrg } 6470f7df2e56Smrg return (char *) ledWire; 647105b261ecSmrg} 647205b261ecSmrg 647305b261ecSmrgstatic char * 6474f7df2e56SmrgSetDeviceIndicators(char *wire, 6475f7df2e56Smrg DeviceIntPtr dev, 6476f7df2e56Smrg unsigned changed, 6477f7df2e56Smrg int num, 6478f7df2e56Smrg int *status_rtrn, 6479f7df2e56Smrg ClientPtr client, xkbExtensionDeviceNotify * ev) 648005b261ecSmrg{ 6481f7df2e56Smrg xkbDeviceLedsWireDesc *ledWire; 6482f7df2e56Smrg int i; 6483f7df2e56Smrg XkbEventCauseRec cause; 6484f7df2e56Smrg unsigned namec, mapc, statec; 6485f7df2e56Smrg xkbExtensionDeviceNotify ed; 6486f7df2e56Smrg XkbChangesRec changes; 6487f7df2e56Smrg DeviceIntPtr kbd; 6488f7df2e56Smrg 6489f7df2e56Smrg memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify)); 6490f7df2e56Smrg memset((char *) &changes, 0, sizeof(XkbChangesRec)); 6491f7df2e56Smrg XkbSetCauseXkbReq(&cause, X_kbSetDeviceInfo, client); 6492f7df2e56Smrg ledWire = (xkbDeviceLedsWireDesc *) wire; 6493f7df2e56Smrg for (i = 0; i < num; i++) { 6494f7df2e56Smrg register int n; 6495f7df2e56Smrg register unsigned bit; 6496f7df2e56Smrg CARD32 *atomWire; 6497f7df2e56Smrg xkbIndicatorMapWireDesc *mapWire; 6498f7df2e56Smrg XkbSrvLedInfoPtr sli; 6499f7df2e56Smrg 6500f7df2e56Smrg namec = mapc = statec = 0; 6501f7df2e56Smrg sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID, 6502f7df2e56Smrg XkbXI_IndicatorMapsMask); 6503f7df2e56Smrg if (!sli) { 6504f7df2e56Smrg /* SHOULD NEVER HAPPEN!! */ 6505f7df2e56Smrg return (char *) ledWire; 6506f7df2e56Smrg } 650705b261ecSmrg 6508f7df2e56Smrg atomWire = (CARD32 *) &ledWire[1]; 6509f7df2e56Smrg if (changed & XkbXI_IndicatorNamesMask) { 6510f7df2e56Smrg namec = sli->namesPresent | ledWire->namesPresent; 6511f7df2e56Smrg memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom)); 6512f7df2e56Smrg } 6513f7df2e56Smrg if (ledWire->namesPresent) { 6514f7df2e56Smrg sli->namesPresent = ledWire->namesPresent; 6515f7df2e56Smrg memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom)); 6516f7df2e56Smrg for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) { 6517f7df2e56Smrg if (ledWire->namesPresent & bit) { 6518f7df2e56Smrg sli->names[n] = (Atom) *atomWire; 6519f7df2e56Smrg if (sli->names[n] == None) 6520f7df2e56Smrg ledWire->namesPresent &= ~bit; 6521f7df2e56Smrg atomWire++; 6522f7df2e56Smrg } 6523f7df2e56Smrg } 6524f7df2e56Smrg } 6525f7df2e56Smrg mapWire = (xkbIndicatorMapWireDesc *) atomWire; 6526f7df2e56Smrg if (changed & XkbXI_IndicatorMapsMask) { 6527f7df2e56Smrg mapc = sli->mapsPresent | ledWire->mapsPresent; 6528f7df2e56Smrg sli->mapsPresent = ledWire->mapsPresent; 6529f7df2e56Smrg memset((char *) sli->maps, 0, 6530f7df2e56Smrg XkbNumIndicators * sizeof(XkbIndicatorMapRec)); 6531f7df2e56Smrg } 6532f7df2e56Smrg if (ledWire->mapsPresent) { 6533f7df2e56Smrg for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) { 6534f7df2e56Smrg if (ledWire->mapsPresent & bit) { 6535f7df2e56Smrg sli->maps[n].flags = mapWire->flags; 6536f7df2e56Smrg sli->maps[n].which_groups = mapWire->whichGroups; 6537f7df2e56Smrg sli->maps[n].groups = mapWire->groups; 6538f7df2e56Smrg sli->maps[n].which_mods = mapWire->whichMods; 6539f7df2e56Smrg sli->maps[n].mods.mask = mapWire->mods; 6540f7df2e56Smrg sli->maps[n].mods.real_mods = mapWire->realMods; 6541f7df2e56Smrg sli->maps[n].mods.vmods = mapWire->virtualMods; 6542f7df2e56Smrg sli->maps[n].ctrls = mapWire->ctrls; 6543f7df2e56Smrg mapWire++; 6544f7df2e56Smrg } 6545f7df2e56Smrg } 6546f7df2e56Smrg } 6547f7df2e56Smrg if (changed & XkbXI_IndicatorStateMask) { 6548f7df2e56Smrg statec = sli->effectiveState ^ ledWire->state; 6549f7df2e56Smrg sli->explicitState &= ~statec; 6550f7df2e56Smrg sli->explicitState |= (ledWire->state & statec); 6551f7df2e56Smrg } 6552f7df2e56Smrg if (namec) 6553f7df2e56Smrg XkbApplyLedNameChanges(dev, sli, namec, &ed, &changes, &cause); 6554f7df2e56Smrg if (mapc) 6555f7df2e56Smrg XkbApplyLedMapChanges(dev, sli, mapc, &ed, &changes, &cause); 6556f7df2e56Smrg if (statec) 6557f7df2e56Smrg XkbApplyLedStateChanges(dev, sli, statec, &ed, &changes, &cause); 6558f7df2e56Smrg 6559f7df2e56Smrg kbd = dev; 6560f7df2e56Smrg if ((sli->flags & XkbSLI_HasOwnState) == 0) 6561f7df2e56Smrg kbd = inputInfo.keyboard; 6562f7df2e56Smrg 6563f7df2e56Smrg XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause); 6564f7df2e56Smrg ledWire = (xkbDeviceLedsWireDesc *) mapWire; 6565f7df2e56Smrg } 6566f7df2e56Smrg return (char *) ledWire; 6567f7df2e56Smrg} 656805b261ecSmrg 65694642e01fSmrgstatic int 65704642e01fSmrg_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev, 6571f7df2e56Smrg xkbSetDeviceInfoReq * stuff) 65724642e01fSmrg{ 6573f7df2e56Smrg char *wire; 6574f7df2e56Smrg 6575f7df2e56Smrg wire = (char *) &stuff[1]; 6576f7df2e56Smrg if (stuff->change & XkbXI_ButtonActionsMask) { 6577f7df2e56Smrg if (!dev->button) { 6578f7df2e56Smrg client->errorValue = _XkbErrCode2(XkbErr_BadClass, ButtonClass); 6579f7df2e56Smrg return XkbKeyboardErrorCode; 6580f7df2e56Smrg } 6581f7df2e56Smrg if ((stuff->firstBtn + stuff->nBtns) > dev->button->numButtons) { 6582f7df2e56Smrg client->errorValue = 6583f7df2e56Smrg _XkbErrCode4(0x02, stuff->firstBtn, stuff->nBtns, 6584f7df2e56Smrg dev->button->numButtons); 6585f7df2e56Smrg return BadMatch; 6586f7df2e56Smrg } 6587f7df2e56Smrg wire += (stuff->nBtns * SIZEOF(xkbActionWireDesc)); 6588f7df2e56Smrg } 6589f7df2e56Smrg if (stuff->change & XkbXI_IndicatorsMask) { 6590f7df2e56Smrg int status = Success; 6591f7df2e56Smrg 6592f7df2e56Smrg wire = CheckSetDeviceIndicators(wire, dev, stuff->nDeviceLedFBs, 6593f7df2e56Smrg &status, client); 6594f7df2e56Smrg if (status != Success) 6595f7df2e56Smrg return status; 6596f7df2e56Smrg } 6597f7df2e56Smrg if (((wire - ((char *) stuff)) / 4) != stuff->length) 6598f7df2e56Smrg return BadLength; 659905b261ecSmrg 66004642e01fSmrg return Success; 66014642e01fSmrg} 66024642e01fSmrg 66034642e01fSmrgstatic int 66044642e01fSmrg_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev, 6605f7df2e56Smrg xkbSetDeviceInfoReq * stuff) 66064642e01fSmrg{ 6607f7df2e56Smrg char *wire; 6608f7df2e56Smrg xkbExtensionDeviceNotify ed; 6609f7df2e56Smrg 6610f7df2e56Smrg memset((char *) &ed, 0, SIZEOF(xkbExtensionDeviceNotify)); 6611f7df2e56Smrg ed.deviceID = dev->id; 6612f7df2e56Smrg wire = (char *) &stuff[1]; 6613f7df2e56Smrg if (stuff->change & XkbXI_ButtonActionsMask) { 6614f7df2e56Smrg int nBtns, sz, i; 6615f7df2e56Smrg XkbAction *acts; 6616f7df2e56Smrg DeviceIntPtr kbd; 6617f7df2e56Smrg 6618f7df2e56Smrg nBtns = dev->button->numButtons; 6619f7df2e56Smrg acts = dev->button->xkb_acts; 6620f7df2e56Smrg if (acts == NULL) { 6621f7df2e56Smrg acts = calloc(nBtns, sizeof(XkbAction)); 6622f7df2e56Smrg if (!acts) 6623f7df2e56Smrg return BadAlloc; 6624f7df2e56Smrg dev->button->xkb_acts = acts; 6625f7df2e56Smrg } 6626f7df2e56Smrg sz = stuff->nBtns * SIZEOF(xkbActionWireDesc); 6627f7df2e56Smrg memcpy((char *) &acts[stuff->firstBtn], (char *) wire, sz); 6628f7df2e56Smrg wire += sz; 6629f7df2e56Smrg ed.reason |= XkbXI_ButtonActionsMask; 6630f7df2e56Smrg ed.firstBtn = stuff->firstBtn; 6631f7df2e56Smrg ed.nBtns = stuff->nBtns; 6632f7df2e56Smrg 6633f7df2e56Smrg if (dev->key) 6634f7df2e56Smrg kbd = dev; 6635f7df2e56Smrg else 6636f7df2e56Smrg kbd = inputInfo.keyboard; 6637f7df2e56Smrg acts = &dev->button->xkb_acts[stuff->firstBtn]; 6638f7df2e56Smrg for (i = 0; i < stuff->nBtns; i++, acts++) { 6639f7df2e56Smrg if (acts->type != XkbSA_NoAction) 6640f7df2e56Smrg XkbSetActionKeyMods(kbd->key->xkbInfo->desc, acts, 0); 6641f7df2e56Smrg } 6642f7df2e56Smrg } 6643f7df2e56Smrg if (stuff->change & XkbXI_IndicatorsMask) { 6644f7df2e56Smrg int status = Success; 6645f7df2e56Smrg 6646f7df2e56Smrg wire = SetDeviceIndicators(wire, dev, stuff->change, 6647f7df2e56Smrg stuff->nDeviceLedFBs, &status, client, &ed); 6648f7df2e56Smrg if (status != Success) 6649f7df2e56Smrg return status; 6650f7df2e56Smrg } 6651f7df2e56Smrg if ((stuff->change) && (ed.reason)) 6652f7df2e56Smrg XkbSendExtensionDeviceNotify(dev, client, &ed); 66534642e01fSmrg return Success; 66544642e01fSmrg} 66554642e01fSmrg 66564642e01fSmrgint 66574642e01fSmrgProcXkbSetDeviceInfo(ClientPtr client) 66584642e01fSmrg{ 6659f7df2e56Smrg DeviceIntPtr dev; 6660f7df2e56Smrg int rc; 66614642e01fSmrg 66624642e01fSmrg REQUEST(xkbSetDeviceInfoReq); 66634642e01fSmrg REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq); 66644642e01fSmrg 6665f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 6666f7df2e56Smrg return BadAccess; 66674642e01fSmrg 66684642e01fSmrg CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); 6669f7df2e56Smrg CHK_MASK_LEGAL(0x01, stuff->change, XkbXI_AllFeaturesMask); 66704642e01fSmrg 66714642e01fSmrg rc = _XkbSetDeviceInfoCheck(client, dev, stuff); 66724642e01fSmrg 66734642e01fSmrg if (rc != Success) 66744642e01fSmrg return rc; 66754642e01fSmrg 6676f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd || 6677f7df2e56Smrg stuff->deviceSpec == XkbUseCorePtr) { 66784642e01fSmrg DeviceIntPtr other; 6679f7df2e56Smrg 6680f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 6681f7df2e56Smrg if (((other != dev) && !IsMaster(other) && 6682f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) && 66834642e01fSmrg ((stuff->deviceSpec == XkbUseCoreKbd && other->key) || 6684f7df2e56Smrg (stuff->deviceSpec == XkbUseCorePtr && other->button))) { 6685f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 6686f7df2e56Smrg DixManageAccess); 6687f7df2e56Smrg if (rc == Success) { 66884642e01fSmrg rc = _XkbSetDeviceInfoCheck(client, other, stuff); 66894642e01fSmrg if (rc != Success) 66904642e01fSmrg return rc; 66914642e01fSmrg } 66924642e01fSmrg } 66934642e01fSmrg } 66944642e01fSmrg } 66954642e01fSmrg 66964642e01fSmrg /* checks done, apply */ 66974642e01fSmrg rc = _XkbSetDeviceInfo(client, dev, stuff); 66984642e01fSmrg if (rc != Success) 66994642e01fSmrg return rc; 67004642e01fSmrg 6701f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd || 6702f7df2e56Smrg stuff->deviceSpec == XkbUseCorePtr) { 67034642e01fSmrg DeviceIntPtr other; 6704f7df2e56Smrg 6705f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 6706f7df2e56Smrg if (((other != dev) && !IsMaster(other) && 6707f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) && 67084642e01fSmrg ((stuff->deviceSpec == XkbUseCoreKbd && other->key) || 6709f7df2e56Smrg (stuff->deviceSpec == XkbUseCorePtr && other->button))) { 6710f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 6711f7df2e56Smrg DixManageAccess); 6712f7df2e56Smrg if (rc == Success) { 67134642e01fSmrg rc = _XkbSetDeviceInfo(client, other, stuff); 67144642e01fSmrg if (rc != Success) 67154642e01fSmrg return rc; 67164642e01fSmrg } 67174642e01fSmrg } 67184642e01fSmrg } 67194642e01fSmrg } 67204642e01fSmrg 67216747b715Smrg return Success; 672205b261ecSmrg} 672305b261ecSmrg 672405b261ecSmrg/***====================================================================***/ 672505b261ecSmrg 672605b261ecSmrgint 672705b261ecSmrgProcXkbSetDebuggingFlags(ClientPtr client) 672805b261ecSmrg{ 6729f7df2e56Smrg CARD32 newFlags, newCtrls, extraLength; 6730f7df2e56Smrg xkbSetDebuggingFlagsReply rep; 6731f7df2e56Smrg int rc; 673205b261ecSmrg 673305b261ecSmrg REQUEST(xkbSetDebuggingFlagsReq); 673405b261ecSmrg REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq); 673505b261ecSmrg 67364642e01fSmrg rc = XaceHook(XACE_SERVER_ACCESS, client, DixDebugAccess); 67374642e01fSmrg if (rc != Success) 6738f7df2e56Smrg return rc; 67394642e01fSmrg 6740f7df2e56Smrg newFlags = xkbDebugFlags & (~stuff->affectFlags); 6741f7df2e56Smrg newFlags |= (stuff->flags & stuff->affectFlags); 6742f7df2e56Smrg newCtrls = xkbDebugCtrls & (~stuff->affectCtrls); 6743f7df2e56Smrg newCtrls |= (stuff->ctrls & stuff->affectCtrls); 674405b261ecSmrg if (xkbDebugFlags || newFlags || stuff->msgLength) { 6745f7df2e56Smrg ErrorF("[xkb] XkbDebug: Setting debug flags to 0x%lx\n", 6746f7df2e56Smrg (long) newFlags); 6747f7df2e56Smrg if (newCtrls != xkbDebugCtrls) 6748f7df2e56Smrg ErrorF("[xkb] XkbDebug: Setting debug controls to 0x%lx\n", 6749f7df2e56Smrg (long) newCtrls); 6750f7df2e56Smrg } 6751f7df2e56Smrg extraLength = (stuff->length << 2) - sz_xkbSetDebuggingFlagsReq; 6752f7df2e56Smrg if (stuff->msgLength > 0) { 6753f7df2e56Smrg char *msg; 6754f7df2e56Smrg 6755f7df2e56Smrg if (extraLength < XkbPaddedSize(stuff->msgLength)) { 6756f7df2e56Smrg ErrorF 6757f7df2e56Smrg ("[xkb] XkbDebug: msgLength= %d, length= %ld (should be %d)\n", 6758f7df2e56Smrg stuff->msgLength, (long) extraLength, 6759f7df2e56Smrg XkbPaddedSize(stuff->msgLength)); 6760f7df2e56Smrg return BadLength; 6761f7df2e56Smrg } 6762f7df2e56Smrg msg = (char *) &stuff[1]; 6763f7df2e56Smrg if (msg[stuff->msgLength - 1] != '\0') { 6764f7df2e56Smrg ErrorF("[xkb] XkbDebug: message not null-terminated\n"); 6765f7df2e56Smrg return BadValue; 6766f7df2e56Smrg } 6767f7df2e56Smrg ErrorF("[xkb] XkbDebug: %s\n", msg); 676805b261ecSmrg } 676905b261ecSmrg xkbDebugFlags = newFlags; 677005b261ecSmrg xkbDebugCtrls = newCtrls; 677105b261ecSmrg 6772f7df2e56Smrg rep = (xkbSetDebuggingFlagsReply) { 6773f7df2e56Smrg .type = X_Reply, 6774f7df2e56Smrg .sequenceNumber = client->sequence, 6775f7df2e56Smrg .length = 0, 6776f7df2e56Smrg .currentFlags = newFlags, 6777f7df2e56Smrg .currentCtrls = newCtrls, 6778f7df2e56Smrg .supportedFlags = ~0, 6779f7df2e56Smrg .supportedCtrls = ~0 6780f7df2e56Smrg }; 6781f7df2e56Smrg if (client->swapped) { 6782f7df2e56Smrg swaps(&rep.sequenceNumber); 6783f7df2e56Smrg swapl(&rep.currentFlags); 6784f7df2e56Smrg swapl(&rep.currentCtrls); 6785f7df2e56Smrg swapl(&rep.supportedFlags); 6786f7df2e56Smrg swapl(&rep.supportedCtrls); 6787f7df2e56Smrg } 6788f7df2e56Smrg WriteToClient(client, SIZEOF(xkbSetDebuggingFlagsReply), &rep); 67896747b715Smrg return Success; 679005b261ecSmrg} 679105b261ecSmrg 679205b261ecSmrg/***====================================================================***/ 679305b261ecSmrg 679405b261ecSmrgstatic int 6795f7df2e56SmrgProcXkbDispatch(ClientPtr client) 679605b261ecSmrg{ 679705b261ecSmrg REQUEST(xReq); 6798f7df2e56Smrg switch (stuff->data) { 679905b261ecSmrg case X_kbUseExtension: 6800f7df2e56Smrg return ProcXkbUseExtension(client); 680105b261ecSmrg case X_kbSelectEvents: 6802f7df2e56Smrg return ProcXkbSelectEvents(client); 680305b261ecSmrg case X_kbBell: 6804f7df2e56Smrg return ProcXkbBell(client); 680505b261ecSmrg case X_kbGetState: 6806f7df2e56Smrg return ProcXkbGetState(client); 680705b261ecSmrg case X_kbLatchLockState: 6808f7df2e56Smrg return ProcXkbLatchLockState(client); 680905b261ecSmrg case X_kbGetControls: 6810f7df2e56Smrg return ProcXkbGetControls(client); 681105b261ecSmrg case X_kbSetControls: 6812f7df2e56Smrg return ProcXkbSetControls(client); 681305b261ecSmrg case X_kbGetMap: 6814f7df2e56Smrg return ProcXkbGetMap(client); 681505b261ecSmrg case X_kbSetMap: 6816f7df2e56Smrg return ProcXkbSetMap(client); 681705b261ecSmrg case X_kbGetCompatMap: 6818f7df2e56Smrg return ProcXkbGetCompatMap(client); 681905b261ecSmrg case X_kbSetCompatMap: 6820f7df2e56Smrg return ProcXkbSetCompatMap(client); 682105b261ecSmrg case X_kbGetIndicatorState: 6822f7df2e56Smrg return ProcXkbGetIndicatorState(client); 682305b261ecSmrg case X_kbGetIndicatorMap: 6824f7df2e56Smrg return ProcXkbGetIndicatorMap(client); 682505b261ecSmrg case X_kbSetIndicatorMap: 6826f7df2e56Smrg return ProcXkbSetIndicatorMap(client); 682705b261ecSmrg case X_kbGetNamedIndicator: 6828f7df2e56Smrg return ProcXkbGetNamedIndicator(client); 682905b261ecSmrg case X_kbSetNamedIndicator: 6830f7df2e56Smrg return ProcXkbSetNamedIndicator(client); 683105b261ecSmrg case X_kbGetNames: 6832f7df2e56Smrg return ProcXkbGetNames(client); 683305b261ecSmrg case X_kbSetNames: 6834f7df2e56Smrg return ProcXkbSetNames(client); 683505b261ecSmrg case X_kbGetGeometry: 6836f7df2e56Smrg return ProcXkbGetGeometry(client); 683705b261ecSmrg case X_kbSetGeometry: 6838f7df2e56Smrg return ProcXkbSetGeometry(client); 683905b261ecSmrg case X_kbPerClientFlags: 6840f7df2e56Smrg return ProcXkbPerClientFlags(client); 684105b261ecSmrg case X_kbListComponents: 6842f7df2e56Smrg return ProcXkbListComponents(client); 684305b261ecSmrg case X_kbGetKbdByName: 6844f7df2e56Smrg return ProcXkbGetKbdByName(client); 684505b261ecSmrg case X_kbGetDeviceInfo: 6846f7df2e56Smrg return ProcXkbGetDeviceInfo(client); 684705b261ecSmrg case X_kbSetDeviceInfo: 6848f7df2e56Smrg return ProcXkbSetDeviceInfo(client); 684905b261ecSmrg case X_kbSetDebuggingFlags: 6850f7df2e56Smrg return ProcXkbSetDebuggingFlags(client); 685105b261ecSmrg default: 6852f7df2e56Smrg return BadRequest; 685305b261ecSmrg } 685405b261ecSmrg} 685505b261ecSmrg 685605b261ecSmrgstatic int 6857f7df2e56SmrgXkbClientGone(void *data, XID id) 685805b261ecSmrg{ 6859f7df2e56Smrg DevicePtr pXDev = (DevicePtr) data; 686005b261ecSmrg 6861f7df2e56Smrg if (!XkbRemoveResourceClient(pXDev, id)) { 6862f7df2e56Smrg ErrorF 6863f7df2e56Smrg ("[xkb] Internal Error! bad RemoveResourceClient in XkbClientGone\n"); 686405b261ecSmrg } 686505b261ecSmrg return 1; 686605b261ecSmrg} 686705b261ecSmrg 686805b261ecSmrgvoid 686905b261ecSmrgXkbExtensionInit(void) 687005b261ecSmrg{ 687105b261ecSmrg ExtensionEntry *extEntry; 687205b261ecSmrg 68736747b715Smrg RT_XKBCLIENT = CreateNewResourceType(XkbClientGone, "XkbClient"); 68746747b715Smrg if (!RT_XKBCLIENT) 6875f7df2e56Smrg return; 68766747b715Smrg 68776747b715Smrg if (!XkbInitPrivates()) 6878f7df2e56Smrg return; 68796747b715Smrg 688005b261ecSmrg if ((extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors, 6881f7df2e56Smrg ProcXkbDispatch, SProcXkbDispatch, 6882f7df2e56Smrg NULL, StandardMinorOpcode))) { 6883f7df2e56Smrg XkbReqCode = (unsigned char) extEntry->base; 6884f7df2e56Smrg XkbEventBase = (unsigned char) extEntry->eventBase; 6885f7df2e56Smrg XkbErrorBase = (unsigned char) extEntry->errorBase; 6886f7df2e56Smrg XkbKeyboardErrorCode = XkbErrorBase + XkbKeyboard; 688705b261ecSmrg } 688805b261ecSmrg return; 688905b261ecSmrg} 6890