summaryrefslogtreecommitdiff
path: root/xkb/xkbUtils.c
diff options
context:
space:
mode:
authorDaniel Stone <daniel@fooishbar.org>2006-11-02 00:45:23 +0200
committerDaniel Stone <daniels@endtroducing.fooishbar.org>2006-11-02 00:45:23 +0200
commitd9a5e3e964b6c91fbca88b50674fce9660b972a4 (patch)
treec2d181c0a18e2ddfb4b7bedf07ec50921d6a5e44 /xkb/xkbUtils.c
parentd7d931abe01a8cf555b027f2bcfcccd5e9053e52 (diff)
XkbCopyKeymap: be more careful with levels, allocate compat/geom
Take various extra precautions with copying levels across (thanks Chris Lee for a gdb session), including allocating when we don't already have a coherent map. Only free type components if they're present. Allocate geometry and compat components if we don't already have them in the dest map.
Diffstat (limited to 'xkb/xkbUtils.c')
-rw-r--r--xkb/xkbUtils.c111
1 files changed, 70 insertions, 41 deletions
diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c
index 0c1ac9cde..627ab20f9 100644
--- a/xkb/xkbUtils.c
+++ b/xkb/xkbUtils.c
@@ -1082,52 +1082,61 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
stype = src->map->types;
dtype = dst->map->types;
for (i = 0; i < src->map->num_types; i++, dtype++, stype++) {
- if (stype->num_levels != dtype->num_levels) {
- if (dtype->level_names)
+ if (stype->num_levels) {
+ if (stype->num_levels != dtype->num_levels &&
+ dtype->num_levels && dtype->level_names) {
tmp = xrealloc(dtype->level_names,
stype->num_levels * sizeof(Atom));
- else
+ if (!tmp)
+ continue;
+ dtype->level_names = tmp;
+ }
+ else if (!dtype->num_levels || !dtype->level_names) {
tmp = xalloc(stype->num_levels * sizeof(Atom));
- if (!tmp)
- continue; /* don't return FALSE here, try to whack
- all the pointers we can, so we don't
- double-free when going down. */
- dtype->level_names = tmp;
+ if (!tmp)
+ continue;
+ dtype->level_names = tmp;
+ }
dtype->num_levels = stype->num_levels;
+ memcpy(dtype->level_names, stype->level_names,
+ stype->num_levels * sizeof(Atom));
+ }
+ else {
+ if (dtype->num_levels && dtype->level_names)
+ xfree(dtype->level_names);
+ dtype->num_levels = 0;
+ dtype->level_names = NULL;
}
- memcpy(dtype->level_names, stype->level_names,
- stype->num_levels * sizeof(Atom));
dtype->name = stype->name;
memcpy(&dtype->mods, &stype->mods, sizeof(XkbModsRec));
- if (stype->map) {
- if (dtype->map) {
- if (stype->map_count != dtype->map_count) {
+ if (stype->map_count) {
+ if (stype->map) {
+ if (stype->map_count != dtype->map_count &&
+ dtype->map_count && dtype->map) {
tmp = xrealloc(dtype->map,
stype->map_count *
sizeof(XkbKTMapEntryRec));
if (!tmp)
return FALSE;
dtype->map = tmp;
+ }
+ else if (!dtype->map_count || !dtype->map) {
+ tmp = xalloc(stype->map_count *
+ sizeof(XkbKTMapEntryRec));
+ if (!tmp)
+ return FALSE;
+ dtype->map = tmp;
}
- }
- else {
- tmp = xalloc(stype->map_count *
- sizeof(XkbKTMapEntryRec));
- if (!tmp)
- return FALSE;
- dtype->map = tmp;
- }
- dtype->map_count = stype->map_count;
- memcpy(dtype->map, stype->map, stype->map_count *
- sizeof(XkbKTMapEntryRec));
- }
+ memcpy(dtype->map, stype->map,
+ stype->map_count * sizeof(XkbKTMapEntryRec));
+ }
- if (stype->preserve) {
- if (dtype->preserve) {
- if (stype->map_count != dtype->map_count) {
+ if (stype->preserve) {
+ if (stype->map_count != dtype->map_count &&
+ dtype->map_count && dtype->preserve) {
tmp = xrealloc(dtype->preserve,
stype->map_count *
sizeof(XkbModsRec));
@@ -1135,22 +1144,30 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
return FALSE;
dtype->preserve = tmp;
}
- }
- else {
- tmp = xalloc(stype->map_count * sizeof(XkbModsRec));
- if (!tmp)
- return FALSE;
- dtype->preserve = tmp;
+ else if (!dtype->preserve || !dtype->map_count) {
+ tmp = xalloc(stype->map_count *
+ sizeof(XkbModsRec));
+ if (!tmp)
+ return FALSE;
+ dtype->preserve = tmp;
+ }
+
+ memcpy(dtype->preserve, stype->preserve,
+ stype->map_count * sizeof(XkbModsRec));
}
- memcpy(dtype->preserve, stype->preserve,
- stype->map_count * sizeof(XkbModsRec));
+ dtype->map_count = stype->map_count;
}
else {
- if (dtype->preserve) {
- xfree(dtype->preserve);
- dtype->preserve = NULL;
+ if (dtype->map_count) {
+ if (dtype->map)
+ xfree(dtype->map);
+ if (dtype->preserve)
+ xfree(dtype->preserve);
+ dtype->map_count = 0;
}
+ dtype->map = NULL;
+ dtype->preserve = NULL;
}
}
}
@@ -1160,9 +1177,9 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
i++, dtype++) {
if (dtype->level_names)
xfree(dtype->level_names);
- if (dtype->map)
+ if (dtype->map && dtype->map_count)
xfree(dtype->map);
- if (dtype->preserve)
+ if (dtype->preserve && dtype->preserve)
xfree(dtype->preserve);
}
xfree(dst->map->types);
@@ -1451,6 +1468,12 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
/* compat */
if (src->compat) {
+ if (!dst->compat) {
+ dst->compat = xcalloc(1, sizeof(XkbCompatMapRec));
+ if (!dst->compat)
+ return FALSE;
+ }
+
if (src->compat->sym_interpret) {
if (src->compat->size_si != dst->compat->size_si) {
if (dst->compat->sym_interpret)
@@ -1486,6 +1509,12 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
/* geometry */
if (src->geom) {
+ if (!dst->geom) {
+ dst->geom = xcalloc(sizeof(XkbGeometryRec), 1);
+ if (!dst->geom)
+ return FALSE;
+ }
+
/* properties */
if (src->geom->num_properties) {
if (src->geom->num_properties != dst->geom->sz_properties) {