1 /************************************************************
2 Copyright (c) 1995 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 static void
_FreeComponentNames(int num,XkbComponentNamePtr names)38 _FreeComponentNames(int num, XkbComponentNamePtr names)
39 {
40 int i;
41 XkbComponentNamePtr tmp;
42
43 if ((num < 1) || (names == NULL))
44 return;
45 for (i = 0, tmp = names; i < num; i++, tmp++) {
46 if (tmp->name) {
47 _XkbFree(tmp->name);
48 tmp->name = NULL;
49 }
50 }
51 _XkbFree(names);
52 return;
53 }
54
55 /***====================================================================***/
56
57 static XkbComponentNamePtr
_ReadListing(XkbReadBufferPtr buf,int count,Status * status_rtrn)58 _ReadListing(XkbReadBufferPtr buf, int count, Status * status_rtrn)
59 {
60 XkbComponentNamePtr first, this;
61 register int i;
62 CARD16 *flags;
63 int slen, wlen;
64 char *str;
65
66 if (count < 1)
67 return NULL;
68 first = _XkbTypedCalloc(count, XkbComponentNameRec);
69 if (!first)
70 return NULL;
71 for (this = first, i = 0; i < count; i++, this++) {
72 flags = (CARD16 *) _XkbGetReadBufferPtr(buf, 2 * sizeof(CARD16));
73 if (!flags)
74 goto BAILOUT;
75 this->flags = flags[0];
76 slen = flags[1];
77 wlen = ((slen + 1) / 2) * 2; /* pad to 2 byte boundary */
78 this->name = _XkbTypedCalloc(slen + 1, char);
79
80 if (!this->name)
81 goto BAILOUT;
82 str = (char *) _XkbGetReadBufferPtr(buf, wlen);
83 if (!str)
84 goto BAILOUT;
85 memcpy(this->name, str, (size_t) slen);
86 }
87 return first;
88 BAILOUT:
89 *status_rtrn = BadAlloc;
90 _FreeComponentNames(i, first);
91 return NULL;
92 }
93
94 /***====================================================================***/
95
96 XkbComponentListPtr
XkbListComponents(Display * dpy,unsigned deviceSpec,XkbComponentNamesPtr ptrns,int * max_inout)97 XkbListComponents(Display *dpy,
98 unsigned deviceSpec,
99 XkbComponentNamesPtr ptrns,
100 int *max_inout)
101 {
102 register xkbListComponentsReq *req;
103 xkbListComponentsReply rep;
104 XkbInfoPtr xkbi;
105 XkbComponentListPtr list;
106 XkbReadBufferRec buf;
107 int left;
108 char *str;
109 int extraLen, len, mapLen, codesLen, typesLen, compatLen, symsLen, geomLen;
110
111 if ((dpy == NULL) || (dpy->flags & XlibDisplayNoXkb) ||
112 (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)) ||
113 (ptrns == NULL) || (max_inout == NULL))
114 return NULL;
115
116 xkbi = dpy->xkb_info;
117 LockDisplay(dpy);
118 GetReq(kbListComponents, req);
119 req->reqType = xkbi->codes->major_opcode;
120 req->xkbReqType = X_kbListComponents;
121 req->deviceSpec = deviceSpec;
122 req->maxNames = *max_inout;
123
124 mapLen = codesLen = typesLen = compatLen = symsLen = geomLen = 0;
125 if (ptrns->keymap)
126 mapLen = (int) strlen(ptrns->keymap);
127 if (ptrns->keycodes)
128 codesLen = (int) strlen(ptrns->keycodes);
129 if (ptrns->types)
130 typesLen = (int) strlen(ptrns->types);
131 if (ptrns->compat)
132 compatLen = (int) strlen(ptrns->compat);
133 if (ptrns->symbols)
134 symsLen = (int) strlen(ptrns->symbols);
135 if (ptrns->geometry)
136 geomLen = (int) strlen(ptrns->geometry);
137 if (mapLen > 255)
138 mapLen = 255;
139 if (codesLen > 255)
140 codesLen = 255;
141 if (typesLen > 255)
142 typesLen = 255;
143 if (compatLen > 255)
144 compatLen = 255;
145 if (symsLen > 255)
146 symsLen = 255;
147 if (geomLen > 255)
148 geomLen = 255;
149
150 len = mapLen + codesLen + typesLen + compatLen + symsLen + geomLen + 6;
151 len = XkbPaddedSize(len);
152 req->length += len / 4;
153 BufAlloc(char *, str, len);
154
155 *str++ = mapLen;
156 if (mapLen > 0) {
157 memcpy(str, ptrns->keymap, (size_t) mapLen);
158 str += mapLen;
159 }
160 *str++ = codesLen;
161 if (codesLen > 0) {
162 memcpy(str, ptrns->keycodes, (size_t) codesLen);
163 str += codesLen;
164 }
165 *str++ = typesLen;
166 if (typesLen > 0) {
167 memcpy(str, ptrns->types, (size_t) typesLen);
168 str += typesLen;
169 }
170 *str++ = compatLen;
171 if (compatLen > 0) {
172 memcpy(str, ptrns->compat, (size_t) compatLen);
173 str += compatLen;
174 }
175 *str++ = symsLen;
176 if (symsLen > 0) {
177 memcpy(str, ptrns->symbols, (size_t) symsLen);
178 str += symsLen;
179 }
180 *str++ = geomLen;
181 if (geomLen > 0) {
182 memcpy(str, ptrns->geometry, (size_t) geomLen);
183 str += geomLen;
184 }
185 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse))
186 goto BAILOUT;
187 extraLen = (int) rep.length * 4;
188 *max_inout = rep.extra;
189 if (extraLen == 0) { /* no matches, but we don't want to report a failure */
190 list = _XkbTypedCalloc(1, XkbComponentListRec);
191 UnlockDisplay(dpy);
192 SyncHandle();
193 return list;
194 }
195 if (_XkbInitReadBuffer(dpy, &buf, extraLen)) {
196 Status status = Success;
197
198 list = _XkbTypedCalloc(1, XkbComponentListRec);
199 if (!list) {
200 _XkbFreeReadBuffer(&buf);
201 goto BAILOUT;
202 }
203 list->num_keymaps = rep.nKeymaps;
204 list->num_keycodes = rep.nKeycodes;
205 list->num_types = rep.nTypes;
206 list->num_compat = rep.nCompatMaps;
207 list->num_symbols = rep.nSymbols;
208 list->num_geometry = rep.nGeometries;
209 if ((status == Success) && (list->num_keymaps > 0))
210 list->keymaps = _ReadListing(&buf, list->num_keymaps, &status);
211 if ((status == Success) && (list->num_keycodes > 0))
212 list->keycodes = _ReadListing(&buf, list->num_keycodes, &status);
213 if ((status == Success) && (list->num_types > 0))
214 list->types = _ReadListing(&buf, list->num_types, &status);
215 if ((status == Success) && (list->num_compat > 0))
216 list->compat = _ReadListing(&buf, list->num_compat, &status);
217 if ((status == Success) && (list->num_symbols > 0))
218 list->symbols = _ReadListing(&buf, list->num_symbols, &status);
219 if ((status == Success) && (list->num_geometry > 0))
220 list->geometry = _ReadListing(&buf, list->num_geometry, &status);
221 left = _XkbFreeReadBuffer(&buf);
222 if ((status != Success) || (buf.error) || (left > 2)) {
223 XkbFreeComponentList(list);
224 goto BAILOUT;
225 }
226 UnlockDisplay(dpy);
227 SyncHandle();
228 return list;
229 }
230 BAILOUT:
231 UnlockDisplay(dpy);
232 SyncHandle();
233 return NULL;
234 }
235
236 void
XkbFreeComponentList(XkbComponentListPtr list)237 XkbFreeComponentList(XkbComponentListPtr list)
238 {
239 if (list) {
240 if (list->keymaps)
241 _FreeComponentNames(list->num_keymaps, list->keymaps);
242 if (list->keycodes)
243 _FreeComponentNames(list->num_keycodes, list->keycodes);
244 if (list->types)
245 _FreeComponentNames(list->num_types, list->types);
246 if (list->compat)
247 _FreeComponentNames(list->num_compat, list->compat);
248 if (list->symbols)
249 _FreeComponentNames(list->num_symbols, list->symbols);
250 if (list->geometry)
251 _FreeComponentNames(list->num_geometry, list->geometry);
252 bzero((char *) list, sizeof(XkbComponentListRec));
253 _XkbFree(list);
254 }
255 return;
256 }
257