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