XKBList.c 8.13 KB
Newer Older
1 2 3 4 5 6 7 8
/************************************************************
Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.

Permission to use, copy, modify, and distribute this
software and its documentation for any purpose and without
fee is hereby granted, provided that the above copyright
notice appear in all copies and that both that copyright
notice and this permission notice appear in supporting
9 10
documentation, and that the name of Silicon Graphics not be
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 14 15
of this software for any purpose. It is provided "as is"
without any express or implied warranty.

16 17
SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18
AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 20 21
GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 23 24 25 26 27 28 29 30 31
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
THE USE OR PERFORMANCE OF THIS SOFTWARE.

********************************************************/

#define	NEED_MAP_READERS
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "Xlibint.h"
32
#include <nx-X11/extensions/XKBproto.h>
33 34 35 36 37
#include "XKBlibint.h"

/***====================================================================***/

static void
38
_FreeComponentNames(int num, XkbComponentNamePtr names)
39
{
40 41 42 43 44 45 46 47 48 49
    int i;
    XkbComponentNamePtr tmp;

    if ((num < 1) || (names == NULL))
        return;
    for (i = 0, tmp = names; i < num; i++, tmp++) {
        if (tmp->name) {
            _XkbFree(tmp->name);
            tmp->name = NULL;
        }
50 51 52 53 54 55 56 57
    }
    _XkbFree(names);
    return;
}

/***====================================================================***/

static XkbComponentNamePtr
58
_ReadListing(XkbReadBufferPtr buf, int count, Status * status_rtrn)
59
{
60 61 62 63 64 65 66 67 68
    XkbComponentNamePtr first, this;
    register int i;
    CARD16 *flags;
    int slen, wlen;
    char *str;

    if (count < 1)
        return NULL;
    first = _XkbTypedCalloc(count, XkbComponentNameRec);
69
    if (!first)
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
        return NULL;
    for (this = first, i = 0; i < count; i++, this++) {
        flags = (CARD16 *) _XkbGetReadBufferPtr(buf, 2 * sizeof(CARD16));
        if (!flags)
            goto BAILOUT;
        this->flags = flags[0];
        slen = flags[1];
        wlen = ((slen + 1) / 2) * 2;    /* pad to 2 byte boundary */
        this->name = _XkbTypedCalloc(slen + 1, char);

        if (!this->name)
            goto BAILOUT;
        str = (char *) _XkbGetReadBufferPtr(buf, wlen);
        if (!str)
            goto BAILOUT;
        memcpy(this->name, str, slen);
86 87
    }
    return first;
88 89 90
 BAILOUT:
    *status_rtrn = BadAlloc;
    _FreeComponentNames(i, first);
91 92 93 94 95 96
    return NULL;
}

/***====================================================================***/

XkbComponentListPtr
97 98 99 100
XkbListComponents(Display *dpy,
                  unsigned deviceSpec,
                  XkbComponentNamesPtr ptrns,
                  int *max_inout)
101
{
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
    register xkbListComponentsReq *req;
    xkbListComponentsReply rep;
    XkbInfoPtr xkbi;
    XkbComponentListPtr list;
    XkbReadBufferRec buf;
    int left;
    char *str;
    int extraLen, len, mapLen, codesLen, typesLen, compatLen, symsLen, geomLen;

    if ((dpy == NULL) || (dpy->flags & XlibDisplayNoXkb) ||
        (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)) ||
        (ptrns == NULL) || (max_inout == NULL))
        return NULL;

    xkbi = dpy->xkb_info;
117 118
    LockDisplay(dpy);
    GetReq(kbListComponents, req);
119 120 121 122
    req->reqType = xkbi->codes->major_opcode;
    req->xkbReqType = X_kbListComponents;
    req->deviceSpec = deviceSpec;
    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 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
        geomLen = (int) strlen(ptrns->geometry);
    if (mapLen > 255)
        mapLen = 255;
    if (codesLen > 255)
        codesLen = 255;
    if (typesLen > 255)
        typesLen = 255;
    if (compatLen > 255)
        compatLen = 255;
    if (symsLen > 255)
        symsLen = 255;
    if (geomLen > 255)
        geomLen = 255;

    len = mapLen + codesLen + typesLen + compatLen + symsLen + geomLen + 6;
    len = XkbPaddedSize(len);
    req->length += len / 4;
    BufAlloc(char *, str, len);

    *str++ = mapLen;
    if (mapLen > 0) {
        memcpy(str, ptrns->keymap, mapLen);
        str += mapLen;
159
    }
160 161 162 163
    *str++ = codesLen;
    if (codesLen > 0) {
        memcpy(str, ptrns->keycodes, codesLen);
        str += codesLen;
164
    }
165 166 167 168
    *str++ = typesLen;
    if (typesLen > 0) {
        memcpy(str, ptrns->types, typesLen);
        str += typesLen;
169
    }
170 171 172 173
    *str++ = compatLen;
    if (compatLen > 0) {
        memcpy(str, ptrns->compat, compatLen);
        str += compatLen;
174
    }
175 176 177 178
    *str++ = symsLen;
    if (symsLen > 0) {
        memcpy(str, ptrns->symbols, symsLen);
        str += symsLen;
179
    }
180 181 182 183
    *str++ = geomLen;
    if (geomLen > 0) {
        memcpy(str, ptrns->geometry, geomLen);
        str += geomLen;
184
    }
185 186 187 188 189 190 191 192 193
    if (!_XReply(dpy, (xReply *) &rep, 0, xFalse))
        goto BAILOUT;
    extraLen = (int) rep.length * 4;
    *max_inout = rep.extra;
    if (extraLen == 0) {        /* no matches, but we don't want to report a failure */
        list = _XkbTypedCalloc(1, XkbComponentListRec);
        UnlockDisplay(dpy);
        SyncHandle();
        return list;
194
    }
195
    if (_XkbInitReadBuffer(dpy, &buf, extraLen)) {
196
        Status status = Success;
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228

        list = _XkbTypedCalloc(1, XkbComponentListRec);
        if (!list) {
            _XkbFreeReadBuffer(&buf);
            goto BAILOUT;
        }
        list->num_keymaps = rep.nKeymaps;
        list->num_keycodes = rep.nKeycodes;
        list->num_types = rep.nTypes;
        list->num_compat = rep.nCompatMaps;
        list->num_symbols = rep.nSymbols;
        list->num_geometry = rep.nGeometries;
        if ((status == Success) && (list->num_keymaps > 0))
            list->keymaps = _ReadListing(&buf, list->num_keymaps, &status);
        if ((status == Success) && (list->num_keycodes > 0))
            list->keycodes = _ReadListing(&buf, list->num_keycodes, &status);
        if ((status == Success) && (list->num_types > 0))
            list->types = _ReadListing(&buf, list->num_types, &status);
        if ((status == Success) && (list->num_compat > 0))
            list->compat = _ReadListing(&buf, list->num_compat, &status);
        if ((status == Success) && (list->num_symbols > 0))
            list->symbols = _ReadListing(&buf, list->num_symbols, &status);
        if ((status == Success) && (list->num_geometry > 0))
            list->geometry = _ReadListing(&buf, list->num_geometry, &status);
        left = _XkbFreeReadBuffer(&buf);
        if ((status != Success) || (buf.error) || (left > 2)) {
            XkbFreeComponentList(list);
            goto BAILOUT;
        }
        UnlockDisplay(dpy);
        SyncHandle();
        return list;
229
    }
230
 BAILOUT:
231 232 233 234 235 236 237 238 239
    UnlockDisplay(dpy);
    SyncHandle();
    return NULL;
}

void
XkbFreeComponentList(XkbComponentListPtr list)
{
    if (list) {
240 241 242 243 244 245 246 247 248 249 250 251 252 253
        if (list->keymaps)
            _FreeComponentNames(list->num_keymaps, list->keymaps);
        if (list->keycodes)
            _FreeComponentNames(list->num_keycodes, list->keycodes);
        if (list->types)
            _FreeComponentNames(list->num_types, list->types);
        if (list->compat)
            _FreeComponentNames(list->num_compat, list->compat);
        if (list->symbols)
            _FreeComponentNames(list->num_symbols, list->symbols);
        if (list->geometry)
            _FreeComponentNames(list->num_geometry, list->geometry);
        bzero((char *) list, sizeof(XkbComponentListRec));
        _XkbFree(list);
254 255 256
    }
    return;
}