67499d68fafc02d21164a56595799def9dae76b6
[platform/upstream/libxkbcommon.git] / src / galloc.c
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 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29 #include "X11/extensions/XKBcommon.h"
30 #include "XKBcommonint.h"
31 #include <X11/X.h>
32 #include <X11/Xdefs.h>
33 #include <X11/extensions/XKB.h>
34
35 static void
36 _XkbFreeGeomLeafElems(Bool freeAll, int first, int count,
37                       unsigned short *num_inout, unsigned short *sz_inout,
38                       char **elems, unsigned int elem_sz)
39 {
40     if (freeAll || !(*elems)) {
41         *num_inout = *sz_inout = 0;
42         if (*elems) {
43             _XkbFree(*elems);
44             *elems = NULL;
45         }
46         return;
47     }
48
49     if ((first >= (*num_inout)) || (first < 0) || (count < 1))
50         return;
51
52     if (first + count >= (*num_inout))
53         /* truncating the array is easy */
54         (*num_inout) = first;
55     else {
56         char *ptr = *elems;
57         int extra = ((*num_inout) - first + count) * elem_sz;
58
59         if (extra > 0)
60             memmove(&ptr[first * elem_sz], &ptr[(first + count) * elem_sz],
61                     extra);
62
63         (*num_inout) -= count;
64     }
65 }
66
67 typedef void (*ContentsClearFunc)(char *priv);
68
69 static void
70 _XkbFreeGeomNonLeafElems(Bool freeAll, int first, int count,
71                          unsigned short *num_inout, unsigned short *sz_inout,
72                          char **elems, unsigned int elem_sz,
73                          ContentsClearFunc freeFunc)
74 {
75     int i;
76     char *ptr;
77
78     if (freeAll) {
79         first = 0;
80         count = *num_inout;
81     }
82     else if ((first >= (*num_inout)) || (first < 0) || (count < 1))
83         return;
84     else if (first + count > (*num_inout))
85         count = (*num_inout) - first;
86
87     if (!(*elems))
88         return;
89
90     if (freeFunc) {
91         ptr = *elems;
92         ptr += first * elem_sz;
93         for (i = 0; i < count; i++) {
94             (*freeFunc)(ptr);
95             ptr += elem_sz;
96         }
97     }
98
99     if (freeAll) {
100         *num_inout = *sz_inout = 0;
101         if (*elems) {
102             _XkbFree(*elems);
103             *elems = NULL;
104         }
105     }
106     else if (first + count >= (*num_inout))
107         *num_inout = first;
108     else {
109         i = ((*num_inout) - first + count) * elem_sz;
110         ptr = *elems;
111         memmove(&ptr[first * elem_sz], &ptr[(first + count) * elem_sz], i);
112         (*num_inout) -= count;
113     }
114 }
115
116 static void
117 _XkbClearProperty(char *prop_in)
118 {
119     XkbPropertyPtr prop = (XkbPropertyPtr)prop_in;
120
121     if (prop->name) {
122         _XkbFree(prop->name);
123         prop->name = NULL;
124     }
125     if (prop->value) {
126         _XkbFree(prop->value);
127         prop->value = NULL;
128     }
129 }
130
131 void
132 XkbcFreeGeomProperties(XkbGeometryPtr geom, int first, int count, Bool freeAll)
133 {
134     _XkbFreeGeomNonLeafElems(freeAll, first, count,
135                              &geom->num_properties, &geom->sz_properties,
136                              (char **)&geom->properties,
137                              sizeof(XkbPropertyRec),
138                              _XkbClearProperty);
139 }
140
141 void
142 XkbcFreeGeomKeyAliases(XkbGeometryPtr geom, int first, int count, Bool freeAll)
143 {
144     _XkbFreeGeomLeafElems(freeAll, first, count,
145                           &geom->num_key_aliases, &geom->sz_key_aliases,
146                           (char **)&geom->key_aliases,
147                           sizeof(XkbKeyAliasRec));
148 }
149
150 static void
151 _XkbClearColor(char *color_in)
152 {
153     XkbColorPtr color = (XkbColorPtr)color_in;
154
155     if (color->spec)
156         _XkbFree(color->spec);
157 }
158
159 void
160 XkbcFreeGeomColors(XkbGeometryPtr geom, int first, int count, Bool freeAll)
161 {
162     _XkbFreeGeomNonLeafElems(freeAll, first, count,
163                              &geom->num_colors, &geom->sz_colors,
164                              (char **)&geom->colors, sizeof(XkbColorRec),
165                              _XkbClearColor);
166 }
167
168 void
169 XkbcFreeGeomPoints(XkbOutlinePtr outline, int first, int count, Bool freeAll)
170 {
171     _XkbFreeGeomLeafElems(freeAll, first, count,
172                           &outline->num_points, &outline->sz_points,
173                           (char **)&outline->points, sizeof(XkbPointRec));
174 }
175
176 static void
177 _XkbClearOutline(char *outline_in)
178 {
179     XkbOutlinePtr outline = (XkbOutlinePtr)outline_in;
180
181     if (outline->points)
182         XkbcFreeGeomPoints(outline, 0, outline->num_points, True);
183 }
184
185 void
186 XkbcFreeGeomOutlines(XkbShapePtr shape, int first, int count, Bool freeAll)
187 {
188     _XkbFreeGeomNonLeafElems(freeAll, first, count,
189                              &shape->num_outlines, &shape->sz_outlines,
190                              (char **)&shape->outlines, sizeof(XkbOutlineRec),
191                              _XkbClearOutline);
192 }
193
194 static void
195 _XkbClearShape(char *shape_in)
196 {
197     XkbShapePtr shape = (XkbShapePtr)shape_in;
198
199     if (shape->outlines)
200         XkbcFreeGeomOutlines(shape, 0, shape->num_outlines, True);
201 }
202
203 void
204 XkbcFreeGeomShapes(XkbGeometryPtr geom, int first, int count, Bool freeAll)
205 {
206     _XkbFreeGeomNonLeafElems(freeAll, first, count,
207                              &geom->num_shapes, &geom->sz_shapes,
208                              (char **)&geom->shapes, sizeof(XkbShapeRec),
209                              _XkbClearShape);
210 }
211
212 void
213 XkbcFreeGeomOverlayKeys(XkbOverlayRowPtr row, int first, int count,
214                         Bool freeAll)
215 {
216     _XkbFreeGeomLeafElems(freeAll, first, count,
217                           &row->num_keys, &row->sz_keys,
218                           (char **)&row->keys, sizeof(XkbOverlayKeyRec));
219 }
220
221
222 static void
223 _XkbClearOverlayRow(char *row_in)
224 {
225     XkbOverlayRowPtr row = (XkbOverlayRowPtr)row_in;
226
227     if (row->keys)
228         XkbcFreeGeomOverlayKeys(row, 0, row->num_keys, True);
229 }
230
231 void
232 XkbcFreeGeomOverlayRows(XkbOverlayPtr overlay, int first, int count,
233                         Bool freeAll)
234 {
235     _XkbFreeGeomNonLeafElems(freeAll, first, count,
236                              &overlay->num_rows, &overlay->sz_rows,
237                              (char **)&overlay->rows,
238                              sizeof(XkbOverlayRowRec),
239                              _XkbClearOverlayRow);
240 }
241
242
243 static void
244 _XkbClearOverlay(char *overlay_in)
245 {
246     XkbOverlayPtr overlay = (XkbOverlayPtr)overlay_in;
247
248     if (overlay->rows)
249         XkbcFreeGeomOverlayRows(overlay, 0, overlay->num_rows, True);
250 }
251
252 void
253 XkbcFreeGeomOverlays(XkbSectionPtr section, int first, int count, Bool freeAll)
254 {
255     _XkbFreeGeomNonLeafElems(freeAll, first, count,
256                              &section->num_overlays, &section->sz_overlays,
257                              (char **)&section->overlays,
258                              sizeof(XkbOverlayRec),
259                              _XkbClearOverlay);
260 }
261
262
263 void
264 XkbcFreeGeomKeys(XkbRowPtr row, int first, int count, Bool freeAll)
265 {
266     _XkbFreeGeomLeafElems(freeAll, first, count,
267                           &row->num_keys, &row->sz_keys,
268                           (char **)&row->keys, sizeof(XkbKeyRec));
269 }
270
271
272 static void
273 _XkbClearRow(char *row_in)
274 {
275     XkbRowPtr row = (XkbRowPtr)row_in;
276
277     if (row->keys)
278         XkbcFreeGeomKeys(row, 0, row->num_keys, True);
279 }
280
281 void
282 XkbcFreeGeomRows(XkbSectionPtr section, int first, int count, Bool freeAll)
283 {
284     _XkbFreeGeomNonLeafElems(freeAll, first, count,
285                              &section->num_rows, &section->sz_rows,
286                              (char **)&section->rows, sizeof(XkbRowRec),
287                              _XkbClearRow);
288 }
289
290
291 static void
292 _XkbClearSection(char *section_in)
293 {
294     XkbSectionPtr section = (XkbSectionPtr)section_in;
295
296     if (section->rows)
297         XkbcFreeGeomRows(section, 0, section->num_rows, True);
298     if (section->doodads) {
299         XkbcFreeGeomDoodads(section->doodads, section->num_doodads, True);
300         section->doodads = NULL;
301     }
302 }
303
304 void
305 XkbcFreeGeomSections(XkbGeometryPtr geom, int first, int count, Bool freeAll)
306 {
307     _XkbFreeGeomNonLeafElems(freeAll, first, count,
308                              &geom->num_sections, &geom->sz_sections,
309                              (char **)&geom->sections, sizeof(XkbSectionRec),
310                              _XkbClearSection);
311 }
312
313
314 static void
315 _XkbClearDoodad(char *doodad_in)
316 {
317     XkbDoodadPtr doodad = (XkbDoodadPtr)doodad_in;
318
319     switch (doodad->any.type) {
320     case XkbTextDoodad:
321         if (doodad->text.text) {
322             _XkbFree(doodad->text.text);
323             doodad->text.text = NULL;
324         }
325         if (doodad->text.font) {
326             _XkbFree(doodad->text.font);
327             doodad->text.font = NULL;
328         }
329         break;
330
331     case XkbLogoDoodad:
332         if (doodad->logo.logo_name) {
333             _XkbFree(doodad->logo.logo_name);
334             doodad->logo.logo_name = NULL;
335         }
336         break;
337     }
338 }
339
340 void
341 XkbcFreeGeomDoodads(XkbDoodadPtr doodads, int nDoodads, Bool freeAll)
342 {
343     int i;
344     XkbDoodadPtr doodad;
345
346     if (doodads) {
347         for (i = 0, doodad = doodads; i < nDoodads; i++, doodad++)
348             _XkbClearDoodad((char *)doodad);
349         if (freeAll)
350             _XkbFree(doodads);
351     }
352 }
353
354 void
355 XkbcFreeGeometry(XkbGeometryPtr geom, unsigned which, Bool freeMap)
356 {
357     if (!geom)
358         return;
359
360     if (freeMap)
361         which = XkbGeomAllMask;
362
363     if ((which & XkbGeomPropertiesMask) && geom->properties)
364         XkbcFreeGeomProperties(geom, 0, geom->num_properties, True);
365
366     if ((which & XkbGeomColorsMask) && geom->colors)
367         XkbcFreeGeomColors(geom, 0, geom->num_colors, True);
368
369     if ((which & XkbGeomShapesMask) && geom->shapes)
370         XkbcFreeGeomShapes(geom, 0, geom->num_shapes, True);
371
372     if ((which & XkbGeomSectionsMask) && geom->sections)
373         XkbcFreeGeomSections(geom, 0, geom->num_sections, True);
374
375     if ((which & XkbGeomDoodadsMask) && geom->doodads) {
376         XkbcFreeGeomDoodads(geom->doodads, geom->num_doodads, True);
377         geom->doodads = NULL;
378         geom->num_doodads = geom->sz_doodads = 0;
379     }
380
381     if ((which & XkbGeomKeyAliasesMask) && geom->key_aliases)
382         XkbcFreeGeomKeyAliases(geom, 0, geom->num_key_aliases, True);
383
384     if (freeMap) {
385         if (geom->label_font) {
386             _XkbFree(geom->label_font);
387             geom->label_font = NULL;
388         }
389         _XkbFree(geom);
390     }
391 }
392
393 static int
394 _XkbGeomAlloc(char **old, unsigned short *num, unsigned short *total,
395               int num_new, size_t sz_elem)
396 {
397     if (num_new < 1)
398         return Success;
399
400     if (!(*old))
401         *num = *total = 0;
402
403     if ((*num) + num_new <= (*total))
404         return Success;
405
406     *total = (*num) + num_new;
407
408     if (*old)
409         *old = (char *)_XkbRealloc(*old, (*total) * sz_elem);
410     else
411         *old = (char *)_XkbCalloc(*total, sz_elem);
412     if (!(*old)) {
413         *total = *num = 0;
414         return BadAlloc;
415     }
416
417     if (*num > 0) {
418         char *tmp = *old;
419         bzero(&tmp[sz_elem * (*num)], num_new * sz_elem);
420     }
421
422     return Success;
423 }
424
425 #define _XkbAllocProps(g, n)    _XkbGeomAlloc((char **)&(g)->properties, \
426                                               &(g)->num_properties, \
427                                               &(g)->sz_properties, \
428                                               (n), sizeof(XkbPropertyRec))
429 #define _XkbAllocColors(g, n)   _XkbGeomAlloc((char **)&(g)->colors, \
430                                               &(g)->num_colors, \
431                                               &(g)->sz_colors, \
432                                               (n), sizeof(XkbColorRec))
433 #define _XkbAllocShapes(g, n)   _XkbGeomAlloc((char **)&(g)->shapes, \
434                                               &(g)->num_shapes, \
435                                               &(g)->sz_shapes, \
436                                               (n), sizeof(XkbShapeRec))
437 #define _XkbAllocSections(g, n) _XkbGeomAlloc((char **)&(g)->sections, \
438                                               &(g)->num_sections, \
439                                               &(g)->sz_sections, \
440                                               (n), sizeof(XkbSectionRec))
441 #define _XkbAllocDoodads(g, n)  _XkbGeomAlloc((char **)&(g)->doodads, \
442                                               &(g)->num_doodads, \
443                                               &(g)->sz_doodads, \
444                                               (n), sizeof(XkbDoodadRec))
445 #define _XkbAllocKeyAliases(g, n)   _XkbGeomAlloc((char **)&(g)->key_aliases, \
446                                                   &(g)->num_key_aliases, \
447                                                   &(g)->sz_key_aliases, \
448                                                   (n), sizeof(XkbKeyAliasRec))
449
450 #define _XkbAllocOutlines(s, n) _XkbGeomAlloc((char **)&(s)->outlines, \
451                                               &(s)->num_outlines, \
452                                               &(s)->sz_outlines, \
453                                               (n), sizeof(XkbOutlineRec))
454 #define _XkbAllocRows(s, n)     _XkbGeomAlloc((char **)&(s)->rows, \
455                                               &(s)->num_rows, \
456                                               &(s)->sz_rows, \
457                                               (n), sizeof(XkbRowRec))
458 #define _XkbAllocPoints(o, n)   _XkbGeomAlloc((char **)&(o)->points, \
459                                               &(o)->num_points, \
460                                               &(o)->sz_points, \
461                                               (n), sizeof(XkbPointRec))
462 #define _XkbAllocKeys(r, n)     _XkbGeomAlloc((char **)&(r)->keys, \
463                                               &(r)->num_keys, \
464                                               &(r)->sz_keys, \
465                                               (n), sizeof(XkbKeyRec))
466 #define _XkbAllocOverlays(s, n) _XkbGeomAlloc((char **)&(s)->overlays, \
467                                               &(s)->num_overlays, \
468                                               &(s)->sz_overlays, \
469                                               (n), sizeof(XkbOverlayRec))
470 #define _XkbAllocOverlayRows(o, n)  _XkbGeomAlloc((char **)&(o)->rows, \
471                                                   &(o)->num_rows, \
472                                                   &(o)->sz_rows, \
473                                                   (n), sizeof(XkbOverlayRowRec))
474 #define _XkbAllocOverlayKeys(r, n)  _XkbGeomAlloc((char **)&(r)->keys, \
475                                                   &(r)->num_keys, \
476                                                   &(r)->sz_keys, \
477                                                   (n), sizeof(XkbOverlayKeyRec))
478
479 int
480 XkbcAllocGeometry(XkbcDescPtr xkb, XkbGeometrySizesPtr sizes)
481 {
482     XkbGeometryPtr geom;
483     int rtrn;
484
485     if (!xkb->geom) {
486         xkb->geom = _XkbTypedCalloc(1, XkbGeometryRec);
487         if (!xkb->geom)
488             return BadAlloc;
489     }
490     geom = xkb->geom;
491
492     if ((sizes->which & XkbGeomPropertiesMask) &&
493         ((rtrn = _XkbAllocProps(geom, sizes->num_properties)) != Success))
494         goto bail;
495
496     if ((sizes->which & XkbGeomColorsMask) &&
497         ((rtrn = _XkbAllocColors(geom, sizes->num_colors)) != Success))
498         goto bail;
499
500     if ((sizes->which & XkbGeomShapesMask) &&
501         ((rtrn = _XkbAllocShapes(geom, sizes->num_shapes)) != Success))
502         goto bail;
503
504     if ((sizes->which & XkbGeomSectionsMask) &&
505         ((rtrn = _XkbAllocSections(geom, sizes->num_sections)) != Success))
506         goto bail;
507
508     if ((sizes->which & XkbGeomDoodadsMask) &&
509         ((rtrn = _XkbAllocDoodads(geom, sizes->num_doodads)) != Success))
510         goto bail;
511
512     if ((sizes->which & XkbGeomKeyAliasesMask) &&
513         ((rtrn = _XkbAllocKeyAliases(geom, sizes->num_key_aliases)) != Success))
514         goto bail;
515
516     return Success;
517 bail:
518     XkbcFreeGeometry(geom, XkbGeomAllMask, True);
519     xkb->geom = NULL;
520     return rtrn;
521 }