xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

xkb.c (232285B)


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