1/************************************************************ 2Copyright (c) 1995 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 37static void 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 57static XkbComponentNamePtr 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 96XkbComponentListPtr 97XkbListComponents(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 236void 237XkbFreeComponentList(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