1 /************************************************************
2 Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3 
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be
10 used in advertising or publicity pertaining to distribution
11 of the software without specific prior written permission.
12 Silicon Graphics makes no representation about the suitability
13 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
15 
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23 THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 
25 ********************************************************/
26 
27 #define	NEED_MAP_READERS
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include "Xlibint.h"
32 #include <X11/extensions/XKBproto.h>
33 #include "XKBlibint.h"
34 
35 /***====================================================================***/
36 
37 XkbDescPtr
XkbGetKeyboardByName(Display * dpy,unsigned deviceSpec,XkbComponentNamesPtr names,unsigned want,unsigned need,Bool load)38 XkbGetKeyboardByName(Display *dpy,
39                      unsigned deviceSpec,
40                      XkbComponentNamesPtr names,
41                      unsigned want,
42                      unsigned need,
43                      Bool load)
44 {
45     register xkbGetKbdByNameReq *req;
46     xkbGetKbdByNameReply rep;
47     int len, extraLen = 0;
48     char *str;
49     XkbDescPtr xkb;
50     int mapLen, codesLen, typesLen, compatLen;
51     int symsLen, geomLen;
52     XkbInfoPtr xkbi;
53 
54     if ((dpy == NULL) || (dpy->flags & XlibDisplayNoXkb) ||
55         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
56         return NULL;
57 
58     xkbi = dpy->xkb_info;
59     xkb = (XkbDescRec *) _XkbCalloc(1, sizeof(XkbDescRec));
60     if (!xkb)
61         return NULL;
62     xkb->device_spec = deviceSpec;
63     xkb->map = (XkbClientMapRec *) _XkbCalloc(1, sizeof(XkbClientMapRec));
64     xkb->dpy = dpy;
65 
66     LockDisplay(dpy);
67     GetReq(kbGetKbdByName, req);
68     req->reqType = xkbi->codes->major_opcode;
69     req->xkbReqType = X_kbGetKbdByName;
70     req->deviceSpec = xkb->device_spec;
71     req->want = want;
72     req->need = need;
73     req->load = load;
74 
75     mapLen = codesLen = typesLen = compatLen = symsLen = geomLen = 0;
76     if (names) {
77         if (names->keymap)
78             mapLen = (int) strlen(names->keymap);
79         if (names->keycodes)
80             codesLen = (int) strlen(names->keycodes);
81         if (names->types)
82             typesLen = (int) strlen(names->types);
83         if (names->compat)
84             compatLen = (int) strlen(names->compat);
85         if (names->symbols)
86             symsLen = (int) strlen(names->symbols);
87         if (names->geometry)
88             geomLen = (int) strlen(names->geometry);
89         if (mapLen > 255)
90             mapLen = 255;
91         if (codesLen > 255)
92             codesLen = 255;
93         if (typesLen > 255)
94             typesLen = 255;
95         if (compatLen > 255)
96             compatLen = 255;
97         if (symsLen > 255)
98             symsLen = 255;
99         if (geomLen > 255)
100             geomLen = 255;
101     }
102     else
103         mapLen = codesLen = typesLen = compatLen = symsLen = geomLen = 0;
104 
105     len = mapLen + codesLen + typesLen + compatLen + symsLen + geomLen + 6;
106     len = XkbPaddedSize(len);
107     req->length += len / 4;
108     BufAlloc(char *, str, len);
109 
110     *str++ = mapLen;
111     if (mapLen > 0) {
112         memcpy(str, names->keymap, (size_t) mapLen);
113         str += mapLen;
114     }
115     *str++ = codesLen;
116     if (codesLen > 0) {
117         memcpy(str, names->keycodes, (size_t) codesLen);
118         str += codesLen;
119     }
120     *str++ = typesLen;
121     if (typesLen > 0) {
122         memcpy(str, names->types, (size_t) typesLen);
123         str += typesLen;
124     }
125     *str++ = compatLen;
126     if (compatLen > 0) {
127         memcpy(str, names->compat, (size_t) compatLen);
128         str += compatLen;
129     }
130     *str++ = symsLen;
131     if (symsLen > 0) {
132         memcpy(str, names->symbols, (size_t) symsLen);
133         str += symsLen;
134     }
135     *str++ = geomLen;
136     if (geomLen > 0) {
137         memcpy(str, names->geometry, (size_t) geomLen);
138         str += geomLen;
139     }
140     if ((!_XReply(dpy, (xReply *) &rep, 0, xFalse)) || (!rep.reported))
141         goto BAILOUT;
142     extraLen = (int) rep.length * 4;
143 
144     xkb->device_spec = rep.deviceID;
145     xkb->min_key_code = rep.minKeyCode;
146     xkb->max_key_code = rep.maxKeyCode;
147     if (rep.reported & (XkbGBN_SymbolsMask | XkbGBN_TypesMask)) {
148         xkbGetMapReply mrep;
149         Status status;
150         int nread = 0;
151 
152         _XRead(dpy, (char *) &mrep, SIZEOF(xkbGetMapReply));
153         extraLen -= SIZEOF(xkbGetMapReply);
154         status = _XkbReadGetMapReply(dpy, &mrep, xkb, &nread);
155         extraLen -= nread;
156         if (status != Success)
157             goto BAILOUT;
158     }
159     if (rep.reported & XkbGBN_CompatMapMask) {
160         xkbGetCompatMapReply crep;
161         Status status;
162         int nread = 0;
163 
164         _XRead(dpy, (char *) &crep, SIZEOF(xkbGetCompatMapReply));
165         extraLen -= SIZEOF(xkbGetCompatMapReply);
166         status = _XkbReadGetCompatMapReply(dpy, &crep, xkb, &nread);
167         extraLen -= nread;
168         if (status != Success)
169             goto BAILOUT;
170     }
171     if (rep.reported & XkbGBN_IndicatorMapMask) {
172         xkbGetIndicatorMapReply irep;
173         Status status;
174         int nread = 0;
175 
176         _XRead(dpy, (char *) &irep, SIZEOF(xkbGetIndicatorMapReply));
177         extraLen -= SIZEOF(xkbGetIndicatorMapReply);
178         status = _XkbReadGetIndicatorMapReply(dpy, &irep, xkb, &nread);
179         extraLen -= nread;
180         if (status != Success)
181             goto BAILOUT;
182     }
183     if (rep.reported & (XkbGBN_KeyNamesMask | XkbGBN_OtherNamesMask)) {
184         xkbGetNamesReply nrep;
185         Status status;
186         int nread = 0;
187 
188         _XRead(dpy, (char *) &nrep, SIZEOF(xkbGetNamesReply));
189         extraLen -= SIZEOF(xkbGetNamesReply);
190         status = _XkbReadGetNamesReply(dpy, &nrep, xkb, &nread);
191         extraLen -= nread;
192         if (status != Success)
193             goto BAILOUT;
194     }
195     if (rep.reported & XkbGBN_GeometryMask) {
196         xkbGetGeometryReply grep;
197         Status status;
198         int nread = 0;
199 
200         _XRead(dpy, (char *) &grep, SIZEOF(xkbGetGeometryReply));
201         extraLen -= SIZEOF(xkbGetGeometryReply);
202         status = _XkbReadGetGeometryReply(dpy, &grep, xkb, &nread);
203         extraLen -= nread;
204         if (status != Success)
205             goto BAILOUT;
206     }
207     if (extraLen > 0)
208         goto BAILOUT;
209     UnlockDisplay(dpy);
210     SyncHandle();
211     return xkb;
212  BAILOUT:
213     if (xkb != NULL)
214         XkbFreeKeyboard(xkb, XkbAllComponentsMask, xTrue);
215     if (extraLen > 0)
216         _XEatData(dpy, extraLen);
217     UnlockDisplay(dpy);
218     SyncHandle();
219     return NULL;
220 }
221 
222 XkbDescPtr
XkbGetKeyboard(Display * dpy,unsigned which,unsigned deviceSpec)223 XkbGetKeyboard(Display *dpy, unsigned which, unsigned deviceSpec)
224 {
225     return XkbGetKeyboardByName(dpy, deviceSpec, NULL, which, which, False);
226 }
227