11ab64890Smrg/************************************************************
21ab64890SmrgCopyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
31ab64890Smrg
41ab64890SmrgPermission to use, copy, modify, and distribute this
51ab64890Smrgsoftware and its documentation for any purpose and without
61ab64890Smrgfee is hereby granted, provided that the above copyright
71ab64890Smrgnotice appear in all copies and that both that copyright
81ab64890Smrgnotice and this permission notice appear in supporting
961b2299dSmrgdocumentation, and that the name of Silicon Graphics not be
1061b2299dSmrgused in advertising or publicity pertaining to distribution
111ab64890Smrgof the software without specific prior written permission.
1261b2299dSmrgSilicon Graphics makes no representation about the suitability
131ab64890Smrgof this software for any purpose. It is provided "as is"
141ab64890Smrgwithout any express or implied warranty.
151ab64890Smrg
1661b2299dSmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
1761b2299dSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
181ab64890SmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
1961b2299dSmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
2061b2299dSmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
2161b2299dSmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
221ab64890SmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
231ab64890SmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE.
241ab64890Smrg
251ab64890Smrg********************************************************/
261ab64890Smrg
271ab64890Smrg#define	NEED_MAP_READERS
281ab64890Smrg#ifdef HAVE_CONFIG_H
291ab64890Smrg#include <config.h>
301ab64890Smrg#endif
311ab64890Smrg#include "Xlibint.h"
321ab64890Smrg#include <X11/extensions/XKBproto.h>
331ab64890Smrg#include "XKBlibint.h"
341ab64890Smrg
351ab64890Smrg/***====================================================================***/
361ab64890Smrg
371ab64890Smrgstatic void
38818534a1Smrg_FreeComponentNames(int num, XkbComponentNamePtr names)
391ab64890Smrg{
40818534a1Smrg    int i;
41818534a1Smrg    XkbComponentNamePtr tmp;
42818534a1Smrg
43818534a1Smrg    if ((num < 1) || (names == NULL))
44818534a1Smrg        return;
45818534a1Smrg    for (i = 0, tmp = names; i < num; i++, tmp++) {
46818534a1Smrg        if (tmp->name) {
47818534a1Smrg            _XkbFree(tmp->name);
48818534a1Smrg            tmp->name = NULL;
49818534a1Smrg        }
501ab64890Smrg    }
511ab64890Smrg    _XkbFree(names);
521ab64890Smrg    return;
531ab64890Smrg}
541ab64890Smrg
551ab64890Smrg/***====================================================================***/
561ab64890Smrg
571ab64890Smrgstatic XkbComponentNamePtr
58818534a1Smrg_ReadListing(XkbReadBufferPtr buf, int count, Status * status_rtrn)
591ab64890Smrg{
60818534a1Smrg    XkbComponentNamePtr first, this;
61818534a1Smrg    register int i;
62818534a1Smrg    CARD16 *flags;
63818534a1Smrg    int slen, wlen;
64818534a1Smrg    char *str;
65818534a1Smrg
66818534a1Smrg    if (count < 1)
67818534a1Smrg        return NULL;
68818534a1Smrg    first = _XkbTypedCalloc(count, XkbComponentNameRec);
691ab64890Smrg    if (!first)
70818534a1Smrg        return NULL;
71818534a1Smrg    for (this = first, i = 0; i < count; i++, this++) {
72818534a1Smrg        flags = (CARD16 *) _XkbGetReadBufferPtr(buf, 2 * sizeof(CARD16));
73818534a1Smrg        if (!flags)
74818534a1Smrg            goto BAILOUT;
75818534a1Smrg        this->flags = flags[0];
76818534a1Smrg        slen = flags[1];
77818534a1Smrg        wlen = ((slen + 1) / 2) * 2;    /* pad to 2 byte boundary */
78818534a1Smrg        this->name = _XkbTypedCalloc(slen + 1, char);
79818534a1Smrg
80818534a1Smrg        if (!this->name)
81818534a1Smrg            goto BAILOUT;
82818534a1Smrg        str = (char *) _XkbGetReadBufferPtr(buf, wlen);
83818534a1Smrg        if (!str)
84818534a1Smrg            goto BAILOUT;
859c019ec5Smaya        memcpy(this->name, str, (size_t) slen);
861ab64890Smrg    }
871ab64890Smrg    return first;
88818534a1Smrg BAILOUT:
89818534a1Smrg    *status_rtrn = BadAlloc;
90818534a1Smrg    _FreeComponentNames(i, first);
911ab64890Smrg    return NULL;
921ab64890Smrg}
931ab64890Smrg
941ab64890Smrg/***====================================================================***/
951ab64890Smrg
961ab64890SmrgXkbComponentListPtr
97818534a1SmrgXkbListComponents(Display *dpy,
98818534a1Smrg                  unsigned deviceSpec,
99818534a1Smrg                  XkbComponentNamesPtr ptrns,
100818534a1Smrg                  int *max_inout)
1011ab64890Smrg{
102818534a1Smrg    register xkbListComponentsReq *req;
103818534a1Smrg    xkbListComponentsReply rep;
104818534a1Smrg    XkbInfoPtr xkbi;
105818534a1Smrg    XkbComponentListPtr list;
106818534a1Smrg    XkbReadBufferRec buf;
107818534a1Smrg    int left;
108818534a1Smrg    char *str;
109818534a1Smrg    int extraLen, len, mapLen, codesLen, typesLen, compatLen, symsLen, geomLen;
110818534a1Smrg
111818534a1Smrg    if ((dpy == NULL) || (dpy->flags & XlibDisplayNoXkb) ||
112818534a1Smrg        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)) ||
113818534a1Smrg        (ptrns == NULL) || (max_inout == NULL))
114818534a1Smrg        return NULL;
115818534a1Smrg
116818534a1Smrg    xkbi = dpy->xkb_info;
1171ab64890Smrg    LockDisplay(dpy);
1181ab64890Smrg    GetReq(kbListComponents, req);
119818534a1Smrg    req->reqType = xkbi->codes->major_opcode;
120818534a1Smrg    req->xkbReqType = X_kbListComponents;
121818534a1Smrg    req->deviceSpec = deviceSpec;
122818534a1Smrg    req->maxNames = *max_inout;
1231ab64890Smrg
124818534a1Smrg    mapLen = codesLen = typesLen = compatLen = symsLen = geomLen = 0;
1251ab64890Smrg    if (ptrns->keymap)
126818534a1Smrg        mapLen = (int) strlen(ptrns->keymap);
1271ab64890Smrg    if (ptrns->keycodes)
128818534a1Smrg        codesLen = (int) strlen(ptrns->keycodes);
1291ab64890Smrg    if (ptrns->types)
130818534a1Smrg        typesLen = (int) strlen(ptrns->types);
1311ab64890Smrg    if (ptrns->compat)
132818534a1Smrg        compatLen = (int) strlen(ptrns->compat);
1331ab64890Smrg    if (ptrns->symbols)
134818534a1Smrg        symsLen = (int) strlen(ptrns->symbols);
1351ab64890Smrg    if (ptrns->geometry)
136818534a1Smrg        geomLen = (int) strlen(ptrns->geometry);
137818534a1Smrg    if (mapLen > 255)
138818534a1Smrg        mapLen = 255;
139818534a1Smrg    if (codesLen > 255)
140818534a1Smrg        codesLen = 255;
141818534a1Smrg    if (typesLen > 255)
142818534a1Smrg        typesLen = 255;
143818534a1Smrg    if (compatLen > 255)
144818534a1Smrg        compatLen = 255;
145818534a1Smrg    if (symsLen > 255)
146818534a1Smrg        symsLen = 255;
147818534a1Smrg    if (geomLen > 255)
148818534a1Smrg        geomLen = 255;
149818534a1Smrg
150818534a1Smrg    len = mapLen + codesLen + typesLen + compatLen + symsLen + geomLen + 6;
151818534a1Smrg    len = XkbPaddedSize(len);
152818534a1Smrg    req->length += len / 4;
153818534a1Smrg    BufAlloc(char *, str, len);
154818534a1Smrg
155818534a1Smrg    *str++ = mapLen;
156818534a1Smrg    if (mapLen > 0) {
1579c019ec5Smaya        memcpy(str, ptrns->keymap, (size_t) mapLen);
158818534a1Smrg        str += mapLen;
1591ab64890Smrg    }
160818534a1Smrg    *str++ = codesLen;
161818534a1Smrg    if (codesLen > 0) {
1629c019ec5Smaya        memcpy(str, ptrns->keycodes, (size_t) codesLen);
163818534a1Smrg        str += codesLen;
1641ab64890Smrg    }
165818534a1Smrg    *str++ = typesLen;
166818534a1Smrg    if (typesLen > 0) {
1679c019ec5Smaya        memcpy(str, ptrns->types, (size_t) typesLen);
168818534a1Smrg        str += typesLen;
1691ab64890Smrg    }
170818534a1Smrg    *str++ = compatLen;
171818534a1Smrg    if (compatLen > 0) {
1729c019ec5Smaya        memcpy(str, ptrns->compat, (size_t) compatLen);
173818534a1Smrg        str += compatLen;
1741ab64890Smrg    }
175818534a1Smrg    *str++ = symsLen;
176818534a1Smrg    if (symsLen > 0) {
1779c019ec5Smaya        memcpy(str, ptrns->symbols, (size_t) symsLen);
178818534a1Smrg        str += symsLen;
1791ab64890Smrg    }
180818534a1Smrg    *str++ = geomLen;
181818534a1Smrg    if (geomLen > 0) {
1829c019ec5Smaya        memcpy(str, ptrns->geometry, (size_t) geomLen);
183818534a1Smrg        str += geomLen;
1841ab64890Smrg    }
185818534a1Smrg    if (!_XReply(dpy, (xReply *) &rep, 0, xFalse))
186818534a1Smrg        goto BAILOUT;
187818534a1Smrg    extraLen = (int) rep.length * 4;
188818534a1Smrg    *max_inout = rep.extra;
189818534a1Smrg    if (extraLen == 0) {        /* no matches, but we don't want to report a failure */
190818534a1Smrg        list = _XkbTypedCalloc(1, XkbComponentListRec);
191818534a1Smrg        UnlockDisplay(dpy);
192818534a1Smrg        SyncHandle();
193818534a1Smrg        return list;
1941ab64890Smrg    }
195818534a1Smrg    if (_XkbInitReadBuffer(dpy, &buf, extraLen)) {
196818534a1Smrg        Status status = Success;
197818534a1Smrg
198818534a1Smrg        list = _XkbTypedCalloc(1, XkbComponentListRec);
199818534a1Smrg        if (!list) {
200818534a1Smrg            _XkbFreeReadBuffer(&buf);
201818534a1Smrg            goto BAILOUT;
202818534a1Smrg        }
203818534a1Smrg        list->num_keymaps = rep.nKeymaps;
204818534a1Smrg        list->num_keycodes = rep.nKeycodes;
205818534a1Smrg        list->num_types = rep.nTypes;
206818534a1Smrg        list->num_compat = rep.nCompatMaps;
207818534a1Smrg        list->num_symbols = rep.nSymbols;
208818534a1Smrg        list->num_geometry = rep.nGeometries;
209818534a1Smrg        if ((status == Success) && (list->num_keymaps > 0))
210818534a1Smrg            list->keymaps = _ReadListing(&buf, list->num_keymaps, &status);
211818534a1Smrg        if ((status == Success) && (list->num_keycodes > 0))
212818534a1Smrg            list->keycodes = _ReadListing(&buf, list->num_keycodes, &status);
213818534a1Smrg        if ((status == Success) && (list->num_types > 0))
214818534a1Smrg            list->types = _ReadListing(&buf, list->num_types, &status);
215818534a1Smrg        if ((status == Success) && (list->num_compat > 0))
216818534a1Smrg            list->compat = _ReadListing(&buf, list->num_compat, &status);
217818534a1Smrg        if ((status == Success) && (list->num_symbols > 0))
218818534a1Smrg            list->symbols = _ReadListing(&buf, list->num_symbols, &status);
219818534a1Smrg        if ((status == Success) && (list->num_geometry > 0))
220818534a1Smrg            list->geometry = _ReadListing(&buf, list->num_geometry, &status);
221818534a1Smrg        left = _XkbFreeReadBuffer(&buf);
222818534a1Smrg        if ((status != Success) || (buf.error) || (left > 2)) {
223818534a1Smrg            XkbFreeComponentList(list);
224818534a1Smrg            goto BAILOUT;
225818534a1Smrg        }
226818534a1Smrg        UnlockDisplay(dpy);
227818534a1Smrg        SyncHandle();
228818534a1Smrg        return list;
2291ab64890Smrg    }
230818534a1Smrg BAILOUT:
2311ab64890Smrg    UnlockDisplay(dpy);
2321ab64890Smrg    SyncHandle();
2331ab64890Smrg    return NULL;
2341ab64890Smrg}
2351ab64890Smrg
2361ab64890Smrgvoid
2371ab64890SmrgXkbFreeComponentList(XkbComponentListPtr list)
2381ab64890Smrg{
2391ab64890Smrg    if (list) {
240818534a1Smrg        if (list->keymaps)
241818534a1Smrg            _FreeComponentNames(list->num_keymaps, list->keymaps);
242818534a1Smrg        if (list->keycodes)
243818534a1Smrg            _FreeComponentNames(list->num_keycodes, list->keycodes);
244818534a1Smrg        if (list->types)
245818534a1Smrg            _FreeComponentNames(list->num_types, list->types);
246818534a1Smrg        if (list->compat)
247818534a1Smrg            _FreeComponentNames(list->num_compat, list->compat);
248818534a1Smrg        if (list->symbols)
249818534a1Smrg            _FreeComponentNames(list->num_symbols, list->symbols);
250818534a1Smrg        if (list->geometry)
251818534a1Smrg            _FreeComponentNames(list->num_geometry, list->geometry);
252818534a1Smrg        bzero((char *) list, sizeof(XkbComponentListRec));
253818534a1Smrg        _XkbFree(list);
2541ab64890Smrg    }
2551ab64890Smrg    return;
2561ab64890Smrg}
257