| 1 | /************************************************************ |
| 2 | Copyright (c) 1993 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 | #ifdef HAVE_DIX_CONFIG_H |
| 28 | #include <dix-config.h> |
| 29 | #endif |
| 30 | |
| 31 | #include <stdio.h> |
| 32 | #include <X11/X.h> |
| 33 | #include <X11/Xproto.h> |
| 34 | #include "misc.h" |
| 35 | #include "inputstr.h" |
| 36 | #include <xkbsrv.h> |
| 37 | #include "xkbgeom.h" |
| 38 | #include <os.h> |
| 39 | #include <string.h> |
| 40 | |
| 41 | /***===================================================================***/ |
| 42 | |
| 43 | /*ARGSUSED*/ Status |
| 44 | XkbAllocCompatMap(XkbDescPtr xkb, unsigned which, unsigned nSI) |
| 45 | { |
| 46 | XkbCompatMapPtr compat; |
| 47 | XkbSymInterpretRec *prev_interpret; |
| 48 | |
| 49 | if (!xkb) |
| 50 | return BadMatch; |
| 51 | if (xkb->compat) { |
| 52 | if (xkb->compat->size_si >= nSI) |
| 53 | return Success; |
| 54 | compat = xkb->compat; |
| 55 | compat->size_si = nSI; |
| 56 | if (compat->sym_interpret == NULL) |
| 57 | compat->num_si = 0; |
| 58 | prev_interpret = compat->sym_interpret; |
| 59 | compat->sym_interpret = realloc(compat->sym_interpret, |
| 60 | nSI * sizeof(XkbSymInterpretRec)); |
| 61 | if (compat->sym_interpret == NULL) { |
| 62 | free(prev_interpret); |
| 63 | compat->size_si = compat->num_si = 0; |
| 64 | return BadAlloc; |
| 65 | } |
| 66 | if (compat->num_si != 0) { |
| 67 | memset(&compat->sym_interpret[compat->num_si], 0, |
| 68 | (compat->size_si - |
| 69 | compat->num_si) * sizeof(XkbSymInterpretRec)); |
| 70 | } |
| 71 | return Success; |
| 72 | } |
| 73 | compat = calloc(1, sizeof(XkbCompatMapRec)); |
| 74 | if (compat == NULL) |
| 75 | return BadAlloc; |
| 76 | if (nSI > 0) { |
| 77 | compat->sym_interpret = calloc(nSI, sizeof(XkbSymInterpretRec)); |
| 78 | if (!compat->sym_interpret) { |
| 79 | free(compat); |
| 80 | return BadAlloc; |
| 81 | } |
| 82 | } |
| 83 | compat->size_si = nSI; |
| 84 | compat->num_si = 0; |
| 85 | memset((char *) &compat->groups[0], 0, |
| 86 | XkbNumKbdGroups * sizeof(XkbModsRec)); |
| 87 | xkb->compat = compat; |
| 88 | return Success; |
| 89 | } |
| 90 | |
| 91 | void |
| 92 | XkbFreeCompatMap(XkbDescPtr xkb, unsigned which, Bool freeMap) |
| 93 | { |
| 94 | register XkbCompatMapPtr compat; |
| 95 | |
| 96 | if ((xkb == NULL) || (xkb->compat == NULL)) |
| 97 | return; |
| 98 | compat = xkb->compat; |
| 99 | if (freeMap) |
| 100 | which = XkbAllCompatMask; |
| 101 | if (which & XkbGroupCompatMask) |
| 102 | memset((char *) &compat->groups[0], 0, |
| 103 | XkbNumKbdGroups * sizeof(XkbModsRec)); |
| 104 | if (which & XkbSymInterpMask) { |
| 105 | if ((compat->sym_interpret) && (compat->size_si > 0)) |
| 106 | free(compat->sym_interpret); |
| 107 | compat->size_si = compat->num_si = 0; |
| 108 | compat->sym_interpret = NULL; |
| 109 | } |
| 110 | if (freeMap) { |
| 111 | free(compat); |
| 112 | xkb->compat = NULL; |
| 113 | } |
| 114 | return; |
| 115 | } |
| 116 | |
| 117 | /***===================================================================***/ |
| 118 | |
| 119 | Status |
| 120 | XkbAllocNames(XkbDescPtr xkb, unsigned which, int nTotalRG, int nTotalAliases) |
| 121 | { |
| 122 | XkbNamesPtr names; |
| 123 | |
| 124 | if (xkb == NULL) |
| 125 | return BadMatch; |
| 126 | if (xkb->names == NULL) { |
| 127 | xkb->names = calloc(1, sizeof(XkbNamesRec)); |
| 128 | if (xkb->names == NULL) |
| 129 | return BadAlloc; |
| 130 | } |
| 131 | names = xkb->names; |
| 132 | if ((which & XkbKTLevelNamesMask) && (xkb->map != NULL) && |
| 133 | (xkb->map->types != NULL)) { |
| 134 | register int i; |
| 135 | XkbKeyTypePtr type; |
| 136 | |
| 137 | type = xkb->map->types; |
| 138 | for (i = 0; i < xkb->map->num_types; i++, type++) { |
| 139 | if (type->level_names == NULL) { |
| 140 | type->level_names = calloc(type->num_levels, sizeof(Atom)); |
| 141 | if (type->level_names == NULL) |
| 142 | return BadAlloc; |
| 143 | } |
| 144 | } |
| 145 | } |
| 146 | if ((which & XkbKeyNamesMask) && (names->keys == NULL)) { |
| 147 | if ((!XkbIsLegalKeycode(xkb->min_key_code)) || |
| 148 | (!XkbIsLegalKeycode(xkb->max_key_code)) || |
| 149 | (xkb->max_key_code < xkb->min_key_code)) |
| 150 | return BadValue; |
| 151 | names->keys = calloc((xkb->max_key_code + 1), sizeof(XkbKeyNameRec)); |
| 152 | if (names->keys == NULL) |
| 153 | return BadAlloc; |
| 154 | } |
| 155 | if ((which & XkbKeyAliasesMask) && (nTotalAliases > 0)) { |
| 156 | if (names->key_aliases == NULL) { |
| 157 | names->key_aliases = calloc(nTotalAliases, sizeof(XkbKeyAliasRec)); |
| 158 | } |
| 159 | else if (nTotalAliases > names->num_key_aliases) { |
| 160 | XkbKeyAliasRec *prev_aliases = names->key_aliases; |
| 161 | |
| 162 | names->key_aliases = realloc(names->key_aliases, |
| 163 | nTotalAliases * |
| 164 | sizeof(XkbKeyAliasRec)); |
| 165 | if (names->key_aliases != NULL) { |
| 166 | memset(&names->key_aliases[names->num_key_aliases], 0, |
| 167 | (nTotalAliases - |
| 168 | names->num_key_aliases) * sizeof(XkbKeyAliasRec)); |
| 169 | } |
| 170 | else { |
| 171 | free(prev_aliases); |
| 172 | } |
| 173 | } |
| 174 | if (names->key_aliases == NULL) { |
| 175 | names->num_key_aliases = 0; |
| 176 | return BadAlloc; |
| 177 | } |
| 178 | names->num_key_aliases = nTotalAliases; |
| 179 | } |
| 180 | if ((which & XkbRGNamesMask) && (nTotalRG > 0)) { |
| 181 | if (names->radio_groups == NULL) { |
| 182 | names->radio_groups = calloc(nTotalRG, sizeof(Atom)); |
| 183 | } |
| 184 | else if (nTotalRG > names->num_rg) { |
| 185 | Atom *prev_radio_groups = names->radio_groups; |
| 186 | |
| 187 | names->radio_groups = realloc(names->radio_groups, |
| 188 | nTotalRG * sizeof(Atom)); |
| 189 | if (names->radio_groups != NULL) { |
| 190 | memset(&names->radio_groups[names->num_rg], 0, |
| 191 | (nTotalRG - names->num_rg) * sizeof(Atom)); |
| 192 | } |
| 193 | else { |
| 194 | free(prev_radio_groups); |
| 195 | } |
| 196 | } |
| 197 | if (names->radio_groups == NULL) |
| 198 | return BadAlloc; |
| 199 | names->num_rg = nTotalRG; |
| 200 | } |
| 201 | return Success; |
| 202 | } |
| 203 | |
| 204 | void |
| 205 | XkbFreeNames(XkbDescPtr xkb, unsigned which, Bool freeMap) |
| 206 | { |
| 207 | XkbNamesPtr names; |
| 208 | |
| 209 | if ((xkb == NULL) || (xkb->names == NULL)) |
| 210 | return; |
| 211 | names = xkb->names; |
| 212 | if (freeMap) |
| 213 | which = XkbAllNamesMask; |
| 214 | if (which & XkbKTLevelNamesMask) { |
| 215 | XkbClientMapPtr map = xkb->map; |
| 216 | |
| 217 | if ((map != NULL) && (map->types != NULL)) { |
| 218 | register int i; |
| 219 | register XkbKeyTypePtr type; |
| 220 | |
| 221 | type = map->types; |
| 222 | for (i = 0; i < map->num_types; i++, type++) { |
| 223 | free(type->level_names); |
| 224 | type->level_names = NULL; |
| 225 | } |
| 226 | } |
| 227 | } |
| 228 | if ((which & XkbKeyNamesMask) && (names->keys != NULL)) { |
| 229 | free(names->keys); |
| 230 | names->keys = NULL; |
| 231 | names->num_keys = 0; |
| 232 | } |
| 233 | if ((which & XkbKeyAliasesMask) && (names->key_aliases)) { |
| 234 | free(names->key_aliases); |
| 235 | names->key_aliases = NULL; |
| 236 | names->num_key_aliases = 0; |
| 237 | } |
| 238 | if ((which & XkbRGNamesMask) && (names->radio_groups)) { |
| 239 | free(names->radio_groups); |
| 240 | names->radio_groups = NULL; |
| 241 | names->num_rg = 0; |
| 242 | } |
| 243 | if (freeMap) { |
| 244 | free(names); |
| 245 | xkb->names = NULL; |
| 246 | } |
| 247 | return; |
| 248 | } |
| 249 | |
| 250 | /***===================================================================***/ |
| 251 | |
| 252 | /*ARGSUSED*/ Status |
| 253 | XkbAllocControls(XkbDescPtr xkb, unsigned which) |
| 254 | { |
| 255 | if (xkb == NULL) |
| 256 | return BadMatch; |
| 257 | |
| 258 | if (xkb->ctrls == NULL) { |
| 259 | xkb->ctrls = calloc(1, sizeof(XkbControlsRec)); |
| 260 | if (!xkb->ctrls) |
| 261 | return BadAlloc; |
| 262 | } |
| 263 | return Success; |
| 264 | } |
| 265 | |
| 266 | /*ARGSUSED*/ static void |
| 267 | XkbFreeControls(XkbDescPtr xkb, unsigned which, Bool freeMap) |
| 268 | { |
| 269 | if (freeMap && (xkb != NULL) && (xkb->ctrls != NULL)) { |
| 270 | free(xkb->ctrls); |
| 271 | xkb->ctrls = NULL; |
| 272 | } |
| 273 | return; |
| 274 | } |
| 275 | |
| 276 | /***===================================================================***/ |
| 277 | |
| 278 | Status |
| 279 | XkbAllocIndicatorMaps(XkbDescPtr xkb) |
| 280 | { |
| 281 | if (xkb == NULL) |
| 282 | return BadMatch; |
| 283 | if (xkb->indicators == NULL) { |
| 284 | xkb->indicators = calloc(1, sizeof(XkbIndicatorRec)); |
| 285 | if (!xkb->indicators) |
| 286 | return BadAlloc; |
| 287 | } |
| 288 | return Success; |
| 289 | } |
| 290 | |
| 291 | static void |
| 292 | XkbFreeIndicatorMaps(XkbDescPtr xkb) |
| 293 | { |
| 294 | if ((xkb != NULL) && (xkb->indicators != NULL)) { |
| 295 | free(xkb->indicators); |
| 296 | xkb->indicators = NULL; |
| 297 | } |
| 298 | return; |
| 299 | } |
| 300 | |
| 301 | /***====================================================================***/ |
| 302 | |
| 303 | XkbDescRec * |
| 304 | XkbAllocKeyboard(void) |
| 305 | { |
| 306 | XkbDescRec *xkb; |
| 307 | |
| 308 | xkb = calloc(1, sizeof(XkbDescRec)); |
| 309 | if (xkb) |
| 310 | xkb->device_spec = XkbUseCoreKbd; |
| 311 | return xkb; |
| 312 | } |
| 313 | |
| 314 | void |
| 315 | XkbFreeKeyboard(XkbDescPtr xkb, unsigned which, Bool freeAll) |
| 316 | { |
| 317 | if (xkb == NULL) |
| 318 | return; |
| 319 | if (freeAll) |
| 320 | which = XkbAllComponentsMask; |
| 321 | if (which & XkbClientMapMask) |
| 322 | XkbFreeClientMap(xkb, XkbAllClientInfoMask, TRUE); |
| 323 | if (which & XkbServerMapMask) |
| 324 | XkbFreeServerMap(xkb, XkbAllServerInfoMask, TRUE); |
| 325 | if (which & XkbCompatMapMask) |
| 326 | XkbFreeCompatMap(xkb, XkbAllCompatMask, TRUE); |
| 327 | if (which & XkbIndicatorMapMask) |
| 328 | XkbFreeIndicatorMaps(xkb); |
| 329 | if (which & XkbNamesMask) |
| 330 | XkbFreeNames(xkb, XkbAllNamesMask, TRUE); |
| 331 | if ((which & XkbGeometryMask) && (xkb->geom != NULL)) { |
| 332 | XkbFreeGeometry(xkb->geom, XkbGeomAllMask, TRUE); |
| 333 | /* PERHAPS BONGHITS etc */ |
| 334 | xkb->geom = NULL; |
| 335 | } |
| 336 | if (which & XkbControlsMask) |
| 337 | XkbFreeControls(xkb, XkbAllControlsMask, TRUE); |
| 338 | if (freeAll) |
| 339 | free(xkb); |
| 340 | return; |
| 341 | } |
| 342 | |
| 343 | /***====================================================================***/ |
| 344 | |
| 345 | void |
| 346 | XkbFreeComponentNames(XkbComponentNamesPtr names, Bool freeNames) |
| 347 | { |
| 348 | if (names) { |
| 349 | free(names->keycodes); |
| 350 | free(names->types); |
| 351 | free(names->compat); |
| 352 | free(names->symbols); |
| 353 | free(names->geometry); |
| 354 | memset(names, 0, sizeof(XkbComponentNamesRec)); |
| 355 | } |
| 356 | if (freeNames) |
| 357 | free(names); |
| 358 | } |