1/************************************************************
2Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3
4Permission to use, copy, modify, and distribute this
5software and its documentation for any purpose and without
6fee is hereby granted, provided that the above copyright
7notice appear in all copies and that both that copyright
8notice and this permission notice appear in supporting
9documentation, and that the name of Silicon Graphics not be
10used in advertising or publicity pertaining to distribution
11of the software without specific prior written permission.
12Silicon Graphics makes no representation about the suitability
13of this software for any purpose. It is provided "as is"
14without any express or implied warranty.
15
16SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23THE 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
37XkbDescPtr
38XkbGetKeyboardByName(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
222XkbDescPtr
223XkbGetKeyboard(Display *dpy, unsigned which, unsigned deviceSpec)
224{
225    return XkbGetKeyboardByName(dpy, deviceSpec, NULL, which, which, False);
226}
227