Refactor XkbFindFileInPath
[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 "xkbgeom.h"
30 #include "xkbcommon/xkbcommon.h"
31 #include "XKBcommonint.h"
32 #include <X11/extensions/XKB.h>
33
34 typedef void (*ContentsClearFunc)(void *priv);
35
36 static void
37 _XkbFreeGeomNonLeafElems(unsigned short *num_inout, unsigned short *sz_inout,
38                          void *elems, size_t elem_sz,
39                          ContentsClearFunc freeFunc)
40 {
41     int i;
42     char *start, *ptr;
43
44     if (!elems)
45         return;
46
47     start = *(char **)elems;
48     if (!start)
49         return;
50
51     ptr = start;
52     for (i = 0; i < *num_inout; i++) {
53         freeFunc(ptr);
54         ptr += elem_sz;
55     }
56
57     *num_inout = *sz_inout = 0;
58     free(start);
59 }
60
61 static void
62 _XkbClearProperty(void *prop_in)
63 {
64     struct xkb_property * prop = prop_in;
65
66     free(prop->name);
67     prop->name = NULL;
68     free(prop->value);
69     prop->value = NULL;
70 }
71
72 static void
73 XkbcFreeGeomProperties(struct xkb_geometry * geom)
74 {
75     _XkbFreeGeomNonLeafElems(&geom->num_properties, &geom->sz_properties,
76                              &geom->properties, sizeof(struct xkb_property),
77                              _XkbClearProperty);
78 }
79
80 static void
81 _XkbClearColor(void *color_in)
82 {
83     struct xkb_color * color = color_in;
84
85     free(color->spec);
86 }
87
88 static void
89 XkbcFreeGeomColors(struct xkb_geometry * geom)
90 {
91     _XkbFreeGeomNonLeafElems(&geom->num_colors, &geom->sz_colors,
92                              &geom->colors, sizeof(struct xkb_color),
93                              _XkbClearColor);
94 }
95
96 static void
97 _XkbClearOutline(void *outline_in)
98 {
99     struct xkb_outline * outline = outline_in;
100
101     free(outline->points);
102 }
103
104 static void
105 XkbcFreeGeomOutlines(struct xkb_shape * shape)
106 {
107     _XkbFreeGeomNonLeafElems(&shape->num_outlines, &shape->sz_outlines,
108                              &shape->outlines, sizeof(struct xkb_outline),
109                              _XkbClearOutline);
110 }
111
112 static void
113 _XkbClearShape(void *shape_in)
114 {
115     struct xkb_shape * shape = shape_in;
116
117     XkbcFreeGeomOutlines(shape);
118 }
119
120 static void
121 XkbcFreeGeomShapes(struct xkb_geometry * geom)
122 {
123     _XkbFreeGeomNonLeafElems(&geom->num_shapes, &geom->sz_shapes,
124                              &geom->shapes, sizeof(struct xkb_shape),
125                              _XkbClearShape);
126 }
127
128 static void
129 _XkbClearRow(void *row_in)
130 {
131     struct xkb_row * row = row_in;
132
133     free(row->keys);
134 }
135
136 static void
137 XkbcFreeGeomRows(struct xkb_section * section)
138 {
139     _XkbFreeGeomNonLeafElems(&section->num_rows, &section->sz_rows,
140                              &section->rows, sizeof(struct xkb_row),
141                              _XkbClearRow);
142 }
143
144 static void
145 _XkbClearDoodad(union xkb_doodad *doodad)
146 {
147     switch (doodad->any.type) {
148     case XkbTextDoodad:
149         free(doodad->text.text);
150         doodad->text.text = NULL;
151         free(doodad->text.font);
152         doodad->text.font = NULL;
153         break;
154
155     case XkbLogoDoodad:
156         free(doodad->logo.logo_name);
157         doodad->logo.logo_name = NULL;
158         break;
159     }
160 }
161
162 static void
163 XkbcFreeGeomDoodads(union xkb_doodad * doodads, int nDoodads)
164 {
165     int i;
166     union xkb_doodad * doodad;
167
168     for (i = 0, doodad = doodads; i < nDoodads && doodad; i++, doodad++)
169         _XkbClearDoodad(doodad);
170     free(doodads);
171 }
172
173 static void
174 _XkbClearSection(void *section_in)
175 {
176     struct xkb_section * section = section_in;
177
178     XkbcFreeGeomRows(section);
179     XkbcFreeGeomDoodads(section->doodads, section->num_doodads);
180     section->doodads = NULL;
181 }
182
183 static void
184 XkbcFreeGeomSections(struct xkb_geometry * geom)
185 {
186     _XkbFreeGeomNonLeafElems(&geom->num_sections, &geom->sz_sections,
187                              &geom->sections, sizeof(struct xkb_section),
188                              _XkbClearSection);
189 }
190
191 void
192 XkbcFreeGeometry(struct xkb_desc * xkb)
193 {
194     struct xkb_geometry *geom;
195
196     if (!xkb || !xkb->geom)
197         return;
198
199     geom = xkb->geom;
200
201     XkbcFreeGeomProperties(geom);
202     XkbcFreeGeomColors(geom);
203     XkbcFreeGeomShapes(geom);
204     XkbcFreeGeomSections(geom);
205     XkbcFreeGeomDoodads(geom->doodads, geom->num_doodads);
206     free(geom->key_aliases);
207     free(geom->label_font);
208     free(geom);
209 }
210
211 static int
212 _XkbGeomAlloc(char **old, unsigned short *num, unsigned short *total,
213               int num_new, size_t sz_elem)
214 {
215     if (num_new < 1)
216         return Success;
217
218     if (!(*old))
219         *num = *total = 0;
220
221     if ((*num) + num_new <= (*total))
222         return Success;
223
224     *total = (*num) + num_new;
225
226     if (*old)
227         *old = realloc(*old, (*total) * sz_elem);
228     else
229         *old = calloc(*total, sz_elem);
230     if (!(*old)) {
231         *total = *num = 0;
232         return BadAlloc;
233     }
234
235     if (*num > 0) {
236         char *tmp = *old;
237         memset(&tmp[sz_elem * (*num)], 0, num_new * sz_elem);
238     }
239
240     return Success;
241 }
242
243 #define _XkbAllocProps(g, n)    _XkbGeomAlloc((char **)&(g)->properties, \
244                                               &(g)->num_properties, \
245                                               &(g)->sz_properties, \
246                                               (n), sizeof(struct xkb_property))
247 #define _XkbAllocColors(g, n)   _XkbGeomAlloc((char **)&(g)->colors, \
248                                               &(g)->num_colors, \
249                                               &(g)->sz_colors, \
250                                               (n), sizeof(struct xkb_color))
251 #define _XkbAllocShapes(g, n)   _XkbGeomAlloc((char **)&(g)->shapes, \
252                                               &(g)->num_shapes, \
253                                               &(g)->sz_shapes, \
254                                               (n), sizeof(struct xkb_shape))
255 #define _XkbAllocSections(g, n) _XkbGeomAlloc((char **)&(g)->sections, \
256                                               &(g)->num_sections, \
257                                               &(g)->sz_sections, \
258                                               (n), sizeof(struct xkb_section))
259 #define _XkbAllocDoodads(g, n)  _XkbGeomAlloc((char **)&(g)->doodads, \
260                                               &(g)->num_doodads, \
261                                               &(g)->sz_doodads, \
262                                               (n), sizeof(union xkb_doodad))
263 #define _XkbAllocKeyAliases(g, n)   _XkbGeomAlloc((char **)&(g)->key_aliases, \
264                                                   &(g)->num_key_aliases, \
265                                                   &(g)->sz_key_aliases, \
266                                                   (n), sizeof(struct xkb_key_alias))
267
268 #define _XkbAllocOutlines(s, n) _XkbGeomAlloc((char **)&(s)->outlines, \
269                                               &(s)->num_outlines, \
270                                               &(s)->sz_outlines, \
271                                               (n), sizeof(struct xkb_outline))
272 #define _XkbAllocRows(s, n)     _XkbGeomAlloc((char **)&(s)->rows, \
273                                               &(s)->num_rows, \
274                                               &(s)->sz_rows, \
275                                               (n), sizeof(struct xkb_row))
276 #define _XkbAllocPoints(o, n)   _XkbGeomAlloc((char **)&(o)->points, \
277                                               &(o)->num_points, \
278                                               &(o)->sz_points, \
279                                               (n), sizeof(struct xkb_point))
280 #define _XkbAllocKeys(r, n)     _XkbGeomAlloc((char **)&(r)->keys, \
281                                               &(r)->num_keys, \
282                                               &(r)->sz_keys, \
283                                               (n), sizeof(struct xkb_key))
284 #define _XkbAllocOverlays(s, n) _XkbGeomAlloc((char **)&(s)->overlays, \
285                                               &(s)->num_overlays, \
286                                               &(s)->sz_overlays, \
287                                               (n), sizeof(struct xkb_overlay))
288 #define _XkbAllocOverlayRows(o, n)  _XkbGeomAlloc((char **)&(o)->rows, \
289                                                   &(o)->num_rows, \
290                                                   &(o)->sz_rows, \
291                                                   (n), sizeof(struct xkb_overlay_row))
292 #define _XkbAllocOverlayKeys(r, n)  _XkbGeomAlloc((char **)&(r)->keys, \
293                                                   &(r)->num_keys, \
294                                                   &(r)->sz_keys, \
295                                                   (n), sizeof(struct xkb_overlay_key))
296
297 int
298 XkbcAllocGeomKeyAliases(struct xkb_geometry * geom, int nKeyAliases)
299 {
300     return _XkbAllocKeyAliases(geom, nKeyAliases);
301 }
302
303 int
304 XkbcAllocGeometry(struct xkb_desc * xkb, struct xkb_geometry_sizes * sizes)
305 {
306     struct xkb_geometry * geom;
307     int rtrn;
308
309     if (!xkb->geom) {
310         xkb->geom = _XkbTypedCalloc(1, struct xkb_geometry);
311         if (!xkb->geom)
312             return BadAlloc;
313     }
314     geom = xkb->geom;
315
316     if ((sizes->which & XkbGeomPropertiesMask) &&
317         ((rtrn = _XkbAllocProps(geom, sizes->num_properties)) != Success))
318         goto bail;
319
320     if ((sizes->which & XkbGeomColorsMask) &&
321         ((rtrn = _XkbAllocColors(geom, sizes->num_colors)) != Success))
322         goto bail;
323
324     if ((sizes->which & XkbGeomShapesMask) &&
325         ((rtrn = _XkbAllocShapes(geom, sizes->num_shapes)) != Success))
326         goto bail;
327
328     if ((sizes->which & XkbGeomSectionsMask) &&
329         ((rtrn = _XkbAllocSections(geom, sizes->num_sections)) != Success))
330         goto bail;
331
332     if ((sizes->which & XkbGeomDoodadsMask) &&
333         ((rtrn = _XkbAllocDoodads(geom, sizes->num_doodads)) != Success))
334         goto bail;
335
336     if ((sizes->which & XkbGeomKeyAliasesMask) &&
337         ((rtrn = _XkbAllocKeyAliases(geom, sizes->num_key_aliases)) != Success))
338         goto bail;
339
340     return Success;
341 bail:
342     XkbcFreeGeometry(xkb);
343     xkb->geom = NULL;
344     return rtrn;
345 }
346
347 struct xkb_property *
348 XkbcAddGeomProperty(struct xkb_geometry * geom,const char *name,const char *value)
349 {
350     int i;
351     struct xkb_property * prop;
352
353     if ((!geom)||(!name)||(!value))
354         return NULL;
355     for (i=0,prop=geom->properties;i<geom->num_properties;i++,prop++) {
356         if ((prop->name)&&(strcmp(name,prop->name)==0)) {
357             free(prop->value);
358             prop->value = strdup(value);
359             return prop;
360         }
361     }
362     if ((geom->num_properties>=geom->sz_properties)&&
363                                         (_XkbAllocProps(geom,1)!=Success)) {
364         return NULL;
365     }
366     prop= &geom->properties[geom->num_properties];
367     prop->name = strdup(name);
368     if (!prop->name)
369         return NULL;
370     prop->value = strdup(value);
371     if (!prop->value) {
372         free(prop->name);
373         prop->name= NULL;
374         return NULL;
375     }
376     geom->num_properties++;
377     return prop;
378 }
379
380 struct xkb_color *
381 XkbcAddGeomColor(struct xkb_geometry * geom,const char *spec,unsigned int pixel)
382 {
383     int i;
384     struct xkb_color * color;
385
386     if ((!geom)||(!spec))
387         return NULL;
388     for (i=0,color=geom->colors;i<geom->num_colors;i++,color++) {
389         if ((color->spec)&&(strcmp(color->spec,spec)==0)) {
390             color->pixel= pixel;
391             return color;
392         }
393     }
394     if ((geom->num_colors>=geom->sz_colors)&&
395                                         (_XkbAllocColors(geom,1)!=Success)) {
396         return NULL;
397     }
398     color= &geom->colors[geom->num_colors];
399     color->pixel= pixel;
400     color->spec = strdup(spec);
401     if (!color->spec)
402         return NULL;
403     geom->num_colors++;
404     return color;
405 }
406
407 struct xkb_outline *
408 XkbcAddGeomOutline(struct xkb_shape * shape,int sz_points)
409 {
410 struct xkb_outline *    outline;
411
412     if ((!shape)||(sz_points<0))
413         return NULL;
414     if ((shape->num_outlines>=shape->sz_outlines)&&
415                                         (_XkbAllocOutlines(shape,1)!=Success)) {
416         return NULL;
417     }
418     outline= &shape->outlines[shape->num_outlines];
419     memset(outline, 0, sizeof(struct xkb_outline));
420     if ((sz_points>0)&&(_XkbAllocPoints(outline,sz_points)!=Success))
421         return NULL;
422     shape->num_outlines++;
423     return outline;
424 }
425
426 struct xkb_shape *
427 XkbcAddGeomShape(struct xkb_geometry * geom,uint32_t name,int sz_outlines)
428 {
429     struct xkb_shape *shape;
430     int i;
431
432     if ((!geom)||(!name)||(sz_outlines<0))
433         return NULL;
434     if (geom->num_shapes>0) {
435         for (shape=geom->shapes,i=0;i<geom->num_shapes;i++,shape++) {
436             if (name==shape->name)
437                 return shape;
438         }
439     }
440     if ((geom->num_shapes>=geom->sz_shapes)&&
441                                         (_XkbAllocShapes(geom,1)!=Success))
442         return NULL;
443     shape= &geom->shapes[geom->num_shapes];
444     memset(shape, 0, sizeof(struct xkb_shape));
445     if ((sz_outlines>0)&&(_XkbAllocOutlines(shape,sz_outlines)!=Success))
446         return NULL;
447     shape->name= name;
448     shape->primary= shape->approx= NULL;
449     geom->num_shapes++;
450     return shape;
451 }
452
453 struct xkb_key *
454 XkbcAddGeomKey(struct xkb_row * row)
455 {
456 struct xkb_key *        key;
457     if (!row)
458         return NULL;
459     if ((row->num_keys>=row->sz_keys)&&(_XkbAllocKeys(row,1)!=Success))
460         return NULL;
461     key= &row->keys[row->num_keys++];
462     memset(key, 0, sizeof(struct xkb_key));
463     return key;
464 }
465
466 struct xkb_row *
467 XkbcAddGeomRow(struct xkb_section * section,int sz_keys)
468 {
469 struct xkb_row *        row;
470
471     if ((!section)||(sz_keys<0))
472         return NULL;
473     if ((section->num_rows>=section->sz_rows)&&
474                                         (_XkbAllocRows(section,1)!=Success))
475         return NULL;
476     row= &section->rows[section->num_rows];
477     memset(row, 0, sizeof(struct xkb_row));
478     if ((sz_keys>0)&&(_XkbAllocKeys(row,sz_keys)!=Success))
479         return NULL;
480     section->num_rows++;
481     return row;
482 }
483
484 struct xkb_section *
485 XkbcAddGeomSection(     struct xkb_geometry *   geom,
486                         uint32_t                name,
487                         int             sz_rows,
488                         int             sz_doodads,
489                         int             sz_over)
490 {
491     int i;
492     struct xkb_section *        section;
493
494     if ((!geom)||(name==None)||(sz_rows<0))
495         return NULL;
496     for (i=0,section=geom->sections;i<geom->num_sections;i++,section++) {
497         if (section->name!=name)
498             continue;
499         if (((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))||
500             ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success))||
501             ((sz_over>0)&&(_XkbAllocOverlays(section,sz_over)!=Success)))
502             return NULL;
503         return section;
504     }
505     if ((geom->num_sections>=geom->sz_sections)&&
506                                         (_XkbAllocSections(geom,1)!=Success))
507         return NULL;
508     section= &geom->sections[geom->num_sections];
509     if ((sz_rows>0)&&(_XkbAllocRows(section,sz_rows)!=Success))
510         return NULL;
511     if ((sz_doodads>0)&&(_XkbAllocDoodads(section,sz_doodads)!=Success)) {
512         free(section->rows);
513         section->rows= NULL;
514         section->sz_rows= section->num_rows= 0;
515         return NULL;
516     }
517     section->name= name;
518     geom->num_sections++;
519     return section;
520 }
521
522 union xkb_doodad *
523 XkbcAddGeomDoodad(struct xkb_geometry * geom,struct xkb_section * section,uint32_t name)
524 {
525     union xkb_doodad *old, *doodad;
526     int i, nDoodads;
527
528     if ((!geom)||(name==None))
529         return NULL;
530     if ((section!=NULL)&&(section->num_doodads>0)) {
531         old= section->doodads;
532         nDoodads= section->num_doodads;
533     }
534     else {
535         old= geom->doodads;
536         nDoodads= geom->num_doodads;
537     }
538     for (i=0,doodad=old;i<nDoodads;i++,doodad++) {
539         if (doodad->any.name==name)
540             return doodad;
541     }
542     if (section) {
543         if ((section->num_doodads>=geom->sz_doodads)&&
544             (_XkbAllocDoodads(section,1)!=Success)) {
545             return NULL;
546         }
547         doodad= &section->doodads[section->num_doodads++];
548     }
549     else {
550         if ((geom->num_doodads>=geom->sz_doodads)&&
551                                         (_XkbAllocDoodads(geom,1)!=Success))
552             return NULL;
553         doodad= &geom->doodads[geom->num_doodads++];
554     }
555     memset(doodad, 0, sizeof(union xkb_doodad));
556     doodad->any.name= name;
557     return doodad;
558 }
559
560 struct xkb_overlay_row *
561 XkbcAddGeomOverlayRow(struct xkb_overlay * overlay,int row_under,int sz_keys)
562 {
563     int i;
564     struct xkb_overlay_row *row;
565
566     if ((!overlay)||(sz_keys<0))
567         return NULL;
568     if (row_under>=overlay->section_under->num_rows)
569         return NULL;
570     for (i=0;i<overlay->num_rows;i++) {
571         if (overlay->rows[i].row_under==row_under) {
572             row= &overlay->rows[i];
573             if ((row->sz_keys<sz_keys)&&
574                                 (_XkbAllocOverlayKeys(row,sz_keys)!=Success)) {
575                 return NULL;
576             }
577             return &overlay->rows[i];
578         }
579     }
580     if ((overlay->num_rows>=overlay->sz_rows)&&
581                                 (_XkbAllocOverlayRows(overlay,1)!=Success))
582         return NULL;
583     row= &overlay->rows[overlay->num_rows];
584     memset(row, 0, sizeof(struct xkb_overlay_row));
585     if ((sz_keys>0)&&(_XkbAllocOverlayKeys(row,sz_keys)!=Success))
586         return NULL;
587     row->row_under= row_under;
588     overlay->num_rows++;
589     return row;
590 }
591
592 struct xkb_overlay *
593 XkbcAddGeomOverlay(struct xkb_section * section,uint32_t name,int sz_rows)
594 {
595     int i;
596     struct xkb_overlay *overlay;
597
598     if ((!section)||(name==None)||(sz_rows==0))
599         return NULL;
600
601     for (i=0,overlay=section->overlays;i<section->num_overlays;i++,overlay++) {
602         if (overlay->name==name) {
603             if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success))
604                 return NULL;
605             return overlay;
606         }
607     }
608     if ((section->num_overlays>=section->sz_overlays)&&
609                                 (_XkbAllocOverlays(section,1)!=Success))
610         return NULL;
611     overlay= &section->overlays[section->num_overlays];
612     if ((sz_rows>0)&&(_XkbAllocOverlayRows(overlay,sz_rows)!=Success))
613         return NULL;
614     overlay->name= name;
615     overlay->section_under= section;
616     section->num_overlays++;
617     return overlay;
618 }