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