xkb.c revision f7df2e56
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; 175f7df2e56Smrg client->vMajor = stuff->wantedMajor; 176f7df2e56Smrg client->vMinor = stuff->wantedMinor; 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)) { 2391f7df2e56Smrg if (client->vMajor != 1) { /* pre 1.0 versions of Xlib have a bug */ 2392f7df2e56Smrg req->minKeyCode = xkb->min_key_code; 2393f7df2e56Smrg req->maxKeyCode = xkb->max_key_code; 2394f7df2e56Smrg } 2395f7df2e56Smrg else { 2396f7df2e56Smrg if (!XkbIsLegalKeycode(req->minKeyCode)) { 2397f7df2e56Smrg client->errorValue = 2398f7df2e56Smrg _XkbErrCode3(2, req->minKeyCode, req->maxKeyCode); 2399f7df2e56Smrg return BadValue; 2400f7df2e56Smrg } 2401f7df2e56Smrg if (req->minKeyCode > req->maxKeyCode) { 2402f7df2e56Smrg client->errorValue = 2403f7df2e56Smrg _XkbErrCode3(3, req->minKeyCode, req->maxKeyCode); 2404f7df2e56Smrg return BadMatch; 2405f7df2e56Smrg } 2406f7df2e56Smrg } 240705b261ecSmrg } 240805b261ecSmrg 24094642e01fSmrg if ((req->present & XkbKeyTypesMask) && 2410f7df2e56Smrg (!CheckKeyTypes(client, xkb, req, (xkbKeyTypeWireDesc **) &values, 2411f7df2e56Smrg &nTypes, mapWidths))) { 2412f7df2e56Smrg client->errorValue = nTypes; 2413f7df2e56Smrg return BadValue; 241405b261ecSmrg } 24159ace9065Smrg 24169ace9065Smrg /* symsPerKey/mapWidths must be filled regardless of client-side flags */ 24179ace9065Smrg map = &xkb->map->key_sym_map[xkb->min_key_code]; 2418f7df2e56Smrg for (i = xkb->min_key_code; i < xkb->max_key_code; i++, map++) { 2419f7df2e56Smrg register int g, ng, w; 2420f7df2e56Smrg 2421f7df2e56Smrg ng = XkbNumGroups(map->group_info); 2422f7df2e56Smrg for (w = g = 0; g < ng; g++) { 2423f7df2e56Smrg if (map->kt_index[g] >= (unsigned) nTypes) { 2424f7df2e56Smrg client->errorValue = _XkbErrCode4(0x13, i, g, map->kt_index[g]); 2425f7df2e56Smrg return 0; 2426f7df2e56Smrg } 2427f7df2e56Smrg if (mapWidths[map->kt_index[g]] > w) 2428f7df2e56Smrg w = mapWidths[map->kt_index[g]]; 2429f7df2e56Smrg } 2430f7df2e56Smrg symsPerKey[i] = w * ng; 24319ace9065Smrg } 24329ace9065Smrg 24334642e01fSmrg if ((req->present & XkbKeySymsMask) && 2434f7df2e56Smrg (!CheckKeySyms(client, xkb, req, nTypes, mapWidths, symsPerKey, 2435f7df2e56Smrg (xkbSymMapWireDesc **) &values, &error))) { 2436f7df2e56Smrg client->errorValue = error; 2437f7df2e56Smrg return BadValue; 243805b261ecSmrg } 243905b261ecSmrg 24404642e01fSmrg if ((req->present & XkbKeyActionsMask) && 2441f7df2e56Smrg (!CheckKeyActions(xkb, req, nTypes, mapWidths, symsPerKey, 2442f7df2e56Smrg (CARD8 **) &values, &nActions))) { 2443f7df2e56Smrg client->errorValue = nActions; 2444f7df2e56Smrg return BadValue; 244505b261ecSmrg } 244605b261ecSmrg 24474642e01fSmrg if ((req->present & XkbKeyBehaviorsMask) && 2448f7df2e56Smrg (!CheckKeyBehaviors 2449f7df2e56Smrg (xkb, req, (xkbBehaviorWireDesc **) &values, &error))) { 2450f7df2e56Smrg client->errorValue = error; 2451f7df2e56Smrg return BadValue; 245205b261ecSmrg } 245305b261ecSmrg 24544642e01fSmrg if ((req->present & XkbVirtualModsMask) && 2455f7df2e56Smrg (!CheckVirtualMods(xkb, req, (CARD8 **) &values, &error))) { 2456f7df2e56Smrg client->errorValue = error; 2457f7df2e56Smrg return BadValue; 245805b261ecSmrg } 2459f7df2e56Smrg if ((req->present & XkbExplicitComponentsMask) && 2460f7df2e56Smrg (!CheckKeyExplicit(xkb, req, (CARD8 **) &values, &error))) { 2461f7df2e56Smrg client->errorValue = error; 2462f7df2e56Smrg return BadValue; 246305b261ecSmrg } 2464f7df2e56Smrg if ((req->present & XkbModifierMapMask) && 2465f7df2e56Smrg (!CheckModifierMap(xkb, req, (CARD8 **) &values, &error))) { 2466f7df2e56Smrg client->errorValue = error; 2467f7df2e56Smrg return BadValue; 246805b261ecSmrg } 2469f7df2e56Smrg if ((req->present & XkbVirtualModMapMask) && 2470f7df2e56Smrg (!CheckVirtualModMap 2471f7df2e56Smrg (xkb, req, (xkbVModMapWireDesc **) &values, &error))) { 2472f7df2e56Smrg client->errorValue = error; 2473f7df2e56Smrg return BadValue; 247405b261ecSmrg } 24754642e01fSmrg 2476f7df2e56Smrg if (((values - ((char *) req)) / 4) != req->length) { 2477f7df2e56Smrg ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after check)\n"); 2478f7df2e56Smrg client->errorValue = values - ((char *) &req[1]); 2479f7df2e56Smrg return BadLength; 248005b261ecSmrg } 24814642e01fSmrg 24824642e01fSmrg return Success; 24834642e01fSmrg} 24844642e01fSmrg 24854642e01fSmrg/** 24864642e01fSmrg * Apply the given request on the given device. 24874642e01fSmrg */ 24884642e01fSmrgstatic int 2489f7df2e56Smrg_XkbSetMap(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq * req, char *values) 24904642e01fSmrg{ 2491f7df2e56Smrg XkbEventCauseRec cause; 2492f7df2e56Smrg XkbChangesRec change; 2493f7df2e56Smrg Bool sentNKN; 2494f7df2e56Smrg XkbSrvInfoPtr xkbi; 2495f7df2e56Smrg XkbDescPtr xkb; 24964642e01fSmrg 2497f7df2e56Smrg xkbi = dev->key->xkbInfo; 24984642e01fSmrg xkb = xkbi->desc; 24994642e01fSmrg 2500f7df2e56Smrg XkbSetCauseXkbReq(&cause, X_kbSetMap, client); 25016747b715Smrg memset(&change, 0, sizeof(change)); 25026747b715Smrg sentNKN = FALSE; 2503f7df2e56Smrg if ((xkb->min_key_code != req->minKeyCode) || 2504f7df2e56Smrg (xkb->max_key_code != req->maxKeyCode)) { 2505f7df2e56Smrg Status status; 2506f7df2e56Smrg xkbNewKeyboardNotify nkn; 2507f7df2e56Smrg 2508f7df2e56Smrg nkn.deviceID = nkn.oldDeviceID = dev->id; 2509f7df2e56Smrg nkn.oldMinKeyCode = xkb->min_key_code; 2510f7df2e56Smrg nkn.oldMaxKeyCode = xkb->max_key_code; 2511f7df2e56Smrg status = XkbChangeKeycodeRange(xkb, req->minKeyCode, 2512f7df2e56Smrg req->maxKeyCode, &change); 2513f7df2e56Smrg if (status != Success) 2514f7df2e56Smrg return status; /* oh-oh. what about the other keyboards? */ 2515f7df2e56Smrg nkn.minKeyCode = xkb->min_key_code; 2516f7df2e56Smrg nkn.maxKeyCode = xkb->max_key_code; 2517f7df2e56Smrg nkn.requestMajor = XkbReqCode; 2518f7df2e56Smrg nkn.requestMinor = X_kbSetMap; 2519f7df2e56Smrg nkn.changed = XkbNKN_KeycodesMask; 2520f7df2e56Smrg XkbSendNewKeyboardNotify(dev, &nkn); 2521f7df2e56Smrg sentNKN = TRUE; 2522f7df2e56Smrg } 2523f7df2e56Smrg 2524f7df2e56Smrg if (req->present & XkbKeyTypesMask) { 2525f7df2e56Smrg values = SetKeyTypes(xkb, req, (xkbKeyTypeWireDesc *) values, &change); 2526f7df2e56Smrg if (!values) 2527f7df2e56Smrg goto allocFailure; 2528f7df2e56Smrg } 2529f7df2e56Smrg if (req->present & XkbKeySymsMask) { 2530f7df2e56Smrg values = 2531f7df2e56Smrg SetKeySyms(client, xkb, req, (xkbSymMapWireDesc *) values, &change, 2532f7df2e56Smrg dev); 2533f7df2e56Smrg if (!values) 2534f7df2e56Smrg goto allocFailure; 2535f7df2e56Smrg } 2536f7df2e56Smrg if (req->present & XkbKeyActionsMask) { 2537f7df2e56Smrg values = SetKeyActions(xkb, req, (CARD8 *) values, &change); 2538f7df2e56Smrg if (!values) 2539f7df2e56Smrg goto allocFailure; 2540f7df2e56Smrg } 2541f7df2e56Smrg if (req->present & XkbKeyBehaviorsMask) { 2542f7df2e56Smrg values = 2543f7df2e56Smrg SetKeyBehaviors(xkbi, req, (xkbBehaviorWireDesc *) values, &change); 2544f7df2e56Smrg if (!values) 2545f7df2e56Smrg goto allocFailure; 2546f7df2e56Smrg } 2547f7df2e56Smrg if (req->present & XkbVirtualModsMask) 2548f7df2e56Smrg values = SetVirtualMods(xkbi, req, (CARD8 *) values, &change); 2549f7df2e56Smrg if (req->present & XkbExplicitComponentsMask) 2550f7df2e56Smrg values = SetKeyExplicit(xkbi, req, (CARD8 *) values, &change); 2551f7df2e56Smrg if (req->present & XkbModifierMapMask) 2552f7df2e56Smrg values = SetModifierMap(xkbi, req, (CARD8 *) values, &change); 2553f7df2e56Smrg if (req->present & XkbVirtualModMapMask) 2554f7df2e56Smrg values = 2555f7df2e56Smrg SetVirtualModMap(xkbi, req, (xkbVModMapWireDesc *) values, &change); 2556f7df2e56Smrg if (((values - ((char *) req)) / 4) != req->length) { 2557f7df2e56Smrg ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after set)\n"); 2558f7df2e56Smrg client->errorValue = values - ((char *) &req[1]); 2559f7df2e56Smrg return BadLength; 2560f7df2e56Smrg } 2561f7df2e56Smrg if (req->flags & XkbSetMapRecomputeActions) { 2562f7df2e56Smrg KeyCode first, last, firstMM, lastMM; 2563f7df2e56Smrg 2564f7df2e56Smrg if (change.map.num_key_syms > 0) { 2565f7df2e56Smrg first = change.map.first_key_sym; 2566f7df2e56Smrg last = first + change.map.num_key_syms - 1; 2567f7df2e56Smrg } 2568f7df2e56Smrg else 2569f7df2e56Smrg first = last = 0; 2570f7df2e56Smrg if (change.map.num_modmap_keys > 0) { 2571f7df2e56Smrg firstMM = change.map.first_modmap_key; 2572f7df2e56Smrg lastMM = first + change.map.num_modmap_keys - 1; 2573f7df2e56Smrg } 2574f7df2e56Smrg else 2575f7df2e56Smrg firstMM = lastMM = 0; 2576f7df2e56Smrg if ((last > 0) && (lastMM > 0)) { 2577f7df2e56Smrg if (firstMM < first) 2578f7df2e56Smrg first = firstMM; 2579f7df2e56Smrg if (lastMM > last) 2580f7df2e56Smrg last = lastMM; 2581f7df2e56Smrg } 2582f7df2e56Smrg else if (lastMM > 0) { 2583f7df2e56Smrg first = firstMM; 2584f7df2e56Smrg last = lastMM; 2585f7df2e56Smrg } 2586f7df2e56Smrg if (last > 0) { 2587f7df2e56Smrg unsigned check = 0; 2588f7df2e56Smrg 2589f7df2e56Smrg XkbUpdateActions(dev, first, (last - first + 1), &change, &check, 2590f7df2e56Smrg &cause); 2591f7df2e56Smrg if (check) 2592f7df2e56Smrg XkbCheckSecondaryEffects(xkbi, check, &change, &cause); 2593f7df2e56Smrg } 259405b261ecSmrg } 259505b261ecSmrg if (!sentNKN) 2596f7df2e56Smrg XkbSendNotification(dev, &change, &cause); 259705b261ecSmrg 25984642e01fSmrg return Success; 2599f7df2e56Smrg allocFailure: 260005b261ecSmrg return BadAlloc; 260105b261ecSmrg} 260205b261ecSmrg 26034642e01fSmrgint 26044642e01fSmrgProcXkbSetMap(ClientPtr client) 26054642e01fSmrg{ 2606f7df2e56Smrg DeviceIntPtr dev; 2607f7df2e56Smrg char *tmp; 2608f7df2e56Smrg int rc; 26094642e01fSmrg 26104642e01fSmrg REQUEST(xkbSetMapReq); 26114642e01fSmrg REQUEST_AT_LEAST_SIZE(xkbSetMapReq); 26124642e01fSmrg 2613f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 2614f7df2e56Smrg return BadAccess; 26154642e01fSmrg 26164642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); 2617f7df2e56Smrg CHK_MASK_LEGAL(0x01, stuff->present, XkbAllMapComponentsMask); 26184642e01fSmrg 2619f7df2e56Smrg tmp = (char *) &stuff[1]; 26204642e01fSmrg 26214642e01fSmrg /* Check if we can to the SetMap on the requested device. If this 26224642e01fSmrg succeeds, do the same thing for all extension devices (if needed). 26234642e01fSmrg If any of them fails, fail. */ 26244642e01fSmrg rc = _XkbSetMapChecks(client, dev, stuff, tmp); 26254642e01fSmrg 26264642e01fSmrg if (rc != Success) 26274642e01fSmrg return rc; 26284642e01fSmrg 2629f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd) { 26304642e01fSmrg DeviceIntPtr other; 2631f7df2e56Smrg 2632f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 2633f7df2e56Smrg if ((other != dev) && other->key && !IsMaster(other) && 2634f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) { 2635f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 2636f7df2e56Smrg DixManageAccess); 2637f7df2e56Smrg if (rc == Success) { 26384642e01fSmrg rc = _XkbSetMapChecks(client, other, stuff, tmp); 26394642e01fSmrg if (rc != Success) 26404642e01fSmrg return rc; 26414642e01fSmrg } 26424642e01fSmrg } 26434642e01fSmrg } 26444642e01fSmrg } 26454642e01fSmrg 26464642e01fSmrg /* We know now that we will succed with the SetMap. In theory anyway. */ 26474642e01fSmrg rc = _XkbSetMap(client, dev, stuff, tmp); 26484642e01fSmrg if (rc != Success) 26494642e01fSmrg return rc; 26504642e01fSmrg 2651f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd) { 26524642e01fSmrg DeviceIntPtr other; 2653f7df2e56Smrg 2654f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 2655f7df2e56Smrg if ((other != dev) && other->key && !IsMaster(other) && 2656f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) { 2657f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 2658f7df2e56Smrg DixManageAccess); 26594642e01fSmrg if (rc == Success) 26604642e01fSmrg _XkbSetMap(client, other, stuff, tmp); 26614642e01fSmrg /* ignore rc. if the SetMap failed although the check above 26624642e01fSmrg reported true there isn't much we can do. we still need to 26634642e01fSmrg set all other devices, hoping that at least they stay in 26644642e01fSmrg sync. */ 26654642e01fSmrg } 26664642e01fSmrg } 26674642e01fSmrg } 26684642e01fSmrg 26696747b715Smrg return Success; 26704642e01fSmrg} 26714642e01fSmrg 267205b261ecSmrg/***====================================================================***/ 267305b261ecSmrg 267405b261ecSmrgstatic Status 2675f7df2e56SmrgXkbComputeGetCompatMapReplySize(XkbCompatMapPtr compat, 2676f7df2e56Smrg xkbGetCompatMapReply * rep) 267705b261ecSmrg{ 2678f7df2e56Smrg unsigned size, nGroups; 2679f7df2e56Smrg 2680f7df2e56Smrg nGroups = 0; 2681f7df2e56Smrg if (rep->groups != 0) { 2682f7df2e56Smrg register int i, bit; 2683f7df2e56Smrg 2684f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) { 2685f7df2e56Smrg if (rep->groups & bit) 2686f7df2e56Smrg nGroups++; 2687f7df2e56Smrg } 2688f7df2e56Smrg } 2689f7df2e56Smrg size = nGroups * SIZEOF(xkbModsWireDesc); 2690f7df2e56Smrg size += (rep->nSI * SIZEOF(xkbSymInterpretWireDesc)); 2691f7df2e56Smrg rep->length = size / 4; 269205b261ecSmrg return Success; 269305b261ecSmrg} 269405b261ecSmrg 269505b261ecSmrgstatic int 2696f7df2e56SmrgXkbSendCompatMap(ClientPtr client, 2697f7df2e56Smrg XkbCompatMapPtr compat, xkbGetCompatMapReply * rep) 269805b261ecSmrg{ 2699f7df2e56Smrg char *data; 2700f7df2e56Smrg int size; 2701f7df2e56Smrg 2702f7df2e56Smrg if (rep->length > 0) { 2703f7df2e56Smrg data = xallocarray(rep->length, 4); 2704f7df2e56Smrg if (data) { 2705f7df2e56Smrg register unsigned i, bit; 2706f7df2e56Smrg xkbModsWireDesc *grp; 2707f7df2e56Smrg XkbSymInterpretPtr sym = &compat->sym_interpret[rep->firstSI]; 2708f7df2e56Smrg xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *) data; 2709f7df2e56Smrg 2710f7df2e56Smrg size = rep->length * 4; 2711f7df2e56Smrg 2712f7df2e56Smrg for (i = 0; i < rep->nSI; i++, sym++, wire++) { 2713f7df2e56Smrg wire->sym = sym->sym; 2714f7df2e56Smrg wire->mods = sym->mods; 2715f7df2e56Smrg wire->match = sym->match; 2716f7df2e56Smrg wire->virtualMod = sym->virtual_mod; 2717f7df2e56Smrg wire->flags = sym->flags; 2718f7df2e56Smrg memcpy((char *) &wire->act, (char *) &sym->act, 2719f7df2e56Smrg sz_xkbActionWireDesc); 2720f7df2e56Smrg if (client->swapped) { 2721f7df2e56Smrg swapl(&wire->sym); 2722f7df2e56Smrg } 2723f7df2e56Smrg } 2724f7df2e56Smrg if (rep->groups) { 2725f7df2e56Smrg grp = (xkbModsWireDesc *) wire; 2726f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) { 2727f7df2e56Smrg if (rep->groups & bit) { 2728f7df2e56Smrg grp->mask = compat->groups[i].mask; 2729f7df2e56Smrg grp->realMods = compat->groups[i].real_mods; 2730f7df2e56Smrg grp->virtualMods = compat->groups[i].vmods; 2731f7df2e56Smrg if (client->swapped) { 2732f7df2e56Smrg swaps(&grp->virtualMods); 2733f7df2e56Smrg } 2734f7df2e56Smrg grp++; 2735f7df2e56Smrg } 2736f7df2e56Smrg } 2737f7df2e56Smrg wire = (xkbSymInterpretWireDesc *) grp; 2738f7df2e56Smrg } 2739f7df2e56Smrg } 2740f7df2e56Smrg else 2741f7df2e56Smrg return BadAlloc; 2742f7df2e56Smrg } 2743f7df2e56Smrg else 2744f7df2e56Smrg data = NULL; 274505b261ecSmrg 274605b261ecSmrg if (client->swapped) { 2747f7df2e56Smrg swaps(&rep->sequenceNumber); 2748f7df2e56Smrg swapl(&rep->length); 2749f7df2e56Smrg swaps(&rep->firstSI); 2750f7df2e56Smrg swaps(&rep->nSI); 2751f7df2e56Smrg swaps(&rep->nTotalSI); 275205b261ecSmrg } 275305b261ecSmrg 2754f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetCompatMapReply), rep); 275505b261ecSmrg if (data) { 2756f7df2e56Smrg WriteToClient(client, size, data); 2757f7df2e56Smrg free((char *) data); 275805b261ecSmrg } 27596747b715Smrg return Success; 276005b261ecSmrg} 276105b261ecSmrg 276205b261ecSmrgint 276305b261ecSmrgProcXkbGetCompatMap(ClientPtr client) 276405b261ecSmrg{ 2765f7df2e56Smrg xkbGetCompatMapReply rep; 2766f7df2e56Smrg DeviceIntPtr dev; 2767f7df2e56Smrg XkbDescPtr xkb; 2768f7df2e56Smrg XkbCompatMapPtr compat; 276905b261ecSmrg 277005b261ecSmrg REQUEST(xkbGetCompatMapReq); 277105b261ecSmrg REQUEST_SIZE_MATCH(xkbGetCompatMapReq); 277205b261ecSmrg 2773f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 2774f7df2e56Smrg return BadAccess; 277505b261ecSmrg 27764642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); 277705b261ecSmrg 277805b261ecSmrg xkb = dev->key->xkbInfo->desc; 2779f7df2e56Smrg compat = xkb->compat; 278005b261ecSmrg 2781f7df2e56Smrg rep = (xkbGetCompatMapReply) { 2782f7df2e56Smrg .type = X_Reply, 2783f7df2e56Smrg .sequenceNumber = client->sequence, 2784f7df2e56Smrg .length = 0, 2785f7df2e56Smrg .deviceID = dev->id, 2786f7df2e56Smrg .firstSI = stuff->firstSI, 2787f7df2e56Smrg .nSI = stuff->nSI 2788f7df2e56Smrg }; 278905b261ecSmrg if (stuff->getAllSI) { 2790f7df2e56Smrg rep.firstSI = 0; 2791f7df2e56Smrg rep.nSI = compat->num_si; 279205b261ecSmrg } 2793f7df2e56Smrg else if ((((unsigned) stuff->nSI) > 0) && 2794f7df2e56Smrg ((unsigned) (stuff->firstSI + stuff->nSI - 1) >= compat->num_si)) { 2795f7df2e56Smrg client->errorValue = _XkbErrCode2(0x05, compat->num_si); 2796f7df2e56Smrg return BadValue; 279705b261ecSmrg } 279805b261ecSmrg rep.nTotalSI = compat->num_si; 2799f7df2e56Smrg rep.groups = stuff->groups; 2800f7df2e56Smrg XkbComputeGetCompatMapReplySize(compat, &rep); 2801f7df2e56Smrg return XkbSendCompatMap(client, compat, &rep); 280205b261ecSmrg} 280305b261ecSmrg 28044642e01fSmrg/** 28054642e01fSmrg * Apply the given request on the given device. 28066747b715Smrg * If dryRun is TRUE, then value checks are performed, but the device isn't 28074642e01fSmrg * modified. 28084642e01fSmrg */ 28094642e01fSmrgstatic int 28104642e01fSmrg_XkbSetCompatMap(ClientPtr client, DeviceIntPtr dev, 2811f7df2e56Smrg xkbSetCompatMapReq * req, char *data, BOOL dryRun) 281205b261ecSmrg{ 2813f7df2e56Smrg XkbSrvInfoPtr xkbi; 2814f7df2e56Smrg XkbDescPtr xkb; 2815f7df2e56Smrg XkbCompatMapPtr compat; 2816f7df2e56Smrg int nGroups; 2817f7df2e56Smrg unsigned i, bit; 281805b261ecSmrg 281905b261ecSmrg xkbi = dev->key->xkbInfo; 28204642e01fSmrg xkb = xkbi->desc; 28214642e01fSmrg compat = xkb->compat; 28224642e01fSmrg 2823f7df2e56Smrg if ((req->nSI > 0) || (req->truncateSI)) { 2824f7df2e56Smrg xkbSymInterpretWireDesc *wire; 2825f7df2e56Smrg 2826f7df2e56Smrg if (req->firstSI > compat->num_si) { 2827f7df2e56Smrg client->errorValue = _XkbErrCode2(0x02, compat->num_si); 2828f7df2e56Smrg return BadValue; 2829f7df2e56Smrg } 2830f7df2e56Smrg wire = (xkbSymInterpretWireDesc *) data; 2831f7df2e56Smrg wire += req->nSI; 2832f7df2e56Smrg data = (char *) wire; 283305b261ecSmrg } 28344642e01fSmrg 2835f7df2e56Smrg nGroups = 0; 2836f7df2e56Smrg if (req->groups != 0) { 2837f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) { 2838f7df2e56Smrg if (req->groups & bit) 2839f7df2e56Smrg nGroups++; 2840f7df2e56Smrg } 284105b261ecSmrg } 2842f7df2e56Smrg data += nGroups * SIZEOF(xkbModsWireDesc); 2843f7df2e56Smrg if (((data - ((char *) req)) / 4) != req->length) { 2844f7df2e56Smrg return BadLength; 284505b261ecSmrg } 28464642e01fSmrg 28474642e01fSmrg /* Done all the checks we can do */ 28484642e01fSmrg if (dryRun) 28494642e01fSmrg return Success; 28504642e01fSmrg 2851f7df2e56Smrg data = (char *) &req[1]; 2852f7df2e56Smrg if (req->nSI > 0) { 2853f7df2e56Smrg xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *) data; 2854f7df2e56Smrg XkbSymInterpretPtr sym; 2855f7df2e56Smrg unsigned int skipped = 0; 2856f7df2e56Smrg 2857f7df2e56Smrg if ((unsigned) (req->firstSI + req->nSI) > compat->num_si) { 2858f7df2e56Smrg compat->num_si = req->firstSI + req->nSI; 2859f7df2e56Smrg compat->sym_interpret = reallocarray(compat->sym_interpret, 2860f7df2e56Smrg compat->num_si, 2861f7df2e56Smrg sizeof(XkbSymInterpretRec)); 2862f7df2e56Smrg if (!compat->sym_interpret) { 2863f7df2e56Smrg compat->num_si = 0; 2864f7df2e56Smrg return BadAlloc; 2865f7df2e56Smrg } 2866f7df2e56Smrg } 2867f7df2e56Smrg else if (req->truncateSI) { 2868f7df2e56Smrg compat->num_si = req->firstSI + req->nSI; 2869f7df2e56Smrg } 2870f7df2e56Smrg sym = &compat->sym_interpret[req->firstSI]; 2871f7df2e56Smrg for (i = 0; i < req->nSI; i++, wire++) { 2872f7df2e56Smrg if (client->swapped) { 2873f7df2e56Smrg swapl(&wire->sym); 2874f7df2e56Smrg } 2875f7df2e56Smrg if (wire->sym == NoSymbol && wire->match == XkbSI_AnyOfOrNone && 2876f7df2e56Smrg (wire->mods & 0xff) == 0xff && 2877f7df2e56Smrg wire->act.type == XkbSA_XFree86Private) { 2878f7df2e56Smrg ErrorF("XKB: Skipping broken Any+AnyOfOrNone(All) -> Private " 2879f7df2e56Smrg "action from client\n"); 2880f7df2e56Smrg skipped++; 2881f7df2e56Smrg continue; 2882f7df2e56Smrg } 2883f7df2e56Smrg sym->sym = wire->sym; 2884f7df2e56Smrg sym->mods = wire->mods; 2885f7df2e56Smrg sym->match = wire->match; 2886f7df2e56Smrg sym->flags = wire->flags; 2887f7df2e56Smrg sym->virtual_mod = wire->virtualMod; 2888f7df2e56Smrg memcpy((char *) &sym->act, (char *) &wire->act, 2889f7df2e56Smrg SIZEOF(xkbActionWireDesc)); 2890f7df2e56Smrg sym++; 2891f7df2e56Smrg } 2892f7df2e56Smrg if (skipped) { 2893f7df2e56Smrg if (req->firstSI + req->nSI < compat->num_si) 2894f7df2e56Smrg memmove(sym, sym + skipped, 2895f7df2e56Smrg (compat->num_si - req->firstSI - req->nSI) * 2896f7df2e56Smrg sizeof(*sym)); 2897f7df2e56Smrg compat->num_si -= skipped; 2898f7df2e56Smrg } 2899f7df2e56Smrg data = (char *) wire; 290005b261ecSmrg } 29014642e01fSmrg else if (req->truncateSI) { 2902f7df2e56Smrg compat->num_si = req->firstSI; 2903f7df2e56Smrg } 2904f7df2e56Smrg 2905f7df2e56Smrg if (req->groups != 0) { 2906f7df2e56Smrg xkbModsWireDesc *wire = (xkbModsWireDesc *) data; 2907f7df2e56Smrg 2908f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) { 2909f7df2e56Smrg if (req->groups & bit) { 2910f7df2e56Smrg if (client->swapped) { 2911f7df2e56Smrg swaps(&wire->virtualMods); 2912f7df2e56Smrg } 2913f7df2e56Smrg compat->groups[i].mask = wire->realMods; 2914f7df2e56Smrg compat->groups[i].real_mods = wire->realMods; 2915f7df2e56Smrg compat->groups[i].vmods = wire->virtualMods; 2916f7df2e56Smrg if (wire->virtualMods != 0) { 2917f7df2e56Smrg unsigned tmp; 2918f7df2e56Smrg 2919f7df2e56Smrg tmp = XkbMaskForVMask(xkb, wire->virtualMods); 2920f7df2e56Smrg compat->groups[i].mask |= tmp; 2921f7df2e56Smrg } 2922f7df2e56Smrg data += SIZEOF(xkbModsWireDesc); 2923f7df2e56Smrg wire = (xkbModsWireDesc *) data; 2924f7df2e56Smrg } 2925f7df2e56Smrg } 2926f7df2e56Smrg } 2927f7df2e56Smrg i = XkbPaddedSize((data - ((char *) req))); 2928f7df2e56Smrg if ((i / 4) != req->length) { 2929f7df2e56Smrg ErrorF("[xkb] Internal length error on read in _XkbSetCompatMap\n"); 2930f7df2e56Smrg return BadLength; 293105b261ecSmrg } 29324642e01fSmrg 293305b261ecSmrg if (dev->xkb_interest) { 2934f7df2e56Smrg xkbCompatMapNotify ev; 2935f7df2e56Smrg 2936f7df2e56Smrg ev.deviceID = dev->id; 2937f7df2e56Smrg ev.changedGroups = req->groups; 2938f7df2e56Smrg ev.firstSI = req->firstSI; 2939f7df2e56Smrg ev.nSI = req->nSI; 2940f7df2e56Smrg ev.nTotalSI = compat->num_si; 2941f7df2e56Smrg XkbSendCompatMapNotify(dev, &ev); 294205b261ecSmrg } 294305b261ecSmrg 29444642e01fSmrg if (req->recomputeActions) { 2945f7df2e56Smrg XkbChangesRec change; 2946f7df2e56Smrg unsigned check; 2947f7df2e56Smrg XkbEventCauseRec cause; 2948f7df2e56Smrg 2949f7df2e56Smrg XkbSetCauseXkbReq(&cause, X_kbSetCompatMap, client); 2950f7df2e56Smrg memset(&change, 0, sizeof(XkbChangesRec)); 2951f7df2e56Smrg XkbUpdateActions(dev, xkb->min_key_code, XkbNumKeys(xkb), &change, 2952f7df2e56Smrg &check, &cause); 2953f7df2e56Smrg if (check) 2954f7df2e56Smrg XkbCheckSecondaryEffects(xkbi, check, &change, &cause); 2955f7df2e56Smrg XkbSendNotification(dev, &change, &cause); 295605b261ecSmrg } 29574642e01fSmrg return Success; 29584642e01fSmrg} 29594642e01fSmrg 29604642e01fSmrgint 29614642e01fSmrgProcXkbSetCompatMap(ClientPtr client) 29624642e01fSmrg{ 2963f7df2e56Smrg DeviceIntPtr dev; 2964f7df2e56Smrg char *data; 2965f7df2e56Smrg int rc; 29664642e01fSmrg 29674642e01fSmrg REQUEST(xkbSetCompatMapReq); 29684642e01fSmrg REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq); 29694642e01fSmrg 2970f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 2971f7df2e56Smrg return BadAccess; 29724642e01fSmrg 29734642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); 29744642e01fSmrg 2975f7df2e56Smrg data = (char *) &stuff[1]; 29764642e01fSmrg 29774642e01fSmrg /* check first using a dry-run */ 29784642e01fSmrg rc = _XkbSetCompatMap(client, dev, stuff, data, TRUE); 29794642e01fSmrg if (rc != Success) 29804642e01fSmrg return rc; 2981f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd) { 29824642e01fSmrg DeviceIntPtr other; 2983f7df2e56Smrg 2984f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 2985f7df2e56Smrg if ((other != dev) && other->key && !IsMaster(other) && 2986f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) { 2987f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 2988f7df2e56Smrg DixManageAccess); 2989f7df2e56Smrg if (rc == Success) { 29904642e01fSmrg /* dry-run */ 29914642e01fSmrg rc = _XkbSetCompatMap(client, other, stuff, data, TRUE); 29924642e01fSmrg if (rc != Success) 29934642e01fSmrg return rc; 29944642e01fSmrg } 29954642e01fSmrg } 29964642e01fSmrg } 29974642e01fSmrg } 29984642e01fSmrg 29994642e01fSmrg /* Yay, the dry-runs succeed. Let's apply */ 30004642e01fSmrg rc = _XkbSetCompatMap(client, dev, stuff, data, FALSE); 30014642e01fSmrg if (rc != Success) 30024642e01fSmrg return rc; 3003f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd) { 30044642e01fSmrg DeviceIntPtr other; 3005f7df2e56Smrg 3006f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 3007f7df2e56Smrg if ((other != dev) && other->key && !IsMaster(other) && 3008f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) { 3009f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 3010f7df2e56Smrg DixManageAccess); 3011f7df2e56Smrg if (rc == Success) { 30124642e01fSmrg rc = _XkbSetCompatMap(client, other, stuff, data, FALSE); 30134642e01fSmrg if (rc != Success) 30144642e01fSmrg return rc; 30154642e01fSmrg } 30164642e01fSmrg } 30174642e01fSmrg } 30184642e01fSmrg } 30194642e01fSmrg 30206747b715Smrg return Success; 302105b261ecSmrg} 302205b261ecSmrg 302305b261ecSmrg/***====================================================================***/ 302405b261ecSmrg 302505b261ecSmrgint 302605b261ecSmrgProcXkbGetIndicatorState(ClientPtr client) 302705b261ecSmrg{ 3028f7df2e56Smrg xkbGetIndicatorStateReply rep; 3029f7df2e56Smrg XkbSrvLedInfoPtr sli; 3030f7df2e56Smrg DeviceIntPtr dev; 303105b261ecSmrg 303205b261ecSmrg REQUEST(xkbGetIndicatorStateReq); 303305b261ecSmrg REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq); 303405b261ecSmrg 3035f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 3036f7df2e56Smrg return BadAccess; 303705b261ecSmrg 30384642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess); 303905b261ecSmrg 3040f7df2e56Smrg sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 3041f7df2e56Smrg XkbXI_IndicatorStateMask); 304205b261ecSmrg if (!sli) 3043f7df2e56Smrg return BadAlloc; 304405b261ecSmrg 3045f7df2e56Smrg rep = (xkbGetIndicatorStateReply) { 3046f7df2e56Smrg .type = X_Reply, 3047f7df2e56Smrg .deviceID = dev->id, 3048f7df2e56Smrg .sequenceNumber = client->sequence, 3049f7df2e56Smrg .length = 0, 3050f7df2e56Smrg .state = sli->effectiveState 3051f7df2e56Smrg }; 305205b261ecSmrg 305305b261ecSmrg if (client->swapped) { 3054f7df2e56Smrg swaps(&rep.sequenceNumber); 3055f7df2e56Smrg swapl(&rep.state); 305605b261ecSmrg } 3057f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetIndicatorStateReply), &rep); 30586747b715Smrg return Success; 305905b261ecSmrg} 306005b261ecSmrg 306105b261ecSmrg/***====================================================================***/ 306205b261ecSmrg 306305b261ecSmrgstatic Status 3064f7df2e56SmrgXkbComputeGetIndicatorMapReplySize(XkbIndicatorPtr indicators, 3065f7df2e56Smrg xkbGetIndicatorMapReply * rep) 306605b261ecSmrg{ 3067f7df2e56Smrg register int i, bit; 3068f7df2e56Smrg int nIndicators; 306905b261ecSmrg 307005b261ecSmrg rep->realIndicators = indicators->phys_indicators; 3071f7df2e56Smrg for (i = nIndicators = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 3072f7df2e56Smrg if (rep->which & bit) 3073f7df2e56Smrg nIndicators++; 307405b261ecSmrg } 3075f7df2e56Smrg rep->length = (nIndicators * SIZEOF(xkbIndicatorMapWireDesc)) / 4; 3076f7df2e56Smrg rep->nIndicators = nIndicators; 307705b261ecSmrg return Success; 307805b261ecSmrg} 307905b261ecSmrg 308005b261ecSmrgstatic int 3081f7df2e56SmrgXkbSendIndicatorMap(ClientPtr client, 3082f7df2e56Smrg XkbIndicatorPtr indicators, xkbGetIndicatorMapReply * rep) 308305b261ecSmrg{ 3084f7df2e56Smrg int length; 3085f7df2e56Smrg CARD8 *map; 3086f7df2e56Smrg register int i; 3087f7df2e56Smrg register unsigned bit; 3088f7df2e56Smrg 3089f7df2e56Smrg if (rep->length > 0) { 3090f7df2e56Smrg CARD8 *to; 3091f7df2e56Smrg 3092f7df2e56Smrg to = map = xallocarray(rep->length, 4); 3093f7df2e56Smrg if (map) { 3094f7df2e56Smrg xkbIndicatorMapWireDesc *wire = (xkbIndicatorMapWireDesc *) to; 3095f7df2e56Smrg 3096f7df2e56Smrg length = rep->length * 4; 3097f7df2e56Smrg 3098f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 3099f7df2e56Smrg if (rep->which & bit) { 3100f7df2e56Smrg wire->flags = indicators->maps[i].flags; 3101f7df2e56Smrg wire->whichGroups = indicators->maps[i].which_groups; 3102f7df2e56Smrg wire->groups = indicators->maps[i].groups; 3103f7df2e56Smrg wire->whichMods = indicators->maps[i].which_mods; 3104f7df2e56Smrg wire->mods = indicators->maps[i].mods.mask; 3105f7df2e56Smrg wire->realMods = indicators->maps[i].mods.real_mods; 3106f7df2e56Smrg wire->virtualMods = indicators->maps[i].mods.vmods; 3107f7df2e56Smrg wire->ctrls = indicators->maps[i].ctrls; 3108f7df2e56Smrg if (client->swapped) { 3109f7df2e56Smrg swaps(&wire->virtualMods); 3110f7df2e56Smrg swapl(&wire->ctrls); 3111f7df2e56Smrg } 3112f7df2e56Smrg wire++; 3113f7df2e56Smrg } 3114f7df2e56Smrg } 3115f7df2e56Smrg to = (CARD8 *) wire; 3116f7df2e56Smrg if ((to - map) != length) { 3117f7df2e56Smrg client->errorValue = _XkbErrCode2(0xff, length); 3118f7df2e56Smrg free(map); 3119f7df2e56Smrg return BadLength; 3120f7df2e56Smrg } 3121f7df2e56Smrg } 3122f7df2e56Smrg else 3123f7df2e56Smrg return BadAlloc; 3124f7df2e56Smrg } 3125f7df2e56Smrg else 3126f7df2e56Smrg map = NULL; 312705b261ecSmrg if (client->swapped) { 3128f7df2e56Smrg swaps(&rep->sequenceNumber); 3129f7df2e56Smrg swapl(&rep->length); 3130f7df2e56Smrg swapl(&rep->which); 3131f7df2e56Smrg swapl(&rep->realIndicators); 313205b261ecSmrg } 3133f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetIndicatorMapReply), rep); 313405b261ecSmrg if (map) { 3135f7df2e56Smrg WriteToClient(client, length, map); 3136f7df2e56Smrg free((char *) map); 313705b261ecSmrg } 31386747b715Smrg return Success; 313905b261ecSmrg} 314005b261ecSmrg 314105b261ecSmrgint 314205b261ecSmrgProcXkbGetIndicatorMap(ClientPtr client) 314305b261ecSmrg{ 3144f7df2e56Smrg xkbGetIndicatorMapReply rep; 3145f7df2e56Smrg DeviceIntPtr dev; 3146f7df2e56Smrg XkbDescPtr xkb; 3147f7df2e56Smrg XkbIndicatorPtr leds; 314805b261ecSmrg 314905b261ecSmrg REQUEST(xkbGetIndicatorMapReq); 315005b261ecSmrg REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq); 315105b261ecSmrg 3152f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 3153f7df2e56Smrg return BadAccess; 315405b261ecSmrg 31554642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); 315605b261ecSmrg 3157f7df2e56Smrg xkb = dev->key->xkbInfo->desc; 3158f7df2e56Smrg leds = xkb->indicators; 3159f7df2e56Smrg 3160f7df2e56Smrg rep = (xkbGetIndicatorMapReply) { 3161f7df2e56Smrg .type = X_Reply, 3162f7df2e56Smrg .deviceID = dev->id, 3163f7df2e56Smrg .sequenceNumber = client->sequence, 3164f7df2e56Smrg .length = 0, 3165f7df2e56Smrg .which = stuff->which 3166f7df2e56Smrg }; 3167f7df2e56Smrg XkbComputeGetIndicatorMapReplySize(leds, &rep); 3168f7df2e56Smrg return XkbSendIndicatorMap(client, leds, &rep); 316905b261ecSmrg} 317005b261ecSmrg 31714642e01fSmrg/** 31724642e01fSmrg * Apply the given map to the given device. Which specifies which components 31734642e01fSmrg * to apply. 31744642e01fSmrg */ 31754642e01fSmrgstatic int 31764642e01fSmrg_XkbSetIndicatorMap(ClientPtr client, DeviceIntPtr dev, 3177f7df2e56Smrg int which, xkbIndicatorMapWireDesc * desc) 31784642e01fSmrg{ 3179f7df2e56Smrg XkbSrvInfoPtr xkbi; 3180f7df2e56Smrg XkbSrvLedInfoPtr sli; 3181f7df2e56Smrg XkbEventCauseRec cause; 3182f7df2e56Smrg int i, bit; 31834642e01fSmrg 31844642e01fSmrg xkbi = dev->key->xkbInfo; 31854642e01fSmrg 3186f7df2e56Smrg sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 3187f7df2e56Smrg XkbXI_IndicatorMapsMask); 31884642e01fSmrg if (!sli) 3189f7df2e56Smrg return BadAlloc; 31904642e01fSmrg 31914642e01fSmrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 3192f7df2e56Smrg if (which & bit) { 3193f7df2e56Smrg sli->maps[i].flags = desc->flags; 3194f7df2e56Smrg sli->maps[i].which_groups = desc->whichGroups; 3195f7df2e56Smrg sli->maps[i].groups = desc->groups; 3196f7df2e56Smrg sli->maps[i].which_mods = desc->whichMods; 3197f7df2e56Smrg sli->maps[i].mods.mask = desc->mods; 3198f7df2e56Smrg sli->maps[i].mods.real_mods = desc->mods; 3199f7df2e56Smrg sli->maps[i].mods.vmods = desc->virtualMods; 3200f7df2e56Smrg sli->maps[i].ctrls = desc->ctrls; 3201f7df2e56Smrg if (desc->virtualMods != 0) { 3202f7df2e56Smrg unsigned tmp; 3203f7df2e56Smrg 3204f7df2e56Smrg tmp = XkbMaskForVMask(xkbi->desc, desc->virtualMods); 3205f7df2e56Smrg sli->maps[i].mods.mask = desc->mods | tmp; 3206f7df2e56Smrg } 3207f7df2e56Smrg desc++; 3208f7df2e56Smrg } 3209f7df2e56Smrg } 3210f7df2e56Smrg 3211f7df2e56Smrg XkbSetCauseXkbReq(&cause, X_kbSetIndicatorMap, client); 3212f7df2e56Smrg XkbApplyLedMapChanges(dev, sli, which, NULL, NULL, &cause); 32134642e01fSmrg 32144642e01fSmrg return Success; 32154642e01fSmrg} 32164642e01fSmrg 321705b261ecSmrgint 321805b261ecSmrgProcXkbSetIndicatorMap(ClientPtr client) 321905b261ecSmrg{ 3220f7df2e56Smrg int i, bit; 3221f7df2e56Smrg int nIndicators; 3222f7df2e56Smrg DeviceIntPtr dev; 3223f7df2e56Smrg xkbIndicatorMapWireDesc *from; 3224f7df2e56Smrg int rc; 322505b261ecSmrg 322605b261ecSmrg REQUEST(xkbSetIndicatorMapReq); 322705b261ecSmrg REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq); 322805b261ecSmrg 3229f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 3230f7df2e56Smrg return BadAccess; 323105b261ecSmrg 32324642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess); 323305b261ecSmrg 3234f7df2e56Smrg if (stuff->which == 0) 3235f7df2e56Smrg return Success; 323605b261ecSmrg 3237f7df2e56Smrg for (nIndicators = i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 3238f7df2e56Smrg if (stuff->which & bit) 3239f7df2e56Smrg nIndicators++; 324005b261ecSmrg } 3241f7df2e56Smrg if (stuff->length != ((SIZEOF(xkbSetIndicatorMapReq) + 3242f7df2e56Smrg (nIndicators * SIZEOF(xkbIndicatorMapWireDesc))) / 3243f7df2e56Smrg 4)) { 3244f7df2e56Smrg return BadLength; 324505b261ecSmrg } 324605b261ecSmrg 3247f7df2e56Smrg from = (xkbIndicatorMapWireDesc *) &stuff[1]; 3248f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 3249f7df2e56Smrg if (stuff->which & bit) { 3250f7df2e56Smrg if (client->swapped) { 3251f7df2e56Smrg swaps(&from->virtualMods); 3252f7df2e56Smrg swapl(&from->ctrls); 3253f7df2e56Smrg } 3254f7df2e56Smrg CHK_MASK_LEGAL(i, from->whichGroups, XkbIM_UseAnyGroup); 3255f7df2e56Smrg CHK_MASK_LEGAL(i, from->whichMods, XkbIM_UseAnyMods); 3256f7df2e56Smrg from++; 3257f7df2e56Smrg } 325805b261ecSmrg } 325905b261ecSmrg 3260f7df2e56Smrg from = (xkbIndicatorMapWireDesc *) &stuff[1]; 32614642e01fSmrg rc = _XkbSetIndicatorMap(client, dev, stuff->which, from); 32624642e01fSmrg if (rc != Success) 32634642e01fSmrg return rc; 32644642e01fSmrg 3265f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd) { 32664642e01fSmrg DeviceIntPtr other; 3267f7df2e56Smrg 3268f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 3269f7df2e56Smrg if ((other != dev) && other->key && !IsMaster(other) && 3270f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) { 3271f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 3272f7df2e56Smrg DixSetAttrAccess); 32734642e01fSmrg if (rc == Success) 32744642e01fSmrg _XkbSetIndicatorMap(client, other, stuff->which, from); 32754642e01fSmrg } 32764642e01fSmrg } 327705b261ecSmrg } 327805b261ecSmrg 32794642e01fSmrg return Success; 328005b261ecSmrg} 328105b261ecSmrg 328205b261ecSmrg/***====================================================================***/ 328305b261ecSmrg 328405b261ecSmrgint 328505b261ecSmrgProcXkbGetNamedIndicator(ClientPtr client) 328605b261ecSmrg{ 3287f7df2e56Smrg DeviceIntPtr dev; 3288f7df2e56Smrg xkbGetNamedIndicatorReply rep; 3289f7df2e56Smrg register int i = 0; 3290f7df2e56Smrg XkbSrvLedInfoPtr sli; 3291f7df2e56Smrg XkbIndicatorMapPtr map = NULL; 329205b261ecSmrg 329305b261ecSmrg REQUEST(xkbGetNamedIndicatorReq); 329405b261ecSmrg REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq); 329505b261ecSmrg 3296f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 3297f7df2e56Smrg return BadAccess; 329805b261ecSmrg 32994642e01fSmrg CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess); 330005b261ecSmrg CHK_ATOM_ONLY(stuff->indicator); 330105b261ecSmrg 3302f7df2e56Smrg sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID, 0); 330305b261ecSmrg if (!sli) 3304f7df2e56Smrg return BadAlloc; 3305f7df2e56Smrg 3306f7df2e56Smrg i = 0; 3307f7df2e56Smrg map = NULL; 3308f7df2e56Smrg if ((sli->names) && (sli->maps)) { 3309f7df2e56Smrg for (i = 0; i < XkbNumIndicators; i++) { 3310f7df2e56Smrg if (stuff->indicator == sli->names[i]) { 3311f7df2e56Smrg map = &sli->maps[i]; 331205b261ecSmrg break; 331305b261ecSmrg } 331405b261ecSmrg } 331505b261ecSmrg } 331605b261ecSmrg 3317f7df2e56Smrg rep = (xkbGetNamedIndicatorReply) { 3318f7df2e56Smrg .type = X_Reply, 3319f7df2e56Smrg .sequenceNumber = client->sequence, 3320f7df2e56Smrg .length = 0, 3321f7df2e56Smrg .deviceID = dev->id, 3322f7df2e56Smrg .indicator = stuff->indicator 3323f7df2e56Smrg }; 3324f7df2e56Smrg if (map != NULL) { 3325f7df2e56Smrg rep.found = TRUE; 3326f7df2e56Smrg rep.on = ((sli->effectiveState & (1 << i)) != 0); 3327f7df2e56Smrg rep.realIndicator = ((sli->physIndicators & (1 << i)) != 0); 3328f7df2e56Smrg rep.ndx = i; 3329f7df2e56Smrg rep.flags = map->flags; 3330f7df2e56Smrg rep.whichGroups = map->which_groups; 3331f7df2e56Smrg rep.groups = map->groups; 3332f7df2e56Smrg rep.whichMods = map->which_mods; 3333f7df2e56Smrg rep.mods = map->mods.mask; 3334f7df2e56Smrg rep.realMods = map->mods.real_mods; 3335f7df2e56Smrg rep.virtualMods = map->mods.vmods; 3336f7df2e56Smrg rep.ctrls = map->ctrls; 3337f7df2e56Smrg rep.supported = TRUE; 3338f7df2e56Smrg } 3339f7df2e56Smrg else { 3340f7df2e56Smrg rep.found = FALSE; 3341f7df2e56Smrg rep.on = FALSE; 3342f7df2e56Smrg rep.realIndicator = FALSE; 3343f7df2e56Smrg rep.ndx = XkbNoIndicator; 3344f7df2e56Smrg rep.flags = 0; 3345f7df2e56Smrg rep.whichGroups = 0; 3346f7df2e56Smrg rep.groups = 0; 3347f7df2e56Smrg rep.whichMods = 0; 3348f7df2e56Smrg rep.mods = 0; 3349f7df2e56Smrg rep.realMods = 0; 3350f7df2e56Smrg rep.virtualMods = 0; 3351f7df2e56Smrg rep.ctrls = 0; 3352f7df2e56Smrg rep.supported = TRUE; 3353f7df2e56Smrg } 3354f7df2e56Smrg if (client->swapped) { 3355f7df2e56Smrg swapl(&rep.length); 3356f7df2e56Smrg swaps(&rep.sequenceNumber); 3357f7df2e56Smrg swapl(&rep.indicator); 3358f7df2e56Smrg swaps(&rep.virtualMods); 3359f7df2e56Smrg swapl(&rep.ctrls); 3360f7df2e56Smrg } 3361f7df2e56Smrg 3362f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetNamedIndicatorReply), &rep); 33636747b715Smrg return Success; 336405b261ecSmrg} 336505b261ecSmrg 33664642e01fSmrg/** 33674642e01fSmrg * Find the IM on the device. 33684642e01fSmrg * Returns the map, or NULL if the map doesn't exist. 33694642e01fSmrg * If the return value is NULL, led_return is undefined. Otherwise, led_return 33704642e01fSmrg * is set to the led index of the map. 33714642e01fSmrg */ 33724642e01fSmrgstatic XkbIndicatorMapPtr 3373f7df2e56Smrg_XkbFindNamedIndicatorMap(XkbSrvLedInfoPtr sli, Atom indicator, int *led_return) 33744642e01fSmrg{ 3375f7df2e56Smrg XkbIndicatorMapPtr map; 337605b261ecSmrg 33774642e01fSmrg /* search for the right indicator */ 33784642e01fSmrg map = NULL; 337905b261ecSmrg if (sli->names && sli->maps) { 3380f7df2e56Smrg int led; 33816747b715Smrg 3382f7df2e56Smrg for (led = 0; (led < XkbNumIndicators) && (map == NULL); led++) { 3383f7df2e56Smrg if (sli->names[led] == indicator) { 3384f7df2e56Smrg map = &sli->maps[led]; 3385f7df2e56Smrg *led_return = led; 3386f7df2e56Smrg break; 3387f7df2e56Smrg } 3388f7df2e56Smrg } 338905b261ecSmrg } 339005b261ecSmrg 33914642e01fSmrg return map; 33924642e01fSmrg} 33934642e01fSmrg 33944642e01fSmrg/** 33956747b715Smrg * Creates an indicator map on the device. If dryRun is TRUE, it only checks 33964642e01fSmrg * if creation is possible, but doesn't actually create it. 33974642e01fSmrg */ 33984642e01fSmrgstatic int 33994642e01fSmrg_XkbCreateIndicatorMap(DeviceIntPtr dev, Atom indicator, 34004642e01fSmrg int ledClass, int ledID, 3401f7df2e56Smrg XkbIndicatorMapPtr * map_return, int *led_return, 34024642e01fSmrg Bool dryRun) 34034642e01fSmrg{ 3404f7df2e56Smrg XkbSrvLedInfoPtr sli; 3405f7df2e56Smrg XkbIndicatorMapPtr map; 3406f7df2e56Smrg int led; 34074642e01fSmrg 34084642e01fSmrg sli = XkbFindSrvLedInfo(dev, ledClass, ledID, XkbXI_IndicatorsMask); 34094642e01fSmrg if (!sli) 34104642e01fSmrg return BadAlloc; 34114642e01fSmrg 34124642e01fSmrg map = _XkbFindNamedIndicatorMap(sli, indicator, &led); 34134642e01fSmrg 3414f7df2e56Smrg if (!map) { 34154642e01fSmrg /* find first unused indicator maps and assign the name to it */ 3416f7df2e56Smrg for (led = 0, map = NULL; (led < XkbNumIndicators) && (map == NULL); 3417f7df2e56Smrg led++) { 34184642e01fSmrg if ((sli->names) && (sli->maps) && (sli->names[led] == None) && 3419f7df2e56Smrg (!XkbIM_InUse(&sli->maps[led]))) { 34204642e01fSmrg map = &sli->maps[led]; 34214642e01fSmrg if (!dryRun) 34224642e01fSmrg sli->names[led] = indicator; 34234642e01fSmrg break; 34244642e01fSmrg } 34254642e01fSmrg } 34264642e01fSmrg } 34274642e01fSmrg 34284642e01fSmrg if (!map) 34294642e01fSmrg return BadAlloc; 34304642e01fSmrg 34314642e01fSmrg *led_return = led; 34324642e01fSmrg *map_return = map; 34334642e01fSmrg return Success; 34344642e01fSmrg} 34354642e01fSmrg 34364642e01fSmrgstatic int 34374642e01fSmrg_XkbSetNamedIndicator(ClientPtr client, DeviceIntPtr dev, 3438f7df2e56Smrg xkbSetNamedIndicatorReq * stuff) 34394642e01fSmrg{ 3440f7df2e56Smrg unsigned int extDevReason; 3441f7df2e56Smrg unsigned int statec, namec, mapc; 3442f7df2e56Smrg XkbSrvLedInfoPtr sli; 3443f7df2e56Smrg int led = 0; 3444f7df2e56Smrg XkbIndicatorMapPtr map; 3445f7df2e56Smrg DeviceIntPtr kbd; 3446f7df2e56Smrg XkbEventCauseRec cause; 3447f7df2e56Smrg xkbExtensionDeviceNotify ed; 3448f7df2e56Smrg XkbChangesRec changes; 3449f7df2e56Smrg int rc; 34504642e01fSmrg 34514642e01fSmrg rc = _XkbCreateIndicatorMap(dev, stuff->indicator, stuff->ledClass, 34524642e01fSmrg stuff->ledID, &map, &led, FALSE); 3453f7df2e56Smrg if (rc != Success || !map) /* oh-oh */ 34544642e01fSmrg return rc; 34554642e01fSmrg 34564642e01fSmrg sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID, 34574642e01fSmrg XkbXI_IndicatorsMask); 34584642e01fSmrg if (!sli) 34594642e01fSmrg return BadAlloc; 34604642e01fSmrg 34614642e01fSmrg namec = mapc = statec = 0; 34624642e01fSmrg extDevReason = 0; 34634642e01fSmrg 3464f7df2e56Smrg namec |= (1 << led); 34654642e01fSmrg sli->namesPresent |= ((stuff->indicator != None) ? (1 << led) : 0); 34664642e01fSmrg extDevReason |= XkbXI_IndicatorNamesMask; 34674642e01fSmrg 34684642e01fSmrg if (stuff->setMap) { 34694642e01fSmrg map->flags = stuff->flags; 34704642e01fSmrg map->which_groups = stuff->whichGroups; 34714642e01fSmrg map->groups = stuff->groups; 34724642e01fSmrg map->which_mods = stuff->whichMods; 34734642e01fSmrg map->mods.mask = stuff->realMods; 34744642e01fSmrg map->mods.real_mods = stuff->realMods; 3475f7df2e56Smrg map->mods.vmods = stuff->virtualMods; 34764642e01fSmrg map->ctrls = stuff->ctrls; 3477f7df2e56Smrg mapc |= (1 << led); 34784642e01fSmrg } 34794642e01fSmrg 3480f7df2e56Smrg if ((stuff->setState) && ((map->flags & XkbIM_NoExplicit) == 0)) { 3481f7df2e56Smrg if (stuff->on) 3482f7df2e56Smrg sli->explicitState |= (1 << led); 3483f7df2e56Smrg else 3484f7df2e56Smrg sli->explicitState &= ~(1 << led); 34854642e01fSmrg statec |= ((sli->effectiveState ^ sli->explicitState) & (1 << led)); 348605b261ecSmrg } 34874642e01fSmrg 3488f7df2e56Smrg memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify)); 3489f7df2e56Smrg memset((char *) &changes, 0, sizeof(XkbChangesRec)); 3490f7df2e56Smrg XkbSetCauseXkbReq(&cause, X_kbSetNamedIndicator, client); 349105b261ecSmrg if (namec) 3492f7df2e56Smrg XkbApplyLedNameChanges(dev, sli, namec, &ed, &changes, &cause); 349305b261ecSmrg if (mapc) 3494f7df2e56Smrg XkbApplyLedMapChanges(dev, sli, mapc, &ed, &changes, &cause); 349505b261ecSmrg if (statec) 3496f7df2e56Smrg XkbApplyLedStateChanges(dev, sli, statec, &ed, &changes, &cause); 349705b261ecSmrg 34984642e01fSmrg kbd = dev; 3499f7df2e56Smrg if ((sli->flags & XkbSLI_HasOwnState) == 0) 35004642e01fSmrg kbd = inputInfo.keyboard; 35014642e01fSmrg XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause); 35024642e01fSmrg 35034642e01fSmrg return Success; 35044642e01fSmrg} 35054642e01fSmrg 35064642e01fSmrgint 35074642e01fSmrgProcXkbSetNamedIndicator(ClientPtr client) 35084642e01fSmrg{ 3509f7df2e56Smrg int rc; 3510f7df2e56Smrg DeviceIntPtr dev; 3511f7df2e56Smrg int led = 0; 3512f7df2e56Smrg XkbIndicatorMapPtr map; 35134642e01fSmrg 35144642e01fSmrg REQUEST(xkbSetNamedIndicatorReq); 35154642e01fSmrg REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq); 35164642e01fSmrg 3517f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 3518f7df2e56Smrg return BadAccess; 35194642e01fSmrg 35204642e01fSmrg CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess); 35214642e01fSmrg CHK_ATOM_ONLY(stuff->indicator); 3522f7df2e56Smrg CHK_MASK_LEGAL(0x10, stuff->whichGroups, XkbIM_UseAnyGroup); 3523f7df2e56Smrg CHK_MASK_LEGAL(0x11, stuff->whichMods, XkbIM_UseAnyMods); 35244642e01fSmrg 35254642e01fSmrg /* Dry-run for checks */ 35264642e01fSmrg rc = _XkbCreateIndicatorMap(dev, stuff->indicator, 35274642e01fSmrg stuff->ledClass, stuff->ledID, 35284642e01fSmrg &map, &led, TRUE); 3529f7df2e56Smrg if (rc != Success || !map) /* couldn't be created or didn't exist */ 35304642e01fSmrg return rc; 35314642e01fSmrg 35324642e01fSmrg if (stuff->deviceSpec == XkbUseCoreKbd || 3533f7df2e56Smrg stuff->deviceSpec == XkbUseCorePtr) { 35344642e01fSmrg DeviceIntPtr other; 3535f7df2e56Smrg 3536f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 3537f7df2e56Smrg if ((other != dev) && !IsMaster(other) && 3538f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev && (other->kbdfeed || 3539f7df2e56Smrg other->leds) && 3540f7df2e56Smrg (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) 3541f7df2e56Smrg == Success)) { 35424642e01fSmrg rc = _XkbCreateIndicatorMap(other, stuff->indicator, 3543f7df2e56Smrg stuff->ledClass, stuff->ledID, &map, 3544f7df2e56Smrg &led, TRUE); 35454642e01fSmrg if (rc != Success || !map) 35464642e01fSmrg return rc; 35474642e01fSmrg } 35484642e01fSmrg } 35494642e01fSmrg } 35504642e01fSmrg 35514642e01fSmrg /* All checks passed, let's do it */ 35524642e01fSmrg rc = _XkbSetNamedIndicator(client, dev, stuff); 35534642e01fSmrg if (rc != Success) 35544642e01fSmrg return rc; 35554642e01fSmrg 35564642e01fSmrg if (stuff->deviceSpec == XkbUseCoreKbd || 3557f7df2e56Smrg stuff->deviceSpec == XkbUseCorePtr) { 35584642e01fSmrg DeviceIntPtr other; 3559f7df2e56Smrg 3560f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 3561f7df2e56Smrg if ((other != dev) && !IsMaster(other) && 3562f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev && (other->kbdfeed || 3563f7df2e56Smrg other->leds) && 3564f7df2e56Smrg (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess) 3565f7df2e56Smrg == Success)) { 35664642e01fSmrg _XkbSetNamedIndicator(client, other, stuff); 35674642e01fSmrg } 35684642e01fSmrg } 35694642e01fSmrg } 35704642e01fSmrg 35716747b715Smrg return Success; 357205b261ecSmrg} 357305b261ecSmrg 357405b261ecSmrg/***====================================================================***/ 357505b261ecSmrg 357605b261ecSmrgstatic CARD32 3577f7df2e56Smrg_XkbCountAtoms(Atom *atoms, int maxAtoms, int *count) 357805b261ecSmrg{ 3579f7df2e56Smrg register unsigned int i, bit, nAtoms; 3580f7df2e56Smrg register CARD32 atomsPresent; 358105b261ecSmrg 3582f7df2e56Smrg for (i = nAtoms = atomsPresent = 0, bit = 1; i < maxAtoms; i++, bit <<= 1) { 3583f7df2e56Smrg if (atoms[i] != None) { 3584f7df2e56Smrg atomsPresent |= bit; 3585f7df2e56Smrg nAtoms++; 3586f7df2e56Smrg } 358705b261ecSmrg } 358805b261ecSmrg if (count) 3589f7df2e56Smrg *count = nAtoms; 359005b261ecSmrg return atomsPresent; 359105b261ecSmrg} 359205b261ecSmrg 359305b261ecSmrgstatic char * 3594f7df2e56Smrg_XkbWriteAtoms(char *wire, Atom *atoms, int maxAtoms, int swap) 359505b261ecSmrg{ 3596f7df2e56Smrg register unsigned int i; 3597f7df2e56Smrg Atom *atm; 3598f7df2e56Smrg 3599f7df2e56Smrg atm = (Atom *) wire; 3600f7df2e56Smrg for (i = 0; i < maxAtoms; i++) { 3601f7df2e56Smrg if (atoms[i] != None) { 3602f7df2e56Smrg *atm = atoms[i]; 3603f7df2e56Smrg if (swap) { 3604f7df2e56Smrg swapl(atm); 3605f7df2e56Smrg } 3606f7df2e56Smrg atm++; 3607f7df2e56Smrg } 3608f7df2e56Smrg } 3609f7df2e56Smrg return (char *) atm; 361005b261ecSmrg} 361105b261ecSmrg 361205b261ecSmrgstatic Status 3613f7df2e56SmrgXkbComputeGetNamesReplySize(XkbDescPtr xkb, xkbGetNamesReply * rep) 361405b261ecSmrg{ 3615f7df2e56Smrg register unsigned which, length; 3616f7df2e56Smrg register int i; 3617f7df2e56Smrg 3618f7df2e56Smrg rep->minKeyCode = xkb->min_key_code; 3619f7df2e56Smrg rep->maxKeyCode = xkb->max_key_code; 3620f7df2e56Smrg which = rep->which; 3621f7df2e56Smrg length = 0; 3622f7df2e56Smrg if (xkb->names != NULL) { 3623f7df2e56Smrg if (which & XkbKeycodesNameMask) 3624f7df2e56Smrg length++; 3625f7df2e56Smrg if (which & XkbGeometryNameMask) 3626f7df2e56Smrg length++; 3627f7df2e56Smrg if (which & XkbSymbolsNameMask) 3628f7df2e56Smrg length++; 3629f7df2e56Smrg if (which & XkbPhysSymbolsNameMask) 3630f7df2e56Smrg length++; 3631f7df2e56Smrg if (which & XkbTypesNameMask) 3632f7df2e56Smrg length++; 3633f7df2e56Smrg if (which & XkbCompatNameMask) 3634f7df2e56Smrg length++; 3635f7df2e56Smrg } 3636f7df2e56Smrg else 3637f7df2e56Smrg which &= ~XkbComponentNamesMask; 3638f7df2e56Smrg 3639f7df2e56Smrg if (xkb->map != NULL) { 3640f7df2e56Smrg if (which & XkbKeyTypeNamesMask) 3641f7df2e56Smrg length += xkb->map->num_types; 3642f7df2e56Smrg rep->nTypes = xkb->map->num_types; 3643f7df2e56Smrg if (which & XkbKTLevelNamesMask) { 3644f7df2e56Smrg XkbKeyTypePtr pType = xkb->map->types; 3645f7df2e56Smrg int nKTLevels = 0; 3646f7df2e56Smrg 3647f7df2e56Smrg length += XkbPaddedSize(xkb->map->num_types) / 4; 3648f7df2e56Smrg for (i = 0; i < xkb->map->num_types; i++, pType++) { 3649f7df2e56Smrg if (pType->level_names != NULL) 3650f7df2e56Smrg nKTLevels += pType->num_levels; 3651f7df2e56Smrg } 3652f7df2e56Smrg rep->nKTLevels = nKTLevels; 3653f7df2e56Smrg length += nKTLevels; 3654f7df2e56Smrg } 365505b261ecSmrg } 365605b261ecSmrg else { 3657f7df2e56Smrg rep->nTypes = 0; 3658f7df2e56Smrg rep->nKTLevels = 0; 3659f7df2e56Smrg which &= ~(XkbKeyTypeNamesMask | XkbKTLevelNamesMask); 3660f7df2e56Smrg } 3661f7df2e56Smrg 3662f7df2e56Smrg rep->minKeyCode = xkb->min_key_code; 3663f7df2e56Smrg rep->maxKeyCode = xkb->max_key_code; 3664f7df2e56Smrg rep->indicators = 0; 3665f7df2e56Smrg rep->virtualMods = 0; 3666f7df2e56Smrg rep->groupNames = 0; 3667f7df2e56Smrg if (xkb->names != NULL) { 3668f7df2e56Smrg if (which & XkbIndicatorNamesMask) { 3669f7df2e56Smrg int nLeds; 3670f7df2e56Smrg 3671f7df2e56Smrg rep->indicators = 3672f7df2e56Smrg _XkbCountAtoms(xkb->names->indicators, XkbNumIndicators, 3673f7df2e56Smrg &nLeds); 3674f7df2e56Smrg length += nLeds; 3675f7df2e56Smrg if (nLeds == 0) 3676f7df2e56Smrg which &= ~XkbIndicatorNamesMask; 3677f7df2e56Smrg } 3678f7df2e56Smrg 3679f7df2e56Smrg if (which & XkbVirtualModNamesMask) { 3680f7df2e56Smrg int nVMods; 3681f7df2e56Smrg 3682f7df2e56Smrg rep->virtualMods = 3683f7df2e56Smrg _XkbCountAtoms(xkb->names->vmods, XkbNumVirtualMods, &nVMods); 3684f7df2e56Smrg length += nVMods; 3685f7df2e56Smrg if (nVMods == 0) 3686f7df2e56Smrg which &= ~XkbVirtualModNamesMask; 3687f7df2e56Smrg } 3688f7df2e56Smrg 3689f7df2e56Smrg if (which & XkbGroupNamesMask) { 3690f7df2e56Smrg int nGroups; 3691f7df2e56Smrg 3692f7df2e56Smrg rep->groupNames = 3693f7df2e56Smrg _XkbCountAtoms(xkb->names->groups, XkbNumKbdGroups, &nGroups); 3694f7df2e56Smrg length += nGroups; 3695f7df2e56Smrg if (nGroups == 0) 3696f7df2e56Smrg which &= ~XkbGroupNamesMask; 3697f7df2e56Smrg } 3698f7df2e56Smrg 3699f7df2e56Smrg if ((which & XkbKeyNamesMask) && (xkb->names->keys)) 3700f7df2e56Smrg length += rep->nKeys; 3701f7df2e56Smrg else 3702f7df2e56Smrg which &= ~XkbKeyNamesMask; 3703f7df2e56Smrg 3704f7df2e56Smrg if ((which & XkbKeyAliasesMask) && 3705f7df2e56Smrg (xkb->names->key_aliases) && (xkb->names->num_key_aliases > 0)) { 3706f7df2e56Smrg rep->nKeyAliases = xkb->names->num_key_aliases; 3707f7df2e56Smrg length += rep->nKeyAliases * 2; 3708f7df2e56Smrg } 3709f7df2e56Smrg else { 3710f7df2e56Smrg which &= ~XkbKeyAliasesMask; 3711f7df2e56Smrg rep->nKeyAliases = 0; 3712f7df2e56Smrg } 3713f7df2e56Smrg 3714f7df2e56Smrg if ((which & XkbRGNamesMask) && (xkb->names->num_rg > 0)) 3715f7df2e56Smrg length += xkb->names->num_rg; 3716f7df2e56Smrg else 3717f7df2e56Smrg which &= ~XkbRGNamesMask; 371805b261ecSmrg } 371905b261ecSmrg else { 3720f7df2e56Smrg which &= ~(XkbIndicatorNamesMask | XkbVirtualModNamesMask); 3721f7df2e56Smrg which &= ~(XkbGroupNamesMask | XkbKeyNamesMask | XkbKeyAliasesMask); 3722f7df2e56Smrg which &= ~XkbRGNamesMask; 372305b261ecSmrg } 372405b261ecSmrg 3725f7df2e56Smrg rep->length = length; 3726f7df2e56Smrg rep->which = which; 372705b261ecSmrg return Success; 372805b261ecSmrg} 372905b261ecSmrg 373005b261ecSmrgstatic int 3731f7df2e56SmrgXkbSendNames(ClientPtr client, XkbDescPtr xkb, xkbGetNamesReply * rep) 373205b261ecSmrg{ 3733f7df2e56Smrg register unsigned i, length, which; 3734f7df2e56Smrg char *start; 3735f7df2e56Smrg char *desc; 373605b261ecSmrg 3737f7df2e56Smrg length = rep->length * 4; 3738f7df2e56Smrg which = rep->which; 373905b261ecSmrg if (client->swapped) { 3740f7df2e56Smrg swaps(&rep->sequenceNumber); 3741f7df2e56Smrg swapl(&rep->length); 3742f7df2e56Smrg swapl(&rep->which); 3743f7df2e56Smrg swaps(&rep->virtualMods); 3744f7df2e56Smrg swapl(&rep->indicators); 374505b261ecSmrg } 374605b261ecSmrg 37479ace9065Smrg start = desc = calloc(1, length); 3748f7df2e56Smrg if (!start) 3749f7df2e56Smrg return BadAlloc; 375005b261ecSmrg if (xkb->names) { 3751f7df2e56Smrg if (which & XkbKeycodesNameMask) { 3752f7df2e56Smrg *((CARD32 *) desc) = xkb->names->keycodes; 375305b261ecSmrg if (client->swapped) { 3754f7df2e56Smrg swapl((int *) desc); 375505b261ecSmrg } 3756f7df2e56Smrg desc += 4; 375705b261ecSmrg } 3758f7df2e56Smrg if (which & XkbGeometryNameMask) { 3759f7df2e56Smrg *((CARD32 *) desc) = xkb->names->geometry; 376005b261ecSmrg if (client->swapped) { 3761f7df2e56Smrg swapl((int *) desc); 376205b261ecSmrg } 3763f7df2e56Smrg desc += 4; 376405b261ecSmrg } 3765f7df2e56Smrg if (which & XkbSymbolsNameMask) { 3766f7df2e56Smrg *((CARD32 *) desc) = xkb->names->symbols; 376705b261ecSmrg if (client->swapped) { 3768f7df2e56Smrg swapl((int *) desc); 376905b261ecSmrg } 3770f7df2e56Smrg desc += 4; 377105b261ecSmrg } 3772f7df2e56Smrg if (which & XkbPhysSymbolsNameMask) { 3773f7df2e56Smrg register CARD32 *atm = (CARD32 *) desc; 3774f7df2e56Smrg 3775f7df2e56Smrg atm[0] = (CARD32) xkb->names->phys_symbols; 377605b261ecSmrg if (client->swapped) { 3777f7df2e56Smrg swapl(&atm[0]); 377805b261ecSmrg } 3779f7df2e56Smrg desc += 4; 378005b261ecSmrg } 3781f7df2e56Smrg if (which & XkbTypesNameMask) { 3782f7df2e56Smrg *((CARD32 *) desc) = (CARD32) xkb->names->types; 378305b261ecSmrg if (client->swapped) { 3784f7df2e56Smrg swapl((int *) desc); 378505b261ecSmrg } 3786f7df2e56Smrg desc += 4; 378705b261ecSmrg } 3788f7df2e56Smrg if (which & XkbCompatNameMask) { 3789f7df2e56Smrg *((CARD32 *) desc) = (CARD32) xkb->names->compat; 379005b261ecSmrg if (client->swapped) { 3791f7df2e56Smrg swapl((int *) desc); 379205b261ecSmrg } 3793f7df2e56Smrg desc += 4; 379405b261ecSmrg } 3795f7df2e56Smrg if (which & XkbKeyTypeNamesMask) { 3796f7df2e56Smrg register CARD32 *atm = (CARD32 *) desc; 3797f7df2e56Smrg register XkbKeyTypePtr type = xkb->map->types; 379805b261ecSmrg 3799f7df2e56Smrg for (i = 0; i < xkb->map->num_types; i++, atm++, type++) { 3800f7df2e56Smrg *atm = (CARD32) type->name; 380105b261ecSmrg if (client->swapped) { 3802f7df2e56Smrg swapl(atm); 380305b261ecSmrg } 380405b261ecSmrg } 3805f7df2e56Smrg desc = (char *) atm; 380605b261ecSmrg } 3807f7df2e56Smrg if (which & XkbKTLevelNamesMask && xkb->map) { 380805b261ecSmrg XkbKeyTypePtr type = xkb->map->types; 380905b261ecSmrg register CARD32 *atm; 3810f7df2e56Smrg 3811f7df2e56Smrg for (i = 0; i < rep->nTypes; i++, type++) { 381205b261ecSmrg *desc++ = type->num_levels; 381305b261ecSmrg } 3814f7df2e56Smrg desc += XkbPaddedSize(rep->nTypes) - rep->nTypes; 381505b261ecSmrg 3816f7df2e56Smrg atm = (CARD32 *) desc; 381705b261ecSmrg type = xkb->map->types; 3818f7df2e56Smrg for (i = 0; i < xkb->map->num_types; i++, type++) { 381905b261ecSmrg register unsigned l; 3820f7df2e56Smrg 382105b261ecSmrg if (type->level_names) { 3822f7df2e56Smrg for (l = 0; l < type->num_levels; l++, atm++) { 3823f7df2e56Smrg *atm = type->level_names[l]; 382405b261ecSmrg if (client->swapped) { 3825f7df2e56Smrg swapl(atm); 382605b261ecSmrg } 382705b261ecSmrg } 3828f7df2e56Smrg desc += type->num_levels * 4; 382905b261ecSmrg } 383005b261ecSmrg } 383105b261ecSmrg } 3832f7df2e56Smrg if (which & XkbIndicatorNamesMask) { 3833f7df2e56Smrg desc = 3834f7df2e56Smrg _XkbWriteAtoms(desc, xkb->names->indicators, XkbNumIndicators, 3835f7df2e56Smrg client->swapped); 383605b261ecSmrg } 3837f7df2e56Smrg if (which & XkbVirtualModNamesMask) { 3838f7df2e56Smrg desc = _XkbWriteAtoms(desc, xkb->names->vmods, XkbNumVirtualMods, 3839f7df2e56Smrg client->swapped); 384005b261ecSmrg } 3841f7df2e56Smrg if (which & XkbGroupNamesMask) { 3842f7df2e56Smrg desc = _XkbWriteAtoms(desc, xkb->names->groups, XkbNumKbdGroups, 3843f7df2e56Smrg client->swapped); 384405b261ecSmrg } 3845f7df2e56Smrg if (which & XkbKeyNamesMask) { 3846f7df2e56Smrg for (i = 0; i < rep->nKeys; i++, desc += sizeof(XkbKeyNameRec)) { 3847f7df2e56Smrg *((XkbKeyNamePtr) desc) = xkb->names->keys[i + rep->firstKey]; 384805b261ecSmrg } 384905b261ecSmrg } 3850f7df2e56Smrg if (which & XkbKeyAliasesMask) { 3851f7df2e56Smrg XkbKeyAliasPtr pAl; 3852f7df2e56Smrg 3853f7df2e56Smrg pAl = xkb->names->key_aliases; 3854f7df2e56Smrg for (i = 0; i < rep->nKeyAliases; 3855f7df2e56Smrg i++, pAl++, desc += 2 * XkbKeyNameLength) { 3856f7df2e56Smrg *((XkbKeyAliasPtr) desc) = *pAl; 385705b261ecSmrg } 385805b261ecSmrg } 3859f7df2e56Smrg if ((which & XkbRGNamesMask) && (rep->nRadioGroups > 0)) { 3860f7df2e56Smrg register CARD32 *atm = (CARD32 *) desc; 3861f7df2e56Smrg 3862f7df2e56Smrg for (i = 0; i < rep->nRadioGroups; i++, atm++) { 3863f7df2e56Smrg *atm = (CARD32) xkb->names->radio_groups[i]; 386405b261ecSmrg if (client->swapped) { 3865f7df2e56Smrg swapl(atm); 386605b261ecSmrg } 386705b261ecSmrg } 3868f7df2e56Smrg desc += rep->nRadioGroups * 4; 386905b261ecSmrg } 387005b261ecSmrg } 387105b261ecSmrg 3872f7df2e56Smrg if ((desc - start) != (length)) { 3873f7df2e56Smrg ErrorF("[xkb] BOGUS LENGTH in write names, expected %d, got %ld\n", 3874f7df2e56Smrg length, (unsigned long) (desc - start)); 387505b261ecSmrg } 3876f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetNamesReply), rep); 387705b261ecSmrg WriteToClient(client, length, start); 3878f7df2e56Smrg free((char *) start); 38796747b715Smrg return Success; 388005b261ecSmrg} 388105b261ecSmrg 388205b261ecSmrgint 388305b261ecSmrgProcXkbGetNames(ClientPtr client) 388405b261ecSmrg{ 3885f7df2e56Smrg DeviceIntPtr dev; 3886f7df2e56Smrg XkbDescPtr xkb; 3887f7df2e56Smrg xkbGetNamesReply rep; 388805b261ecSmrg 388905b261ecSmrg REQUEST(xkbGetNamesReq); 389005b261ecSmrg REQUEST_SIZE_MATCH(xkbGetNamesReq); 389105b261ecSmrg 3892f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 3893f7df2e56Smrg return BadAccess; 389405b261ecSmrg 38954642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); 3896f7df2e56Smrg CHK_MASK_LEGAL(0x01, stuff->which, XkbAllNamesMask); 389705b261ecSmrg 389805b261ecSmrg xkb = dev->key->xkbInfo->desc; 3899f7df2e56Smrg rep = (xkbGetNamesReply) { 3900f7df2e56Smrg .type = X_Reply, 3901f7df2e56Smrg .deviceID = dev->id, 3902f7df2e56Smrg .sequenceNumber = client->sequence, 3903f7df2e56Smrg .length = 0, 3904f7df2e56Smrg .which = stuff->which, 3905f7df2e56Smrg .nTypes = xkb->map->num_types, 3906f7df2e56Smrg .firstKey = xkb->min_key_code, 3907f7df2e56Smrg .nKeys = XkbNumKeys(xkb), 3908f7df2e56Smrg .nKeyAliases = xkb->names ? xkb->names->num_key_aliases : 0, 3909f7df2e56Smrg .nRadioGroups = xkb->names ? xkb->names->num_rg : 0 3910f7df2e56Smrg }; 3911f7df2e56Smrg XkbComputeGetNamesReplySize(xkb, &rep); 3912f7df2e56Smrg return XkbSendNames(client, xkb, &rep); 391305b261ecSmrg} 391405b261ecSmrg 391505b261ecSmrg/***====================================================================***/ 391605b261ecSmrg 391705b261ecSmrgstatic CARD32 * 3918f7df2e56Smrg_XkbCheckAtoms(CARD32 *wire, int nAtoms, int swapped, Atom *pError) 391905b261ecSmrg{ 3920f7df2e56Smrg register int i; 3921f7df2e56Smrg 3922f7df2e56Smrg for (i = 0; i < nAtoms; i++, wire++) { 3923f7df2e56Smrg if (swapped) { 3924f7df2e56Smrg swapl(wire); 3925f7df2e56Smrg } 3926f7df2e56Smrg if ((((Atom) *wire) != None) && (!ValidAtom((Atom) *wire))) { 3927f7df2e56Smrg *pError = ((Atom) *wire); 3928f7df2e56Smrg return NULL; 3929f7df2e56Smrg } 393005b261ecSmrg } 393105b261ecSmrg return wire; 393205b261ecSmrg} 393305b261ecSmrg 393405b261ecSmrgstatic CARD32 * 3935f7df2e56Smrg_XkbCheckMaskedAtoms(CARD32 *wire, int nAtoms, CARD32 present, int swapped, 3936f7df2e56Smrg Atom *pError) 393705b261ecSmrg{ 3938f7df2e56Smrg register unsigned i, bit; 3939f7df2e56Smrg 3940f7df2e56Smrg for (i = 0, bit = 1; (i < nAtoms) && (present); i++, bit <<= 1) { 3941f7df2e56Smrg if ((present & bit) == 0) 3942f7df2e56Smrg continue; 3943f7df2e56Smrg if (swapped) { 3944f7df2e56Smrg swapl(wire); 3945f7df2e56Smrg } 3946f7df2e56Smrg if ((((Atom) *wire) != None) && (!ValidAtom(((Atom) *wire)))) { 3947f7df2e56Smrg *pError = (Atom) *wire; 3948f7df2e56Smrg return NULL; 3949f7df2e56Smrg } 3950f7df2e56Smrg wire++; 395105b261ecSmrg } 395205b261ecSmrg return wire; 395305b261ecSmrg} 395405b261ecSmrg 395505b261ecSmrgstatic Atom * 3956f7df2e56Smrg_XkbCopyMaskedAtoms(Atom *wire, Atom *dest, int nAtoms, CARD32 present) 395705b261ecSmrg{ 3958f7df2e56Smrg register int i, bit; 395905b261ecSmrg 3960f7df2e56Smrg for (i = 0, bit = 1; (i < nAtoms) && (present); i++, bit <<= 1) { 3961f7df2e56Smrg if ((present & bit) == 0) 3962f7df2e56Smrg continue; 3963f7df2e56Smrg dest[i] = *wire++; 396405b261ecSmrg } 396505b261ecSmrg return wire; 396605b261ecSmrg} 396705b261ecSmrg 396805b261ecSmrgstatic Bool 3969f7df2e56Smrg_XkbCheckTypeName(Atom name, int typeNdx) 397005b261ecSmrg{ 3971f7df2e56Smrg const char *str; 397205b261ecSmrg 3973f7df2e56Smrg str = NameForAtom(name); 3974f7df2e56Smrg if ((strcmp(str, "ONE_LEVEL") == 0) || (strcmp(str, "TWO_LEVEL") == 0) || 3975f7df2e56Smrg (strcmp(str, "ALPHABETIC") == 0) || (strcmp(str, "KEYPAD") == 0)) 3976f7df2e56Smrg return FALSE; 39776747b715Smrg return TRUE; 397805b261ecSmrg} 397905b261ecSmrg 39804642e01fSmrg/** 39814642e01fSmrg * Check the device-dependent data in the request against the device. Returns 39824642e01fSmrg * Success, or the appropriate error code. 39834642e01fSmrg */ 39844642e01fSmrgstatic int 39854642e01fSmrg_XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev, 3986f7df2e56Smrg xkbSetNamesReq * stuff, CARD32 *data) 398705b261ecSmrg{ 3988f7df2e56Smrg XkbDescRec *xkb; 3989f7df2e56Smrg CARD32 *tmp; 3990f7df2e56Smrg Atom bad = None; 399105b261ecSmrg 39924642e01fSmrg tmp = data; 39934642e01fSmrg xkb = dev->key->xkbInfo->desc; 39944642e01fSmrg 39954642e01fSmrg if (stuff->which & XkbKeyTypeNamesMask) { 39964642e01fSmrg int i; 3997f7df2e56Smrg CARD32 *old; 3998f7df2e56Smrg 3999f7df2e56Smrg if (stuff->nTypes < 1) { 4000f7df2e56Smrg client->errorValue = _XkbErrCode2(0x02, stuff->nTypes); 40014642e01fSmrg return BadValue; 40024642e01fSmrg } 4003f7df2e56Smrg if ((unsigned) (stuff->firstType + stuff->nTypes - 1) >= 4004f7df2e56Smrg xkb->map->num_types) { 4005f7df2e56Smrg client->errorValue = 4006f7df2e56Smrg _XkbErrCode4(0x03, stuff->firstType, stuff->nTypes, 4007f7df2e56Smrg xkb->map->num_types); 40084642e01fSmrg return BadValue; 40094642e01fSmrg } 4010f7df2e56Smrg if (((unsigned) stuff->firstType) <= XkbLastRequiredType) { 4011f7df2e56Smrg client->errorValue = _XkbErrCode2(0x04, stuff->firstType); 40124642e01fSmrg return BadAccess; 40134642e01fSmrg } 4014f7df2e56Smrg old = tmp; 4015f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, stuff->nTypes, client->swapped, &bad); 40164642e01fSmrg if (!tmp) { 4017f7df2e56Smrg client->errorValue = bad; 40184642e01fSmrg return BadAtom; 40194642e01fSmrg } 4020f7df2e56Smrg for (i = 0; i < stuff->nTypes; i++, old++) { 4021f7df2e56Smrg if (!_XkbCheckTypeName((Atom) *old, stuff->firstType + i)) 4022f7df2e56Smrg client->errorValue = _XkbErrCode2(0x05, i); 40234642e01fSmrg } 40244642e01fSmrg } 4025f7df2e56Smrg if (stuff->which & XkbKTLevelNamesMask) { 40264642e01fSmrg unsigned i; 4027f7df2e56Smrg XkbKeyTypePtr type; 4028f7df2e56Smrg CARD8 *width; 4029f7df2e56Smrg 4030f7df2e56Smrg if (stuff->nKTLevels < 1) { 4031f7df2e56Smrg client->errorValue = _XkbErrCode2(0x05, stuff->nKTLevels); 40324642e01fSmrg return BadValue; 40334642e01fSmrg } 4034f7df2e56Smrg if ((unsigned) (stuff->firstKTLevel + stuff->nKTLevels - 1) >= 4035f7df2e56Smrg xkb->map->num_types) { 4036f7df2e56Smrg client->errorValue = _XkbErrCode4(0x06, stuff->firstKTLevel, 4037f7df2e56Smrg stuff->nKTLevels, 4038f7df2e56Smrg xkb->map->num_types); 40394642e01fSmrg return BadValue; 40404642e01fSmrg } 4041f7df2e56Smrg width = (CARD8 *) tmp; 4042f7df2e56Smrg tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels)); 40434642e01fSmrg type = &xkb->map->types[stuff->firstKTLevel]; 4044f7df2e56Smrg for (i = 0; i < stuff->nKTLevels; i++, type++) { 4045f7df2e56Smrg if (width[i] == 0) 40464642e01fSmrg continue; 4047f7df2e56Smrg else if (width[i] != type->num_levels) { 4048f7df2e56Smrg client->errorValue = _XkbErrCode4(0x07, i + stuff->firstKTLevel, 4049f7df2e56Smrg type->num_levels, width[i]); 40504642e01fSmrg return BadMatch; 40514642e01fSmrg } 4052f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, width[i], client->swapped, &bad); 40534642e01fSmrg if (!tmp) { 4054f7df2e56Smrg client->errorValue = bad; 40554642e01fSmrg return BadAtom; 40564642e01fSmrg } 40574642e01fSmrg } 40584642e01fSmrg } 4059f7df2e56Smrg if (stuff->which & XkbIndicatorNamesMask) { 4060f7df2e56Smrg if (stuff->indicators == 0) { 4061f7df2e56Smrg client->errorValue = 0x08; 40624642e01fSmrg return BadMatch; 40634642e01fSmrg } 4064f7df2e56Smrg tmp = _XkbCheckMaskedAtoms(tmp, XkbNumIndicators, stuff->indicators, 4065f7df2e56Smrg client->swapped, &bad); 40664642e01fSmrg if (!tmp) { 4067f7df2e56Smrg client->errorValue = bad; 40684642e01fSmrg return BadAtom; 40694642e01fSmrg } 40704642e01fSmrg } 4071f7df2e56Smrg if (stuff->which & XkbVirtualModNamesMask) { 4072f7df2e56Smrg if (stuff->virtualMods == 0) { 4073f7df2e56Smrg client->errorValue = 0x09; 40744642e01fSmrg return BadMatch; 40754642e01fSmrg } 4076f7df2e56Smrg tmp = _XkbCheckMaskedAtoms(tmp, XkbNumVirtualMods, 4077f7df2e56Smrg (CARD32) stuff->virtualMods, 4078f7df2e56Smrg client->swapped, &bad); 40794642e01fSmrg if (!tmp) { 40804642e01fSmrg client->errorValue = bad; 40814642e01fSmrg return BadAtom; 40824642e01fSmrg } 40834642e01fSmrg } 4084f7df2e56Smrg if (stuff->which & XkbGroupNamesMask) { 4085f7df2e56Smrg if (stuff->groupNames == 0) { 4086f7df2e56Smrg client->errorValue = 0x0a; 40874642e01fSmrg return BadMatch; 40884642e01fSmrg } 4089f7df2e56Smrg tmp = _XkbCheckMaskedAtoms(tmp, XkbNumKbdGroups, 4090f7df2e56Smrg (CARD32) stuff->groupNames, 4091f7df2e56Smrg client->swapped, &bad); 40924642e01fSmrg if (!tmp) { 40934642e01fSmrg client->errorValue = bad; 40944642e01fSmrg return BadAtom; 40954642e01fSmrg } 40964642e01fSmrg } 4097f7df2e56Smrg if (stuff->which & XkbKeyNamesMask) { 4098f7df2e56Smrg if (stuff->firstKey < (unsigned) xkb->min_key_code) { 4099f7df2e56Smrg client->errorValue = _XkbErrCode3(0x0b, xkb->min_key_code, 4100f7df2e56Smrg stuff->firstKey); 41014642e01fSmrg return BadValue; 41024642e01fSmrg } 4103f7df2e56Smrg if (((unsigned) (stuff->firstKey + stuff->nKeys - 1) > 4104f7df2e56Smrg xkb->max_key_code) || (stuff->nKeys < 1)) { 4105f7df2e56Smrg client->errorValue = 4106f7df2e56Smrg _XkbErrCode4(0x0c, xkb->max_key_code, stuff->firstKey, 4107f7df2e56Smrg stuff->nKeys); 41084642e01fSmrg return BadValue; 41094642e01fSmrg } 4110f7df2e56Smrg tmp += stuff->nKeys; 41114642e01fSmrg } 4112f7df2e56Smrg if ((stuff->which & XkbKeyAliasesMask) && (stuff->nKeyAliases > 0)) { 4113f7df2e56Smrg tmp += stuff->nKeyAliases * 2; 41144642e01fSmrg } 4115f7df2e56Smrg if (stuff->which & XkbRGNamesMask) { 4116f7df2e56Smrg if (stuff->nRadioGroups < 1) { 4117f7df2e56Smrg client->errorValue = _XkbErrCode2(0x0d, stuff->nRadioGroups); 41184642e01fSmrg return BadValue; 41194642e01fSmrg } 4120f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, stuff->nRadioGroups, client->swapped, &bad); 41214642e01fSmrg if (!tmp) { 4122f7df2e56Smrg client->errorValue = bad; 41234642e01fSmrg return BadAtom; 41244642e01fSmrg } 41254642e01fSmrg } 4126f7df2e56Smrg if ((tmp - ((CARD32 *) stuff)) != stuff->length) { 41274642e01fSmrg client->errorValue = stuff->length; 41284642e01fSmrg return BadLength; 41294642e01fSmrg } 41304642e01fSmrg 41314642e01fSmrg return Success; 41324642e01fSmrg} 41334642e01fSmrg 41344642e01fSmrgstatic int 4135f7df2e56Smrg_XkbSetNames(ClientPtr client, DeviceIntPtr dev, xkbSetNamesReq * stuff) 41364642e01fSmrg{ 4137f7df2e56Smrg XkbDescRec *xkb; 4138f7df2e56Smrg XkbNamesRec *names; 4139f7df2e56Smrg CARD32 *tmp; 4140f7df2e56Smrg xkbNamesNotify nn; 41414642e01fSmrg 4142f7df2e56Smrg tmp = (CARD32 *) &stuff[1]; 41434642e01fSmrg xkb = dev->key->xkbInfo->desc; 41444642e01fSmrg names = xkb->names; 41454642e01fSmrg 4146f7df2e56Smrg if (XkbAllocNames(xkb, stuff->which, stuff->nRadioGroups, 4147f7df2e56Smrg stuff->nKeyAliases) != Success) { 41484642e01fSmrg return BadAlloc; 41494642e01fSmrg } 41504642e01fSmrg 41516747b715Smrg memset(&nn, 0, sizeof(xkbNamesNotify)); 4152f7df2e56Smrg nn.changed = stuff->which; 4153f7df2e56Smrg tmp = (CARD32 *) &stuff[1]; 4154f7df2e56Smrg if (stuff->which & XkbKeycodesNameMask) 4155f7df2e56Smrg names->keycodes = *tmp++; 4156f7df2e56Smrg if (stuff->which & XkbGeometryNameMask) 4157f7df2e56Smrg names->geometry = *tmp++; 4158f7df2e56Smrg if (stuff->which & XkbSymbolsNameMask) 4159f7df2e56Smrg names->symbols = *tmp++; 4160f7df2e56Smrg if (stuff->which & XkbPhysSymbolsNameMask) 4161f7df2e56Smrg names->phys_symbols = *tmp++; 4162f7df2e56Smrg if (stuff->which & XkbTypesNameMask) 4163f7df2e56Smrg names->types = *tmp++; 4164f7df2e56Smrg if (stuff->which & XkbCompatNameMask) 4165f7df2e56Smrg names->compat = *tmp++; 4166f7df2e56Smrg if ((stuff->which & XkbKeyTypeNamesMask) && (stuff->nTypes > 0)) { 41674642e01fSmrg register unsigned i; 41684642e01fSmrg register XkbKeyTypePtr type; 41694642e01fSmrg 4170f7df2e56Smrg type = &xkb->map->types[stuff->firstType]; 4171f7df2e56Smrg for (i = 0; i < stuff->nTypes; i++, type++) { 4172f7df2e56Smrg type->name = *tmp++; 41734642e01fSmrg } 4174f7df2e56Smrg nn.firstType = stuff->firstType; 4175f7df2e56Smrg nn.nTypes = stuff->nTypes; 41764642e01fSmrg } 4177f7df2e56Smrg if (stuff->which & XkbKTLevelNamesMask) { 4178f7df2e56Smrg register XkbKeyTypePtr type; 41794642e01fSmrg register unsigned i; 41804642e01fSmrg CARD8 *width; 41814642e01fSmrg 4182f7df2e56Smrg width = (CARD8 *) tmp; 4183f7df2e56Smrg tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels)); 4184f7df2e56Smrg type = &xkb->map->types[stuff->firstKTLevel]; 4185f7df2e56Smrg for (i = 0; i < stuff->nKTLevels; i++, type++) { 4186f7df2e56Smrg if (width[i] > 0) { 41874642e01fSmrg if (type->level_names) { 41884642e01fSmrg register unsigned n; 4189f7df2e56Smrg 4190f7df2e56Smrg for (n = 0; n < width[i]; n++) { 4191f7df2e56Smrg type->level_names[n] = tmp[n]; 41924642e01fSmrg } 41934642e01fSmrg } 4194f7df2e56Smrg tmp += width[i]; 41954642e01fSmrg } 41964642e01fSmrg } 4197f7df2e56Smrg nn.firstLevelName = 0; 4198f7df2e56Smrg nn.nLevelNames = stuff->nTypes; 4199f7df2e56Smrg } 4200f7df2e56Smrg if (stuff->which & XkbIndicatorNamesMask) { 4201f7df2e56Smrg tmp = _XkbCopyMaskedAtoms(tmp, names->indicators, XkbNumIndicators, 4202f7df2e56Smrg stuff->indicators); 4203f7df2e56Smrg nn.changedIndicators = stuff->indicators; 4204f7df2e56Smrg } 4205f7df2e56Smrg if (stuff->which & XkbVirtualModNamesMask) { 4206f7df2e56Smrg tmp = _XkbCopyMaskedAtoms(tmp, names->vmods, XkbNumVirtualMods, 4207f7df2e56Smrg stuff->virtualMods); 4208f7df2e56Smrg nn.changedVirtualMods = stuff->virtualMods; 4209f7df2e56Smrg } 4210f7df2e56Smrg if (stuff->which & XkbGroupNamesMask) { 4211f7df2e56Smrg tmp = _XkbCopyMaskedAtoms(tmp, names->groups, XkbNumKbdGroups, 4212f7df2e56Smrg stuff->groupNames); 4213f7df2e56Smrg nn.changedVirtualMods = stuff->groupNames; 4214f7df2e56Smrg } 4215f7df2e56Smrg if (stuff->which & XkbKeyNamesMask) { 4216f7df2e56Smrg memcpy((char *) &names->keys[stuff->firstKey], (char *) tmp, 4217f7df2e56Smrg stuff->nKeys * XkbKeyNameLength); 4218f7df2e56Smrg tmp += stuff->nKeys; 4219f7df2e56Smrg nn.firstKey = stuff->firstKey; 4220f7df2e56Smrg nn.nKeys = stuff->nKeys; 4221f7df2e56Smrg } 4222f7df2e56Smrg if (stuff->which & XkbKeyAliasesMask) { 4223f7df2e56Smrg if (stuff->nKeyAliases > 0) { 4224f7df2e56Smrg register int na = stuff->nKeyAliases; 4225f7df2e56Smrg 4226f7df2e56Smrg if (XkbAllocNames(xkb, XkbKeyAliasesMask, 0, na) != Success) 42274642e01fSmrg return BadAlloc; 4228f7df2e56Smrg memcpy((char *) names->key_aliases, (char *) tmp, 4229f7df2e56Smrg stuff->nKeyAliases * sizeof(XkbKeyAliasRec)); 4230f7df2e56Smrg tmp += stuff->nKeyAliases * 2; 42314642e01fSmrg } 4232f7df2e56Smrg else if (names->key_aliases != NULL) { 42336747b715Smrg free(names->key_aliases); 4234f7df2e56Smrg names->key_aliases = NULL; 4235f7df2e56Smrg names->num_key_aliases = 0; 42364642e01fSmrg } 4237f7df2e56Smrg nn.nAliases = names->num_key_aliases; 42384642e01fSmrg } 4239f7df2e56Smrg if (stuff->which & XkbRGNamesMask) { 4240f7df2e56Smrg if (stuff->nRadioGroups > 0) { 4241f7df2e56Smrg register unsigned i, nrg; 4242f7df2e56Smrg 4243f7df2e56Smrg nrg = stuff->nRadioGroups; 4244f7df2e56Smrg if (XkbAllocNames(xkb, XkbRGNamesMask, nrg, 0) != Success) 42454642e01fSmrg return BadAlloc; 42464642e01fSmrg 4247f7df2e56Smrg for (i = 0; i < stuff->nRadioGroups; i++) { 4248f7df2e56Smrg names->radio_groups[i] = tmp[i]; 42494642e01fSmrg } 4250f7df2e56Smrg tmp += stuff->nRadioGroups; 42514642e01fSmrg } 42524642e01fSmrg else if (names->radio_groups) { 42536747b715Smrg free(names->radio_groups); 4254f7df2e56Smrg names->radio_groups = NULL; 4255f7df2e56Smrg names->num_rg = 0; 42564642e01fSmrg } 4257f7df2e56Smrg nn.nRadioGroups = names->num_rg; 42584642e01fSmrg } 42594642e01fSmrg if (nn.changed) { 42604642e01fSmrg Bool needExtEvent; 4261f7df2e56Smrg 4262f7df2e56Smrg needExtEvent = (nn.changed & XkbIndicatorNamesMask) != 0; 4263f7df2e56Smrg XkbSendNamesNotify(dev, &nn); 42644642e01fSmrg if (needExtEvent) { 4265f7df2e56Smrg XkbSrvLedInfoPtr sli; 4266f7df2e56Smrg xkbExtensionDeviceNotify edev; 4267f7df2e56Smrg register int i; 4268f7df2e56Smrg register unsigned bit; 4269f7df2e56Smrg 4270f7df2e56Smrg sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 4271f7df2e56Smrg XkbXI_IndicatorsMask); 4272f7df2e56Smrg sli->namesPresent = 0; 4273f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 4274f7df2e56Smrg if (names->indicators[i] != None) 4275f7df2e56Smrg sli->namesPresent |= bit; 42764642e01fSmrg } 42776747b715Smrg memset(&edev, 0, sizeof(xkbExtensionDeviceNotify)); 4278f7df2e56Smrg edev.reason = XkbXI_IndicatorNamesMask; 4279f7df2e56Smrg edev.ledClass = KbdFeedbackClass; 4280f7df2e56Smrg edev.ledID = dev->kbdfeed->ctrl.id; 4281f7df2e56Smrg edev.ledsDefined = sli->namesPresent | sli->mapsPresent; 4282f7df2e56Smrg edev.ledState = sli->effectiveState; 4283f7df2e56Smrg edev.firstBtn = 0; 4284f7df2e56Smrg edev.nBtns = 0; 4285f7df2e56Smrg edev.supported = XkbXI_AllFeaturesMask; 4286f7df2e56Smrg edev.unsupported = 0; 4287f7df2e56Smrg XkbSendExtensionDeviceNotify(dev, client, &edev); 42884642e01fSmrg } 42894642e01fSmrg } 42904642e01fSmrg return Success; 42914642e01fSmrg} 42924642e01fSmrg 42934642e01fSmrgint 42944642e01fSmrgProcXkbSetNames(ClientPtr client) 42954642e01fSmrg{ 4296f7df2e56Smrg DeviceIntPtr dev; 4297f7df2e56Smrg CARD32 *tmp; 4298f7df2e56Smrg Atom bad; 4299f7df2e56Smrg int rc; 43004642e01fSmrg 430105b261ecSmrg REQUEST(xkbSetNamesReq); 430205b261ecSmrg REQUEST_AT_LEAST_SIZE(xkbSetNamesReq); 430305b261ecSmrg 4304f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 4305f7df2e56Smrg return BadAccess; 430605b261ecSmrg 43074642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); 4308f7df2e56Smrg CHK_MASK_LEGAL(0x01, stuff->which, XkbAllNamesMask); 430905b261ecSmrg 43104642e01fSmrg /* check device-independent stuff */ 4311f7df2e56Smrg tmp = (CARD32 *) &stuff[1]; 4312f7df2e56Smrg 4313f7df2e56Smrg if (stuff->which & XkbKeycodesNameMask) { 4314f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad); 4315f7df2e56Smrg if (!tmp) { 4316f7df2e56Smrg client->errorValue = bad; 4317f7df2e56Smrg return BadAtom; 4318f7df2e56Smrg } 4319f7df2e56Smrg } 4320f7df2e56Smrg if (stuff->which & XkbGeometryNameMask) { 4321f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad); 4322f7df2e56Smrg if (!tmp) { 4323f7df2e56Smrg client->errorValue = bad; 4324f7df2e56Smrg return BadAtom; 4325f7df2e56Smrg } 4326f7df2e56Smrg } 4327f7df2e56Smrg if (stuff->which & XkbSymbolsNameMask) { 4328f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad); 4329f7df2e56Smrg if (!tmp) { 4330f7df2e56Smrg client->errorValue = bad; 4331f7df2e56Smrg return BadAtom; 4332f7df2e56Smrg } 4333f7df2e56Smrg } 4334f7df2e56Smrg if (stuff->which & XkbPhysSymbolsNameMask) { 4335f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad); 4336f7df2e56Smrg if (!tmp) { 4337f7df2e56Smrg client->errorValue = bad; 4338f7df2e56Smrg return BadAtom; 4339f7df2e56Smrg } 4340f7df2e56Smrg } 4341f7df2e56Smrg if (stuff->which & XkbTypesNameMask) { 4342f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad); 4343f7df2e56Smrg if (!tmp) { 4344f7df2e56Smrg client->errorValue = bad; 4345f7df2e56Smrg return BadAtom; 4346f7df2e56Smrg } 4347f7df2e56Smrg } 4348f7df2e56Smrg if (stuff->which & XkbCompatNameMask) { 4349f7df2e56Smrg tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad); 4350f7df2e56Smrg if (!tmp) { 4351f7df2e56Smrg client->errorValue = bad; 4352f7df2e56Smrg return BadAtom; 4353f7df2e56Smrg } 435405b261ecSmrg } 43554642e01fSmrg 43564642e01fSmrg /* start of device-dependent tests */ 43574642e01fSmrg rc = _XkbSetNamesCheck(client, dev, stuff, tmp); 43584642e01fSmrg if (rc != Success) 43594642e01fSmrg return rc; 43604642e01fSmrg 4361f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd) { 43624642e01fSmrg DeviceIntPtr other; 43634642e01fSmrg 4364f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 4365f7df2e56Smrg if ((other != dev) && other->key && !IsMaster(other) && 4366f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) { 4367f7df2e56Smrg 4368f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 4369f7df2e56Smrg DixManageAccess); 4370f7df2e56Smrg if (rc == Success) { 43714642e01fSmrg rc = _XkbSetNamesCheck(client, other, stuff, tmp); 43724642e01fSmrg if (rc != Success) 43734642e01fSmrg return rc; 43744642e01fSmrg } 43754642e01fSmrg } 43764642e01fSmrg } 437705b261ecSmrg } 437805b261ecSmrg 437905b261ecSmrg /* everything is okay -- update names */ 438005b261ecSmrg 43814642e01fSmrg rc = _XkbSetNames(client, dev, stuff); 43824642e01fSmrg if (rc != Success) 43834642e01fSmrg return rc; 438405b261ecSmrg 4385f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd) { 43864642e01fSmrg DeviceIntPtr other; 43874642e01fSmrg 4388f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 4389f7df2e56Smrg if ((other != dev) && other->key && !IsMaster(other) && 4390f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) { 4391f7df2e56Smrg 4392f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 4393f7df2e56Smrg DixManageAccess); 43944642e01fSmrg if (rc == Success) 43954642e01fSmrg _XkbSetNames(client, other, stuff); 43964642e01fSmrg } 43974642e01fSmrg } 439805b261ecSmrg } 43994642e01fSmrg 44004642e01fSmrg /* everything is okay -- update names */ 44014642e01fSmrg 44026747b715Smrg return Success; 440305b261ecSmrg} 440405b261ecSmrg 440505b261ecSmrg/***====================================================================***/ 440605b261ecSmrg 44074642e01fSmrg#include "xkbgeom.h" 440805b261ecSmrg 440905b261ecSmrg#define XkbSizeCountedString(s) ((s)?((((2+strlen(s))+3)/4)*4):4) 441005b261ecSmrg 4411f7df2e56Smrg/** 4412f7df2e56Smrg * Write the zero-terminated string str into wire as a pascal string with a 4413f7df2e56Smrg * 16-bit length field prefixed before the actual string. 4414f7df2e56Smrg * 4415f7df2e56Smrg * @param wire The destination array, usually the wire struct 4416f7df2e56Smrg * @param str The source string as zero-terminated C string 4417f7df2e56Smrg * @param swap If TRUE, the length field is swapped. 4418f7df2e56Smrg * 4419f7df2e56Smrg * @return The input string in the format <string length><string> with a 4420f7df2e56Smrg * (swapped) 16 bit string length, non-zero terminated. 4421f7df2e56Smrg */ 442205b261ecSmrgstatic char * 4423f7df2e56SmrgXkbWriteCountedString(char *wire, const char *str, Bool swap) 442405b261ecSmrg{ 4425f7df2e56Smrg CARD16 len, *pLen, paddedLen; 442605b261ecSmrg 44276747b715Smrg if (!str) 44286747b715Smrg return wire; 44296747b715Smrg 4430f7df2e56Smrg len = strlen(str); 4431f7df2e56Smrg pLen = (CARD16 *) wire; 4432f7df2e56Smrg *pLen = len; 443305b261ecSmrg if (swap) { 4434f7df2e56Smrg swaps(pLen); 443505b261ecSmrg } 4436f7df2e56Smrg paddedLen = pad_to_int32(sizeof(len) + len) - sizeof(len); 4437f7df2e56Smrg strncpy(&wire[sizeof(len)], str, paddedLen); 4438f7df2e56Smrg wire += sizeof(len) + paddedLen; 443905b261ecSmrg return wire; 444005b261ecSmrg} 444105b261ecSmrg 444205b261ecSmrgstatic int 444305b261ecSmrgXkbSizeGeomProperties(XkbGeometryPtr geom) 444405b261ecSmrg{ 4445f7df2e56Smrg register int i, size; 4446f7df2e56Smrg XkbPropertyPtr prop; 4447f7df2e56Smrg 4448f7df2e56Smrg for (size = i = 0, prop = geom->properties; i < geom->num_properties; 4449f7df2e56Smrg i++, prop++) { 4450f7df2e56Smrg size += XkbSizeCountedString(prop->name); 4451f7df2e56Smrg size += XkbSizeCountedString(prop->value); 445205b261ecSmrg } 445305b261ecSmrg return size; 445405b261ecSmrg} 445505b261ecSmrg 445605b261ecSmrgstatic char * 4457f7df2e56SmrgXkbWriteGeomProperties(char *wire, XkbGeometryPtr geom, Bool swap) 445805b261ecSmrg{ 4459f7df2e56Smrg register int i; 4460f7df2e56Smrg register XkbPropertyPtr prop; 4461f7df2e56Smrg 4462f7df2e56Smrg for (i = 0, prop = geom->properties; i < geom->num_properties; i++, prop++) { 4463f7df2e56Smrg wire = XkbWriteCountedString(wire, prop->name, swap); 4464f7df2e56Smrg wire = XkbWriteCountedString(wire, prop->value, swap); 446505b261ecSmrg } 446605b261ecSmrg return wire; 446705b261ecSmrg} 446805b261ecSmrg 446905b261ecSmrgstatic int 447005b261ecSmrgXkbSizeGeomKeyAliases(XkbGeometryPtr geom) 447105b261ecSmrg{ 4472f7df2e56Smrg return geom->num_key_aliases * (2 * XkbKeyNameLength); 447305b261ecSmrg} 447405b261ecSmrg 447505b261ecSmrgstatic char * 4476f7df2e56SmrgXkbWriteGeomKeyAliases(char *wire, XkbGeometryPtr geom, Bool swap) 447705b261ecSmrg{ 4478f7df2e56Smrg register int sz; 4479f7df2e56Smrg 4480f7df2e56Smrg sz = geom->num_key_aliases * (XkbKeyNameLength * 2); 4481f7df2e56Smrg if (sz > 0) { 4482f7df2e56Smrg memcpy(wire, (char *) geom->key_aliases, sz); 4483f7df2e56Smrg wire += sz; 448405b261ecSmrg } 448505b261ecSmrg return wire; 448605b261ecSmrg} 448705b261ecSmrg 448805b261ecSmrgstatic int 448905b261ecSmrgXkbSizeGeomColors(XkbGeometryPtr geom) 449005b261ecSmrg{ 4491f7df2e56Smrg register int i, size; 4492f7df2e56Smrg register XkbColorPtr color; 449305b261ecSmrg 4494f7df2e56Smrg for (i = size = 0, color = geom->colors; i < geom->num_colors; i++, color++) { 4495f7df2e56Smrg size += XkbSizeCountedString(color->spec); 449605b261ecSmrg } 449705b261ecSmrg return size; 449805b261ecSmrg} 449905b261ecSmrg 450005b261ecSmrgstatic char * 4501f7df2e56SmrgXkbWriteGeomColors(char *wire, XkbGeometryPtr geom, Bool swap) 450205b261ecSmrg{ 4503f7df2e56Smrg register int i; 4504f7df2e56Smrg register XkbColorPtr color; 450505b261ecSmrg 4506f7df2e56Smrg for (i = 0, color = geom->colors; i < geom->num_colors; i++, color++) { 4507f7df2e56Smrg wire = XkbWriteCountedString(wire, color->spec, swap); 450805b261ecSmrg } 450905b261ecSmrg return wire; 451005b261ecSmrg} 451105b261ecSmrg 451205b261ecSmrgstatic int 451305b261ecSmrgXkbSizeGeomShapes(XkbGeometryPtr geom) 451405b261ecSmrg{ 4515f7df2e56Smrg register int i, size; 4516f7df2e56Smrg register XkbShapePtr shape; 4517f7df2e56Smrg 4518f7df2e56Smrg for (i = size = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) { 4519f7df2e56Smrg register int n; 4520f7df2e56Smrg register XkbOutlinePtr ol; 4521f7df2e56Smrg 4522f7df2e56Smrg size += SIZEOF(xkbShapeWireDesc); 4523f7df2e56Smrg for (n = 0, ol = shape->outlines; n < shape->num_outlines; n++, ol++) { 4524f7df2e56Smrg size += SIZEOF(xkbOutlineWireDesc); 4525f7df2e56Smrg size += ol->num_points * SIZEOF(xkbPointWireDesc); 4526f7df2e56Smrg } 452705b261ecSmrg } 452805b261ecSmrg return size; 452905b261ecSmrg} 453005b261ecSmrg 453105b261ecSmrgstatic char * 4532f7df2e56SmrgXkbWriteGeomShapes(char *wire, XkbGeometryPtr geom, Bool swap) 453305b261ecSmrg{ 4534f7df2e56Smrg int i; 4535f7df2e56Smrg XkbShapePtr shape; 4536f7df2e56Smrg xkbShapeWireDesc *shapeWire; 4537f7df2e56Smrg 4538f7df2e56Smrg for (i = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) { 4539f7df2e56Smrg register int o; 4540f7df2e56Smrg XkbOutlinePtr ol; 4541f7df2e56Smrg xkbOutlineWireDesc *olWire; 4542f7df2e56Smrg 4543f7df2e56Smrg shapeWire = (xkbShapeWireDesc *) wire; 4544f7df2e56Smrg shapeWire->name = shape->name; 4545f7df2e56Smrg shapeWire->nOutlines = shape->num_outlines; 4546f7df2e56Smrg if (shape->primary != NULL) 4547f7df2e56Smrg shapeWire->primaryNdx = XkbOutlineIndex(shape, shape->primary); 4548f7df2e56Smrg else 4549f7df2e56Smrg shapeWire->primaryNdx = XkbNoShape; 4550f7df2e56Smrg if (shape->approx != NULL) 4551f7df2e56Smrg shapeWire->approxNdx = XkbOutlineIndex(shape, shape->approx); 4552f7df2e56Smrg else 4553f7df2e56Smrg shapeWire->approxNdx = XkbNoShape; 4554f7df2e56Smrg shapeWire->pad = 0; 4555f7df2e56Smrg if (swap) { 4556f7df2e56Smrg swapl(&shapeWire->name); 4557f7df2e56Smrg } 4558f7df2e56Smrg wire = (char *) &shapeWire[1]; 4559f7df2e56Smrg for (o = 0, ol = shape->outlines; o < shape->num_outlines; o++, ol++) { 4560f7df2e56Smrg register int p; 4561f7df2e56Smrg XkbPointPtr pt; 4562f7df2e56Smrg xkbPointWireDesc *ptWire; 4563f7df2e56Smrg 4564f7df2e56Smrg olWire = (xkbOutlineWireDesc *) wire; 4565f7df2e56Smrg olWire->nPoints = ol->num_points; 4566f7df2e56Smrg olWire->cornerRadius = ol->corner_radius; 4567f7df2e56Smrg olWire->pad = 0; 4568f7df2e56Smrg wire = (char *) &olWire[1]; 4569f7df2e56Smrg ptWire = (xkbPointWireDesc *) wire; 4570f7df2e56Smrg for (p = 0, pt = ol->points; p < ol->num_points; p++, pt++) { 4571f7df2e56Smrg ptWire[p].x = pt->x; 4572f7df2e56Smrg ptWire[p].y = pt->y; 4573f7df2e56Smrg if (swap) { 4574f7df2e56Smrg swaps(&ptWire[p].x); 4575f7df2e56Smrg swaps(&ptWire[p].y); 4576f7df2e56Smrg } 4577f7df2e56Smrg } 4578f7df2e56Smrg wire = (char *) &ptWire[ol->num_points]; 4579f7df2e56Smrg } 458005b261ecSmrg } 458105b261ecSmrg return wire; 458205b261ecSmrg} 458305b261ecSmrg 458405b261ecSmrgstatic int 4585f7df2e56SmrgXkbSizeGeomDoodads(int num_doodads, XkbDoodadPtr doodad) 458605b261ecSmrg{ 4587f7df2e56Smrg register int i, size; 4588f7df2e56Smrg 4589f7df2e56Smrg for (i = size = 0; i < num_doodads; i++, doodad++) { 4590f7df2e56Smrg size += SIZEOF(xkbAnyDoodadWireDesc); 4591f7df2e56Smrg if (doodad->any.type == XkbTextDoodad) { 4592f7df2e56Smrg size += XkbSizeCountedString(doodad->text.text); 4593f7df2e56Smrg size += XkbSizeCountedString(doodad->text.font); 4594f7df2e56Smrg } 4595f7df2e56Smrg else if (doodad->any.type == XkbLogoDoodad) { 4596f7df2e56Smrg size += XkbSizeCountedString(doodad->logo.logo_name); 4597f7df2e56Smrg } 459805b261ecSmrg } 459905b261ecSmrg return size; 460005b261ecSmrg} 460105b261ecSmrg 460205b261ecSmrgstatic char * 4603f7df2e56SmrgXkbWriteGeomDoodads(char *wire, int num_doodads, XkbDoodadPtr doodad, Bool swap) 460405b261ecSmrg{ 4605f7df2e56Smrg register int i; 4606f7df2e56Smrg xkbDoodadWireDesc *doodadWire; 4607f7df2e56Smrg 4608f7df2e56Smrg for (i = 0; i < num_doodads; i++, doodad++) { 4609f7df2e56Smrg doodadWire = (xkbDoodadWireDesc *) wire; 4610f7df2e56Smrg wire = (char *) &doodadWire[1]; 4611f7df2e56Smrg memset(doodadWire, 0, SIZEOF(xkbDoodadWireDesc)); 4612f7df2e56Smrg doodadWire->any.name = doodad->any.name; 4613f7df2e56Smrg doodadWire->any.type = doodad->any.type; 4614f7df2e56Smrg doodadWire->any.priority = doodad->any.priority; 4615f7df2e56Smrg doodadWire->any.top = doodad->any.top; 4616f7df2e56Smrg doodadWire->any.left = doodad->any.left; 4617f7df2e56Smrg if (swap) { 4618f7df2e56Smrg swapl(&doodadWire->any.name); 4619f7df2e56Smrg swaps(&doodadWire->any.top); 4620f7df2e56Smrg swaps(&doodadWire->any.left); 4621f7df2e56Smrg } 4622f7df2e56Smrg switch (doodad->any.type) { 4623f7df2e56Smrg case XkbOutlineDoodad: 4624f7df2e56Smrg case XkbSolidDoodad: 4625f7df2e56Smrg doodadWire->shape.angle = doodad->shape.angle; 4626f7df2e56Smrg doodadWire->shape.colorNdx = doodad->shape.color_ndx; 4627f7df2e56Smrg doodadWire->shape.shapeNdx = doodad->shape.shape_ndx; 4628f7df2e56Smrg if (swap) { 4629f7df2e56Smrg swaps(&doodadWire->shape.angle); 4630f7df2e56Smrg } 4631f7df2e56Smrg break; 4632f7df2e56Smrg case XkbTextDoodad: 4633f7df2e56Smrg doodadWire->text.angle = doodad->text.angle; 4634f7df2e56Smrg doodadWire->text.width = doodad->text.width; 4635f7df2e56Smrg doodadWire->text.height = doodad->text.height; 4636f7df2e56Smrg doodadWire->text.colorNdx = doodad->text.color_ndx; 4637f7df2e56Smrg if (swap) { 4638f7df2e56Smrg swaps(&doodadWire->text.angle); 4639f7df2e56Smrg swaps(&doodadWire->text.width); 4640f7df2e56Smrg swaps(&doodadWire->text.height); 4641f7df2e56Smrg } 4642f7df2e56Smrg wire = XkbWriteCountedString(wire, doodad->text.text, swap); 4643f7df2e56Smrg wire = XkbWriteCountedString(wire, doodad->text.font, swap); 4644f7df2e56Smrg break; 4645f7df2e56Smrg case XkbIndicatorDoodad: 4646f7df2e56Smrg doodadWire->indicator.shapeNdx = doodad->indicator.shape_ndx; 4647f7df2e56Smrg doodadWire->indicator.onColorNdx = doodad->indicator.on_color_ndx; 4648f7df2e56Smrg doodadWire->indicator.offColorNdx = doodad->indicator.off_color_ndx; 4649f7df2e56Smrg break; 4650f7df2e56Smrg case XkbLogoDoodad: 4651f7df2e56Smrg doodadWire->logo.angle = doodad->logo.angle; 4652f7df2e56Smrg doodadWire->logo.colorNdx = doodad->logo.color_ndx; 4653f7df2e56Smrg doodadWire->logo.shapeNdx = doodad->logo.shape_ndx; 4654f7df2e56Smrg wire = XkbWriteCountedString(wire, doodad->logo.logo_name, swap); 4655f7df2e56Smrg break; 4656f7df2e56Smrg default: 4657f7df2e56Smrg ErrorF("[xkb] Unknown doodad type %d in XkbWriteGeomDoodads\n", 4658f7df2e56Smrg doodad->any.type); 4659f7df2e56Smrg ErrorF("[xkb] Ignored\n"); 4660f7df2e56Smrg break; 4661f7df2e56Smrg } 466205b261ecSmrg } 466305b261ecSmrg return wire; 466405b261ecSmrg} 466505b261ecSmrg 466605b261ecSmrgstatic char * 4667f7df2e56SmrgXkbWriteGeomOverlay(char *wire, XkbOverlayPtr ol, Bool swap) 466805b261ecSmrg{ 4669f7df2e56Smrg register int r; 4670f7df2e56Smrg XkbOverlayRowPtr row; 4671f7df2e56Smrg xkbOverlayWireDesc *olWire; 4672f7df2e56Smrg 4673f7df2e56Smrg olWire = (xkbOverlayWireDesc *) wire; 4674f7df2e56Smrg olWire->name = ol->name; 4675f7df2e56Smrg olWire->nRows = ol->num_rows; 4676f7df2e56Smrg olWire->pad1 = 0; 4677f7df2e56Smrg olWire->pad2 = 0; 4678f7df2e56Smrg if (swap) { 4679f7df2e56Smrg swapl(&olWire->name); 4680f7df2e56Smrg } 4681f7df2e56Smrg wire = (char *) &olWire[1]; 4682f7df2e56Smrg for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) { 4683f7df2e56Smrg unsigned int k; 4684f7df2e56Smrg XkbOverlayKeyPtr key; 4685f7df2e56Smrg xkbOverlayRowWireDesc *rowWire; 4686f7df2e56Smrg 4687f7df2e56Smrg rowWire = (xkbOverlayRowWireDesc *) wire; 4688f7df2e56Smrg rowWire->rowUnder = row->row_under; 4689f7df2e56Smrg rowWire->nKeys = row->num_keys; 4690f7df2e56Smrg rowWire->pad1 = 0; 4691f7df2e56Smrg wire = (char *) &rowWire[1]; 4692f7df2e56Smrg for (k = 0, key = row->keys; k < row->num_keys; k++, key++) { 4693f7df2e56Smrg xkbOverlayKeyWireDesc *keyWire; 4694f7df2e56Smrg 4695f7df2e56Smrg keyWire = (xkbOverlayKeyWireDesc *) wire; 4696f7df2e56Smrg memcpy(keyWire->over, key->over.name, XkbKeyNameLength); 4697f7df2e56Smrg memcpy(keyWire->under, key->under.name, XkbKeyNameLength); 4698f7df2e56Smrg wire = (char *) &keyWire[1]; 4699f7df2e56Smrg } 4700f7df2e56Smrg } 4701f7df2e56Smrg return wire; 470205b261ecSmrg} 470305b261ecSmrg 470405b261ecSmrgstatic int 470505b261ecSmrgXkbSizeGeomSections(XkbGeometryPtr geom) 470605b261ecSmrg{ 4707f7df2e56Smrg register int i, size; 4708f7df2e56Smrg XkbSectionPtr section; 4709f7df2e56Smrg 4710f7df2e56Smrg for (i = size = 0, section = geom->sections; i < geom->num_sections; 4711f7df2e56Smrg i++, section++) { 4712f7df2e56Smrg size += SIZEOF(xkbSectionWireDesc); 4713f7df2e56Smrg if (section->rows) { 4714f7df2e56Smrg int r; 4715f7df2e56Smrg XkbRowPtr row; 4716f7df2e56Smrg 4717f7df2e56Smrg for (r = 0, row = section->rows; r < section->num_rows; row++, r++) { 4718f7df2e56Smrg size += SIZEOF(xkbRowWireDesc); 4719f7df2e56Smrg size += row->num_keys * SIZEOF(xkbKeyWireDesc); 4720f7df2e56Smrg } 4721f7df2e56Smrg } 4722f7df2e56Smrg if (section->doodads) 4723f7df2e56Smrg size += XkbSizeGeomDoodads(section->num_doodads, section->doodads); 4724f7df2e56Smrg if (section->overlays) { 4725f7df2e56Smrg int o; 4726f7df2e56Smrg XkbOverlayPtr ol; 4727f7df2e56Smrg 4728f7df2e56Smrg for (o = 0, ol = section->overlays; o < section->num_overlays; 4729f7df2e56Smrg o++, ol++) { 4730f7df2e56Smrg int r; 4731f7df2e56Smrg XkbOverlayRowPtr row; 4732f7df2e56Smrg 4733f7df2e56Smrg size += SIZEOF(xkbOverlayWireDesc); 4734f7df2e56Smrg for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) { 4735f7df2e56Smrg size += SIZEOF(xkbOverlayRowWireDesc); 4736f7df2e56Smrg size += row->num_keys * SIZEOF(xkbOverlayKeyWireDesc); 4737f7df2e56Smrg } 4738f7df2e56Smrg } 4739f7df2e56Smrg } 474005b261ecSmrg } 474105b261ecSmrg return size; 474205b261ecSmrg} 474305b261ecSmrg 474405b261ecSmrgstatic char * 4745f7df2e56SmrgXkbWriteGeomSections(char *wire, XkbGeometryPtr geom, Bool swap) 474605b261ecSmrg{ 4747f7df2e56Smrg register int i; 4748f7df2e56Smrg XkbSectionPtr section; 4749f7df2e56Smrg xkbSectionWireDesc *sectionWire; 4750f7df2e56Smrg 4751f7df2e56Smrg for (i = 0, section = geom->sections; i < geom->num_sections; 4752f7df2e56Smrg i++, section++) { 4753f7df2e56Smrg sectionWire = (xkbSectionWireDesc *) wire; 4754f7df2e56Smrg sectionWire->name = section->name; 4755f7df2e56Smrg sectionWire->top = section->top; 4756f7df2e56Smrg sectionWire->left = section->left; 4757f7df2e56Smrg sectionWire->width = section->width; 4758f7df2e56Smrg sectionWire->height = section->height; 4759f7df2e56Smrg sectionWire->angle = section->angle; 4760f7df2e56Smrg sectionWire->priority = section->priority; 4761f7df2e56Smrg sectionWire->nRows = section->num_rows; 4762f7df2e56Smrg sectionWire->nDoodads = section->num_doodads; 4763f7df2e56Smrg sectionWire->nOverlays = section->num_overlays; 4764f7df2e56Smrg sectionWire->pad = 0; 4765f7df2e56Smrg if (swap) { 4766f7df2e56Smrg swapl(§ionWire->name); 4767f7df2e56Smrg swaps(§ionWire->top); 4768f7df2e56Smrg swaps(§ionWire->left); 4769f7df2e56Smrg swaps(§ionWire->width); 4770f7df2e56Smrg swaps(§ionWire->height); 4771f7df2e56Smrg swaps(§ionWire->angle); 4772f7df2e56Smrg } 4773f7df2e56Smrg wire = (char *) §ionWire[1]; 4774f7df2e56Smrg if (section->rows) { 4775f7df2e56Smrg int r; 4776f7df2e56Smrg XkbRowPtr row; 4777f7df2e56Smrg xkbRowWireDesc *rowWire; 4778f7df2e56Smrg 4779f7df2e56Smrg for (r = 0, row = section->rows; r < section->num_rows; r++, row++) { 4780f7df2e56Smrg rowWire = (xkbRowWireDesc *) wire; 4781f7df2e56Smrg rowWire->top = row->top; 4782f7df2e56Smrg rowWire->left = row->left; 4783f7df2e56Smrg rowWire->nKeys = row->num_keys; 4784f7df2e56Smrg rowWire->vertical = row->vertical; 4785f7df2e56Smrg rowWire->pad = 0; 4786f7df2e56Smrg if (swap) { 4787f7df2e56Smrg swaps(&rowWire->top); 4788f7df2e56Smrg swaps(&rowWire->left); 4789f7df2e56Smrg } 4790f7df2e56Smrg wire = (char *) &rowWire[1]; 4791f7df2e56Smrg if (row->keys) { 4792f7df2e56Smrg int k; 4793f7df2e56Smrg XkbKeyPtr key; 4794f7df2e56Smrg xkbKeyWireDesc *keyWire; 4795f7df2e56Smrg 4796f7df2e56Smrg keyWire = (xkbKeyWireDesc *) wire; 4797f7df2e56Smrg for (k = 0, key = row->keys; k < row->num_keys; k++, key++) { 4798f7df2e56Smrg memcpy(keyWire[k].name, key->name.name, 4799f7df2e56Smrg XkbKeyNameLength); 4800f7df2e56Smrg keyWire[k].gap = key->gap; 4801f7df2e56Smrg keyWire[k].shapeNdx = key->shape_ndx; 4802f7df2e56Smrg keyWire[k].colorNdx = key->color_ndx; 4803f7df2e56Smrg if (swap) { 4804f7df2e56Smrg swaps(&keyWire[k].gap); 4805f7df2e56Smrg } 4806f7df2e56Smrg } 4807f7df2e56Smrg wire = (char *) &keyWire[row->num_keys]; 4808f7df2e56Smrg } 4809f7df2e56Smrg } 4810f7df2e56Smrg } 4811f7df2e56Smrg if (section->doodads) { 4812f7df2e56Smrg wire = XkbWriteGeomDoodads(wire, 4813f7df2e56Smrg section->num_doodads, section->doodads, 4814f7df2e56Smrg swap); 4815f7df2e56Smrg } 4816f7df2e56Smrg if (section->overlays) { 4817f7df2e56Smrg register int o; 4818f7df2e56Smrg 4819f7df2e56Smrg for (o = 0; o < section->num_overlays; o++) { 4820f7df2e56Smrg wire = XkbWriteGeomOverlay(wire, §ion->overlays[o], swap); 4821f7df2e56Smrg } 4822f7df2e56Smrg } 482305b261ecSmrg } 482405b261ecSmrg return wire; 482505b261ecSmrg} 482605b261ecSmrg 482705b261ecSmrgstatic Status 4828f7df2e56SmrgXkbComputeGetGeometryReplySize(XkbGeometryPtr geom, 4829f7df2e56Smrg xkbGetGeometryReply * rep, Atom name) 483005b261ecSmrg{ 4831f7df2e56Smrg int len; 4832f7df2e56Smrg 4833f7df2e56Smrg if (geom != NULL) { 4834f7df2e56Smrg len = XkbSizeCountedString(geom->label_font); 4835f7df2e56Smrg len += XkbSizeGeomProperties(geom); 4836f7df2e56Smrg len += XkbSizeGeomColors(geom); 4837f7df2e56Smrg len += XkbSizeGeomShapes(geom); 4838f7df2e56Smrg len += XkbSizeGeomSections(geom); 4839f7df2e56Smrg len += XkbSizeGeomDoodads(geom->num_doodads, geom->doodads); 4840f7df2e56Smrg len += XkbSizeGeomKeyAliases(geom); 4841f7df2e56Smrg rep->length = len / 4; 4842f7df2e56Smrg rep->found = TRUE; 4843f7df2e56Smrg rep->name = geom->name; 4844f7df2e56Smrg rep->widthMM = geom->width_mm; 4845f7df2e56Smrg rep->heightMM = geom->height_mm; 4846f7df2e56Smrg rep->nProperties = geom->num_properties; 4847f7df2e56Smrg rep->nColors = geom->num_colors; 4848f7df2e56Smrg rep->nShapes = geom->num_shapes; 4849f7df2e56Smrg rep->nSections = geom->num_sections; 4850f7df2e56Smrg rep->nDoodads = geom->num_doodads; 4851f7df2e56Smrg rep->nKeyAliases = geom->num_key_aliases; 4852f7df2e56Smrg rep->baseColorNdx = XkbGeomColorIndex(geom, geom->base_color); 4853f7df2e56Smrg rep->labelColorNdx = XkbGeomColorIndex(geom, geom->label_color); 485405b261ecSmrg } 485505b261ecSmrg else { 4856f7df2e56Smrg rep->length = 0; 4857f7df2e56Smrg rep->found = FALSE; 4858f7df2e56Smrg rep->name = name; 4859f7df2e56Smrg rep->widthMM = rep->heightMM = 0; 4860f7df2e56Smrg rep->nProperties = rep->nColors = rep->nShapes = 0; 4861f7df2e56Smrg rep->nSections = rep->nDoodads = 0; 4862f7df2e56Smrg rep->nKeyAliases = 0; 4863f7df2e56Smrg rep->labelColorNdx = rep->baseColorNdx = 0; 486405b261ecSmrg } 486505b261ecSmrg return Success; 486605b261ecSmrg} 486705b261ecSmrgstatic int 4868f7df2e56SmrgXkbSendGeometry(ClientPtr client, 4869f7df2e56Smrg XkbGeometryPtr geom, xkbGetGeometryReply * rep, Bool freeGeom) 487005b261ecSmrg{ 4871f7df2e56Smrg char *desc, *start; 4872f7df2e56Smrg int len; 4873f7df2e56Smrg 4874f7df2e56Smrg if (geom != NULL) { 4875f7df2e56Smrg start = desc = xallocarray(rep->length, 4); 4876f7df2e56Smrg if (!start) 4877f7df2e56Smrg return BadAlloc; 4878f7df2e56Smrg len = rep->length * 4; 4879f7df2e56Smrg desc = XkbWriteCountedString(desc, geom->label_font, client->swapped); 4880f7df2e56Smrg if (rep->nProperties > 0) 4881f7df2e56Smrg desc = XkbWriteGeomProperties(desc, geom, client->swapped); 4882f7df2e56Smrg if (rep->nColors > 0) 4883f7df2e56Smrg desc = XkbWriteGeomColors(desc, geom, client->swapped); 4884f7df2e56Smrg if (rep->nShapes > 0) 4885f7df2e56Smrg desc = XkbWriteGeomShapes(desc, geom, client->swapped); 4886f7df2e56Smrg if (rep->nSections > 0) 4887f7df2e56Smrg desc = XkbWriteGeomSections(desc, geom, client->swapped); 4888f7df2e56Smrg if (rep->nDoodads > 0) 4889f7df2e56Smrg desc = XkbWriteGeomDoodads(desc, geom->num_doodads, geom->doodads, 4890f7df2e56Smrg client->swapped); 4891f7df2e56Smrg if (rep->nKeyAliases > 0) 4892f7df2e56Smrg desc = XkbWriteGeomKeyAliases(desc, geom, client->swapped); 4893f7df2e56Smrg if ((desc - start) != (len)) { 4894f7df2e56Smrg ErrorF 4895f7df2e56Smrg ("[xkb] BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n", 4896f7df2e56Smrg len, (unsigned long) (desc - start)); 4897f7df2e56Smrg } 489805b261ecSmrg } 489905b261ecSmrg else { 4900f7df2e56Smrg len = 0; 4901f7df2e56Smrg start = NULL; 490205b261ecSmrg } 490305b261ecSmrg if (client->swapped) { 4904f7df2e56Smrg swaps(&rep->sequenceNumber); 4905f7df2e56Smrg swapl(&rep->length); 4906f7df2e56Smrg swapl(&rep->name); 4907f7df2e56Smrg swaps(&rep->widthMM); 4908f7df2e56Smrg swaps(&rep->heightMM); 4909f7df2e56Smrg swaps(&rep->nProperties); 4910f7df2e56Smrg swaps(&rep->nColors); 4911f7df2e56Smrg swaps(&rep->nShapes); 4912f7df2e56Smrg swaps(&rep->nSections); 4913f7df2e56Smrg swaps(&rep->nDoodads); 4914f7df2e56Smrg swaps(&rep->nKeyAliases); 4915f7df2e56Smrg } 4916f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetGeometryReply), rep); 4917f7df2e56Smrg if (len > 0) 4918f7df2e56Smrg WriteToClient(client, len, start); 4919f7df2e56Smrg if (start != NULL) 4920f7df2e56Smrg free((char *) start); 492105b261ecSmrg if (freeGeom) 4922f7df2e56Smrg XkbFreeGeometry(geom, XkbGeomAllMask, TRUE); 49236747b715Smrg return Success; 492405b261ecSmrg} 492505b261ecSmrg 492605b261ecSmrgint 492705b261ecSmrgProcXkbGetGeometry(ClientPtr client) 492805b261ecSmrg{ 4929f7df2e56Smrg DeviceIntPtr dev; 493005b261ecSmrg xkbGetGeometryReply rep; 4931f7df2e56Smrg XkbGeometryPtr geom; 4932f7df2e56Smrg Bool shouldFree; 4933f7df2e56Smrg Status status; 493405b261ecSmrg 493505b261ecSmrg REQUEST(xkbGetGeometryReq); 493605b261ecSmrg REQUEST_SIZE_MATCH(xkbGetGeometryReq); 493705b261ecSmrg 4938f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 4939f7df2e56Smrg return BadAccess; 494005b261ecSmrg 49414642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); 494205b261ecSmrg CHK_ATOM_OR_NONE(stuff->name); 494305b261ecSmrg 4944f7df2e56Smrg geom = XkbLookupNamedGeometry(dev, stuff->name, &shouldFree); 4945f7df2e56Smrg rep = (xkbGetGeometryReply) { 4946f7df2e56Smrg .type = X_Reply, 4947f7df2e56Smrg .deviceID = dev->id, 4948f7df2e56Smrg .sequenceNumber = client->sequence, 4949f7df2e56Smrg .length = 0 4950f7df2e56Smrg }; 4951f7df2e56Smrg status = XkbComputeGetGeometryReplySize(geom, &rep, stuff->name); 4952f7df2e56Smrg if (status != Success) 4953f7df2e56Smrg return status; 4954f7df2e56Smrg else 4955f7df2e56Smrg return XkbSendGeometry(client, geom, &rep, shouldFree); 495605b261ecSmrg} 495705b261ecSmrg 495805b261ecSmrg/***====================================================================***/ 495905b261ecSmrg 49601e26616aSmrgstatic Status 49611e26616aSmrg_GetCountedString(char **wire_inout, ClientPtr client, char **str) 496205b261ecSmrg{ 49631e26616aSmrg char *wire, *next; 49641e26616aSmrg CARD16 len; 496505b261ecSmrg 49661e26616aSmrg wire = *wire_inout; 49671e26616aSmrg len = *(CARD16 *) wire; 49681e26616aSmrg if (client->swapped) { 4969f7df2e56Smrg swaps(&len); 497005b261ecSmrg } 49711e26616aSmrg next = wire + XkbPaddedSize(len + 2); 49721e26616aSmrg /* Check we're still within the size of the request */ 49731e26616aSmrg if (client->req_len < 49741e26616aSmrg bytes_to_int32(next - (char *) client->requestBuffer)) 49751e26616aSmrg return BadValue; 49761e26616aSmrg *str = malloc(len + 1); 49771e26616aSmrg if (!*str) 49781e26616aSmrg return BadAlloc; 49791e26616aSmrg memcpy(*str, &wire[2], len); 49801e26616aSmrg *(*str + len) = '\0'; 49811e26616aSmrg *wire_inout = next; 49821e26616aSmrg return Success; 498305b261ecSmrg} 498405b261ecSmrg 498505b261ecSmrgstatic Status 4986f7df2e56Smrg_CheckSetDoodad(char **wire_inout, 4987f7df2e56Smrg XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client) 498805b261ecSmrg{ 4989f7df2e56Smrg char *wire; 4990f7df2e56Smrg xkbDoodadWireDesc *dWire; 4991f7df2e56Smrg xkbAnyDoodadWireDesc any; 4992f7df2e56Smrg xkbTextDoodadWireDesc text; 4993f7df2e56Smrg XkbDoodadPtr doodad; 49941e26616aSmrg Status status; 499505b261ecSmrg 4996f7df2e56Smrg dWire = (xkbDoodadWireDesc *) (*wire_inout); 4997f7df2e56Smrg any = dWire->any; 4998f7df2e56Smrg wire = (char *) &dWire[1]; 499905b261ecSmrg if (client->swapped) { 5000f7df2e56Smrg swapl(&any.name); 5001f7df2e56Smrg swaps(&any.top); 5002f7df2e56Smrg swaps(&any.left); 5003f7df2e56Smrg swaps(&any.angle); 500405b261ecSmrg } 500505b261ecSmrg CHK_ATOM_ONLY(dWire->any.name); 5006f7df2e56Smrg doodad = XkbAddGeomDoodad(geom, section, any.name); 500705b261ecSmrg if (!doodad) 5008f7df2e56Smrg return BadAlloc; 5009f7df2e56Smrg doodad->any.type = dWire->any.type; 5010f7df2e56Smrg doodad->any.priority = dWire->any.priority; 5011f7df2e56Smrg doodad->any.top = any.top; 5012f7df2e56Smrg doodad->any.left = any.left; 5013f7df2e56Smrg doodad->any.angle = any.angle; 501405b261ecSmrg switch (doodad->any.type) { 5015f7df2e56Smrg case XkbOutlineDoodad: 5016f7df2e56Smrg case XkbSolidDoodad: 5017f7df2e56Smrg if (dWire->shape.colorNdx >= geom->num_colors) { 5018f7df2e56Smrg client->errorValue = _XkbErrCode3(0x40, geom->num_colors, 5019f7df2e56Smrg dWire->shape.colorNdx); 5020f7df2e56Smrg return BadMatch; 5021f7df2e56Smrg } 5022f7df2e56Smrg if (dWire->shape.shapeNdx >= geom->num_shapes) { 5023f7df2e56Smrg client->errorValue = _XkbErrCode3(0x41, geom->num_shapes, 5024f7df2e56Smrg dWire->shape.shapeNdx); 5025f7df2e56Smrg return BadMatch; 5026f7df2e56Smrg } 5027f7df2e56Smrg doodad->shape.color_ndx = dWire->shape.colorNdx; 5028f7df2e56Smrg doodad->shape.shape_ndx = dWire->shape.shapeNdx; 5029f7df2e56Smrg break; 5030f7df2e56Smrg case XkbTextDoodad: 5031f7df2e56Smrg if (dWire->text.colorNdx >= geom->num_colors) { 5032f7df2e56Smrg client->errorValue = _XkbErrCode3(0x42, geom->num_colors, 5033f7df2e56Smrg dWire->text.colorNdx); 5034f7df2e56Smrg return BadMatch; 5035f7df2e56Smrg } 5036f7df2e56Smrg text = dWire->text; 5037f7df2e56Smrg if (client->swapped) { 5038f7df2e56Smrg swaps(&text.width); 5039f7df2e56Smrg swaps(&text.height); 5040f7df2e56Smrg } 5041f7df2e56Smrg doodad->text.width = text.width; 5042f7df2e56Smrg doodad->text.height = text.height; 5043f7df2e56Smrg doodad->text.color_ndx = dWire->text.colorNdx; 5044f7df2e56Smrg status = _GetCountedString(&wire, client, &doodad->text.text); 5045f7df2e56Smrg if (status != Success) 5046f7df2e56Smrg return status; 5047f7df2e56Smrg status = _GetCountedString(&wire, client, &doodad->text.font); 5048f7df2e56Smrg if (status != Success) { 5049f7df2e56Smrg free (doodad->text.text); 5050f7df2e56Smrg return status; 5051f7df2e56Smrg } 5052f7df2e56Smrg break; 5053f7df2e56Smrg case XkbIndicatorDoodad: 5054f7df2e56Smrg if (dWire->indicator.onColorNdx >= geom->num_colors) { 5055f7df2e56Smrg client->errorValue = _XkbErrCode3(0x43, geom->num_colors, 5056f7df2e56Smrg dWire->indicator.onColorNdx); 5057f7df2e56Smrg return BadMatch; 5058f7df2e56Smrg } 5059f7df2e56Smrg if (dWire->indicator.offColorNdx >= geom->num_colors) { 5060f7df2e56Smrg client->errorValue = _XkbErrCode3(0x44, geom->num_colors, 5061f7df2e56Smrg dWire->indicator.offColorNdx); 5062f7df2e56Smrg return BadMatch; 5063f7df2e56Smrg } 5064f7df2e56Smrg if (dWire->indicator.shapeNdx >= geom->num_shapes) { 5065f7df2e56Smrg client->errorValue = _XkbErrCode3(0x45, geom->num_shapes, 5066f7df2e56Smrg dWire->indicator.shapeNdx); 5067f7df2e56Smrg return BadMatch; 5068f7df2e56Smrg } 5069f7df2e56Smrg doodad->indicator.shape_ndx = dWire->indicator.shapeNdx; 5070f7df2e56Smrg doodad->indicator.on_color_ndx = dWire->indicator.onColorNdx; 5071f7df2e56Smrg doodad->indicator.off_color_ndx = dWire->indicator.offColorNdx; 5072f7df2e56Smrg break; 5073f7df2e56Smrg case XkbLogoDoodad: 5074f7df2e56Smrg if (dWire->logo.colorNdx >= geom->num_colors) { 5075f7df2e56Smrg client->errorValue = _XkbErrCode3(0x46, geom->num_colors, 5076f7df2e56Smrg dWire->logo.colorNdx); 5077f7df2e56Smrg return BadMatch; 5078f7df2e56Smrg } 5079f7df2e56Smrg if (dWire->logo.shapeNdx >= geom->num_shapes) { 5080f7df2e56Smrg client->errorValue = _XkbErrCode3(0x47, geom->num_shapes, 5081f7df2e56Smrg dWire->logo.shapeNdx); 5082f7df2e56Smrg return BadMatch; 5083f7df2e56Smrg } 5084f7df2e56Smrg doodad->logo.color_ndx = dWire->logo.colorNdx; 5085f7df2e56Smrg doodad->logo.shape_ndx = dWire->logo.shapeNdx; 5086f7df2e56Smrg status = _GetCountedString(&wire, client, &doodad->logo.logo_name); 5087f7df2e56Smrg if (status != Success) 5088f7df2e56Smrg return status; 5089f7df2e56Smrg break; 5090f7df2e56Smrg default: 5091f7df2e56Smrg client->errorValue = _XkbErrCode2(0x4F, dWire->any.type); 5092f7df2e56Smrg return BadValue; 5093f7df2e56Smrg } 5094f7df2e56Smrg *wire_inout = wire; 5095f7df2e56Smrg return Success; 5096f7df2e56Smrg} 5097f7df2e56Smrg 5098f7df2e56Smrgstatic Status 5099f7df2e56Smrg_CheckSetOverlay(char **wire_inout, 5100f7df2e56Smrg XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client) 510105b261ecSmrg{ 5102f7df2e56Smrg register int r; 5103f7df2e56Smrg char *wire; 5104f7df2e56Smrg XkbOverlayPtr ol; 5105f7df2e56Smrg xkbOverlayWireDesc *olWire; 5106f7df2e56Smrg xkbOverlayRowWireDesc *rWire; 510705b261ecSmrg 5108f7df2e56Smrg wire = *wire_inout; 5109f7df2e56Smrg olWire = (xkbOverlayWireDesc *) wire; 5110f7df2e56Smrg if (client->swapped) { 5111f7df2e56Smrg swapl(&olWire->name); 5112f7df2e56Smrg } 5113f7df2e56Smrg CHK_ATOM_ONLY(olWire->name); 5114f7df2e56Smrg ol = XkbAddGeomOverlay(section, olWire->name, olWire->nRows); 5115f7df2e56Smrg rWire = (xkbOverlayRowWireDesc *) &olWire[1]; 5116f7df2e56Smrg for (r = 0; r < olWire->nRows; r++) { 5117f7df2e56Smrg register int k; 5118f7df2e56Smrg xkbOverlayKeyWireDesc *kWire; 5119f7df2e56Smrg XkbOverlayRowPtr row; 5120f7df2e56Smrg 5121f7df2e56Smrg if (rWire->rowUnder > section->num_rows) { 5122f7df2e56Smrg client->errorValue = _XkbErrCode4(0x20, r, section->num_rows, 5123f7df2e56Smrg rWire->rowUnder); 5124f7df2e56Smrg return BadMatch; 5125f7df2e56Smrg } 5126f7df2e56Smrg row = XkbAddGeomOverlayRow(ol, rWire->rowUnder, rWire->nKeys); 5127f7df2e56Smrg kWire = (xkbOverlayKeyWireDesc *) &rWire[1]; 5128f7df2e56Smrg for (k = 0; k < rWire->nKeys; k++, kWire++) { 5129f7df2e56Smrg if (XkbAddGeomOverlayKey(ol, row, 5130f7df2e56Smrg (char *) kWire->over, 5131f7df2e56Smrg (char *) kWire->under) == NULL) { 5132f7df2e56Smrg client->errorValue = _XkbErrCode3(0x21, r, k); 5133f7df2e56Smrg return BadMatch; 5134f7df2e56Smrg } 5135f7df2e56Smrg } 5136f7df2e56Smrg rWire = (xkbOverlayRowWireDesc *) kWire; 5137f7df2e56Smrg } 5138f7df2e56Smrg olWire = (xkbOverlayWireDesc *) rWire; 5139f7df2e56Smrg wire = (char *) olWire; 5140f7df2e56Smrg *wire_inout = wire; 5141f7df2e56Smrg return Success; 5142f7df2e56Smrg} 5143f7df2e56Smrg 5144f7df2e56Smrgstatic Status 5145f7df2e56Smrg_CheckSetSections(XkbGeometryPtr geom, 5146f7df2e56Smrg xkbSetGeometryReq * req, char **wire_inout, ClientPtr client) 5147f7df2e56Smrg{ 5148f7df2e56Smrg Status status; 5149f7df2e56Smrg register int s; 5150f7df2e56Smrg char *wire; 5151f7df2e56Smrg xkbSectionWireDesc *sWire; 5152f7df2e56Smrg XkbSectionPtr section; 5153f7df2e56Smrg 5154f7df2e56Smrg wire = *wire_inout; 5155f7df2e56Smrg if (req->nSections < 1) 5156f7df2e56Smrg return Success; 5157f7df2e56Smrg sWire = (xkbSectionWireDesc *) wire; 5158f7df2e56Smrg for (s = 0; s < req->nSections; s++) { 5159f7df2e56Smrg register int r; 5160f7df2e56Smrg xkbRowWireDesc *rWire; 5161f7df2e56Smrg 5162f7df2e56Smrg if (client->swapped) { 5163f7df2e56Smrg swapl(&sWire->name); 5164f7df2e56Smrg swaps(&sWire->top); 5165f7df2e56Smrg swaps(&sWire->left); 5166f7df2e56Smrg swaps(&sWire->width); 5167f7df2e56Smrg swaps(&sWire->height); 5168f7df2e56Smrg swaps(&sWire->angle); 5169f7df2e56Smrg } 5170f7df2e56Smrg CHK_ATOM_ONLY(sWire->name); 5171f7df2e56Smrg section = XkbAddGeomSection(geom, sWire->name, sWire->nRows, 5172f7df2e56Smrg sWire->nDoodads, sWire->nOverlays); 5173f7df2e56Smrg if (!section) 5174f7df2e56Smrg return BadAlloc; 5175f7df2e56Smrg section->priority = sWire->priority; 5176f7df2e56Smrg section->top = sWire->top; 5177f7df2e56Smrg section->left = sWire->left; 5178f7df2e56Smrg section->width = sWire->width; 5179f7df2e56Smrg section->height = sWire->height; 5180f7df2e56Smrg section->angle = sWire->angle; 5181f7df2e56Smrg rWire = (xkbRowWireDesc *) &sWire[1]; 5182f7df2e56Smrg for (r = 0; r < sWire->nRows; r++) { 5183f7df2e56Smrg register int k; 5184f7df2e56Smrg XkbRowPtr row; 5185f7df2e56Smrg xkbKeyWireDesc *kWire; 5186f7df2e56Smrg 5187f7df2e56Smrg if (client->swapped) { 5188f7df2e56Smrg swaps(&rWire->top); 5189f7df2e56Smrg swaps(&rWire->left); 5190f7df2e56Smrg } 5191f7df2e56Smrg row = XkbAddGeomRow(section, rWire->nKeys); 5192f7df2e56Smrg if (!row) 5193f7df2e56Smrg return BadAlloc; 5194f7df2e56Smrg row->top = rWire->top; 5195f7df2e56Smrg row->left = rWire->left; 5196f7df2e56Smrg row->vertical = rWire->vertical; 5197f7df2e56Smrg kWire = (xkbKeyWireDesc *) &rWire[1]; 5198f7df2e56Smrg for (k = 0; k < rWire->nKeys; k++) { 5199f7df2e56Smrg XkbKeyPtr key; 5200f7df2e56Smrg 5201f7df2e56Smrg key = XkbAddGeomKey(row); 5202f7df2e56Smrg if (!key) 5203f7df2e56Smrg return BadAlloc; 5204f7df2e56Smrg memcpy(key->name.name, kWire[k].name, XkbKeyNameLength); 5205f7df2e56Smrg key->gap = kWire[k].gap; 5206f7df2e56Smrg key->shape_ndx = kWire[k].shapeNdx; 5207f7df2e56Smrg key->color_ndx = kWire[k].colorNdx; 5208f7df2e56Smrg if (key->shape_ndx >= geom->num_shapes) { 5209f7df2e56Smrg client->errorValue = _XkbErrCode3(0x10, key->shape_ndx, 5210f7df2e56Smrg geom->num_shapes); 5211f7df2e56Smrg return BadMatch; 5212f7df2e56Smrg } 5213f7df2e56Smrg if (key->color_ndx >= geom->num_colors) { 5214f7df2e56Smrg client->errorValue = _XkbErrCode3(0x11, key->color_ndx, 5215f7df2e56Smrg geom->num_colors); 5216f7df2e56Smrg return BadMatch; 5217f7df2e56Smrg } 5218f7df2e56Smrg } 5219f7df2e56Smrg rWire = (xkbRowWireDesc *) &kWire[rWire->nKeys]; 5220f7df2e56Smrg } 5221f7df2e56Smrg wire = (char *) rWire; 5222f7df2e56Smrg if (sWire->nDoodads > 0) { 5223f7df2e56Smrg register int d; 5224f7df2e56Smrg 5225f7df2e56Smrg for (d = 0; d < sWire->nDoodads; d++) { 5226f7df2e56Smrg status = _CheckSetDoodad(&wire, geom, section, client); 5227f7df2e56Smrg if (status != Success) 5228f7df2e56Smrg return status; 5229f7df2e56Smrg } 5230f7df2e56Smrg } 5231f7df2e56Smrg if (sWire->nOverlays > 0) { 5232f7df2e56Smrg register int o; 5233f7df2e56Smrg 5234f7df2e56Smrg for (o = 0; o < sWire->nOverlays; o++) { 5235f7df2e56Smrg status = _CheckSetOverlay(&wire, geom, section, client); 5236f7df2e56Smrg if (status != Success) 5237f7df2e56Smrg return status; 5238f7df2e56Smrg } 5239f7df2e56Smrg } 5240f7df2e56Smrg sWire = (xkbSectionWireDesc *) wire; 5241f7df2e56Smrg } 5242f7df2e56Smrg wire = (char *) sWire; 5243f7df2e56Smrg *wire_inout = wire; 5244f7df2e56Smrg return Success; 5245f7df2e56Smrg} 5246f7df2e56Smrg 5247f7df2e56Smrgstatic Status 5248f7df2e56Smrg_CheckSetShapes(XkbGeometryPtr geom, 5249f7df2e56Smrg xkbSetGeometryReq * req, char **wire_inout, ClientPtr client) 5250f7df2e56Smrg{ 5251f7df2e56Smrg register int i; 5252f7df2e56Smrg char *wire; 5253f7df2e56Smrg 5254f7df2e56Smrg wire = *wire_inout; 5255f7df2e56Smrg if (req->nShapes < 1) { 5256f7df2e56Smrg client->errorValue = _XkbErrCode2(0x06, req->nShapes); 5257f7df2e56Smrg return BadValue; 525805b261ecSmrg } 525905b261ecSmrg else { 5260f7df2e56Smrg xkbShapeWireDesc *shapeWire; 5261f7df2e56Smrg XkbShapePtr shape; 5262f7df2e56Smrg register int o; 5263f7df2e56Smrg 5264f7df2e56Smrg shapeWire = (xkbShapeWireDesc *) wire; 5265f7df2e56Smrg for (i = 0; i < req->nShapes; i++) { 5266f7df2e56Smrg xkbOutlineWireDesc *olWire; 5267f7df2e56Smrg XkbOutlinePtr ol; 5268f7df2e56Smrg 5269f7df2e56Smrg shape = 5270f7df2e56Smrg XkbAddGeomShape(geom, shapeWire->name, shapeWire->nOutlines); 5271f7df2e56Smrg if (!shape) 5272f7df2e56Smrg return BadAlloc; 5273f7df2e56Smrg olWire = (xkbOutlineWireDesc *) (&shapeWire[1]); 5274f7df2e56Smrg for (o = 0; o < shapeWire->nOutlines; o++) { 5275f7df2e56Smrg register int p; 5276f7df2e56Smrg XkbPointPtr pt; 5277f7df2e56Smrg xkbPointWireDesc *ptWire; 5278f7df2e56Smrg 5279f7df2e56Smrg ol = XkbAddGeomOutline(shape, olWire->nPoints); 5280f7df2e56Smrg if (!ol) 5281f7df2e56Smrg return BadAlloc; 5282f7df2e56Smrg ol->corner_radius = olWire->cornerRadius; 5283f7df2e56Smrg ptWire = (xkbPointWireDesc *) &olWire[1]; 5284f7df2e56Smrg for (p = 0, pt = ol->points; p < olWire->nPoints; p++, pt++) { 5285f7df2e56Smrg pt->x = ptWire[p].x; 5286f7df2e56Smrg pt->y = ptWire[p].y; 5287f7df2e56Smrg if (client->swapped) { 5288f7df2e56Smrg swaps(&pt->x); 5289f7df2e56Smrg swaps(&pt->y); 5290f7df2e56Smrg } 5291f7df2e56Smrg } 5292f7df2e56Smrg ol->num_points = olWire->nPoints; 5293f7df2e56Smrg olWire = (xkbOutlineWireDesc *) (&ptWire[olWire->nPoints]); 5294f7df2e56Smrg } 5295f7df2e56Smrg if (shapeWire->primaryNdx != XkbNoShape) 5296f7df2e56Smrg shape->primary = &shape->outlines[shapeWire->primaryNdx]; 5297f7df2e56Smrg if (shapeWire->approxNdx != XkbNoShape) 5298f7df2e56Smrg shape->approx = &shape->outlines[shapeWire->approxNdx]; 5299f7df2e56Smrg shapeWire = (xkbShapeWireDesc *) olWire; 5300f7df2e56Smrg } 5301f7df2e56Smrg wire = (char *) shapeWire; 5302f7df2e56Smrg } 5303f7df2e56Smrg if (geom->num_shapes != req->nShapes) { 5304f7df2e56Smrg client->errorValue = _XkbErrCode3(0x07, geom->num_shapes, req->nShapes); 5305f7df2e56Smrg return BadMatch; 5306f7df2e56Smrg } 5307f7df2e56Smrg 5308f7df2e56Smrg *wire_inout = wire; 530905b261ecSmrg return Success; 531005b261ecSmrg} 531105b261ecSmrg 531205b261ecSmrgstatic Status 5313f7df2e56Smrg_CheckSetGeom(XkbGeometryPtr geom, xkbSetGeometryReq * req, ClientPtr client) 531405b261ecSmrg{ 5315f7df2e56Smrg register int i; 5316f7df2e56Smrg Status status; 5317f7df2e56Smrg char *wire; 531805b261ecSmrg 5319f7df2e56Smrg wire = (char *) &req[1]; 53201e26616aSmrg status = _GetCountedString(&wire, client, &geom->label_font); 53211e26616aSmrg if (status != Success) 53221e26616aSmrg return status; 53231e26616aSmrg 53241e26616aSmrg for (i = 0; i < req->nProperties; i++) { 5325f7df2e56Smrg char *name, *val; 53261e26616aSmrg 53271e26616aSmrg status = _GetCountedString(&wire, client, &name); 53281e26616aSmrg if (status != Success) 53291e26616aSmrg return status; 53301e26616aSmrg status = _GetCountedString(&wire, client, &val); 53311e26616aSmrg if (status != Success) { 53326747b715Smrg free(name); 53331e26616aSmrg return status; 533405b261ecSmrg } 5335f7df2e56Smrg if (XkbAddGeomProperty(geom, name, val) == NULL) { 53366747b715Smrg free(name); 53376747b715Smrg free(val); 5338f7df2e56Smrg return BadAlloc; 533905b261ecSmrg } 53406747b715Smrg free(name); 53416747b715Smrg free(val); 534205b261ecSmrg } 534305b261ecSmrg 5344f7df2e56Smrg if (req->nColors < 2) { 5345f7df2e56Smrg client->errorValue = _XkbErrCode3(0x01, 2, req->nColors); 5346f7df2e56Smrg return BadValue; 534705b261ecSmrg } 5348f7df2e56Smrg if (req->baseColorNdx > req->nColors) { 5349f7df2e56Smrg client->errorValue = 5350f7df2e56Smrg _XkbErrCode3(0x03, req->nColors, req->baseColorNdx); 5351f7df2e56Smrg return BadMatch; 535205b261ecSmrg } 5353f7df2e56Smrg if (req->labelColorNdx > req->nColors) { 5354f7df2e56Smrg client->errorValue = 5355f7df2e56Smrg _XkbErrCode3(0x03, req->nColors, req->labelColorNdx); 5356f7df2e56Smrg return BadMatch; 535705b261ecSmrg } 5358f7df2e56Smrg if (req->labelColorNdx == req->baseColorNdx) { 5359f7df2e56Smrg client->errorValue = _XkbErrCode3(0x04, req->baseColorNdx, 5360f7df2e56Smrg req->labelColorNdx); 5361f7df2e56Smrg return BadMatch; 536205b261ecSmrg } 536305b261ecSmrg 53641e26616aSmrg for (i = 0; i < req->nColors; i++) { 5365f7df2e56Smrg char *name; 5366f7df2e56Smrg 53671e26616aSmrg status = _GetCountedString(&wire, client, &name); 53681e26616aSmrg if (status != Success) 53691e26616aSmrg return status; 5370f7df2e56Smrg if (!XkbAddGeomColor(geom, name, geom->num_colors)) { 53716747b715Smrg free(name); 5372f7df2e56Smrg return BadAlloc; 537305b261ecSmrg } 53746747b715Smrg free(name); 537505b261ecSmrg } 5376f7df2e56Smrg if (req->nColors != geom->num_colors) { 5377f7df2e56Smrg client->errorValue = _XkbErrCode3(0x05, req->nColors, geom->num_colors); 5378f7df2e56Smrg return BadMatch; 537905b261ecSmrg } 5380f7df2e56Smrg geom->label_color = &geom->colors[req->labelColorNdx]; 5381f7df2e56Smrg geom->base_color = &geom->colors[req->baseColorNdx]; 538205b261ecSmrg 5383f7df2e56Smrg if ((status = _CheckSetShapes(geom, req, &wire, client)) != Success) 5384f7df2e56Smrg return status; 538505b261ecSmrg 5386f7df2e56Smrg if ((status = _CheckSetSections(geom, req, &wire, client)) != Success) 5387f7df2e56Smrg return status; 538805b261ecSmrg 5389f7df2e56Smrg for (i = 0; i < req->nDoodads; i++) { 5390f7df2e56Smrg status = _CheckSetDoodad(&wire, geom, NULL, client); 5391f7df2e56Smrg if (status != Success) 5392f7df2e56Smrg return status; 539305b261ecSmrg } 539405b261ecSmrg 5395f7df2e56Smrg for (i = 0; i < req->nKeyAliases; i++) { 5396f7df2e56Smrg if (XkbAddGeomKeyAlias(geom, &wire[XkbKeyNameLength], wire) == NULL) 5397f7df2e56Smrg return BadAlloc; 5398f7df2e56Smrg wire += 2 * XkbKeyNameLength; 539905b261ecSmrg } 540005b261ecSmrg return Success; 540105b261ecSmrg} 540205b261ecSmrg 54034642e01fSmrgstatic int 5404f7df2e56Smrg_XkbSetGeometry(ClientPtr client, DeviceIntPtr dev, xkbSetGeometryReq * stuff) 540505b261ecSmrg{ 5406f7df2e56Smrg XkbDescPtr xkb; 5407f7df2e56Smrg Bool new_name; 5408f7df2e56Smrg xkbNewKeyboardNotify nkn; 5409f7df2e56Smrg XkbGeometryPtr geom, old; 5410f7df2e56Smrg XkbGeometrySizesRec sizes; 5411f7df2e56Smrg Status status; 5412f7df2e56Smrg 5413f7df2e56Smrg xkb = dev->key->xkbInfo->desc; 5414f7df2e56Smrg old = xkb->geom; 5415f7df2e56Smrg xkb->geom = NULL; 5416f7df2e56Smrg 5417f7df2e56Smrg sizes.which = XkbGeomAllMask; 5418f7df2e56Smrg sizes.num_properties = stuff->nProperties; 5419f7df2e56Smrg sizes.num_colors = stuff->nColors; 5420f7df2e56Smrg sizes.num_shapes = stuff->nShapes; 5421f7df2e56Smrg sizes.num_sections = stuff->nSections; 5422f7df2e56Smrg sizes.num_doodads = stuff->nDoodads; 5423f7df2e56Smrg sizes.num_key_aliases = stuff->nKeyAliases; 5424f7df2e56Smrg if ((status = XkbAllocGeometry(xkb, &sizes)) != Success) { 5425f7df2e56Smrg xkb->geom = old; 54264642e01fSmrg return status; 542705b261ecSmrg } 5428f7df2e56Smrg geom = xkb->geom; 5429f7df2e56Smrg geom->name = stuff->name; 5430f7df2e56Smrg geom->width_mm = stuff->widthMM; 5431f7df2e56Smrg geom->height_mm = stuff->heightMM; 5432f7df2e56Smrg if ((status = _CheckSetGeom(geom, stuff, client)) != Success) { 5433f7df2e56Smrg XkbFreeGeometry(geom, XkbGeomAllMask, TRUE); 5434f7df2e56Smrg xkb->geom = old; 54354642e01fSmrg return status; 543605b261ecSmrg } 5437f7df2e56Smrg new_name = (xkb->names->geometry != geom->name); 5438f7df2e56Smrg xkb->names->geometry = geom->name; 543905b261ecSmrg if (old) 5440f7df2e56Smrg XkbFreeGeometry(old, XkbGeomAllMask, TRUE); 544105b261ecSmrg if (new_name) { 5442f7df2e56Smrg xkbNamesNotify nn; 5443f7df2e56Smrg 54446747b715Smrg memset(&nn, 0, sizeof(xkbNamesNotify)); 5445f7df2e56Smrg nn.changed = XkbGeometryNameMask; 5446f7df2e56Smrg XkbSendNamesNotify(dev, &nn); 5447f7df2e56Smrg } 5448f7df2e56Smrg nkn.deviceID = nkn.oldDeviceID = dev->id; 5449f7df2e56Smrg nkn.minKeyCode = nkn.oldMinKeyCode = xkb->min_key_code; 5450f7df2e56Smrg nkn.maxKeyCode = nkn.oldMaxKeyCode = xkb->max_key_code; 5451f7df2e56Smrg nkn.requestMajor = XkbReqCode; 5452f7df2e56Smrg nkn.requestMinor = X_kbSetGeometry; 5453f7df2e56Smrg nkn.changed = XkbNKN_GeometryMask; 5454f7df2e56Smrg XkbSendNewKeyboardNotify(dev, &nkn); 545505b261ecSmrg return Success; 545605b261ecSmrg} 545705b261ecSmrg 54584642e01fSmrgint 54594642e01fSmrgProcXkbSetGeometry(ClientPtr client) 54604642e01fSmrg{ 5461f7df2e56Smrg DeviceIntPtr dev; 5462f7df2e56Smrg int rc; 54634642e01fSmrg 54644642e01fSmrg REQUEST(xkbSetGeometryReq); 54654642e01fSmrg REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq); 54664642e01fSmrg 5467f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 5468f7df2e56Smrg return BadAccess; 54694642e01fSmrg 54704642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); 54714642e01fSmrg CHK_ATOM_OR_NONE(stuff->name); 54724642e01fSmrg 54734642e01fSmrg rc = _XkbSetGeometry(client, dev, stuff); 54744642e01fSmrg if (rc != Success) 54754642e01fSmrg return rc; 54764642e01fSmrg 5477f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd) { 54784642e01fSmrg DeviceIntPtr other; 5479f7df2e56Smrg 5480f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 5481f7df2e56Smrg if ((other != dev) && other->key && !IsMaster(other) && 5482f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) { 5483f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 5484f7df2e56Smrg DixManageAccess); 54854642e01fSmrg if (rc == Success) 54864642e01fSmrg _XkbSetGeometry(client, other, stuff); 54874642e01fSmrg } 54884642e01fSmrg } 54894642e01fSmrg } 54904642e01fSmrg 54914642e01fSmrg return Success; 54924642e01fSmrg} 54934642e01fSmrg 549405b261ecSmrg/***====================================================================***/ 549505b261ecSmrg 549605b261ecSmrgint 549705b261ecSmrgProcXkbPerClientFlags(ClientPtr client) 549805b261ecSmrg{ 5499f7df2e56Smrg DeviceIntPtr dev; 5500f7df2e56Smrg xkbPerClientFlagsReply rep; 5501f7df2e56Smrg XkbInterestPtr interest; 55024642e01fSmrg Mask access_mode = DixGetAttrAccess | DixSetAttrAccess; 550305b261ecSmrg 550405b261ecSmrg REQUEST(xkbPerClientFlagsReq); 550505b261ecSmrg REQUEST_SIZE_MATCH(xkbPerClientFlagsReq); 550605b261ecSmrg 5507f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 5508f7df2e56Smrg return BadAccess; 550905b261ecSmrg 55104642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode); 5511f7df2e56Smrg CHK_MASK_LEGAL(0x01, stuff->change, XkbPCF_AllFlagsMask); 5512f7df2e56Smrg CHK_MASK_MATCH(0x02, stuff->change, stuff->value); 551305b261ecSmrg 5514f7df2e56Smrg interest = XkbFindClientResource((DevicePtr) dev, client); 551505b261ecSmrg if (stuff->change) { 5516f7df2e56Smrg client->xkbClientFlags &= ~stuff->change; 5517f7df2e56Smrg client->xkbClientFlags |= stuff->value; 551805b261ecSmrg } 5519f7df2e56Smrg if (stuff->change & XkbPCF_AutoResetControlsMask) { 5520f7df2e56Smrg Bool want; 5521f7df2e56Smrg 5522f7df2e56Smrg want = stuff->value & XkbPCF_AutoResetControlsMask; 5523f7df2e56Smrg if (interest && !want) { 5524f7df2e56Smrg interest->autoCtrls = interest->autoCtrlValues = 0; 5525f7df2e56Smrg } 5526f7df2e56Smrg else if (want && (!interest)) { 5527f7df2e56Smrg XID id = FakeClientID(client->index); 5528f7df2e56Smrg 5529f7df2e56Smrg if (!AddResource(id, RT_XKBCLIENT, dev)) 5530f7df2e56Smrg return BadAlloc; 5531f7df2e56Smrg interest = XkbAddClientResource((DevicePtr) dev, client, id); 5532f7df2e56Smrg if (!interest) 5533f7df2e56Smrg return BadAlloc; 5534f7df2e56Smrg } 5535f7df2e56Smrg if (interest && want) { 5536f7df2e56Smrg register unsigned affect; 5537f7df2e56Smrg 5538f7df2e56Smrg affect = stuff->ctrlsToChange; 5539f7df2e56Smrg 5540f7df2e56Smrg CHK_MASK_LEGAL(0x03, affect, XkbAllBooleanCtrlsMask); 5541f7df2e56Smrg CHK_MASK_MATCH(0x04, affect, stuff->autoCtrls); 5542f7df2e56Smrg CHK_MASK_MATCH(0x05, stuff->autoCtrls, stuff->autoCtrlValues); 5543f7df2e56Smrg 5544f7df2e56Smrg interest->autoCtrls &= ~affect; 5545f7df2e56Smrg interest->autoCtrlValues &= ~affect; 5546f7df2e56Smrg interest->autoCtrls |= stuff->autoCtrls & affect; 5547f7df2e56Smrg interest->autoCtrlValues |= stuff->autoCtrlValues & affect; 5548f7df2e56Smrg } 554905b261ecSmrg } 5550f7df2e56Smrg 5551f7df2e56Smrg rep = (xkbPerClientFlagsReply) { 5552f7df2e56Smrg .type = X_Reply, 5553f7df2e56Smrg .sequenceNumber = client->sequence, 5554f7df2e56Smrg .length = 0, 5555f7df2e56Smrg .supported = XkbPCF_AllFlagsMask, 5556f7df2e56Smrg .value = client->xkbClientFlags & XkbPCF_AllFlagsMask, 5557f7df2e56Smrg .autoCtrls = interest ? interest->autoCtrls : 0, 5558f7df2e56Smrg .autoCtrlValues = interest ? interest->autoCtrlValues : 0, 5559f7df2e56Smrg }; 5560f7df2e56Smrg if (client->swapped) { 5561f7df2e56Smrg swaps(&rep.sequenceNumber); 5562f7df2e56Smrg swapl(&rep.supported); 5563f7df2e56Smrg swapl(&rep.value); 5564f7df2e56Smrg swapl(&rep.autoCtrls); 5565f7df2e56Smrg swapl(&rep.autoCtrlValues); 556605b261ecSmrg } 5567f7df2e56Smrg WriteToClient(client, SIZEOF(xkbPerClientFlagsReply), &rep); 55686747b715Smrg return Success; 556905b261ecSmrg} 557005b261ecSmrg 557105b261ecSmrg/***====================================================================***/ 557205b261ecSmrg 557305b261ecSmrg/* all latin-1 alphanumerics, plus parens, minus, underscore, slash */ 557405b261ecSmrg/* and wildcards */ 557505b261ecSmrgstatic unsigned char componentSpecLegal[] = { 5576f7df2e56Smrg 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x87, 5577f7df2e56Smrg 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07, 5578f7df2e56Smrg 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 5579f7df2e56Smrg 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff 558005b261ecSmrg}; 558105b261ecSmrg 558205b261ecSmrg/* same as above but accepts percent, plus and bar too */ 558305b261ecSmrgstatic unsigned char componentExprLegal[] = { 5584f7df2e56Smrg 0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0xff, 0x87, 5585f7df2e56Smrg 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x17, 5586f7df2e56Smrg 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 5587f7df2e56Smrg 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff 558805b261ecSmrg}; 558905b261ecSmrg 559005b261ecSmrgstatic char * 5591f7df2e56SmrgGetComponentSpec(unsigned char **pWire, Bool allowExpr, int *errRtrn) 559205b261ecSmrg{ 5593f7df2e56Smrg int len; 5594f7df2e56Smrg register int i; 5595f7df2e56Smrg unsigned char *wire, *str, *tmp, *legal; 5596f7df2e56Smrg 5597f7df2e56Smrg if (allowExpr) 5598f7df2e56Smrg legal = &componentExprLegal[0]; 5599f7df2e56Smrg else 5600f7df2e56Smrg legal = &componentSpecLegal[0]; 5601f7df2e56Smrg 5602f7df2e56Smrg wire = *pWire; 5603f7df2e56Smrg len = (*(unsigned char *) wire++); 5604f7df2e56Smrg if (len > 0) { 5605f7df2e56Smrg str = calloc(1, len + 1); 5606f7df2e56Smrg if (str) { 5607f7df2e56Smrg tmp = str; 5608f7df2e56Smrg for (i = 0; i < len; i++) { 5609f7df2e56Smrg if (legal[(*wire) / 8] & (1 << ((*wire) % 8))) 5610f7df2e56Smrg *tmp++ = *wire++; 5611f7df2e56Smrg else 5612f7df2e56Smrg wire++; 5613f7df2e56Smrg } 5614f7df2e56Smrg if (tmp != str) 5615f7df2e56Smrg *tmp++ = '\0'; 5616f7df2e56Smrg else { 5617f7df2e56Smrg free(str); 5618f7df2e56Smrg str = NULL; 5619f7df2e56Smrg } 5620f7df2e56Smrg } 5621f7df2e56Smrg else { 5622f7df2e56Smrg *errRtrn = BadAlloc; 5623f7df2e56Smrg } 562405b261ecSmrg } 562505b261ecSmrg else { 5626f7df2e56Smrg str = NULL; 562705b261ecSmrg } 5628f7df2e56Smrg *pWire = wire; 5629f7df2e56Smrg return (char *) str; 563005b261ecSmrg} 563105b261ecSmrg 563205b261ecSmrg/***====================================================================***/ 563305b261ecSmrg 563405b261ecSmrgint 563505b261ecSmrgProcXkbListComponents(ClientPtr client) 563605b261ecSmrg{ 5637f7df2e56Smrg DeviceIntPtr dev; 5638f7df2e56Smrg xkbListComponentsReply rep; 5639f7df2e56Smrg unsigned len; 5640f7df2e56Smrg unsigned char *str; 5641f7df2e56Smrg uint8_t size; 5642f7df2e56Smrg int i; 564305b261ecSmrg 564405b261ecSmrg REQUEST(xkbListComponentsReq); 564505b261ecSmrg REQUEST_AT_LEAST_SIZE(xkbListComponentsReq); 564605b261ecSmrg 5647f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 5648f7df2e56Smrg return BadAccess; 564905b261ecSmrg 56504642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); 565105b261ecSmrg 5652f7df2e56Smrg /* The request is followed by six Pascal strings (i.e. size in characters 5653f7df2e56Smrg * followed by a string pattern) describing what the client wants us to 5654f7df2e56Smrg * list. We don't care, but might as well check they haven't got the 5655f7df2e56Smrg * length wrong. */ 5656f7df2e56Smrg str = (unsigned char *) &stuff[1]; 5657f7df2e56Smrg for (i = 0; i < 6; i++) { 5658f7df2e56Smrg size = *((uint8_t *)str); 5659f7df2e56Smrg len = (str + size + 1) - ((unsigned char *) stuff); 5660f7df2e56Smrg if ((XkbPaddedSize(len) / 4) > stuff->length) 5661f7df2e56Smrg return BadLength; 5662f7df2e56Smrg str += (size + 1); 5663f7df2e56Smrg } 5664f7df2e56Smrg if ((XkbPaddedSize(len) / 4) != stuff->length) 5665f7df2e56Smrg return BadLength; 5666f7df2e56Smrg rep = (xkbListComponentsReply) { 5667f7df2e56Smrg .type = X_Reply, 5668f7df2e56Smrg .deviceID = dev->id, 5669f7df2e56Smrg .sequenceNumber = client->sequence, 5670f7df2e56Smrg .length = 0, 5671f7df2e56Smrg .nKeymaps = 0, 5672f7df2e56Smrg .nKeycodes = 0, 5673f7df2e56Smrg .nTypes = 0, 5674f7df2e56Smrg .nCompatMaps = 0, 5675f7df2e56Smrg .nSymbols = 0, 5676f7df2e56Smrg .nGeometries = 0, 5677f7df2e56Smrg .extra = 0 5678f7df2e56Smrg }; 567905b261ecSmrg if (client->swapped) { 5680f7df2e56Smrg swaps(&rep.sequenceNumber); 5681f7df2e56Smrg swapl(&rep.length); 5682f7df2e56Smrg swaps(&rep.nKeymaps); 5683f7df2e56Smrg swaps(&rep.nKeycodes); 5684f7df2e56Smrg swaps(&rep.nTypes); 5685f7df2e56Smrg swaps(&rep.nCompatMaps); 5686f7df2e56Smrg swaps(&rep.nSymbols); 5687f7df2e56Smrg swaps(&rep.nGeometries); 5688f7df2e56Smrg swaps(&rep.extra); 5689f7df2e56Smrg } 5690f7df2e56Smrg WriteToClient(client, SIZEOF(xkbListComponentsReply), &rep); 56916747b715Smrg return Success; 569205b261ecSmrg} 569305b261ecSmrg 569405b261ecSmrg/***====================================================================***/ 569505b261ecSmrgint 569605b261ecSmrgProcXkbGetKbdByName(ClientPtr client) 569705b261ecSmrg{ 5698f7df2e56Smrg DeviceIntPtr dev; 5699f7df2e56Smrg DeviceIntPtr tmpd; 5700f7df2e56Smrg DeviceIntPtr master; 5701f7df2e56Smrg xkbGetKbdByNameReply rep = { 0 }; 5702f7df2e56Smrg xkbGetMapReply mrep = { 0 }; 5703f7df2e56Smrg xkbGetCompatMapReply crep = { 0 }; 5704f7df2e56Smrg xkbGetIndicatorMapReply irep = { 0 }; 5705f7df2e56Smrg xkbGetNamesReply nrep = { 0 }; 5706f7df2e56Smrg xkbGetGeometryReply grep = { 0 }; 5707f7df2e56Smrg XkbComponentNamesRec names = { 0 }; 5708f7df2e56Smrg XkbDescPtr xkb, new; 5709f7df2e56Smrg XkbEventCauseRec cause; 5710f7df2e56Smrg unsigned char *str; 5711f7df2e56Smrg char mapFile[PATH_MAX]; 5712f7df2e56Smrg unsigned len; 5713f7df2e56Smrg unsigned fwant, fneed, reported; 5714f7df2e56Smrg int status; 5715f7df2e56Smrg Bool geom_changed; 5716f7df2e56Smrg XkbSrvLedInfoPtr old_sli; 5717f7df2e56Smrg XkbSrvLedInfoPtr sli; 57184642e01fSmrg Mask access_mode = DixGetAttrAccess | DixManageAccess; 571905b261ecSmrg 572005b261ecSmrg REQUEST(xkbGetKbdByNameReq); 572105b261ecSmrg REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq); 572205b261ecSmrg 5723f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 5724f7df2e56Smrg return BadAccess; 572505b261ecSmrg 57264642e01fSmrg CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode); 5727f7df2e56Smrg master = GetMaster(dev, MASTER_KEYBOARD); 572805b261ecSmrg 572905b261ecSmrg xkb = dev->key->xkbInfo->desc; 5730f7df2e56Smrg status = Success; 5731f7df2e56Smrg str = (unsigned char *) &stuff[1]; 5732f7df2e56Smrg if (GetComponentSpec(&str, TRUE, &status)) /* keymap, unsupported */ 57336747b715Smrg return BadMatch; 5734f7df2e56Smrg names.keycodes = GetComponentSpec(&str, TRUE, &status); 5735f7df2e56Smrg names.types = GetComponentSpec(&str, TRUE, &status); 5736f7df2e56Smrg names.compat = GetComponentSpec(&str, TRUE, &status); 5737f7df2e56Smrg names.symbols = GetComponentSpec(&str, TRUE, &status); 5738f7df2e56Smrg names.geometry = GetComponentSpec(&str, TRUE, &status); 5739f7df2e56Smrg if (status != Success) 5740f7df2e56Smrg return status; 5741f7df2e56Smrg len = str - ((unsigned char *) stuff); 5742f7df2e56Smrg if ((XkbPaddedSize(len) / 4) != stuff->length) 5743f7df2e56Smrg return BadLength; 5744f7df2e56Smrg 5745f7df2e56Smrg CHK_MASK_LEGAL(0x01, stuff->want, XkbGBN_AllComponentsMask); 5746f7df2e56Smrg CHK_MASK_LEGAL(0x02, stuff->need, XkbGBN_AllComponentsMask); 5747f7df2e56Smrg 574805b261ecSmrg if (stuff->load) 5749f7df2e56Smrg fwant = XkbGBN_AllComponentsMask; 5750f7df2e56Smrg else 5751f7df2e56Smrg fwant = stuff->want | stuff->need; 5752f7df2e56Smrg if ((!names.compat) && 5753f7df2e56Smrg (fwant & (XkbGBN_CompatMapMask | XkbGBN_IndicatorMapMask))) { 5754f7df2e56Smrg names.compat = Xstrdup("%"); 575505b261ecSmrg } 5756f7df2e56Smrg if ((!names.types) && (fwant & (XkbGBN_TypesMask))) { 5757f7df2e56Smrg names.types = Xstrdup("%"); 57584642e01fSmrg } 5759f7df2e56Smrg if ((!names.symbols) && (fwant & XkbGBN_SymbolsMask)) { 5760f7df2e56Smrg names.symbols = Xstrdup("%"); 57614642e01fSmrg } 5762f7df2e56Smrg geom_changed = ((names.geometry != NULL) && 5763f7df2e56Smrg (strcmp(names.geometry, "%") != 0)); 5764f7df2e56Smrg if ((!names.geometry) && (fwant & XkbGBN_GeometryMask)) { 5765f7df2e56Smrg names.geometry = Xstrdup("%"); 5766f7df2e56Smrg geom_changed = FALSE; 576705b261ecSmrg } 576805b261ecSmrg 57696747b715Smrg memset(mapFile, 0, PATH_MAX); 5770f7df2e56Smrg rep.type = X_Reply; 577105b261ecSmrg rep.deviceID = dev->id; 577205b261ecSmrg rep.sequenceNumber = client->sequence; 577305b261ecSmrg rep.length = 0; 577405b261ecSmrg rep.minKeyCode = xkb->min_key_code; 577505b261ecSmrg rep.maxKeyCode = xkb->max_key_code; 5776f7df2e56Smrg rep.loaded = FALSE; 5777f7df2e56Smrg fwant = 5778f7df2e56Smrg XkbConvertGetByNameComponents(TRUE, stuff->want) | XkmVirtualModsMask; 5779f7df2e56Smrg fneed = XkbConvertGetByNameComponents(TRUE, stuff->need); 5780f7df2e56Smrg rep.reported = XkbConvertGetByNameComponents(FALSE, fwant | fneed); 578105b261ecSmrg if (stuff->load) { 5782f7df2e56Smrg fneed |= XkmKeymapRequired; 5783f7df2e56Smrg fwant |= XkmKeymapLegal; 578405b261ecSmrg } 5785f7df2e56Smrg if ((fwant | fneed) & XkmSymbolsMask) { 5786f7df2e56Smrg fneed |= XkmKeyNamesIndex | XkmTypesIndex; 5787f7df2e56Smrg fwant |= XkmIndicatorsIndex; 578805b261ecSmrg } 578905b261ecSmrg 579005b261ecSmrg /* We pass dev in here so we can get the old names out if needed. */ 5791f7df2e56Smrg rep.found = XkbDDXLoadKeymapByNames(dev, &names, fwant, fneed, &new, 5792f7df2e56Smrg mapFile, PATH_MAX); 5793f7df2e56Smrg rep.newKeyboard = FALSE; 5794f7df2e56Smrg rep.pad1 = rep.pad2 = rep.pad3 = rep.pad4 = 0; 5795f7df2e56Smrg 5796f7df2e56Smrg stuff->want |= stuff->need; 5797f7df2e56Smrg if (new == NULL) 5798f7df2e56Smrg rep.reported = 0; 579905b261ecSmrg else { 5800f7df2e56Smrg if (stuff->load) 5801f7df2e56Smrg rep.loaded = TRUE; 5802f7df2e56Smrg if (stuff->load || 5803f7df2e56Smrg ((rep.reported & XkbGBN_SymbolsMask) && (new->compat))) { 5804f7df2e56Smrg XkbChangesRec changes; 5805f7df2e56Smrg 5806f7df2e56Smrg memset(&changes, 0, sizeof(changes)); 5807f7df2e56Smrg XkbUpdateDescActions(new, 5808f7df2e56Smrg new->min_key_code, XkbNumKeys(new), &changes); 5809f7df2e56Smrg } 581005b261ecSmrg 5811f7df2e56Smrg if (new->map == NULL) 5812f7df2e56Smrg rep.reported &= ~(XkbGBN_SymbolsMask | XkbGBN_TypesMask); 5813f7df2e56Smrg else if (rep.reported & (XkbGBN_SymbolsMask | XkbGBN_TypesMask)) { 5814f7df2e56Smrg mrep.type = X_Reply; 5815f7df2e56Smrg mrep.deviceID = dev->id; 5816f7df2e56Smrg mrep.sequenceNumber = client->sequence; 5817f7df2e56Smrg mrep.length = 5818f7df2e56Smrg ((SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply)) >> 2); 5819f7df2e56Smrg mrep.minKeyCode = new->min_key_code; 5820f7df2e56Smrg mrep.maxKeyCode = new->max_key_code; 5821f7df2e56Smrg mrep.present = 0; 5822f7df2e56Smrg mrep.totalSyms = mrep.totalActs = 5823f7df2e56Smrg mrep.totalKeyBehaviors = mrep.totalKeyExplicit = 5824f7df2e56Smrg mrep.totalModMapKeys = mrep.totalVModMapKeys = 0; 5825f7df2e56Smrg if (rep.reported & (XkbGBN_TypesMask | XkbGBN_ClientSymbolsMask)) { 5826f7df2e56Smrg mrep.present |= XkbKeyTypesMask; 5827f7df2e56Smrg mrep.firstType = 0; 5828f7df2e56Smrg mrep.nTypes = mrep.totalTypes = new->map->num_types; 5829f7df2e56Smrg } 5830f7df2e56Smrg else { 5831f7df2e56Smrg mrep.firstType = mrep.nTypes = 0; 5832f7df2e56Smrg mrep.totalTypes = 0; 5833f7df2e56Smrg } 5834f7df2e56Smrg if (rep.reported & XkbGBN_ClientSymbolsMask) { 5835f7df2e56Smrg mrep.present |= (XkbKeySymsMask | XkbModifierMapMask); 5836f7df2e56Smrg mrep.firstKeySym = mrep.firstModMapKey = new->min_key_code; 5837f7df2e56Smrg mrep.nKeySyms = mrep.nModMapKeys = XkbNumKeys(new); 5838f7df2e56Smrg } 5839f7df2e56Smrg else { 5840f7df2e56Smrg mrep.firstKeySym = mrep.firstModMapKey = 0; 5841f7df2e56Smrg mrep.nKeySyms = mrep.nModMapKeys = 0; 5842f7df2e56Smrg } 5843f7df2e56Smrg if (rep.reported & XkbGBN_ServerSymbolsMask) { 5844f7df2e56Smrg mrep.present |= XkbAllServerInfoMask; 5845f7df2e56Smrg mrep.virtualMods = ~0; 5846f7df2e56Smrg mrep.firstKeyAct = mrep.firstKeyBehavior = 5847f7df2e56Smrg mrep.firstKeyExplicit = new->min_key_code; 5848f7df2e56Smrg mrep.nKeyActs = mrep.nKeyBehaviors = 5849f7df2e56Smrg mrep.nKeyExplicit = XkbNumKeys(new); 5850f7df2e56Smrg mrep.firstVModMapKey = new->min_key_code; 5851f7df2e56Smrg mrep.nVModMapKeys = XkbNumKeys(new); 5852f7df2e56Smrg } 5853f7df2e56Smrg else { 5854f7df2e56Smrg mrep.virtualMods = 0; 5855f7df2e56Smrg mrep.firstKeyAct = mrep.firstKeyBehavior = 5856f7df2e56Smrg mrep.firstKeyExplicit = 0; 5857f7df2e56Smrg mrep.nKeyActs = mrep.nKeyBehaviors = mrep.nKeyExplicit = 0; 5858f7df2e56Smrg } 5859f7df2e56Smrg XkbComputeGetMapReplySize(new, &mrep); 5860f7df2e56Smrg rep.length += SIZEOF(xGenericReply) / 4 + mrep.length; 5861f7df2e56Smrg } 5862f7df2e56Smrg if (new->compat == NULL) 5863f7df2e56Smrg rep.reported &= ~XkbGBN_CompatMapMask; 5864f7df2e56Smrg else if (rep.reported & XkbGBN_CompatMapMask) { 5865f7df2e56Smrg crep.type = X_Reply; 5866f7df2e56Smrg crep.deviceID = dev->id; 5867f7df2e56Smrg crep.sequenceNumber = client->sequence; 5868f7df2e56Smrg crep.length = 0; 5869f7df2e56Smrg crep.groups = XkbAllGroupsMask; 5870f7df2e56Smrg crep.firstSI = 0; 5871f7df2e56Smrg crep.nSI = crep.nTotalSI = new->compat->num_si; 5872f7df2e56Smrg XkbComputeGetCompatMapReplySize(new->compat, &crep); 5873f7df2e56Smrg rep.length += SIZEOF(xGenericReply) / 4 + crep.length; 5874f7df2e56Smrg } 5875f7df2e56Smrg if (new->indicators == NULL) 5876f7df2e56Smrg rep.reported &= ~XkbGBN_IndicatorMapMask; 5877f7df2e56Smrg else if (rep.reported & XkbGBN_IndicatorMapMask) { 5878f7df2e56Smrg irep.type = X_Reply; 5879f7df2e56Smrg irep.deviceID = dev->id; 5880f7df2e56Smrg irep.sequenceNumber = client->sequence; 5881f7df2e56Smrg irep.length = 0; 5882f7df2e56Smrg irep.which = XkbAllIndicatorsMask; 5883f7df2e56Smrg XkbComputeGetIndicatorMapReplySize(new->indicators, &irep); 5884f7df2e56Smrg rep.length += SIZEOF(xGenericReply) / 4 + irep.length; 5885f7df2e56Smrg } 5886f7df2e56Smrg if (new->names == NULL) 5887f7df2e56Smrg rep.reported &= ~(XkbGBN_OtherNamesMask | XkbGBN_KeyNamesMask); 5888f7df2e56Smrg else if (rep.reported & (XkbGBN_OtherNamesMask | XkbGBN_KeyNamesMask)) { 5889f7df2e56Smrg nrep.type = X_Reply; 5890f7df2e56Smrg nrep.deviceID = dev->id; 5891f7df2e56Smrg nrep.sequenceNumber = client->sequence; 5892f7df2e56Smrg nrep.length = 0; 5893f7df2e56Smrg nrep.minKeyCode = new->min_key_code; 5894f7df2e56Smrg nrep.maxKeyCode = new->max_key_code; 5895f7df2e56Smrg if (rep.reported & XkbGBN_OtherNamesMask) { 5896f7df2e56Smrg nrep.which = XkbAllNamesMask; 5897f7df2e56Smrg if (new->map != NULL) 5898f7df2e56Smrg nrep.nTypes = new->map->num_types; 5899f7df2e56Smrg else 5900f7df2e56Smrg nrep.nTypes = 0; 5901f7df2e56Smrg nrep.nKTLevels = 0; 5902f7df2e56Smrg nrep.groupNames = XkbAllGroupsMask; 5903f7df2e56Smrg nrep.virtualMods = XkbAllVirtualModsMask; 5904f7df2e56Smrg nrep.indicators = XkbAllIndicatorsMask; 5905f7df2e56Smrg nrep.nRadioGroups = new->names->num_rg; 5906f7df2e56Smrg } 5907f7df2e56Smrg else { 5908f7df2e56Smrg nrep.which = 0; 5909f7df2e56Smrg nrep.nTypes = 0; 5910f7df2e56Smrg nrep.nKTLevels = 0; 5911f7df2e56Smrg nrep.groupNames = 0; 5912f7df2e56Smrg nrep.virtualMods = 0; 5913f7df2e56Smrg nrep.indicators = 0; 5914f7df2e56Smrg nrep.nRadioGroups = 0; 5915f7df2e56Smrg } 5916f7df2e56Smrg if (rep.reported & XkbGBN_KeyNamesMask) { 5917f7df2e56Smrg nrep.which |= XkbKeyNamesMask; 5918f7df2e56Smrg nrep.firstKey = new->min_key_code; 5919f7df2e56Smrg nrep.nKeys = XkbNumKeys(new); 5920f7df2e56Smrg nrep.nKeyAliases = new->names->num_key_aliases; 5921f7df2e56Smrg if (nrep.nKeyAliases) 5922f7df2e56Smrg nrep.which |= XkbKeyAliasesMask; 5923f7df2e56Smrg } 5924f7df2e56Smrg else { 5925f7df2e56Smrg nrep.which &= ~(XkbKeyNamesMask | XkbKeyAliasesMask); 5926f7df2e56Smrg nrep.firstKey = nrep.nKeys = 0; 5927f7df2e56Smrg nrep.nKeyAliases = 0; 5928f7df2e56Smrg } 5929f7df2e56Smrg XkbComputeGetNamesReplySize(new, &nrep); 5930f7df2e56Smrg rep.length += SIZEOF(xGenericReply) / 4 + nrep.length; 5931f7df2e56Smrg } 5932f7df2e56Smrg if (new->geom == NULL) 5933f7df2e56Smrg rep.reported &= ~XkbGBN_GeometryMask; 5934f7df2e56Smrg else if (rep.reported & XkbGBN_GeometryMask) { 5935f7df2e56Smrg grep.type = X_Reply; 5936f7df2e56Smrg grep.deviceID = dev->id; 5937f7df2e56Smrg grep.sequenceNumber = client->sequence; 5938f7df2e56Smrg grep.length = 0; 5939f7df2e56Smrg grep.found = TRUE; 5940f7df2e56Smrg grep.pad = 0; 5941f7df2e56Smrg grep.widthMM = grep.heightMM = 0; 5942f7df2e56Smrg grep.nProperties = grep.nColors = grep.nShapes = 0; 5943f7df2e56Smrg grep.nSections = grep.nDoodads = 0; 5944f7df2e56Smrg grep.baseColorNdx = grep.labelColorNdx = 0; 5945f7df2e56Smrg XkbComputeGetGeometryReplySize(new->geom, &grep, None); 5946f7df2e56Smrg rep.length += SIZEOF(xGenericReply) / 4 + grep.length; 5947f7df2e56Smrg } 5948f7df2e56Smrg } 5949f7df2e56Smrg 5950f7df2e56Smrg reported = rep.reported; 5951f7df2e56Smrg if (client->swapped) { 5952f7df2e56Smrg swaps(&rep.sequenceNumber); 5953f7df2e56Smrg swapl(&rep.length); 5954f7df2e56Smrg swaps(&rep.found); 5955f7df2e56Smrg swaps(&rep.reported); 5956f7df2e56Smrg } 5957f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetKbdByNameReply), &rep); 5958f7df2e56Smrg if (reported & (XkbGBN_SymbolsMask | XkbGBN_TypesMask)) 5959f7df2e56Smrg XkbSendMap(client, new, &mrep); 5960f7df2e56Smrg if (reported & XkbGBN_CompatMapMask) 5961f7df2e56Smrg XkbSendCompatMap(client, new->compat, &crep); 5962f7df2e56Smrg if (reported & XkbGBN_IndicatorMapMask) 5963f7df2e56Smrg XkbSendIndicatorMap(client, new->indicators, &irep); 5964f7df2e56Smrg if (reported & (XkbGBN_KeyNamesMask | XkbGBN_OtherNamesMask)) 5965f7df2e56Smrg XkbSendNames(client, new, &nrep); 5966f7df2e56Smrg if (reported & XkbGBN_GeometryMask) 5967f7df2e56Smrg XkbSendGeometry(client, new->geom, &grep, FALSE); 5968f7df2e56Smrg if (rep.loaded) { 5969f7df2e56Smrg XkbDescPtr old_xkb; 5970f7df2e56Smrg xkbNewKeyboardNotify nkn; 5971f7df2e56Smrg 5972f7df2e56Smrg old_xkb = xkb; 5973f7df2e56Smrg xkb = new; 5974f7df2e56Smrg dev->key->xkbInfo->desc = xkb; 5975f7df2e56Smrg new = old_xkb; /* so it'll get freed automatically */ 5976f7df2e56Smrg 5977f7df2e56Smrg XkbCopyControls(xkb, old_xkb); 5978f7df2e56Smrg 5979f7df2e56Smrg nkn.deviceID = nkn.oldDeviceID = dev->id; 5980f7df2e56Smrg nkn.minKeyCode = new->min_key_code; 5981f7df2e56Smrg nkn.maxKeyCode = new->max_key_code; 5982f7df2e56Smrg nkn.oldMinKeyCode = xkb->min_key_code; 5983f7df2e56Smrg nkn.oldMaxKeyCode = xkb->max_key_code; 5984f7df2e56Smrg nkn.requestMajor = XkbReqCode; 5985f7df2e56Smrg nkn.requestMinor = X_kbGetKbdByName; 5986f7df2e56Smrg nkn.changed = XkbNKN_KeycodesMask; 5987f7df2e56Smrg if (geom_changed) 5988f7df2e56Smrg nkn.changed |= XkbNKN_GeometryMask; 5989f7df2e56Smrg XkbSendNewKeyboardNotify(dev, &nkn); 5990f7df2e56Smrg 5991f7df2e56Smrg /* Update the map and LED info on the device itself, as well as 5992f7df2e56Smrg * any slaves if it's an MD, or its MD if it's an SD and was the 5993f7df2e56Smrg * last device used on that MD. */ 599405b261ecSmrg for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) { 5995f7df2e56Smrg if (tmpd != dev && GetMaster(tmpd, MASTER_KEYBOARD) != dev && 5996f7df2e56Smrg (tmpd != master || dev != master->lastSlave)) 5997f7df2e56Smrg continue; 5998f7df2e56Smrg 5999f7df2e56Smrg if (tmpd != dev) 6000f7df2e56Smrg XkbDeviceApplyKeymap(tmpd, xkb); 6001f7df2e56Smrg 6002f7df2e56Smrg if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) { 6003f7df2e56Smrg old_sli = tmpd->kbdfeed->xkb_sli; 6004f7df2e56Smrg tmpd->kbdfeed->xkb_sli = NULL; 6005f7df2e56Smrg sli = XkbAllocSrvLedInfo(tmpd, tmpd->kbdfeed, NULL, 0); 6006f7df2e56Smrg if (sli) { 6007f7df2e56Smrg sli->explicitState = old_sli->explicitState; 6008f7df2e56Smrg sli->effectiveState = old_sli->effectiveState; 600905b261ecSmrg } 6010f7df2e56Smrg tmpd->kbdfeed->xkb_sli = sli; 6011f7df2e56Smrg XkbFreeSrvLedInfo(old_sli); 601205b261ecSmrg } 601305b261ecSmrg } 6014f7df2e56Smrg } 6015f7df2e56Smrg if ((new != NULL) && (new != xkb)) { 6016f7df2e56Smrg XkbFreeKeyboard(new, XkbAllComponentsMask, TRUE); 6017f7df2e56Smrg new = NULL; 601805b261ecSmrg } 60199ace9065Smrg XkbFreeComponentNames(&names, FALSE); 6020f7df2e56Smrg XkbSetCauseXkbReq(&cause, X_kbGetKbdByName, client); 6021f7df2e56Smrg XkbUpdateAllDeviceIndicators(NULL, &cause); 6022f7df2e56Smrg 60236747b715Smrg return Success; 602405b261ecSmrg} 602505b261ecSmrg 602605b261ecSmrg/***====================================================================***/ 602705b261ecSmrg 602805b261ecSmrgstatic int 6029f7df2e56SmrgComputeDeviceLedInfoSize(DeviceIntPtr dev, 6030f7df2e56Smrg unsigned int what, XkbSrvLedInfoPtr sli) 603105b261ecSmrg{ 6032f7df2e56Smrg int nNames, nMaps; 6033f7df2e56Smrg register unsigned n, bit; 6034f7df2e56Smrg 6035f7df2e56Smrg if (sli == NULL) 6036f7df2e56Smrg return 0; 6037f7df2e56Smrg nNames = nMaps = 0; 6038f7df2e56Smrg if ((what & XkbXI_IndicatorNamesMask) == 0) 6039f7df2e56Smrg sli->namesPresent = 0; 6040f7df2e56Smrg if ((what & XkbXI_IndicatorMapsMask) == 0) 6041f7df2e56Smrg sli->mapsPresent = 0; 6042f7df2e56Smrg 6043f7df2e56Smrg for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) { 6044f7df2e56Smrg if (sli->names && sli->names[n] != None) { 6045f7df2e56Smrg sli->namesPresent |= bit; 6046f7df2e56Smrg nNames++; 6047f7df2e56Smrg } 6048f7df2e56Smrg if (sli->maps && XkbIM_InUse(&sli->maps[n])) { 6049f7df2e56Smrg sli->mapsPresent |= bit; 6050f7df2e56Smrg nMaps++; 6051f7df2e56Smrg } 6052f7df2e56Smrg } 6053f7df2e56Smrg return (nNames * 4) + (nMaps * SIZEOF(xkbIndicatorMapWireDesc)); 605405b261ecSmrg} 605505b261ecSmrg 6056f7df2e56Smrgstatic int 6057f7df2e56SmrgCheckDeviceLedFBs(DeviceIntPtr dev, 6058f7df2e56Smrg int class, 6059f7df2e56Smrg int id, xkbGetDeviceInfoReply * rep, ClientPtr client) 606005b261ecSmrg{ 6061f7df2e56Smrg int nFBs = 0; 6062f7df2e56Smrg int length = 0; 6063f7df2e56Smrg Bool classOk; 6064f7df2e56Smrg 6065f7df2e56Smrg if (class == XkbDfltXIClass) { 6066f7df2e56Smrg if (dev->kbdfeed) 6067f7df2e56Smrg class = KbdFeedbackClass; 6068f7df2e56Smrg else if (dev->leds) 6069f7df2e56Smrg class = LedFeedbackClass; 6070f7df2e56Smrg else { 6071f7df2e56Smrg client->errorValue = _XkbErrCode2(XkbErr_BadClass, class); 6072f7df2e56Smrg return XkbKeyboardErrorCode; 6073f7df2e56Smrg } 6074f7df2e56Smrg } 6075f7df2e56Smrg classOk = FALSE; 6076f7df2e56Smrg if ((dev->kbdfeed) && 6077f7df2e56Smrg ((class == KbdFeedbackClass) || (class == XkbAllXIClasses))) { 6078f7df2e56Smrg KbdFeedbackPtr kf; 6079f7df2e56Smrg 6080f7df2e56Smrg classOk = TRUE; 6081f7df2e56Smrg for (kf = dev->kbdfeed; (kf); kf = kf->next) { 6082f7df2e56Smrg if ((id != XkbAllXIIds) && (id != XkbDfltXIId) && 6083f7df2e56Smrg (id != kf->ctrl.id)) 6084f7df2e56Smrg continue; 6085f7df2e56Smrg nFBs++; 6086f7df2e56Smrg length += SIZEOF(xkbDeviceLedsWireDesc); 6087f7df2e56Smrg if (!kf->xkb_sli) 6088f7df2e56Smrg kf->xkb_sli = XkbAllocSrvLedInfo(dev, kf, NULL, 0); 6089f7df2e56Smrg length += ComputeDeviceLedInfoSize(dev, rep->present, kf->xkb_sli); 6090f7df2e56Smrg if (id != XkbAllXIIds) 6091f7df2e56Smrg break; 6092f7df2e56Smrg } 6093f7df2e56Smrg } 6094f7df2e56Smrg if ((dev->leds) && 6095f7df2e56Smrg ((class == LedFeedbackClass) || (class == XkbAllXIClasses))) { 6096f7df2e56Smrg LedFeedbackPtr lf; 6097f7df2e56Smrg 6098f7df2e56Smrg classOk = TRUE; 6099f7df2e56Smrg for (lf = dev->leds; (lf); lf = lf->next) { 6100f7df2e56Smrg if ((id != XkbAllXIIds) && (id != XkbDfltXIId) && 6101f7df2e56Smrg (id != lf->ctrl.id)) 6102f7df2e56Smrg continue; 6103f7df2e56Smrg nFBs++; 6104f7df2e56Smrg length += SIZEOF(xkbDeviceLedsWireDesc); 6105f7df2e56Smrg if (!lf->xkb_sli) 6106f7df2e56Smrg lf->xkb_sli = XkbAllocSrvLedInfo(dev, NULL, lf, 0); 6107f7df2e56Smrg length += ComputeDeviceLedInfoSize(dev, rep->present, lf->xkb_sli); 6108f7df2e56Smrg if (id != XkbAllXIIds) 6109f7df2e56Smrg break; 6110f7df2e56Smrg } 6111f7df2e56Smrg } 6112f7df2e56Smrg if (nFBs > 0) { 6113f7df2e56Smrg rep->nDeviceLedFBs = nFBs; 6114f7df2e56Smrg rep->length += (length / 4); 6115f7df2e56Smrg return Success; 6116f7df2e56Smrg } 6117f7df2e56Smrg if (classOk) 6118f7df2e56Smrg client->errorValue = _XkbErrCode2(XkbErr_BadId, id); 6119f7df2e56Smrg else 6120f7df2e56Smrg client->errorValue = _XkbErrCode2(XkbErr_BadClass, class); 612105b261ecSmrg return XkbKeyboardErrorCode; 612205b261ecSmrg} 612305b261ecSmrg 612405b261ecSmrgstatic int 6125f7df2e56SmrgSendDeviceLedInfo(XkbSrvLedInfoPtr sli, ClientPtr client) 612605b261ecSmrg{ 6127f7df2e56Smrg xkbDeviceLedsWireDesc wire; 6128f7df2e56Smrg int length; 6129f7df2e56Smrg 6130f7df2e56Smrg length = 0; 6131f7df2e56Smrg wire.ledClass = sli->class; 6132f7df2e56Smrg wire.ledID = sli->id; 6133f7df2e56Smrg wire.namesPresent = sli->namesPresent; 6134f7df2e56Smrg wire.mapsPresent = sli->mapsPresent; 6135f7df2e56Smrg wire.physIndicators = sli->physIndicators; 6136f7df2e56Smrg wire.state = sli->effectiveState; 613705b261ecSmrg if (client->swapped) { 6138f7df2e56Smrg swaps(&wire.ledClass); 6139f7df2e56Smrg swaps(&wire.ledID); 6140f7df2e56Smrg swapl(&wire.namesPresent); 6141f7df2e56Smrg swapl(&wire.mapsPresent); 6142f7df2e56Smrg swapl(&wire.physIndicators); 6143f7df2e56Smrg swapl(&wire.state); 6144f7df2e56Smrg } 6145f7df2e56Smrg WriteToClient(client, SIZEOF(xkbDeviceLedsWireDesc), &wire); 6146f7df2e56Smrg length += SIZEOF(xkbDeviceLedsWireDesc); 6147f7df2e56Smrg if (sli->namesPresent | sli->mapsPresent) { 6148f7df2e56Smrg register unsigned i, bit; 6149f7df2e56Smrg 6150f7df2e56Smrg if (sli->namesPresent) { 6151f7df2e56Smrg CARD32 awire; 6152f7df2e56Smrg 6153f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 6154f7df2e56Smrg if (sli->namesPresent & bit) { 6155f7df2e56Smrg awire = (CARD32) sli->names[i]; 6156f7df2e56Smrg if (client->swapped) { 6157f7df2e56Smrg swapl(&awire); 6158f7df2e56Smrg } 6159f7df2e56Smrg WriteToClient(client, 4, &awire); 6160f7df2e56Smrg length += 4; 6161f7df2e56Smrg } 6162f7df2e56Smrg } 6163f7df2e56Smrg } 6164f7df2e56Smrg if (sli->mapsPresent) { 6165f7df2e56Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 6166f7df2e56Smrg xkbIndicatorMapWireDesc iwire; 6167f7df2e56Smrg 6168f7df2e56Smrg if (sli->mapsPresent & bit) { 6169f7df2e56Smrg iwire.flags = sli->maps[i].flags; 6170f7df2e56Smrg iwire.whichGroups = sli->maps[i].which_groups; 6171f7df2e56Smrg iwire.groups = sli->maps[i].groups; 6172f7df2e56Smrg iwire.whichMods = sli->maps[i].which_mods; 6173f7df2e56Smrg iwire.mods = sli->maps[i].mods.mask; 6174f7df2e56Smrg iwire.realMods = sli->maps[i].mods.real_mods; 6175f7df2e56Smrg iwire.virtualMods = sli->maps[i].mods.vmods; 6176f7df2e56Smrg iwire.ctrls = sli->maps[i].ctrls; 6177f7df2e56Smrg if (client->swapped) { 6178f7df2e56Smrg swaps(&iwire.virtualMods); 6179f7df2e56Smrg swapl(&iwire.ctrls); 6180f7df2e56Smrg } 6181f7df2e56Smrg WriteToClient(client, SIZEOF(xkbIndicatorMapWireDesc), 6182f7df2e56Smrg &iwire); 6183f7df2e56Smrg length += SIZEOF(xkbIndicatorMapWireDesc); 6184f7df2e56Smrg } 6185f7df2e56Smrg } 6186f7df2e56Smrg } 618705b261ecSmrg } 618805b261ecSmrg return length; 618905b261ecSmrg} 619005b261ecSmrg 619105b261ecSmrgstatic int 6192f7df2e56SmrgSendDeviceLedFBs(DeviceIntPtr dev, 6193f7df2e56Smrg int class, int id, unsigned wantLength, ClientPtr client) 619405b261ecSmrg{ 6195f7df2e56Smrg int length = 0; 6196f7df2e56Smrg 6197f7df2e56Smrg if (class == XkbDfltXIClass) { 6198f7df2e56Smrg if (dev->kbdfeed) 6199f7df2e56Smrg class = KbdFeedbackClass; 6200f7df2e56Smrg else if (dev->leds) 6201f7df2e56Smrg class = LedFeedbackClass; 6202f7df2e56Smrg } 6203f7df2e56Smrg if ((dev->kbdfeed) && 6204f7df2e56Smrg ((class == KbdFeedbackClass) || (class == XkbAllXIClasses))) { 6205f7df2e56Smrg KbdFeedbackPtr kf; 6206f7df2e56Smrg 6207f7df2e56Smrg for (kf = dev->kbdfeed; (kf); kf = kf->next) { 6208f7df2e56Smrg if ((id == XkbAllXIIds) || (id == XkbDfltXIId) || 6209f7df2e56Smrg (id == kf->ctrl.id)) { 6210f7df2e56Smrg length += SendDeviceLedInfo(kf->xkb_sli, client); 6211f7df2e56Smrg if (id != XkbAllXIIds) 6212f7df2e56Smrg break; 6213f7df2e56Smrg } 6214f7df2e56Smrg } 6215f7df2e56Smrg } 6216f7df2e56Smrg if ((dev->leds) && 6217f7df2e56Smrg ((class == LedFeedbackClass) || (class == XkbAllXIClasses))) { 6218f7df2e56Smrg LedFeedbackPtr lf; 6219f7df2e56Smrg 6220f7df2e56Smrg for (lf = dev->leds; (lf); lf = lf->next) { 6221f7df2e56Smrg if ((id == XkbAllXIIds) || (id == XkbDfltXIId) || 6222f7df2e56Smrg (id == lf->ctrl.id)) { 6223f7df2e56Smrg length += SendDeviceLedInfo(lf->xkb_sli, client); 6224f7df2e56Smrg if (id != XkbAllXIIds) 6225f7df2e56Smrg break; 6226f7df2e56Smrg } 6227f7df2e56Smrg } 6228f7df2e56Smrg } 6229f7df2e56Smrg if (length == wantLength) 6230f7df2e56Smrg return Success; 6231f7df2e56Smrg else 6232f7df2e56Smrg return BadLength; 623305b261ecSmrg} 623405b261ecSmrg 623505b261ecSmrgint 623605b261ecSmrgProcXkbGetDeviceInfo(ClientPtr client) 623705b261ecSmrg{ 6238f7df2e56Smrg DeviceIntPtr dev; 6239f7df2e56Smrg xkbGetDeviceInfoReply rep; 6240f7df2e56Smrg int status, nDeviceLedFBs; 6241f7df2e56Smrg unsigned length, nameLen; 6242f7df2e56Smrg CARD16 ledClass, ledID; 6243f7df2e56Smrg unsigned wanted; 6244f7df2e56Smrg char *str; 624505b261ecSmrg 624605b261ecSmrg REQUEST(xkbGetDeviceInfoReq); 624705b261ecSmrg REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq); 624805b261ecSmrg 6249f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 6250f7df2e56Smrg return BadAccess; 625105b261ecSmrg 6252f7df2e56Smrg wanted = stuff->wanted; 625305b261ecSmrg 62544642e01fSmrg CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess); 6255f7df2e56Smrg CHK_MASK_LEGAL(0x01, wanted, XkbXI_AllDeviceFeaturesMask); 6256f7df2e56Smrg 6257f7df2e56Smrg if ((!dev->button) || ((stuff->nBtns < 1) && (!stuff->allBtns))) 6258f7df2e56Smrg wanted &= ~XkbXI_ButtonActionsMask; 6259f7df2e56Smrg if ((!dev->kbdfeed) && (!dev->leds)) 6260f7df2e56Smrg wanted &= ~XkbXI_IndicatorsMask; 6261f7df2e56Smrg 6262f7df2e56Smrg nameLen = XkbSizeCountedString(dev->name); 6263f7df2e56Smrg rep = (xkbGetDeviceInfoReply) { 6264f7df2e56Smrg .type = X_Reply, 6265f7df2e56Smrg .deviceID = dev->id, 6266f7df2e56Smrg .sequenceNumber = client->sequence, 6267f7df2e56Smrg .length = nameLen / 4, 6268f7df2e56Smrg .present = wanted, 6269f7df2e56Smrg .supported = XkbXI_AllDeviceFeaturesMask, 6270f7df2e56Smrg .unsupported = 0, 6271f7df2e56Smrg .nDeviceLedFBs = 0, 6272f7df2e56Smrg .firstBtnWanted = 0, 6273f7df2e56Smrg .nBtnsWanted = 0, 6274f7df2e56Smrg .firstBtnRtrn = 0, 6275f7df2e56Smrg .nBtnsRtrn = 0, 6276f7df2e56Smrg .totalBtns = dev->button ? dev->button->numButtons : 0, 6277f7df2e56Smrg .hasOwnState = (dev->key && dev->key->xkbInfo), 6278f7df2e56Smrg .dfltKbdFB = dev->kbdfeed ? dev->kbdfeed->ctrl.id : XkbXINone, 6279f7df2e56Smrg .dfltLedFB = dev->leds ? dev->leds->ctrl.id : XkbXINone, 6280f7df2e56Smrg .devType = dev->xinput_type 6281f7df2e56Smrg }; 6282f7df2e56Smrg 6283f7df2e56Smrg ledClass = stuff->ledClass; 6284f7df2e56Smrg ledID = stuff->ledID; 6285f7df2e56Smrg 6286f7df2e56Smrg if (wanted & XkbXI_ButtonActionsMask) { 6287f7df2e56Smrg if (stuff->allBtns) { 6288f7df2e56Smrg stuff->firstBtn = 0; 6289f7df2e56Smrg stuff->nBtns = dev->button->numButtons; 6290f7df2e56Smrg } 629105b261ecSmrg 6292f7df2e56Smrg if ((stuff->firstBtn + stuff->nBtns) > dev->button->numButtons) { 6293f7df2e56Smrg client->errorValue = _XkbErrCode4(0x02, dev->button->numButtons, 6294f7df2e56Smrg stuff->firstBtn, stuff->nBtns); 6295f7df2e56Smrg return BadValue; 6296f7df2e56Smrg } 6297f7df2e56Smrg else { 6298f7df2e56Smrg rep.firstBtnWanted = stuff->firstBtn; 6299f7df2e56Smrg rep.nBtnsWanted = stuff->nBtns; 6300f7df2e56Smrg if (dev->button->xkb_acts != NULL) { 6301f7df2e56Smrg XkbAction *act; 6302f7df2e56Smrg register int i; 6303f7df2e56Smrg 6304f7df2e56Smrg rep.firstBtnRtrn = stuff->firstBtn; 6305f7df2e56Smrg rep.nBtnsRtrn = stuff->nBtns; 6306f7df2e56Smrg act = &dev->button->xkb_acts[rep.firstBtnWanted]; 6307f7df2e56Smrg for (i = 0; i < rep.nBtnsRtrn; i++, act++) { 6308f7df2e56Smrg if (act->type != XkbSA_NoAction) 6309f7df2e56Smrg break; 6310f7df2e56Smrg } 6311f7df2e56Smrg rep.firstBtnRtrn += i; 6312f7df2e56Smrg rep.nBtnsRtrn -= i; 6313f7df2e56Smrg act = 6314f7df2e56Smrg &dev->button->xkb_acts[rep.firstBtnRtrn + rep.nBtnsRtrn - 6315f7df2e56Smrg 1]; 6316f7df2e56Smrg for (i = 0; i < rep.nBtnsRtrn; i++, act--) { 6317f7df2e56Smrg if (act->type != XkbSA_NoAction) 6318f7df2e56Smrg break; 6319f7df2e56Smrg } 6320f7df2e56Smrg rep.nBtnsRtrn -= i; 6321f7df2e56Smrg } 6322f7df2e56Smrg rep.length += (rep.nBtnsRtrn * SIZEOF(xkbActionWireDesc)) / 4; 6323f7df2e56Smrg } 6324f7df2e56Smrg } 632505b261ecSmrg 6326f7df2e56Smrg if (wanted & XkbXI_IndicatorsMask) { 6327f7df2e56Smrg status = CheckDeviceLedFBs(dev, ledClass, ledID, &rep, client); 6328f7df2e56Smrg if (status != Success) 6329f7df2e56Smrg return status; 6330f7df2e56Smrg } 6331f7df2e56Smrg length = rep.length * 4; 633205b261ecSmrg nDeviceLedFBs = rep.nDeviceLedFBs; 633305b261ecSmrg if (client->swapped) { 6334f7df2e56Smrg swaps(&rep.sequenceNumber); 6335f7df2e56Smrg swapl(&rep.length); 6336f7df2e56Smrg swaps(&rep.present); 6337f7df2e56Smrg swaps(&rep.supported); 6338f7df2e56Smrg swaps(&rep.unsupported); 6339f7df2e56Smrg swaps(&rep.nDeviceLedFBs); 6340f7df2e56Smrg swaps(&rep.dfltKbdFB); 6341f7df2e56Smrg swaps(&rep.dfltLedFB); 6342f7df2e56Smrg swapl(&rep.devType); 6343f7df2e56Smrg } 6344f7df2e56Smrg WriteToClient(client, SIZEOF(xkbGetDeviceInfoReply), &rep); 6345f7df2e56Smrg 6346f7df2e56Smrg str = malloc(nameLen); 6347f7df2e56Smrg if (!str) 6348f7df2e56Smrg return BadAlloc; 6349f7df2e56Smrg XkbWriteCountedString(str, dev->name, client->swapped); 6350f7df2e56Smrg WriteToClient(client, nameLen, str); 63516747b715Smrg free(str); 6352f7df2e56Smrg length -= nameLen; 6353f7df2e56Smrg 6354f7df2e56Smrg if (rep.nBtnsRtrn > 0) { 6355f7df2e56Smrg int sz; 6356f7df2e56Smrg xkbActionWireDesc *awire; 6357f7df2e56Smrg 6358f7df2e56Smrg sz = rep.nBtnsRtrn * SIZEOF(xkbActionWireDesc); 6359f7df2e56Smrg awire = (xkbActionWireDesc *) &dev->button->xkb_acts[rep.firstBtnRtrn]; 6360f7df2e56Smrg WriteToClient(client, sz, awire); 6361f7df2e56Smrg length -= sz; 6362f7df2e56Smrg } 6363f7df2e56Smrg if (nDeviceLedFBs > 0) { 6364f7df2e56Smrg status = SendDeviceLedFBs(dev, ledClass, ledID, length, client); 6365f7df2e56Smrg if (status != Success) 6366f7df2e56Smrg return status; 6367f7df2e56Smrg } 6368f7df2e56Smrg else if (length != 0) { 6369f7df2e56Smrg ErrorF("[xkb] Internal Error! BadLength in ProcXkbGetDeviceInfo\n"); 6370f7df2e56Smrg ErrorF("[xkb] Wrote %d fewer bytes than expected\n", 6371f7df2e56Smrg length); 6372f7df2e56Smrg return BadLength; 637305b261ecSmrg } 63746747b715Smrg return Success; 637505b261ecSmrg} 637605b261ecSmrg 637705b261ecSmrgstatic char * 6378f7df2e56SmrgCheckSetDeviceIndicators(char *wire, 6379f7df2e56Smrg DeviceIntPtr dev, 6380f7df2e56Smrg int num, int *status_rtrn, ClientPtr client) 638105b261ecSmrg{ 6382f7df2e56Smrg xkbDeviceLedsWireDesc *ledWire; 6383f7df2e56Smrg int i; 6384f7df2e56Smrg XkbSrvLedInfoPtr sli; 6385f7df2e56Smrg 6386f7df2e56Smrg ledWire = (xkbDeviceLedsWireDesc *) wire; 6387f7df2e56Smrg for (i = 0; i < num; i++) { 6388f7df2e56Smrg if (client->swapped) { 6389f7df2e56Smrg swaps(&ledWire->ledClass); 6390f7df2e56Smrg swaps(&ledWire->ledID); 6391f7df2e56Smrg swapl(&ledWire->namesPresent); 6392f7df2e56Smrg swapl(&ledWire->mapsPresent); 6393f7df2e56Smrg swapl(&ledWire->physIndicators); 6394f7df2e56Smrg } 6395f7df2e56Smrg 6396f7df2e56Smrg sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID, 6397f7df2e56Smrg XkbXI_IndicatorsMask); 6398f7df2e56Smrg if (sli != NULL) { 6399f7df2e56Smrg register int n; 6400f7df2e56Smrg register unsigned bit; 6401f7df2e56Smrg int nMaps, nNames; 6402f7df2e56Smrg CARD32 *atomWire; 6403f7df2e56Smrg xkbIndicatorMapWireDesc *mapWire; 6404f7df2e56Smrg 6405f7df2e56Smrg nMaps = nNames = 0; 6406f7df2e56Smrg for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) { 6407f7df2e56Smrg if (ledWire->namesPresent & bit) 6408f7df2e56Smrg nNames++; 6409f7df2e56Smrg if (ledWire->mapsPresent & bit) 6410f7df2e56Smrg nMaps++; 6411f7df2e56Smrg } 6412f7df2e56Smrg atomWire = (CARD32 *) &ledWire[1]; 6413f7df2e56Smrg if (nNames > 0) { 6414f7df2e56Smrg for (n = 0; n < nNames; n++) { 6415f7df2e56Smrg if (client->swapped) { 6416f7df2e56Smrg swapl(atomWire); 6417f7df2e56Smrg } 6418f7df2e56Smrg CHK_ATOM_OR_NONE3(((Atom) (*atomWire)), client->errorValue, 6419f7df2e56Smrg *status_rtrn, NULL); 6420f7df2e56Smrg atomWire++; 6421f7df2e56Smrg } 6422f7df2e56Smrg } 6423f7df2e56Smrg mapWire = (xkbIndicatorMapWireDesc *) atomWire; 6424f7df2e56Smrg if (nMaps > 0) { 6425f7df2e56Smrg for (n = 0; n < nMaps; n++) { 6426f7df2e56Smrg if (client->swapped) { 6427f7df2e56Smrg swaps(&mapWire->virtualMods); 6428f7df2e56Smrg swapl(&mapWire->ctrls); 6429f7df2e56Smrg } 6430f7df2e56Smrg CHK_MASK_LEGAL3(0x21, mapWire->whichGroups, 6431f7df2e56Smrg XkbIM_UseAnyGroup, 6432f7df2e56Smrg client->errorValue, *status_rtrn, NULL); 6433f7df2e56Smrg CHK_MASK_LEGAL3(0x22, mapWire->whichMods, XkbIM_UseAnyMods, 6434f7df2e56Smrg client->errorValue, *status_rtrn, NULL); 6435f7df2e56Smrg mapWire++; 6436f7df2e56Smrg } 6437f7df2e56Smrg } 6438f7df2e56Smrg ledWire = (xkbDeviceLedsWireDesc *) mapWire; 6439f7df2e56Smrg } 6440f7df2e56Smrg else { 6441f7df2e56Smrg /* SHOULD NEVER HAPPEN */ 6442f7df2e56Smrg return (char *) ledWire; 6443f7df2e56Smrg } 6444f7df2e56Smrg } 6445f7df2e56Smrg return (char *) ledWire; 644605b261ecSmrg} 644705b261ecSmrg 644805b261ecSmrgstatic char * 6449f7df2e56SmrgSetDeviceIndicators(char *wire, 6450f7df2e56Smrg DeviceIntPtr dev, 6451f7df2e56Smrg unsigned changed, 6452f7df2e56Smrg int num, 6453f7df2e56Smrg int *status_rtrn, 6454f7df2e56Smrg ClientPtr client, xkbExtensionDeviceNotify * ev) 645505b261ecSmrg{ 6456f7df2e56Smrg xkbDeviceLedsWireDesc *ledWire; 6457f7df2e56Smrg int i; 6458f7df2e56Smrg XkbEventCauseRec cause; 6459f7df2e56Smrg unsigned namec, mapc, statec; 6460f7df2e56Smrg xkbExtensionDeviceNotify ed; 6461f7df2e56Smrg XkbChangesRec changes; 6462f7df2e56Smrg DeviceIntPtr kbd; 6463f7df2e56Smrg 6464f7df2e56Smrg memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify)); 6465f7df2e56Smrg memset((char *) &changes, 0, sizeof(XkbChangesRec)); 6466f7df2e56Smrg XkbSetCauseXkbReq(&cause, X_kbSetDeviceInfo, client); 6467f7df2e56Smrg ledWire = (xkbDeviceLedsWireDesc *) wire; 6468f7df2e56Smrg for (i = 0; i < num; i++) { 6469f7df2e56Smrg register int n; 6470f7df2e56Smrg register unsigned bit; 6471f7df2e56Smrg CARD32 *atomWire; 6472f7df2e56Smrg xkbIndicatorMapWireDesc *mapWire; 6473f7df2e56Smrg XkbSrvLedInfoPtr sli; 6474f7df2e56Smrg 6475f7df2e56Smrg namec = mapc = statec = 0; 6476f7df2e56Smrg sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID, 6477f7df2e56Smrg XkbXI_IndicatorMapsMask); 6478f7df2e56Smrg if (!sli) { 6479f7df2e56Smrg /* SHOULD NEVER HAPPEN!! */ 6480f7df2e56Smrg return (char *) ledWire; 6481f7df2e56Smrg } 648205b261ecSmrg 6483f7df2e56Smrg atomWire = (CARD32 *) &ledWire[1]; 6484f7df2e56Smrg if (changed & XkbXI_IndicatorNamesMask) { 6485f7df2e56Smrg namec = sli->namesPresent | ledWire->namesPresent; 6486f7df2e56Smrg memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom)); 6487f7df2e56Smrg } 6488f7df2e56Smrg if (ledWire->namesPresent) { 6489f7df2e56Smrg sli->namesPresent = ledWire->namesPresent; 6490f7df2e56Smrg memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom)); 6491f7df2e56Smrg for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) { 6492f7df2e56Smrg if (ledWire->namesPresent & bit) { 6493f7df2e56Smrg sli->names[n] = (Atom) *atomWire; 6494f7df2e56Smrg if (sli->names[n] == None) 6495f7df2e56Smrg ledWire->namesPresent &= ~bit; 6496f7df2e56Smrg atomWire++; 6497f7df2e56Smrg } 6498f7df2e56Smrg } 6499f7df2e56Smrg } 6500f7df2e56Smrg mapWire = (xkbIndicatorMapWireDesc *) atomWire; 6501f7df2e56Smrg if (changed & XkbXI_IndicatorMapsMask) { 6502f7df2e56Smrg mapc = sli->mapsPresent | ledWire->mapsPresent; 6503f7df2e56Smrg sli->mapsPresent = ledWire->mapsPresent; 6504f7df2e56Smrg memset((char *) sli->maps, 0, 6505f7df2e56Smrg XkbNumIndicators * sizeof(XkbIndicatorMapRec)); 6506f7df2e56Smrg } 6507f7df2e56Smrg if (ledWire->mapsPresent) { 6508f7df2e56Smrg for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) { 6509f7df2e56Smrg if (ledWire->mapsPresent & bit) { 6510f7df2e56Smrg sli->maps[n].flags = mapWire->flags; 6511f7df2e56Smrg sli->maps[n].which_groups = mapWire->whichGroups; 6512f7df2e56Smrg sli->maps[n].groups = mapWire->groups; 6513f7df2e56Smrg sli->maps[n].which_mods = mapWire->whichMods; 6514f7df2e56Smrg sli->maps[n].mods.mask = mapWire->mods; 6515f7df2e56Smrg sli->maps[n].mods.real_mods = mapWire->realMods; 6516f7df2e56Smrg sli->maps[n].mods.vmods = mapWire->virtualMods; 6517f7df2e56Smrg sli->maps[n].ctrls = mapWire->ctrls; 6518f7df2e56Smrg mapWire++; 6519f7df2e56Smrg } 6520f7df2e56Smrg } 6521f7df2e56Smrg } 6522f7df2e56Smrg if (changed & XkbXI_IndicatorStateMask) { 6523f7df2e56Smrg statec = sli->effectiveState ^ ledWire->state; 6524f7df2e56Smrg sli->explicitState &= ~statec; 6525f7df2e56Smrg sli->explicitState |= (ledWire->state & statec); 6526f7df2e56Smrg } 6527f7df2e56Smrg if (namec) 6528f7df2e56Smrg XkbApplyLedNameChanges(dev, sli, namec, &ed, &changes, &cause); 6529f7df2e56Smrg if (mapc) 6530f7df2e56Smrg XkbApplyLedMapChanges(dev, sli, mapc, &ed, &changes, &cause); 6531f7df2e56Smrg if (statec) 6532f7df2e56Smrg XkbApplyLedStateChanges(dev, sli, statec, &ed, &changes, &cause); 6533f7df2e56Smrg 6534f7df2e56Smrg kbd = dev; 6535f7df2e56Smrg if ((sli->flags & XkbSLI_HasOwnState) == 0) 6536f7df2e56Smrg kbd = inputInfo.keyboard; 6537f7df2e56Smrg 6538f7df2e56Smrg XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause); 6539f7df2e56Smrg ledWire = (xkbDeviceLedsWireDesc *) mapWire; 6540f7df2e56Smrg } 6541f7df2e56Smrg return (char *) ledWire; 6542f7df2e56Smrg} 654305b261ecSmrg 65444642e01fSmrgstatic int 65454642e01fSmrg_XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev, 6546f7df2e56Smrg xkbSetDeviceInfoReq * stuff) 65474642e01fSmrg{ 6548f7df2e56Smrg char *wire; 6549f7df2e56Smrg 6550f7df2e56Smrg wire = (char *) &stuff[1]; 6551f7df2e56Smrg if (stuff->change & XkbXI_ButtonActionsMask) { 6552f7df2e56Smrg if (!dev->button) { 6553f7df2e56Smrg client->errorValue = _XkbErrCode2(XkbErr_BadClass, ButtonClass); 6554f7df2e56Smrg return XkbKeyboardErrorCode; 6555f7df2e56Smrg } 6556f7df2e56Smrg if ((stuff->firstBtn + stuff->nBtns) > dev->button->numButtons) { 6557f7df2e56Smrg client->errorValue = 6558f7df2e56Smrg _XkbErrCode4(0x02, stuff->firstBtn, stuff->nBtns, 6559f7df2e56Smrg dev->button->numButtons); 6560f7df2e56Smrg return BadMatch; 6561f7df2e56Smrg } 6562f7df2e56Smrg wire += (stuff->nBtns * SIZEOF(xkbActionWireDesc)); 6563f7df2e56Smrg } 6564f7df2e56Smrg if (stuff->change & XkbXI_IndicatorsMask) { 6565f7df2e56Smrg int status = Success; 6566f7df2e56Smrg 6567f7df2e56Smrg wire = CheckSetDeviceIndicators(wire, dev, stuff->nDeviceLedFBs, 6568f7df2e56Smrg &status, client); 6569f7df2e56Smrg if (status != Success) 6570f7df2e56Smrg return status; 6571f7df2e56Smrg } 6572f7df2e56Smrg if (((wire - ((char *) stuff)) / 4) != stuff->length) 6573f7df2e56Smrg return BadLength; 657405b261ecSmrg 65754642e01fSmrg return Success; 65764642e01fSmrg} 65774642e01fSmrg 65784642e01fSmrgstatic int 65794642e01fSmrg_XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev, 6580f7df2e56Smrg xkbSetDeviceInfoReq * stuff) 65814642e01fSmrg{ 6582f7df2e56Smrg char *wire; 6583f7df2e56Smrg xkbExtensionDeviceNotify ed; 6584f7df2e56Smrg 6585f7df2e56Smrg memset((char *) &ed, 0, SIZEOF(xkbExtensionDeviceNotify)); 6586f7df2e56Smrg ed.deviceID = dev->id; 6587f7df2e56Smrg wire = (char *) &stuff[1]; 6588f7df2e56Smrg if (stuff->change & XkbXI_ButtonActionsMask) { 6589f7df2e56Smrg int nBtns, sz, i; 6590f7df2e56Smrg XkbAction *acts; 6591f7df2e56Smrg DeviceIntPtr kbd; 6592f7df2e56Smrg 6593f7df2e56Smrg nBtns = dev->button->numButtons; 6594f7df2e56Smrg acts = dev->button->xkb_acts; 6595f7df2e56Smrg if (acts == NULL) { 6596f7df2e56Smrg acts = calloc(nBtns, sizeof(XkbAction)); 6597f7df2e56Smrg if (!acts) 6598f7df2e56Smrg return BadAlloc; 6599f7df2e56Smrg dev->button->xkb_acts = acts; 6600f7df2e56Smrg } 6601f7df2e56Smrg sz = stuff->nBtns * SIZEOF(xkbActionWireDesc); 6602f7df2e56Smrg memcpy((char *) &acts[stuff->firstBtn], (char *) wire, sz); 6603f7df2e56Smrg wire += sz; 6604f7df2e56Smrg ed.reason |= XkbXI_ButtonActionsMask; 6605f7df2e56Smrg ed.firstBtn = stuff->firstBtn; 6606f7df2e56Smrg ed.nBtns = stuff->nBtns; 6607f7df2e56Smrg 6608f7df2e56Smrg if (dev->key) 6609f7df2e56Smrg kbd = dev; 6610f7df2e56Smrg else 6611f7df2e56Smrg kbd = inputInfo.keyboard; 6612f7df2e56Smrg acts = &dev->button->xkb_acts[stuff->firstBtn]; 6613f7df2e56Smrg for (i = 0; i < stuff->nBtns; i++, acts++) { 6614f7df2e56Smrg if (acts->type != XkbSA_NoAction) 6615f7df2e56Smrg XkbSetActionKeyMods(kbd->key->xkbInfo->desc, acts, 0); 6616f7df2e56Smrg } 6617f7df2e56Smrg } 6618f7df2e56Smrg if (stuff->change & XkbXI_IndicatorsMask) { 6619f7df2e56Smrg int status = Success; 6620f7df2e56Smrg 6621f7df2e56Smrg wire = SetDeviceIndicators(wire, dev, stuff->change, 6622f7df2e56Smrg stuff->nDeviceLedFBs, &status, client, &ed); 6623f7df2e56Smrg if (status != Success) 6624f7df2e56Smrg return status; 6625f7df2e56Smrg } 6626f7df2e56Smrg if ((stuff->change) && (ed.reason)) 6627f7df2e56Smrg XkbSendExtensionDeviceNotify(dev, client, &ed); 66284642e01fSmrg return Success; 66294642e01fSmrg} 66304642e01fSmrg 66314642e01fSmrgint 66324642e01fSmrgProcXkbSetDeviceInfo(ClientPtr client) 66334642e01fSmrg{ 6634f7df2e56Smrg DeviceIntPtr dev; 6635f7df2e56Smrg int rc; 66364642e01fSmrg 66374642e01fSmrg REQUEST(xkbSetDeviceInfoReq); 66384642e01fSmrg REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq); 66394642e01fSmrg 6640f7df2e56Smrg if (!(client->xkbClientFlags & _XkbClientInitialized)) 6641f7df2e56Smrg return BadAccess; 66424642e01fSmrg 66434642e01fSmrg CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess); 6644f7df2e56Smrg CHK_MASK_LEGAL(0x01, stuff->change, XkbXI_AllFeaturesMask); 66454642e01fSmrg 66464642e01fSmrg rc = _XkbSetDeviceInfoCheck(client, dev, stuff); 66474642e01fSmrg 66484642e01fSmrg if (rc != Success) 66494642e01fSmrg return rc; 66504642e01fSmrg 6651f7df2e56Smrg if (stuff->deviceSpec == XkbUseCoreKbd || 6652f7df2e56Smrg stuff->deviceSpec == XkbUseCorePtr) { 66534642e01fSmrg DeviceIntPtr other; 6654f7df2e56Smrg 6655f7df2e56Smrg for (other = inputInfo.devices; other; other = other->next) { 6656f7df2e56Smrg if (((other != dev) && !IsMaster(other) && 6657f7df2e56Smrg GetMaster(other, MASTER_KEYBOARD) == dev) && 66584642e01fSmrg ((stuff->deviceSpec == XkbUseCoreKbd && other->key) || 6659f7df2e56Smrg (stuff->deviceSpec == XkbUseCorePtr && other->button))) { 6660f7df2e56Smrg rc = XaceHook(XACE_DEVICE_ACCESS, client, other, 6661f7df2e56Smrg DixManageAccess); 6662f7df2e56Smrg if (rc == Success) { 66634642e01fSmrg rc = _XkbSetDeviceInfoCheck(client, other, stuff); 66644642e01fSmrg if (rc != Success) 66654642e01fSmrg return rc; 66664642e01fSmrg } 66674642e01fSmrg } 66684642e01fSmrg } 66694642e01fSmrg } 66704642e01fSmrg 66714642e01fSmrg /* checks done, apply */ 66724642e01fSmrg rc = _XkbSetDeviceInfo(client, dev, stuff); 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 = _XkbSetDeviceInfo(client, other, stuff); 66894642e01fSmrg if (rc != Success) 66904642e01fSmrg return rc; 66914642e01fSmrg } 66924642e01fSmrg } 66934642e01fSmrg } 66944642e01fSmrg } 66954642e01fSmrg 66966747b715Smrg return Success; 669705b261ecSmrg} 669805b261ecSmrg 669905b261ecSmrg/***====================================================================***/ 670005b261ecSmrg 670105b261ecSmrgint 670205b261ecSmrgProcXkbSetDebuggingFlags(ClientPtr client) 670305b261ecSmrg{ 6704f7df2e56Smrg CARD32 newFlags, newCtrls, extraLength; 6705f7df2e56Smrg xkbSetDebuggingFlagsReply rep; 6706f7df2e56Smrg int rc; 670705b261ecSmrg 670805b261ecSmrg REQUEST(xkbSetDebuggingFlagsReq); 670905b261ecSmrg REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq); 671005b261ecSmrg 67114642e01fSmrg rc = XaceHook(XACE_SERVER_ACCESS, client, DixDebugAccess); 67124642e01fSmrg if (rc != Success) 6713f7df2e56Smrg return rc; 67144642e01fSmrg 6715f7df2e56Smrg newFlags = xkbDebugFlags & (~stuff->affectFlags); 6716f7df2e56Smrg newFlags |= (stuff->flags & stuff->affectFlags); 6717f7df2e56Smrg newCtrls = xkbDebugCtrls & (~stuff->affectCtrls); 6718f7df2e56Smrg newCtrls |= (stuff->ctrls & stuff->affectCtrls); 671905b261ecSmrg if (xkbDebugFlags || newFlags || stuff->msgLength) { 6720f7df2e56Smrg ErrorF("[xkb] XkbDebug: Setting debug flags to 0x%lx\n", 6721f7df2e56Smrg (long) newFlags); 6722f7df2e56Smrg if (newCtrls != xkbDebugCtrls) 6723f7df2e56Smrg ErrorF("[xkb] XkbDebug: Setting debug controls to 0x%lx\n", 6724f7df2e56Smrg (long) newCtrls); 6725f7df2e56Smrg } 6726f7df2e56Smrg extraLength = (stuff->length << 2) - sz_xkbSetDebuggingFlagsReq; 6727f7df2e56Smrg if (stuff->msgLength > 0) { 6728f7df2e56Smrg char *msg; 6729f7df2e56Smrg 6730f7df2e56Smrg if (extraLength < XkbPaddedSize(stuff->msgLength)) { 6731f7df2e56Smrg ErrorF 6732f7df2e56Smrg ("[xkb] XkbDebug: msgLength= %d, length= %ld (should be %d)\n", 6733f7df2e56Smrg stuff->msgLength, (long) extraLength, 6734f7df2e56Smrg XkbPaddedSize(stuff->msgLength)); 6735f7df2e56Smrg return BadLength; 6736f7df2e56Smrg } 6737f7df2e56Smrg msg = (char *) &stuff[1]; 6738f7df2e56Smrg if (msg[stuff->msgLength - 1] != '\0') { 6739f7df2e56Smrg ErrorF("[xkb] XkbDebug: message not null-terminated\n"); 6740f7df2e56Smrg return BadValue; 6741f7df2e56Smrg } 6742f7df2e56Smrg ErrorF("[xkb] XkbDebug: %s\n", msg); 674305b261ecSmrg } 674405b261ecSmrg xkbDebugFlags = newFlags; 674505b261ecSmrg xkbDebugCtrls = newCtrls; 674605b261ecSmrg 6747f7df2e56Smrg rep = (xkbSetDebuggingFlagsReply) { 6748f7df2e56Smrg .type = X_Reply, 6749f7df2e56Smrg .sequenceNumber = client->sequence, 6750f7df2e56Smrg .length = 0, 6751f7df2e56Smrg .currentFlags = newFlags, 6752f7df2e56Smrg .currentCtrls = newCtrls, 6753f7df2e56Smrg .supportedFlags = ~0, 6754f7df2e56Smrg .supportedCtrls = ~0 6755f7df2e56Smrg }; 6756f7df2e56Smrg if (client->swapped) { 6757f7df2e56Smrg swaps(&rep.sequenceNumber); 6758f7df2e56Smrg swapl(&rep.currentFlags); 6759f7df2e56Smrg swapl(&rep.currentCtrls); 6760f7df2e56Smrg swapl(&rep.supportedFlags); 6761f7df2e56Smrg swapl(&rep.supportedCtrls); 6762f7df2e56Smrg } 6763f7df2e56Smrg WriteToClient(client, SIZEOF(xkbSetDebuggingFlagsReply), &rep); 67646747b715Smrg return Success; 676505b261ecSmrg} 676605b261ecSmrg 676705b261ecSmrg/***====================================================================***/ 676805b261ecSmrg 676905b261ecSmrgstatic int 6770f7df2e56SmrgProcXkbDispatch(ClientPtr client) 677105b261ecSmrg{ 677205b261ecSmrg REQUEST(xReq); 6773f7df2e56Smrg switch (stuff->data) { 677405b261ecSmrg case X_kbUseExtension: 6775f7df2e56Smrg return ProcXkbUseExtension(client); 677605b261ecSmrg case X_kbSelectEvents: 6777f7df2e56Smrg return ProcXkbSelectEvents(client); 677805b261ecSmrg case X_kbBell: 6779f7df2e56Smrg return ProcXkbBell(client); 678005b261ecSmrg case X_kbGetState: 6781f7df2e56Smrg return ProcXkbGetState(client); 678205b261ecSmrg case X_kbLatchLockState: 6783f7df2e56Smrg return ProcXkbLatchLockState(client); 678405b261ecSmrg case X_kbGetControls: 6785f7df2e56Smrg return ProcXkbGetControls(client); 678605b261ecSmrg case X_kbSetControls: 6787f7df2e56Smrg return ProcXkbSetControls(client); 678805b261ecSmrg case X_kbGetMap: 6789f7df2e56Smrg return ProcXkbGetMap(client); 679005b261ecSmrg case X_kbSetMap: 6791f7df2e56Smrg return ProcXkbSetMap(client); 679205b261ecSmrg case X_kbGetCompatMap: 6793f7df2e56Smrg return ProcXkbGetCompatMap(client); 679405b261ecSmrg case X_kbSetCompatMap: 6795f7df2e56Smrg return ProcXkbSetCompatMap(client); 679605b261ecSmrg case X_kbGetIndicatorState: 6797f7df2e56Smrg return ProcXkbGetIndicatorState(client); 679805b261ecSmrg case X_kbGetIndicatorMap: 6799f7df2e56Smrg return ProcXkbGetIndicatorMap(client); 680005b261ecSmrg case X_kbSetIndicatorMap: 6801f7df2e56Smrg return ProcXkbSetIndicatorMap(client); 680205b261ecSmrg case X_kbGetNamedIndicator: 6803f7df2e56Smrg return ProcXkbGetNamedIndicator(client); 680405b261ecSmrg case X_kbSetNamedIndicator: 6805f7df2e56Smrg return ProcXkbSetNamedIndicator(client); 680605b261ecSmrg case X_kbGetNames: 6807f7df2e56Smrg return ProcXkbGetNames(client); 680805b261ecSmrg case X_kbSetNames: 6809f7df2e56Smrg return ProcXkbSetNames(client); 681005b261ecSmrg case X_kbGetGeometry: 6811f7df2e56Smrg return ProcXkbGetGeometry(client); 681205b261ecSmrg case X_kbSetGeometry: 6813f7df2e56Smrg return ProcXkbSetGeometry(client); 681405b261ecSmrg case X_kbPerClientFlags: 6815f7df2e56Smrg return ProcXkbPerClientFlags(client); 681605b261ecSmrg case X_kbListComponents: 6817f7df2e56Smrg return ProcXkbListComponents(client); 681805b261ecSmrg case X_kbGetKbdByName: 6819f7df2e56Smrg return ProcXkbGetKbdByName(client); 682005b261ecSmrg case X_kbGetDeviceInfo: 6821f7df2e56Smrg return ProcXkbGetDeviceInfo(client); 682205b261ecSmrg case X_kbSetDeviceInfo: 6823f7df2e56Smrg return ProcXkbSetDeviceInfo(client); 682405b261ecSmrg case X_kbSetDebuggingFlags: 6825f7df2e56Smrg return ProcXkbSetDebuggingFlags(client); 682605b261ecSmrg default: 6827f7df2e56Smrg return BadRequest; 682805b261ecSmrg } 682905b261ecSmrg} 683005b261ecSmrg 683105b261ecSmrgstatic int 6832f7df2e56SmrgXkbClientGone(void *data, XID id) 683305b261ecSmrg{ 6834f7df2e56Smrg DevicePtr pXDev = (DevicePtr) data; 683505b261ecSmrg 6836f7df2e56Smrg if (!XkbRemoveResourceClient(pXDev, id)) { 6837f7df2e56Smrg ErrorF 6838f7df2e56Smrg ("[xkb] Internal Error! bad RemoveResourceClient in XkbClientGone\n"); 683905b261ecSmrg } 684005b261ecSmrg return 1; 684105b261ecSmrg} 684205b261ecSmrg 684305b261ecSmrgvoid 684405b261ecSmrgXkbExtensionInit(void) 684505b261ecSmrg{ 684605b261ecSmrg ExtensionEntry *extEntry; 684705b261ecSmrg 68486747b715Smrg RT_XKBCLIENT = CreateNewResourceType(XkbClientGone, "XkbClient"); 68496747b715Smrg if (!RT_XKBCLIENT) 6850f7df2e56Smrg return; 68516747b715Smrg 68526747b715Smrg if (!XkbInitPrivates()) 6853f7df2e56Smrg return; 68546747b715Smrg 685505b261ecSmrg if ((extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors, 6856f7df2e56Smrg ProcXkbDispatch, SProcXkbDispatch, 6857f7df2e56Smrg NULL, StandardMinorOpcode))) { 6858f7df2e56Smrg XkbReqCode = (unsigned char) extEntry->base; 6859f7df2e56Smrg XkbEventBase = (unsigned char) extEntry->eventBase; 6860f7df2e56Smrg XkbErrorBase = (unsigned char) extEntry->errorBase; 6861f7df2e56Smrg XkbKeyboardErrorCode = XkbErrorBase + XkbKeyboard; 686205b261ecSmrg } 686305b261ecSmrg return; 686405b261ecSmrg} 6865