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.
This commit is contained in:
Daniel Stone 2006-11-02 00:45:23 +02:00 committed by Daniel Stone
parent d7d931abe0
commit d9a5e3e964

View File

@ -1082,28 +1082,39 @@ 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. */
continue;
dtype->level_names = tmp;
dtype->num_levels = stype->num_levels;
}
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;
}
dtype->name = stype->name;
memcpy(&dtype->mods, &stype->mods, sizeof(XkbModsRec));
if (stype->map_count) {
if (stype->map) {
if (dtype->map) {
if (stype->map_count != dtype->map_count) {
if (stype->map_count != dtype->map_count &&
dtype->map_count && dtype->map) {
tmp = xrealloc(dtype->map,
stype->map_count *
sizeof(XkbKTMapEntryRec));
@ -1111,8 +1122,7 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
return FALSE;
dtype->map = tmp;
}
}
else {
else if (!dtype->map_count || !dtype->map) {
tmp = xalloc(stype->map_count *
sizeof(XkbKTMapEntryRec));
if (!tmp)
@ -1120,14 +1130,13 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
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->map_count != dtype->map_count &&
dtype->map_count && dtype->preserve) {
tmp = xrealloc(dtype->preserve,
stype->map_count *
sizeof(XkbModsRec));
@ -1135,9 +1144,9 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
return FALSE;
dtype->preserve = tmp;
}
}
else {
tmp = xalloc(stype->map_count * sizeof(XkbModsRec));
else if (!dtype->preserve || !dtype->map_count) {
tmp = xalloc(stype->map_count *
sizeof(XkbModsRec));
if (!tmp)
return FALSE;
dtype->preserve = tmp;
@ -1146,11 +1155,19 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
memcpy(dtype->preserve, stype->preserve,
stype->map_count * sizeof(XkbModsRec));
}
else {
if (dtype->preserve) {
xfree(dtype->preserve);
dtype->preserve = NULL;
dtype->map_count = stype->map_count;
}
else {
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) {