diff --git a/include/X11/XkbCommon.h b/include/X11/XkbCommon.h index 416817d..afde5ad 100644 --- a/include/X11/XkbCommon.h +++ b/include/X11/XkbCommon.h @@ -32,6 +32,7 @@ authorization from the authors. #include #include #include +#include /* Common keyboard description structure */ typedef struct _XkbcDesc { @@ -56,4 +57,93 @@ XkbcKeysymToString(KeySym ks); extern KeySym XkbcStringToKeysym(const char *s); +extern int +XkbcAllocCompatMap(XkbcDescPtr xkb, unsigned which, unsigned nSI); + +extern void +XkbcFreeCompatMap(XkbcDescPtr xkb, unsigned which, Bool freeMap); + +extern int +XkbcAllocNames(XkbcDescPtr xkb, unsigned which, int nTotalRG, int nTotalAliases); + +extern void +XkbcFreeNames(XkbcDescPtr xkb, unsigned which, Bool freeMap); + +extern int +XkbcAllocControls(XkbcDescPtr xkb, unsigned which); + +extern void +XkbcFreeControls(XkbcDescPtr xkb, unsigned which, Bool freeMap); + +extern int +XkbcAllocIndicatorMaps(XkbcDescPtr xkb); + +extern void +XkbcFreeIndicatorMaps(XkbcDescPtr xkb); + +extern XkbcDescRec * +XkbcAllocKeyboard(void); + +extern int +XkbcAllocClientMap(XkbcDescPtr xkb, unsigned which, unsigned nTotalTypes); + +extern int +XkbcAllocServerMap(XkbcDescPtr xkb, unsigned which, unsigned nNewActions); + +extern void +XkbcFreeClientMap(XkbcDescPtr xkb, unsigned what, Bool freeMap); + +extern void +XkbcFreeServerMap(XkbcDescPtr xkb, unsigned what, Bool freeMap); + +extern void +XkbcFreeKeyboard(XkbcDescPtr xkb, unsigned which, Bool freeAll); + +extern void +XkbcFreeGeomProperties(XkbGeometryPtr geom, int first, int count, Bool freeAll); + +extern void +XkbcFreeGeomKeyAliases(XkbGeometryPtr geom, int first, int count, Bool freeAll); + +extern void +XkbcFreeGeomColors(XkbGeometryPtr geom, int first, int count, Bool freeAll); + +extern void +XkbcFreeGeomPoints(XkbOutlinePtr outline, int first, int count, Bool freeAll); + +extern void +XkbcFreeGeomOutlines(XkbShapePtr shape, int first, int count, Bool freeAll); + +extern void +XkbcFreeGeomShapes(XkbGeometryPtr geom, int first, int count, Bool freeAll); + +extern void +XkbcFreeGeomOverlayKeys(XkbOverlayRowPtr row, int first, int count, + Bool freeAll); + +extern void +XkbcFreeGeomOverlayRows(XkbOverlayPtr overlay, int first, int count, + Bool freeAll); + +extern void +XkbcFreeGeomOverlays(XkbSectionPtr section, int first, int count, Bool freeAll); + +extern void +XkbcFreeGeomKeys(XkbRowPtr row, int first, int count, Bool freeAll); + +extern void +XkbcFreeGeomRows(XkbSectionPtr section, int first, int count, Bool freeAll); + +extern void +XkbcFreeGeomSections(XkbGeometryPtr geom, int first, int count, Bool freeAll); + +extern void +XkbcFreeGeomDoodads(XkbDoodadPtr doodads, int nDoodads, Bool freeAll); + +extern void +XkbcFreeGeometry(XkbGeometryPtr geom, unsigned which, Bool freeMap); + +extern int +XkbcAllocGeometry(XkbcDescPtr xkb, XkbGeometrySizesPtr sizes); + #endif /* _XKBCOMMON_H_ */ diff --git a/src/Makefile.am b/src/Makefile.am index 4681034..3a0b2fa 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -16,4 +16,6 @@ lib_LTLIBRARIES = libxkbcommon.la libxkbcommon_la_SOURCES = \ XkbCommonInt.h \ ks_tables.h \ + alloc.c \ + galloc.c \ keysym.c diff --git a/src/alloc.c b/src/alloc.c new file mode 100644 index 0000000..dadf4e2 --- /dev/null +++ b/src/alloc.c @@ -0,0 +1,589 @@ +/* +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 +#endif +#include "X11/XkbCommon.h" +#include "XkbCommonInt.h" +#include +#include +#include + +int +XkbcAllocCompatMap(XkbcDescPtr xkb,unsigned which,unsigned nSI) +{ +XkbCompatMapPtr compat; +XkbSymInterpretRec *prev_interpret; + + if (!xkb) + return BadMatch; + if (xkb->compat) { + if (xkb->compat->size_si>=nSI) + return Success; + compat= xkb->compat; + compat->size_si= nSI; + if (compat->sym_interpret==NULL) + compat->num_si= 0; + prev_interpret = compat->sym_interpret; + compat->sym_interpret= _XkbTypedRealloc(compat->sym_interpret, + nSI,XkbSymInterpretRec); + if (compat->sym_interpret==NULL) { + _XkbFree(prev_interpret); + compat->size_si= compat->num_si= 0; + return BadAlloc; + } + if (compat->num_si!=0) { + _XkbClearElems(compat->sym_interpret,compat->num_si, + compat->size_si-1,XkbSymInterpretRec); + } + return Success; + } + compat= _XkbTypedCalloc(1,XkbCompatMapRec); + if (compat==NULL) + return BadAlloc; + if (nSI>0) { + compat->sym_interpret= _XkbTypedCalloc(nSI,XkbSymInterpretRec); + if (!compat->sym_interpret) { + _XkbFree(compat); + return BadAlloc; + } + } + compat->size_si= nSI; + compat->num_si= 0; + bzero((char *)&compat->groups[0],XkbNumKbdGroups*sizeof(XkbModsRec)); + xkb->compat= compat; + return Success; +} + + +void +XkbcFreeCompatMap(XkbcDescPtr xkb,unsigned which,Bool freeMap) +{ +register XkbCompatMapPtr compat; + + if ((xkb==NULL)||(xkb->compat==NULL)) + return; + compat= xkb->compat; + if (freeMap) + which= XkbAllCompatMask; + if (which&XkbGroupCompatMask) + bzero((char *)&compat->groups[0],XkbNumKbdGroups*sizeof(XkbModsRec)); + if (which&XkbSymInterpMask) { + if ((compat->sym_interpret)&&(compat->size_si>0)) + _XkbFree(compat->sym_interpret); + compat->size_si= compat->num_si= 0; + compat->sym_interpret= NULL; + } + if (freeMap) { + _XkbFree(compat); + xkb->compat= NULL; + } + return; +} + +int +XkbcAllocNames(XkbcDescPtr xkb,unsigned which,int nTotalRG,int nTotalAliases) +{ +XkbNamesPtr names; + + if (xkb==NULL) + return BadMatch; + if (xkb->names==NULL) { + xkb->names = _XkbTypedCalloc(1,XkbNamesRec); + if (xkb->names==NULL) + return BadAlloc; + } + names= xkb->names; + if ((which&XkbKTLevelNamesMask)&&(xkb->map!=NULL)&&(xkb->map->types!=NULL)){ + register int i; + XkbKeyTypePtr type; + + type= xkb->map->types; + for (i=0;imap->num_types;i++,type++) { + if (type->level_names==NULL) { + type->level_names= _XkbTypedCalloc(type->num_levels,Atom); + if (type->level_names==NULL) + return BadAlloc; + } + } + } + if ((which&XkbKeyNamesMask)&&(names->keys==NULL)) { + if ((!XkbIsLegalKeycode(xkb->min_key_code))|| + (!XkbIsLegalKeycode(xkb->max_key_code))|| + (xkb->max_key_codemin_key_code)) + return BadValue; + names->keys= _XkbTypedCalloc((xkb->max_key_code+1),XkbKeyNameRec); + if (names->keys==NULL) + return BadAlloc; + } + if ((which&XkbKeyAliasesMask)&&(nTotalAliases>0)) { + if (names->key_aliases==NULL) { + names->key_aliases= _XkbTypedCalloc(nTotalAliases,XkbKeyAliasRec); + } + else if (nTotalAliases>names->num_key_aliases) { + XkbKeyAliasRec *prev_aliases = names->key_aliases; + + names->key_aliases= _XkbTypedRealloc(names->key_aliases, + nTotalAliases,XkbKeyAliasRec); + if (names->key_aliases!=NULL) { + _XkbClearElems(names->key_aliases,names->num_key_aliases, + nTotalAliases-1,XkbKeyAliasRec); + } else { + _XkbFree(prev_aliases); + } + } + if (names->key_aliases==NULL) { + names->num_key_aliases= 0; + return BadAlloc; + } + names->num_key_aliases= nTotalAliases; + } + if ((which&XkbRGNamesMask)&&(nTotalRG>0)) { + if (names->radio_groups==NULL) { + names->radio_groups= _XkbTypedCalloc(nTotalRG,Atom); + } + else if (nTotalRG>names->num_rg) { + Atom *prev_radio_groups = names->radio_groups; + + names->radio_groups= _XkbTypedRealloc(names->radio_groups,nTotalRG, + Atom); + if (names->radio_groups!=NULL) { + _XkbClearElems(names->radio_groups,names->num_rg,nTotalRG-1, + Atom); + } else { + _XkbFree(prev_radio_groups); + } + } + if (names->radio_groups==NULL) + return BadAlloc; + names->num_rg= nTotalRG; + } + return Success; +} + +void +XkbcFreeNames(XkbcDescPtr xkb,unsigned which,Bool freeMap) +{ +XkbNamesPtr names; + + if ((xkb==NULL)||(xkb->names==NULL)) + return; + names= xkb->names; + if (freeMap) + which= XkbAllNamesMask; + if (which&XkbKTLevelNamesMask) { + XkbClientMapPtr map= xkb->map; + if ((map!=NULL)&&(map->types!=NULL)) { + register int i; + register XkbKeyTypePtr type; + type= map->types; + for (i=0;inum_types;i++,type++) { + if (type->level_names!=NULL) { + _XkbFree(type->level_names); + type->level_names= NULL; + } + } + } + } + if ((which&XkbKeyNamesMask)&&(names->keys!=NULL)) { + _XkbFree(names->keys); + names->keys= NULL; + names->num_keys= 0; + } + if ((which&XkbKeyAliasesMask)&&(names->key_aliases)){ + _XkbFree(names->key_aliases); + names->key_aliases=NULL; + names->num_key_aliases=0; + } + if ((which&XkbRGNamesMask)&&(names->radio_groups)) { + _XkbFree(names->radio_groups); + names->radio_groups= NULL; + names->num_rg= 0; + } + if (freeMap) { + _XkbFree(names); + xkb->names= NULL; + } + return; +} + +int +XkbcAllocControls(XkbcDescPtr xkb,unsigned which) +{ + if (xkb==NULL) + return BadMatch; + + if (xkb->ctrls==NULL) { + xkb->ctrls= _XkbTypedCalloc(1,XkbControlsRec); + if (!xkb->ctrls) + return BadAlloc; + } + return Success; +} + +void +XkbcFreeControls(XkbcDescPtr xkb,unsigned which,Bool freeMap) +{ + if (freeMap && (xkb!=NULL) && (xkb->ctrls!=NULL)) { + _XkbFree(xkb->ctrls); + xkb->ctrls= NULL; + } + return; +} + +int +XkbcAllocIndicatorMaps(XkbcDescPtr xkb) +{ + if (xkb==NULL) + return BadMatch; + if (xkb->indicators==NULL) { + xkb->indicators= _XkbTypedCalloc(1,XkbIndicatorRec); + if (!xkb->indicators) + return BadAlloc; + } + return Success; +} + +void +XkbcFreeIndicatorMaps(XkbcDescPtr xkb) +{ + if ((xkb!=NULL)&&(xkb->indicators!=NULL)) { + _XkbFree(xkb->indicators); + xkb->indicators= NULL; + } + return; +} + +XkbcDescRec * +XkbcAllocKeyboard(void) +{ +XkbcDescRec *xkb; + + xkb = _XkbTypedCalloc(1,XkbcDescRec); + if (xkb) + xkb->device_spec= XkbUseCoreKbd; + return xkb; +} + +void +XkbcFreeKeyboard(XkbcDescPtr xkb,unsigned which,Bool freeAll) +{ + if (xkb==NULL) + return; + if (freeAll) + which= XkbAllComponentsMask; + if (which&XkbClientMapMask) + XkbcFreeClientMap(xkb,XkbAllClientInfoMask,True); + if (which&XkbServerMapMask) + XkbcFreeServerMap(xkb,XkbAllServerInfoMask,True); + if (which&XkbCompatMapMask) + XkbcFreeCompatMap(xkb,XkbAllCompatMask,True); + if (which&XkbIndicatorMapMask) + XkbcFreeIndicatorMaps(xkb); + if (which&XkbNamesMask) + XkbcFreeNames(xkb,XkbAllNamesMask,True); + if ((which&XkbGeometryMask) && (xkb->geom!=NULL)) + XkbcFreeGeometry(xkb->geom,XkbGeomAllMask,True); + if (which&XkbControlsMask) + XkbcFreeControls(xkb,XkbAllControlsMask,True); + if (freeAll) + _XkbFree(xkb); + return; +} + +int +XkbcAllocClientMap(XkbcDescPtr xkb,unsigned which,unsigned nTotalTypes) +{ +register int i; +XkbClientMapPtr map; + + if ((xkb==NULL)||((nTotalTypes>0)&&(nTotalTypesmin_key_code))|| + (!XkbIsLegalKeycode(xkb->max_key_code))|| + (xkb->max_key_codemin_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_typestypes; + + 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_codemin_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; +} + +int +XkbcAllocServerMap(XkbcDescPtr 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;ivmods[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_codemin_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_codemin_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)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_codemin_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_codemin_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; +} + +void +XkbcFreeClientMap(XkbcDescPtr 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;inum_types;i++,type++) { + if (type->map!=NULL) { + _XkbFree(type->map); + type->map= NULL; + } + if (type->preserve!=NULL) { + _XkbFree(type->preserve); + type->preserve= NULL; + } + type->map_count= 0; + if (type->level_names!=NULL) { + _XkbFree(type->level_names); + type->level_names= NULL; + } + } + } + _XkbFree(map->types); + map->num_types= map->size_types= 0; + map->types= NULL; + } + } + if (what&XkbKeySymsMask) { + if (map->key_sym_map!=NULL) { + _XkbFree(map->key_sym_map); + map->key_sym_map= NULL; + } + if (map->syms!=NULL) { + _XkbFree(map->syms); + map->size_syms= map->num_syms= 0; + map->syms= NULL; + } + } + if ((what&XkbModifierMapMask)&&(map->modmap!=NULL)) { + _XkbFree(map->modmap); + map->modmap= NULL; + } + if (freeMap) { + _XkbFree(xkb->map); + xkb->map= NULL; + } + return; +} + +void +XkbcFreeServerMap(XkbcDescPtr xkb,unsigned what,Bool freeMap) +{ +XkbServerMapPtr map; + + if ((xkb==NULL)||(xkb->server==NULL)) + return; + if (freeMap) + what= XkbAllServerInfoMask; + map= xkb->server; + if ((what&XkbExplicitComponentsMask)&&(map->explicit!=NULL)) { + _XkbFree(map->explicit); + map->explicit= NULL; + } + if (what&XkbKeyActionsMask) { + if (map->key_acts!=NULL) { + _XkbFree(map->key_acts); + map->key_acts= NULL; + } + if (map->acts!=NULL) { + _XkbFree(map->acts); + map->num_acts= map->size_acts= 0; + map->acts= NULL; + } + } + if ((what&XkbKeyBehaviorsMask)&&(map->behaviors!=NULL)) { + _XkbFree(map->behaviors); + map->behaviors= NULL; + } + if ((what&XkbVirtualModMapMask)&&(map->vmodmap!=NULL)) { + _XkbFree(map->vmodmap); + map->vmodmap= NULL; + } + + if (freeMap) { + _XkbFree(xkb->server); + xkb->server= NULL; + } + return; +} diff --git a/src/galloc.c b/src/galloc.c new file mode 100644 index 0000000..c9b41ab --- /dev/null +++ b/src/galloc.c @@ -0,0 +1,539 @@ +/* +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 +#endif +#include "X11/XkbCommon.h" +#include "XkbCommonInt.h" +#include +#include +#include + +static void +_XkbFreeGeomLeafElems( Bool freeAll, + int first, + int count, + unsigned short * num_inout, + unsigned short * sz_inout, + char ** elems, + unsigned int elem_sz) +{ + if ((freeAll)||(*elems==NULL)) { + *num_inout= *sz_inout= 0; + if (*elems!=NULL) { + _XkbFree(*elems); + *elems= NULL; + } + return; + } + + if ((first>=(*num_inout))||(first<0)||(count<1)) + return; + + if (first+count>=(*num_inout)) { + /* truncating the array is easy */ + (*num_inout)= first; + } + else { + char * ptr; + int extra; + ptr= *elems; + extra= ((*num_inout)-(first+count))*elem_sz; + if (extra>0) + memmove(&ptr[first*elem_sz],&ptr[(first+count)*elem_sz],extra); + (*num_inout)-= count; + } + return; +} + +typedef void (*ContentsClearFunc)( + char * /* priv */ +); + +static void +_XkbFreeGeomNonLeafElems( Bool freeAll, + int first, + int count, + unsigned short * num_inout, + unsigned short * sz_inout, + char ** elems, + unsigned int elem_sz, + ContentsClearFunc freeFunc) +{ +register int i; +register char *ptr; + + if (freeAll) { + first= 0; + count= (*num_inout); + } + else if ((first>=(*num_inout))||(first<0)||(count<1)) + return; + else if (first+count>(*num_inout)) + count= (*num_inout)-first; + if (*elems==NULL) + return; + + if (freeFunc) { + ptr= *elems; + ptr+= first*elem_sz; + for (i=0;i=(*num_inout)) + *num_inout= first; + else { + i= ((*num_inout)-(first+count))*elem_sz; + ptr= *elems; + memmove(&ptr[first*elem_sz],&ptr[(first+count)*elem_sz],i); + (*num_inout)-= count; + } + return; +} + +static void +_XkbClearProperty(char *prop_in) +{ +XkbPropertyPtr prop= (XkbPropertyPtr)prop_in; + + if (prop->name) { + _XkbFree(prop->name); + prop->name= NULL; + } + if (prop->value) { + _XkbFree(prop->value); + prop->value= NULL; + } + return; +} + +void +XkbcFreeGeomProperties( XkbGeometryPtr geom, + int first, + int count, + Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &geom->num_properties,&geom->sz_properties, + (char **)&geom->properties, + sizeof(XkbPropertyRec),_XkbClearProperty); + return; +} + +void +XkbcFreeGeomKeyAliases( XkbGeometryPtr geom, + int first, + int count, + Bool freeAll) +{ + _XkbFreeGeomLeafElems(freeAll,first,count, + &geom->num_key_aliases,&geom->sz_key_aliases, + (char **)&geom->key_aliases, + sizeof(XkbKeyAliasRec)); + return; +} + +static void +_XkbClearColor(char *color_in) +{ +XkbColorPtr color= (XkbColorPtr)color_in; + + if (color->spec) + _XkbFree(color->spec); + return; +} + +void +XkbcFreeGeomColors(XkbGeometryPtr geom,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &geom->num_colors,&geom->sz_colors, + (char **)&geom->colors, + sizeof(XkbColorRec),_XkbClearColor); + return; +} + +void +XkbcFreeGeomPoints(XkbOutlinePtr outline,int first,int count,Bool freeAll) +{ + _XkbFreeGeomLeafElems(freeAll,first,count, + &outline->num_points,&outline->sz_points, + (char **)&outline->points, + sizeof(XkbPointRec)); + return; +} + +static void +_XkbClearOutline(char *outline_in) +{ +XkbOutlinePtr outline= (XkbOutlinePtr)outline_in; + + if (outline->points!=NULL) + XkbcFreeGeomPoints(outline,0,outline->num_points,True); + return; +} + +void +XkbcFreeGeomOutlines(XkbShapePtr shape,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &shape->num_outlines,&shape->sz_outlines, + (char **)&shape->outlines, + sizeof(XkbOutlineRec),_XkbClearOutline); + + return; +} + +static void +_XkbClearShape(char *shape_in) +{ +XkbShapePtr shape= (XkbShapePtr)shape_in; + + if (shape->outlines) + XkbcFreeGeomOutlines(shape,0,shape->num_outlines,True); + return; +} + +void +XkbcFreeGeomShapes(XkbGeometryPtr geom,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &geom->num_shapes,&geom->sz_shapes, + (char **)&geom->shapes, + sizeof(XkbShapeRec),_XkbClearShape); + return; +} + +void +XkbcFreeGeomOverlayKeys(XkbOverlayRowPtr row,int first,int count,Bool freeAll) +{ + _XkbFreeGeomLeafElems(freeAll,first,count, + &row->num_keys,&row->sz_keys, + (char **)&row->keys, + sizeof(XkbOverlayKeyRec)); + return; +} + + +static void +_XkbClearOverlayRow(char *row_in) +{ +XkbOverlayRowPtr row= (XkbOverlayRowPtr)row_in; + + if (row->keys!=NULL) + XkbcFreeGeomOverlayKeys(row,0,row->num_keys,True); + return; +} + +void +XkbcFreeGeomOverlayRows(XkbOverlayPtr overlay,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &overlay->num_rows,&overlay->sz_rows, + (char **)&overlay->rows, + sizeof(XkbOverlayRowRec),_XkbClearOverlayRow); + return; +} + + +static void +_XkbClearOverlay(char *overlay_in) +{ +XkbOverlayPtr overlay= (XkbOverlayPtr)overlay_in; + + if (overlay->rows!=NULL) + XkbcFreeGeomOverlayRows(overlay,0,overlay->num_rows,True); + return; +} + +void +XkbcFreeGeomOverlays(XkbSectionPtr section,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + §ion->num_overlays,§ion->sz_overlays, + (char **)§ion->overlays, + sizeof(XkbOverlayRec),_XkbClearOverlay); + return; +} + + +void +XkbcFreeGeomKeys(XkbRowPtr row,int first,int count,Bool freeAll) +{ + _XkbFreeGeomLeafElems(freeAll,first,count, + &row->num_keys,&row->sz_keys, + (char **)&row->keys, + sizeof(XkbKeyRec)); + return; +} + + +static void +_XkbClearRow(char *row_in) +{ +XkbRowPtr row= (XkbRowPtr)row_in; + + if (row->keys!=NULL) + XkbcFreeGeomKeys(row,0,row->num_keys,True); + return; +} + +void +XkbcFreeGeomRows(XkbSectionPtr section,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + §ion->num_rows,§ion->sz_rows, + (char **)§ion->rows, + sizeof(XkbRowRec),_XkbClearRow); +} + + +static void +_XkbClearSection(char *section_in) +{ +XkbSectionPtr section= (XkbSectionPtr)section_in; + + if (section->rows!=NULL) + XkbcFreeGeomRows(section,0,section->num_rows,True); + if (section->doodads!=NULL) { + XkbcFreeGeomDoodads(section->doodads,section->num_doodads,True); + section->doodads= NULL; + } + return; +} + +void +XkbcFreeGeomSections(XkbGeometryPtr geom,int first,int count,Bool freeAll) +{ + _XkbFreeGeomNonLeafElems(freeAll,first,count, + &geom->num_sections,&geom->sz_sections, + (char **)&geom->sections, + sizeof(XkbSectionRec),_XkbClearSection); + return; +} + + +static void +_XkbClearDoodad(char *doodad_in) +{ +XkbDoodadPtr doodad= (XkbDoodadPtr)doodad_in; + + switch (doodad->any.type) { + case XkbTextDoodad: + { + if (doodad->text.text!=NULL) { + _XkbFree(doodad->text.text); + doodad->text.text= NULL; + } + if (doodad->text.font!=NULL) { + _XkbFree(doodad->text.font); + doodad->text.font= NULL; + } + } + break; + case XkbLogoDoodad: + { + if (doodad->logo.logo_name!=NULL) { + _XkbFree(doodad->logo.logo_name); + doodad->logo.logo_name= NULL; + } + } + break; + } + return; +} + +void +XkbcFreeGeomDoodads(XkbDoodadPtr doodads,int nDoodads,Bool freeAll) +{ +register int i; +register XkbDoodadPtr doodad; + + if (doodads) { + for (i=0,doodad= doodads;iproperties!=NULL)) + XkbcFreeGeomProperties(geom,0,geom->num_properties,True); + if ((which&XkbGeomColorsMask)&&(geom->colors!=NULL)) + XkbcFreeGeomColors(geom,0,geom->num_colors,True); + if ((which&XkbGeomShapesMask)&&(geom->shapes!=NULL)) + XkbcFreeGeomShapes(geom,0,geom->num_shapes,True); + if ((which&XkbGeomSectionsMask)&&(geom->sections!=NULL)) + XkbcFreeGeomSections(geom,0,geom->num_sections,True); + if ((which&XkbGeomDoodadsMask)&&(geom->doodads!= NULL)) { + XkbcFreeGeomDoodads(geom->doodads,geom->num_doodads,True); + geom->doodads= NULL; + geom->num_doodads= geom->sz_doodads= 0; + } + if ((which&XkbGeomKeyAliasesMask)&&(geom->key_aliases!=NULL)) + XkbcFreeGeomKeyAliases(geom,0,geom->num_key_aliases,True); + if (freeMap) { + if (geom->label_font!=NULL) { + _XkbFree(geom->label_font); + geom->label_font= NULL; + } + _XkbFree(geom); + } + return; +} + +static int +_XkbGeomAlloc( char ** old, + unsigned short * num, + unsigned short * total, + int num_new, + size_t sz_elem) +{ + if (num_new<1) + return Success; + if ((*old)==NULL) + *num= *total= 0; + + if ((*num)+num_new<=(*total)) + return Success; + + *total= (*num)+num_new; + if ((*old)!=NULL) + (*old)= (char *)_XkbRealloc((*old),(*total)*sz_elem); + else (*old)= (char *)_XkbCalloc((*total),sz_elem); + if ((*old)==NULL) { + *total= *num= 0; + return BadAlloc; + } + + if (*num>0) { + char *tmp= (char *)(*old); + bzero(&tmp[sz_elem*(*num)],(num_new*sz_elem)); + } + return Success; +} + +#define _XkbAllocProps(g,n) _XkbGeomAlloc((char **)&(g)->properties,\ + &(g)->num_properties,&(g)->sz_properties,\ + (n),sizeof(XkbPropertyRec)) +#define _XkbAllocColors(g,n) _XkbGeomAlloc((char **)&(g)->colors,\ + &(g)->num_colors,&(g)->sz_colors,\ + (n),sizeof(XkbColorRec)) +#define _XkbAllocShapes(g,n) _XkbGeomAlloc((char **)&(g)->shapes,\ + &(g)->num_shapes,&(g)->sz_shapes,\ + (n),sizeof(XkbShapeRec)) +#define _XkbAllocSections(g,n) _XkbGeomAlloc((char **)&(g)->sections,\ + &(g)->num_sections,&(g)->sz_sections,\ + (n),sizeof(XkbSectionRec)) +#define _XkbAllocDoodads(g,n) _XkbGeomAlloc((char **)&(g)->doodads,\ + &(g)->num_doodads,&(g)->sz_doodads,\ + (n),sizeof(XkbDoodadRec)) +#define _XkbAllocKeyAliases(g,n) _XkbGeomAlloc((char **)&(g)->key_aliases,\ + &(g)->num_key_aliases,&(g)->sz_key_aliases,\ + (n),sizeof(XkbKeyAliasRec)) + +#define _XkbAllocOutlines(s,n) _XkbGeomAlloc((char **)&(s)->outlines,\ + &(s)->num_outlines,&(s)->sz_outlines,\ + (n),sizeof(XkbOutlineRec)) +#define _XkbAllocRows(s,n) _XkbGeomAlloc((char **)&(s)->rows,\ + &(s)->num_rows,&(s)->sz_rows,\ + (n),sizeof(XkbRowRec)) +#define _XkbAllocPoints(o,n) _XkbGeomAlloc((char **)&(o)->points,\ + &(o)->num_points,&(o)->sz_points,\ + (n),sizeof(XkbPointRec)) +#define _XkbAllocKeys(r,n) _XkbGeomAlloc((char **)&(r)->keys,\ + &(r)->num_keys,&(r)->sz_keys,\ + (n),sizeof(XkbKeyRec)) +#define _XkbAllocOverlays(s,n) _XkbGeomAlloc((char **)&(s)->overlays,\ + &(s)->num_overlays,&(s)->sz_overlays,\ + (n),sizeof(XkbOverlayRec)) +#define _XkbAllocOverlayRows(o,n) _XkbGeomAlloc((char **)&(o)->rows,\ + &(o)->num_rows,&(o)->sz_rows,\ + (n),sizeof(XkbOverlayRowRec)) +#define _XkbAllocOverlayKeys(r,n) _XkbGeomAlloc((char **)&(r)->keys,\ + &(r)->num_keys,&(r)->sz_keys,\ + (n),sizeof(XkbOverlayKeyRec)) + +int +XkbcAllocGeometry(XkbcDescPtr xkb,XkbGeometrySizesPtr sizes) +{ +XkbGeometryPtr geom; +int rtrn; + + if (xkb->geom==NULL) { + xkb->geom= _XkbTypedCalloc(1,XkbGeometryRec); + if (!xkb->geom) + return BadAlloc; + } + geom= xkb->geom; + if ((sizes->which&XkbGeomPropertiesMask)&& + ((rtrn=_XkbAllocProps(geom,sizes->num_properties))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomColorsMask)&& + ((rtrn=_XkbAllocColors(geom,sizes->num_colors))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomShapesMask)&& + ((rtrn=_XkbAllocShapes(geom,sizes->num_shapes))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomSectionsMask)&& + ((rtrn=_XkbAllocSections(geom,sizes->num_sections))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomDoodadsMask)&& + ((rtrn=_XkbAllocDoodads(geom,sizes->num_doodads))!=Success)) { + goto BAIL; + } + if ((sizes->which&XkbGeomKeyAliasesMask)&& + ((rtrn=_XkbAllocKeyAliases(geom,sizes->num_key_aliases))!=Success)) { + goto BAIL; + } + return Success; +BAIL: + XkbcFreeGeometry(geom,XkbGeomAllMask,True); + xkb->geom= NULL; + return rtrn; +}