aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/lib/src/xkb/XKBMAlloc.c
diff options
context:
space:
mode:
authorMihai Moldovan <ionic@ionic.de>2017-08-25 12:44:49 +0200
committerMihai Moldovan <ionic@ionic.de>2017-08-25 12:44:49 +0200
commitae0a2bfdeb9ceacb80aa03375353039d425b14b9 (patch)
treedaec55145477bcec69273e03d5c9ff10c10a4137 /nx-X11/lib/src/xkb/XKBMAlloc.c
parentcbe2c0e44f412d07024207f374c0f56684adb088 (diff)
parent3b7e5a42f5abecb903a9d730d163d704520efb07 (diff)
downloadnx-libs-ae0a2bfdeb9ceacb80aa03375353039d425b14b9.tar.gz
nx-libs-ae0a2bfdeb9ceacb80aa03375353039d425b14b9.tar.bz2
nx-libs-ae0a2bfdeb9ceacb80aa03375353039d425b14b9.zip
Merge branch 'sunweaver-pr/libnx-x11-autoreconf' into 3.6.x
Attributes GH PR #498: https://github.com/ArcticaProject/nx-libs/pull/498
Diffstat (limited to 'nx-X11/lib/src/xkb/XKBMAlloc.c')
-rw-r--r--nx-X11/lib/src/xkb/XKBMAlloc.c1016
1 files changed, 1016 insertions, 0 deletions
diff --git a/nx-X11/lib/src/xkb/XKBMAlloc.c b/nx-X11/lib/src/xkb/XKBMAlloc.c
new file mode 100644
index 000000000..2467a2024
--- /dev/null
+++ b/nx-X11/lib/src/xkb/XKBMAlloc.c
@@ -0,0 +1,1016 @@
+/************************************************************
+Copyright (c) 1993 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
+documentation, and that the name of Silicon Graphics not be
+used in advertising or publicity pertaining to distribution
+of the software without specific prior written permission.
+Silicon Graphics makes no representation about the suitability
+of this software for any purpose. It is provided "as is"
+without any express or implied warranty.
+
+SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+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
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+********************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include <stdio.h>
+#include "Xlibint.h"
+#include <nx-X11/extensions/XKBproto.h>
+#include <nx-X11/keysym.h>
+#include "XKBlibint.h"
+
+
+/***====================================================================***/
+
+Status
+XkbAllocClientMap(XkbDescPtr xkb, unsigned which, unsigned nTotalTypes)
+{
+ register int i;
+ XkbClientMapPtr map;
+
+ if ((xkb == NULL) ||
+ ((nTotalTypes > 0) && (nTotalTypes < XkbNumRequiredTypes)))
+ return BadValue;
+ if ((which & XkbKeySymsMask) &&
+ ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
+ (!XkbIsLegalKeycode(xkb->max_key_code)) ||
+ (xkb->max_key_code < xkb->min_key_code))) {
+#ifdef DEBUG
+ fprintf(stderr, "bad keycode (%d,%d) in XkbAllocClientMap\n",
+ xkb->min_key_code, xkb->max_key_code);
+#endif
+ return BadValue;
+ }
+
+ if (xkb->map == NULL) {
+ map = _XkbTypedCalloc(1, XkbClientMapRec);
+ if (map == NULL)
+ return BadAlloc;
+ xkb->map = map;
+ }
+ else
+ map = xkb->map;
+
+ if ((which & XkbKeyTypesMask) && (nTotalTypes > 0)) {
+ if (map->types == NULL) {
+ map->types = _XkbTypedCalloc(nTotalTypes, XkbKeyTypeRec);
+ if (map->types == NULL)
+ return BadAlloc;
+ map->num_types = 0;
+ map->size_types = nTotalTypes;
+ }
+ else if (map->size_types < nTotalTypes) {
+ XkbKeyTypeRec *prev_types = map->types;
+
+ map->types =
+ _XkbTypedRealloc(map->types, nTotalTypes, XkbKeyTypeRec);
+ if (map->types == NULL) {
+ _XkbFree(prev_types);
+ map->num_types = map->size_types = 0;
+ return BadAlloc;
+ }
+ map->size_types = nTotalTypes;
+ bzero(&map->types[map->num_types],
+ ((map->size_types - map->num_types) * sizeof(XkbKeyTypeRec)));
+ }
+ }
+ if (which & XkbKeySymsMask) {
+ int nKeys = XkbNumKeys(xkb);
+
+ if (map->syms == NULL) {
+ map->size_syms = (nKeys * 15) / 10;
+ map->syms = _XkbTypedCalloc(map->size_syms, KeySym);
+ if (!map->syms) {
+ map->size_syms = 0;
+ return BadAlloc;
+ }
+ map->num_syms = 1;
+ map->syms[0] = NoSymbol;
+ }
+ if (map->key_sym_map == NULL) {
+ i = xkb->max_key_code + 1;
+ map->key_sym_map = _XkbTypedCalloc(i, XkbSymMapRec);
+ if (map->key_sym_map == NULL)
+ return BadAlloc;
+ }
+ }
+ if (which & XkbModifierMapMask) {
+ if ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
+ (!XkbIsLegalKeycode(xkb->max_key_code)) ||
+ (xkb->max_key_code < xkb->min_key_code))
+ return BadMatch;
+ if (map->modmap == NULL) {
+ i = xkb->max_key_code + 1;
+ map->modmap = _XkbTypedCalloc(i, unsigned char);
+ if (map->modmap == NULL)
+ return BadAlloc;
+ }
+ }
+ return Success;
+}
+
+Status
+XkbAllocServerMap(XkbDescPtr xkb, unsigned which, unsigned nNewActions)
+{
+ register int i;
+ XkbServerMapPtr map;
+
+ if (xkb == NULL)
+ return BadMatch;
+ if (xkb->server == NULL) {
+ map = _XkbTypedCalloc(1, XkbServerMapRec);
+ if (map == NULL)
+ return BadAlloc;
+ for (i = 0; i < XkbNumVirtualMods; i++) {
+ map->vmods[i] = XkbNoModifierMask;
+ }
+ xkb->server = map;
+ }
+ else
+ map = xkb->server;
+ if (which & XkbExplicitComponentsMask) {
+ if ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
+ (!XkbIsLegalKeycode(xkb->max_key_code)) ||
+ (xkb->max_key_code < xkb->min_key_code))
+ return BadMatch;
+ if (map->explicit == NULL) {
+ i = xkb->max_key_code + 1;
+ map->explicit = _XkbTypedCalloc(i, unsigned char);
+ if (map->explicit == NULL)
+ return BadAlloc;
+ }
+ }
+ if (which & XkbKeyActionsMask) {
+ if ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
+ (!XkbIsLegalKeycode(xkb->max_key_code)) ||
+ (xkb->max_key_code < xkb->min_key_code))
+ return BadMatch;
+ if (nNewActions < 1)
+ nNewActions = 1;
+ if (map->acts == NULL) {
+ map->acts = _XkbTypedCalloc((nNewActions + 1), XkbAction);
+ if (map->acts == NULL)
+ return BadAlloc;
+ map->num_acts = 1;
+ map->size_acts = nNewActions + 1;
+ }
+ else if ((map->size_acts - map->num_acts) < nNewActions) {
+ unsigned need;
+ XkbAction *prev_acts = map->acts;
+
+ need = map->num_acts + nNewActions;
+ map->acts = _XkbTypedRealloc(map->acts, need, XkbAction);
+ if (map->acts == NULL) {
+ _XkbFree(prev_acts);
+ map->num_acts = map->size_acts = 0;
+ return BadAlloc;
+ }
+ map->size_acts = need;
+ bzero(&map->acts[map->num_acts],
+ ((map->size_acts - map->num_acts) * sizeof(XkbAction)));
+ }
+ if (map->key_acts == NULL) {
+ i = xkb->max_key_code + 1;
+ map->key_acts = _XkbTypedCalloc(i, unsigned short);
+ if (map->key_acts == NULL)
+ return BadAlloc;
+ }
+ }
+ if (which & XkbKeyBehaviorsMask) {
+ if ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
+ (!XkbIsLegalKeycode(xkb->max_key_code)) ||
+ (xkb->max_key_code < xkb->min_key_code))
+ return BadMatch;
+ if (map->behaviors == NULL) {
+ i = xkb->max_key_code + 1;
+ map->behaviors = _XkbTypedCalloc(i, XkbBehavior);
+ if (map->behaviors == NULL)
+ return BadAlloc;
+ }
+ }
+ if (which & XkbVirtualModMapMask) {
+ if ((!XkbIsLegalKeycode(xkb->min_key_code)) ||
+ (!XkbIsLegalKeycode(xkb->max_key_code)) ||
+ (xkb->max_key_code < xkb->min_key_code))
+ return BadMatch;
+ if (map->vmodmap == NULL) {
+ i = xkb->max_key_code + 1;
+ map->vmodmap = _XkbTypedCalloc(i, unsigned short);
+ if (map->vmodmap == NULL)
+ return BadAlloc;
+ }
+ }
+ return Success;
+}
+
+/***====================================================================***/
+
+Status
+XkbCopyKeyType(XkbKeyTypePtr from, XkbKeyTypePtr into)
+{
+ if ((!from) || (!into))
+ return BadMatch;
+
+ _XkbFree(into->map);
+ into->map = NULL;
+
+ _XkbFree(into->preserve);
+ into->preserve = NULL;
+
+ _XkbFree(into->level_names);
+ into->level_names = NULL;
+
+ *into = *from;
+ if ((from->map) && (into->map_count > 0)) {
+ into->map = _XkbTypedCalloc(into->map_count, XkbKTMapEntryRec);
+ if (!into->map)
+ return BadAlloc;
+ memcpy(into->map, from->map,
+ into->map_count * sizeof(XkbKTMapEntryRec));
+ }
+ if ((from->preserve) && (into->map_count > 0)) {
+ into->preserve = _XkbTypedCalloc(into->map_count, XkbModsRec);
+ if (!into->preserve)
+ return BadAlloc;
+ memcpy(into->preserve, from->preserve,
+ into->map_count * sizeof(XkbModsRec));
+ }
+ if ((from->level_names) && (into->num_levels > 0)) {
+ into->level_names = _XkbTypedCalloc(into->num_levels, Atom);
+ if (!into->level_names)
+ return BadAlloc;
+ memcpy(into->level_names, from->level_names,
+ into->num_levels * sizeof(Atom));
+ }
+ return Success;
+}
+
+Status
+XkbCopyKeyTypes(XkbKeyTypePtr from, XkbKeyTypePtr into, int num_types)
+{
+ register int i, rtrn;
+
+ if ((!from) || (!into) || (num_types < 0))
+ return BadMatch;
+ for (i = 0; i < num_types; i++) {
+ if ((rtrn = XkbCopyKeyType(from++, into++)) != Success)
+ return rtrn;
+ }
+ return Success;
+}
+
+XkbKeyTypePtr
+XkbAddKeyType(XkbDescPtr xkb,
+ Atom name,
+ int map_count,
+ Bool want_preserve,
+ int num_lvls)
+{
+ register int i;
+ unsigned tmp;
+ XkbKeyTypePtr type;
+ XkbClientMapPtr map;
+
+ if ((!xkb) || (num_lvls < 1))
+ return NULL;
+ map = xkb->map;
+ if ((map) && (map->types)) {
+ for (i = 0; i < map->num_types; i++) {
+ if (map->types[i].name == name) {
+ Status status =
+ XkbResizeKeyType(xkb, i, map_count, want_preserve,
+ num_lvls);
+ return (status == Success ? &map->types[i] : NULL);
+ }
+ }
+ }
+ if ((!map) || (!map->types) || (map->num_types < XkbNumRequiredTypes)) {
+ tmp = XkbNumRequiredTypes + 1;
+ if (XkbAllocClientMap(xkb, XkbKeyTypesMask, tmp) != Success)
+ return NULL;
+ if (!map)
+ map = xkb->map;
+ tmp = 0;
+ if (map->num_types <= XkbKeypadIndex)
+ tmp |= XkbKeypadMask;
+ if (map->num_types <= XkbAlphabeticIndex)
+ tmp |= XkbAlphabeticMask;
+ if (map->num_types <= XkbTwoLevelIndex)
+ tmp |= XkbTwoLevelMask;
+ if (map->num_types <= XkbOneLevelIndex)
+ tmp |= XkbOneLevelMask;
+ if (XkbInitCanonicalKeyTypes(xkb, tmp, XkbNoModifier) == Success) {
+ for (i = 0; i < map->num_types; i++) {
+ Status status;
+
+ if (map->types[i].name != name)
+ continue;
+ status = XkbResizeKeyType(xkb, i, map_count, want_preserve,
+ num_lvls);
+ return (status == Success ? &map->types[i] : NULL);
+ }
+ }
+ }
+ if ((map->num_types <= map->size_types) &&
+ (XkbAllocClientMap(xkb, XkbKeyTypesMask, map->num_types + 1) !=
+ Success)) {
+ return NULL;
+ }
+ type = &map->types[map->num_types];
+ map->num_types++;
+ bzero((char *) type, sizeof(XkbKeyTypeRec));
+ type->num_levels = num_lvls;
+ type->map_count = map_count;
+ type->name = name;
+ if (map_count > 0) {
+ type->map = _XkbTypedCalloc(map_count, XkbKTMapEntryRec);
+ if (!type->map) {
+ map->num_types--;
+ return NULL;
+ }
+ if (want_preserve) {
+ type->preserve = _XkbTypedCalloc(map_count, XkbModsRec);
+ if (!type->preserve) {
+ _XkbFree(type->map);
+ map->num_types--;
+ return NULL;
+ }
+ }
+ }
+ return type;
+}
+
+Status
+XkbResizeKeyType(XkbDescPtr xkb,
+ int type_ndx,
+ int map_count,
+ Bool want_preserve,
+ int new_num_lvls)
+{
+ XkbKeyTypePtr type;
+ KeyCode matchingKeys[XkbMaxKeyCount], nMatchingKeys;
+
+ if ((type_ndx < 0) || (type_ndx >= xkb->map->num_types) || (map_count < 0)
+ || (new_num_lvls < 1))
+ return BadValue;
+ switch (type_ndx) {
+ case XkbOneLevelIndex:
+ if (new_num_lvls != 1)
+ return BadMatch;
+ break;
+ case XkbTwoLevelIndex:
+ case XkbAlphabeticIndex:
+ case XkbKeypadIndex:
+ if (new_num_lvls != 2)
+ return BadMatch;
+ break;
+ }
+ type = &xkb->map->types[type_ndx];
+ if (map_count == 0) {
+ _XkbFree(type->map);
+ type->map = NULL;
+ _XkbFree(type->preserve);
+ type->preserve = NULL;
+ type->map_count = 0;
+ }
+ else {
+ XkbKTMapEntryRec *prev_map = type->map;
+
+ if ((map_count > type->map_count) || (type->map == NULL))
+ type->map =
+ _XkbTypedRealloc(type->map, map_count, XkbKTMapEntryRec);
+ if (!type->map) {
+ _XkbFree(prev_map);
+ return BadAlloc;
+ }
+ if (want_preserve) {
+ XkbModsRec *prev_preserve = type->preserve;
+
+ if ((map_count > type->map_count) || (type->preserve == NULL)) {
+ type->preserve = _XkbTypedRealloc(type->preserve, map_count,
+ XkbModsRec);
+ }
+ if (!type->preserve) {
+ _XkbFree(prev_preserve);
+ return BadAlloc;
+ }
+ }
+ else {
+ _XkbFree(type->preserve);
+ type->preserve = NULL;
+ }
+ type->map_count = map_count;
+ }
+
+ if ((new_num_lvls > type->num_levels) || (type->level_names == NULL)) {
+ Atom *prev_level_names = type->level_names;
+
+ type->level_names =
+ _XkbTypedRealloc(type->level_names, new_num_lvls, Atom);
+ if (!type->level_names) {
+ _XkbFree(prev_level_names);
+ return BadAlloc;
+ }
+ }
+ /*
+ * Here's the theory:
+ * If the width of the type changed, we might have to resize the symbol
+ * maps for any keys that use the type for one or more groups. This is
+ * expensive, so we'll try to cull out any keys that are obviously okay:
+ * In any case:
+ * - keys that have a group width <= the old width are okay (because
+ * they could not possibly have been associated with the old type)
+ * If the key type increased in size:
+ * - keys that already have a group width >= to the new width are okay
+ * + keys that have a group width >= the old width but < the new width
+ * might have to be enlarged.
+ * If the key type decreased in size:
+ * - keys that have a group width > the old width don't have to be
+ * resized (because they must have some other wider type associated
+ * with some group).
+ * + keys that have a group width == the old width might have to be
+ * shrunk.
+ * The possibilities marked with '+' require us to examine the key types
+ * associated with each group for the key.
+ */
+ bzero(matchingKeys, XkbMaxKeyCount * sizeof(KeyCode));
+ nMatchingKeys = 0;
+ if (new_num_lvls > type->num_levels) {
+ int nTotal;
+ KeySym *newSyms;
+ int width, match, nResize;
+ register int i, g, nSyms;
+
+ nResize = 0;
+ for (nTotal = 1, i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
+ width = XkbKeyGroupsWidth(xkb, i);
+ if (width < type->num_levels)
+ continue;
+ for (match = 0, g = XkbKeyNumGroups(xkb, i) - 1;
+ (g >= 0) && (!match); g--) {
+ if (XkbKeyKeyTypeIndex(xkb, i, g) == type_ndx) {
+ matchingKeys[nMatchingKeys++] = i;
+ match = 1;
+ }
+ }
+ if ((!match) || (width >= new_num_lvls))
+ nTotal += XkbKeyNumSyms(xkb, i);
+ else {
+ nTotal += XkbKeyNumGroups(xkb, i) * new_num_lvls;
+ nResize++;
+ }
+ }
+ if (nResize > 0) {
+ int nextMatch;
+
+ xkb->map->size_syms = (nTotal * 12) / 10;
+ newSyms = _XkbTypedCalloc(xkb->map->size_syms, KeySym);
+ if (newSyms == NULL)
+ return BadAlloc;
+ nextMatch = 0;
+ nSyms = 1;
+ for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
+ if (matchingKeys[nextMatch] == i) {
+ KeySym *pOld;
+
+ nextMatch++;
+ width = XkbKeyGroupsWidth(xkb, i);
+ pOld = XkbKeySymsPtr(xkb, i);
+ for (g = XkbKeyNumGroups(xkb, i) - 1; g >= 0; g--) {
+ memcpy(&newSyms[nSyms + (new_num_lvls * g)],
+ &pOld[width * g], width * sizeof(KeySym));
+ }
+ xkb->map->key_sym_map[i].offset = nSyms;
+ nSyms += XkbKeyNumGroups(xkb, i) * new_num_lvls;
+ }
+ else {
+ memcpy(&newSyms[nSyms], XkbKeySymsPtr(xkb, i),
+ XkbKeyNumSyms(xkb, i) * sizeof(KeySym));
+ xkb->map->key_sym_map[i].offset = nSyms;
+ nSyms += XkbKeyNumSyms(xkb, i);
+ }
+ }
+ type->num_levels = new_num_lvls;
+ _XkbFree(xkb->map->syms);
+ xkb->map->syms = newSyms;
+ xkb->map->num_syms = nSyms;
+ return Success;
+ }
+ }
+ else if (new_num_lvls < type->num_levels) {
+ int width, match;
+ register int g, i;
+
+ for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
+ width = XkbKeyGroupsWidth(xkb, i);
+ if (width < type->num_levels)
+ continue;
+ for (match = 0, g = XkbKeyNumGroups(xkb, i) - 1;
+ (g >= 0) && (!match); g--) {
+ if (XkbKeyKeyTypeIndex(xkb, i, g) == type_ndx) {
+ matchingKeys[nMatchingKeys++] = i;
+ match = 1;
+ }
+ }
+ }
+ }
+ if (nMatchingKeys > 0) {
+ int key, firstClear;
+ register int i, g;
+
+ if (new_num_lvls > type->num_levels)
+ firstClear = type->num_levels;
+ else
+ firstClear = new_num_lvls;
+ for (i = 0; i < nMatchingKeys; i++) {
+ KeySym *pSyms;
+ int width, nClear;
+
+ key = matchingKeys[i];
+ width = XkbKeyGroupsWidth(xkb, key);
+ nClear = width - firstClear;
+ pSyms = XkbKeySymsPtr(xkb, key);
+ for (g = XkbKeyNumGroups(xkb, key) - 1; g >= 0; g--) {
+ if (XkbKeyKeyTypeIndex(xkb, key, g) == type_ndx) {
+ if (nClear > 0)
+ bzero(&pSyms[g * width + firstClear],
+ nClear * sizeof(KeySym));
+ }
+ }
+ }
+ }
+ type->num_levels = new_num_lvls;
+ return Success;
+}
+
+KeySym *
+XkbResizeKeySyms(XkbDescPtr xkb, int key, int needed)
+{
+ register int i, nSyms, nKeySyms;
+ unsigned nOldSyms;
+ KeySym *newSyms;
+
+ if (needed == 0) {
+ xkb->map->key_sym_map[key].offset = 0;
+ return xkb->map->syms;
+ }
+ nOldSyms = XkbKeyNumSyms(xkb, key);
+ if (nOldSyms >= (unsigned) needed) {
+ return XkbKeySymsPtr(xkb, key);
+ }
+ if (xkb->map->size_syms - xkb->map->num_syms >= (unsigned) needed) {
+ if (nOldSyms > 0) {
+ memcpy(&xkb->map->syms[xkb->map->num_syms], XkbKeySymsPtr(xkb, key),
+ nOldSyms * sizeof(KeySym));
+ }
+ if ((needed - nOldSyms) > 0) {
+ bzero(&xkb->map->syms[xkb->map->num_syms + XkbKeyNumSyms(xkb, key)],
+ (needed - nOldSyms) * sizeof(KeySym));
+ }
+ xkb->map->key_sym_map[key].offset = xkb->map->num_syms;
+ xkb->map->num_syms += needed;
+ return &xkb->map->syms[xkb->map->key_sym_map[key].offset];
+ }
+ xkb->map->size_syms += (needed > 32 ? needed : 32);
+ newSyms = _XkbTypedCalloc(xkb->map->size_syms, KeySym);
+ if (newSyms == NULL)
+ return NULL;
+ newSyms[0] = NoSymbol;
+ nSyms = 1;
+ for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) {
+ int nCopy;
+
+ nCopy = nKeySyms = XkbKeyNumSyms(xkb, i);
+ if ((nKeySyms == 0) && (i != key))
+ continue;
+ if (i == key)
+ nKeySyms = needed;
+ if (nCopy != 0)
+ memcpy(&newSyms[nSyms], XkbKeySymsPtr(xkb, i),
+ nCopy * sizeof(KeySym));
+ if (nKeySyms > nCopy)
+ bzero(&newSyms[nSyms + nCopy], (nKeySyms - nCopy) * sizeof(KeySym));
+ xkb->map->key_sym_map[i].offset = nSyms;
+ nSyms += nKeySyms;
+ }
+ _XkbFree(xkb->map->syms);
+ xkb->map->syms = newSyms;
+ xkb->map->num_syms = nSyms;
+ return &xkb->map->syms[xkb->map->key_sym_map[key].offset];
+}
+
+static unsigned
+_ExtendRange(unsigned int old_flags,
+ unsigned int flag,
+ KeyCode newKC,
+ KeyCode *old_min,
+ unsigned char *old_num)
+{
+ if ((old_flags & flag) == 0) {
+ old_flags |= flag;
+ *old_min = newKC;
+ *old_num = 1;
+ }
+ else {
+ int last = (*old_min) + (*old_num) - 1;
+
+ if (newKC < *old_min) {
+ *old_min = newKC;
+ *old_num = (last - newKC) + 1;
+ }
+ else if (newKC > last) {
+ *old_num = (newKC - (*old_min)) + 1;
+ }
+ }
+ return old_flags;
+}
+
+Status
+XkbChangeKeycodeRange(XkbDescPtr xkb,
+ int minKC,
+ int maxKC,
+ XkbChangesPtr changes)
+{
+ int tmp;
+
+ if ((!xkb) || (minKC < XkbMinLegalKeyCode) || (maxKC > XkbMaxLegalKeyCode))
+ return BadValue;
+ if (minKC > maxKC)
+ return BadMatch;
+ if (minKC < xkb->min_key_code) {
+ if (changes)
+ changes->map.min_key_code = minKC;
+ tmp = xkb->min_key_code - minKC;
+ if (xkb->map) {
+ if (xkb->map->key_sym_map) {
+ bzero((char *) &xkb->map->key_sym_map[minKC],
+ tmp * sizeof(XkbSymMapRec));
+ if (changes) {
+ changes->map.changed = _ExtendRange(changes->map.changed,
+ XkbKeySymsMask, minKC,
+ &changes->map.first_key_sym,
+ &changes->map.num_key_syms);
+ }
+ }
+ if (xkb->map->modmap) {
+ bzero((char *) &xkb->map->modmap[minKC], tmp);
+ if (changes) {
+ changes->map.changed = _ExtendRange(changes->map.changed,
+ XkbModifierMapMask, minKC,
+ &changes->map.first_modmap_key,
+ &changes->map.num_modmap_keys);
+ }
+ }
+ }
+ if (xkb->server) {
+ if (xkb->server->behaviors) {
+ bzero((char *) &xkb->server->behaviors[minKC],
+ tmp * sizeof(XkbBehavior));
+ if (changes) {
+ changes->map.changed = _ExtendRange(changes->map.changed,
+ XkbKeyBehaviorsMask, minKC,
+ &changes->map.first_key_behavior,
+ &changes->map.num_key_behaviors);
+ }
+ }
+ if (xkb->server->key_acts) {
+ bzero((char *) &xkb->server->key_acts[minKC],
+ tmp * sizeof(unsigned short));
+ if (changes) {
+ changes->map.changed = _ExtendRange(changes->map.changed,
+ XkbKeyActionsMask, minKC,
+ &changes->map.first_key_act,
+ &changes->map.num_key_acts);
+ }
+ }
+ if (xkb->server->vmodmap) {
+ bzero((char *) &xkb->server->vmodmap[minKC],
+ tmp * sizeof(unsigned short));
+ if (changes) {
+ changes->map.changed = _ExtendRange(changes->map.changed,
+ XkbVirtualModMapMask, minKC,
+ &changes->map.first_modmap_key,
+ &changes->map.num_vmodmap_keys);
+ }
+ }
+ }
+ if ((xkb->names) && (xkb->names->keys)) {
+ bzero((char *) &xkb->names->keys[minKC],
+ tmp * sizeof(XkbKeyNameRec));
+ if (changes) {
+ changes->names.changed = _ExtendRange(changes->names.changed,
+ XkbKeyNamesMask, minKC,
+ &changes->names.first_key,
+ &changes->names.num_keys);
+ }
+ }
+ xkb->min_key_code = minKC;
+ }
+ if (maxKC > xkb->max_key_code) {
+ if (changes)
+ changes->map.max_key_code = maxKC;
+ tmp = maxKC - xkb->max_key_code;
+ if (xkb->map) {
+ if (xkb->map->key_sym_map) {
+ XkbSymMapRec *prev_key_sym_map = xkb->map->key_sym_map;
+
+ xkb->map->key_sym_map = _XkbTypedRealloc(xkb->map->key_sym_map,
+ (maxKC + 1), XkbSymMapRec);
+ if (!xkb->map->key_sym_map) {
+ _XkbFree(prev_key_sym_map);
+ return BadAlloc;
+ }
+#ifdef NXAGENT_SERVER
+ bzero((char *) &xkb->map->key_sym_map[xkb->max_key_code + 1],
+ tmp * sizeof(XkbSymMapRec));
+#else
+ bzero((char *) &xkb->map->key_sym_map[xkb->max_key_code],
+ tmp * sizeof(XkbSymMapRec));
+#endif
+ if (changes) {
+ changes->map.changed = _ExtendRange(changes->map.changed,
+ XkbKeySymsMask, maxKC,
+ &changes->map.first_key_sym,
+ &changes->map.num_key_syms);
+ }
+ }
+ if (xkb->map->modmap) {
+ unsigned char *prev_modmap = xkb->map->modmap;
+
+ xkb->map->modmap = _XkbTypedRealloc(xkb->map->modmap,
+ (maxKC + 1), unsigned char);
+ if (!xkb->map->modmap) {
+ _XkbFree(prev_modmap);
+ return BadAlloc;
+ }
+#ifdef NXAGENT_SERVER
+ bzero((char *) &xkb->map->modmap[xkb->max_key_code + 1], tmp);
+#else
+ bzero((char *) &xkb->map->modmap[xkb->max_key_code], tmp);
+#endif
+ if (changes) {
+ changes->map.changed = _ExtendRange(changes->map.changed,
+ XkbModifierMapMask, maxKC,
+ &changes->map.first_modmap_key,
+ &changes->map.num_modmap_keys);
+ }
+ }
+ }
+ if (xkb->server) {
+ if (xkb->server->behaviors) {
+ XkbBehavior *prev_behaviors = xkb->server->behaviors;
+
+ xkb->server->behaviors =
+ _XkbTypedRealloc(xkb->server->behaviors, (maxKC + 1),
+ XkbBehavior);
+ if (!xkb->server->behaviors) {
+ _XkbFree(prev_behaviors);
+ return BadAlloc;
+ }
+#ifdef NXAGENT_SERVER
+ bzero((char *) &xkb->server->behaviors[xkb->max_key_code + 1],
+ tmp * sizeof(XkbBehavior));
+#else
+ bzero((char *) &xkb->server->behaviors[xkb->max_key_code],
+ tmp * sizeof(XkbBehavior));
+#endif
+ if (changes) {
+ changes->map.changed = _ExtendRange(changes->map.changed,
+ XkbKeyBehaviorsMask, maxKC,
+ &changes->map.first_key_behavior,
+ &changes->map.num_key_behaviors);
+ }
+ }
+ if (xkb->server->key_acts) {
+ unsigned short *prev_key_acts = xkb->server->key_acts;
+
+ xkb->server->key_acts = _XkbTypedRealloc(xkb->server->key_acts,
+ (maxKC + 1), unsigned short);
+ if (!xkb->server->key_acts) {
+ _XkbFree(prev_key_acts);
+ return BadAlloc;
+ }
+#ifdef NXAGENT_SERVER
+ bzero((char *) &xkb->server->key_acts[xkb->max_key_code + 1],
+ tmp * sizeof(unsigned short));
+#else
+ bzero((char *) &xkb->server->key_acts[xkb->max_key_code],
+ tmp * sizeof(unsigned short));
+#endif
+ if (changes) {
+ changes->map.changed = _ExtendRange(changes->map.changed,
+ XkbKeyActionsMask, maxKC,
+ &changes->map.first_key_act,
+ &changes->map.num_key_acts);
+ }
+ }
+ if (xkb->server->vmodmap) {
+ unsigned short *prev_vmodmap = xkb->server->vmodmap;
+
+ xkb->server->vmodmap = _XkbTypedRealloc(xkb->server->vmodmap,
+ (maxKC + 1), unsigned short);
+ if (!xkb->server->vmodmap) {
+ _XkbFree(prev_vmodmap);
+ return BadAlloc;
+ }
+#ifdef NXAGENT_SERVER
+ bzero((char *) &xkb->server->vmodmap[xkb->max_key_code + 1],
+ tmp * sizeof(unsigned short));
+#else
+ bzero((char *) &xkb->server->vmodmap[xkb->max_key_code],
+ tmp * sizeof(unsigned short));
+#endif
+ if (changes) {
+ changes->map.changed = _ExtendRange(changes->map.changed,
+ XkbVirtualModMapMask, maxKC,
+ &changes->map.first_modmap_key,
+ &changes->map.num_vmodmap_keys);
+ }
+ }
+ }
+ if ((xkb->names) && (xkb->names->keys)) {
+ XkbKeyNameRec *prev_keys = xkb->names->keys;
+
+ xkb->names->keys = _XkbTypedRealloc(xkb->names->keys,
+ (maxKC + 1), XkbKeyNameRec);
+ if (!xkb->names->keys) {
+ _XkbFree(prev_keys);
+ return BadAlloc;
+ }
+#ifdef NXAGENT_SERVER
+ bzero((char *) &xkb->names->keys[xkb->max_key_code + 1],
+ tmp * sizeof(XkbKeyNameRec));
+#else
+ bzero((char *) &xkb->names->keys[xkb->max_key_code],
+ tmp * sizeof(XkbKeyNameRec));
+#endif
+ if (changes) {
+ changes->names.changed = _ExtendRange(changes->names.changed,
+ XkbKeyNamesMask, maxKC,
+ &changes->names.first_key,
+ &changes->names.num_keys);
+ }
+ }
+ xkb->max_key_code = maxKC;
+ }
+ return Success;
+}
+
+XkbAction *
+XkbResizeKeyActions(XkbDescPtr xkb, int key, int needed)
+{
+ register int i, nActs;
+ XkbAction *newActs;
+
+ if (needed == 0) {
+ xkb->server->key_acts[key] = 0;
+ return NULL;
+ }
+ if (XkbKeyHasActions(xkb, key) &&
+ (XkbKeyNumSyms(xkb, key) >= (unsigned) needed))
+ return XkbKeyActionsPtr(xkb, key);
+ if (xkb->server->size_acts - xkb->server->num_acts >= (unsigned) needed) {
+ xkb->server->key_acts[key] = xkb->server->num_acts;
+ xkb->server->num_acts += needed;
+ return &xkb->server->acts[xkb->server->key_acts[key]];
+ }
+ xkb->server->size_acts = xkb->server->num_acts + needed + 8;
+ newActs = _XkbTypedCalloc(xkb->server->size_acts, XkbAction);
+ if (newActs == NULL)
+ return NULL;
+ newActs[0].type = XkbSA_NoAction;
+ nActs = 1;
+ for (i = xkb->min_key_code; i <= (int) xkb->max_key_code; i++) {
+ int nKeyActs, nCopy;
+
+ if ((xkb->server->key_acts[i] == 0) && (i != key))
+ continue;
+
+ nCopy = nKeyActs = XkbKeyNumActions(xkb, i);
+ if (i == key) {
+ nKeyActs = needed;
+ if (needed < nCopy)
+ nCopy = needed;
+ }
+
+ if (nCopy > 0)
+ memcpy(&newActs[nActs], XkbKeyActionsPtr(xkb, i),
+ nCopy * sizeof(XkbAction));
+ if (nCopy < nKeyActs)
+ bzero(&newActs[nActs + nCopy],
+ (nKeyActs - nCopy) * sizeof(XkbAction));
+ xkb->server->key_acts[i] = nActs;
+ nActs += nKeyActs;
+ }
+ _XkbFree(xkb->server->acts);
+ xkb->server->acts = newActs;
+ xkb->server->num_acts = nActs;
+ return &xkb->server->acts[xkb->server->key_acts[key]];
+}
+
+void
+XkbFreeClientMap(XkbDescPtr xkb, unsigned what, Bool freeMap)
+{
+ XkbClientMapPtr map;
+
+ if ((xkb == NULL) || (xkb->map == NULL))
+ return;
+ if (freeMap)
+ what = XkbAllClientInfoMask;
+ map = xkb->map;
+ if (what & XkbKeyTypesMask) {
+ if (map->types != NULL) {
+ if (map->num_types > 0) {
+ register int i;
+ XkbKeyTypePtr type;
+
+ for (i = 0, type = map->types; i < map->num_types; i++, type++) {
+ _XkbFree(type->map);
+ type->map = NULL;
+
+ _XkbFree(type->preserve);
+ type->preserve = NULL;
+
+ type->map_count = 0;
+
+ _XkbFree(type->level_names);
+ type->level_names = NULL;
+ }
+ }
+ _XkbFree(map->types);
+ map->num_types = map->size_types = 0;
+ map->types = NULL;
+ }
+ }
+ if (what & XkbKeySymsMask) {
+ _XkbFree(map->key_sym_map);
+ map->key_sym_map = NULL;
+
+ _XkbFree(map->syms);
+ map->size_syms = map->num_syms = 0;
+ map->syms = NULL;
+ }
+ if (what & XkbModifierMapMask) {
+ _XkbFree(map->modmap);
+ map->modmap = NULL;
+ }
+ if (freeMap) {
+ _XkbFree(xkb->map);
+ xkb->map = NULL;
+ }
+ return;
+}
+
+void
+XkbFreeServerMap(XkbDescPtr xkb, unsigned what, Bool freeMap)
+{
+ XkbServerMapPtr map;
+
+ if ((xkb == NULL) || (xkb->server == NULL))
+ return;
+ if (freeMap)
+ what = XkbAllServerInfoMask;
+ map = xkb->server;
+ if (what & XkbExplicitComponentsMask) {
+ _XkbFree(map->explicit);
+ map->explicit = NULL;
+ }
+ if (what & XkbKeyActionsMask) {
+ _XkbFree(map->key_acts);
+ map->key_acts = NULL;
+
+ _XkbFree(map->acts);
+ map->num_acts = map->size_acts = 0;
+ map->acts = NULL;
+ }
+ if (what & XkbKeyBehaviorsMask) {
+ _XkbFree(map->behaviors);
+ map->behaviors = NULL;
+ }
+ if (what & XkbVirtualModMapMask) {
+ _XkbFree(map->vmodmap);
+ map->vmodmap = NULL;
+ }
+
+ if (freeMap) {
+ _XkbFree(xkb->server);
+ xkb->server = NULL;
+ }
+ return;
+}