2 * $RCSId: xc/lib/fontconfig/src/fcpat.c,v 1.18 2002/09/18 17:11:46 tsi Exp $
4 * Copyright © 2000 Keith Packard
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. Keith Packard makes no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
31 FcPatternCreate (void)
35 p
= (FcPattern
*) malloc (sizeof (FcPattern
));
38 FcMemAlloc (FC_MEM_PATTERN
, sizeof (FcPattern
));
47 FcValueDestroy (FcValue v
)
51 FcStrFree ((FcChar8
*) v
.u
.s
);
54 FcMatrixFree ((FcMatrix
*) v
.u
.m
);
57 FcCharSetDestroy ((FcCharSet
*) v
.u
.c
);
60 FcLangSetDestroy ((FcLangSet
*) v
.u
.l
);
68 FcValueSave (FcValue v
)
72 v
.u
.s
= FcStrCopy (v
.u
.s
);
77 v
.u
.m
= FcMatrixCopy (v
.u
.m
);
82 v
.u
.c
= FcCharSetCopy ((FcCharSet
*) v
.u
.c
);
87 v
.u
.l
= FcLangSetCopy (v
.u
.l
);
98 FcValueListDestroy (FcValueList
*l
)
103 switch (l
->value
.type
) {
105 FcStrFree ((FcChar8
*) l
->value
.u
.s
);
108 FcMatrixFree ((FcMatrix
*) l
->value
.u
.m
);
111 FcCharSetDestroy ((FcCharSet
*) l
->value
.u
.c
);
114 FcLangSetDestroy ((FcLangSet
*) l
->value
.u
.l
);
120 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
126 FcValueEqual (FcValue va
, FcValue vb
)
128 if (va
.type
!= vb
.type
)
130 if (va
.type
== FcTypeInteger
)
132 va
.type
= FcTypeDouble
;
135 if (vb
.type
== FcTypeInteger
)
137 vb
.type
= FcTypeDouble
;
140 if (va
.type
!= vb
.type
)
147 return va
.u
.i
== vb
.u
.i
;
149 return va
.u
.d
== vb
.u
.d
;
151 return FcStrCmpIgnoreCase (va
.u
.s
, vb
.u
.s
) == 0;
153 return va
.u
.b
== vb
.u
.b
;
155 return FcMatrixEqual (va
.u
.m
, vb
.u
.m
);
157 return FcCharSetEqual (va
.u
.c
, vb
.u
.c
);
159 return va
.u
.f
== vb
.u
.f
;
161 return FcLangSetEqual (va
.u
.l
, vb
.u
.l
);
167 FcDoubleHash (double d
)
177 FcStringHash (const FcChar8
*s
)
184 h
= ((h
<< 1) | (h
>> 31)) ^ c
;
189 FcValueHash (FcValue v
)
195 return (FcChar32
) v
.u
.i
;
197 return FcDoubleHash (v
.u
.d
);
199 return FcStringHash (v
.u
.s
);
201 return (FcChar32
) v
.u
.b
;
203 return (FcDoubleHash (v
.u
.m
->xx
) ^
204 FcDoubleHash (v
.u
.m
->xy
) ^
205 FcDoubleHash (v
.u
.m
->yx
) ^
206 FcDoubleHash (v
.u
.m
->yy
));
208 return (FcChar32
) v
.u
.c
->num
;
210 return FcStringHash ((const FcChar8
*) ((FT_Face
) v
.u
.f
)->family_name
) ^
211 FcStringHash ((const FcChar8
*) ((FT_Face
) v
.u
.f
)->style_name
);
213 return FcLangSetHash (v
.u
.l
);
219 FcValueListEqual (FcValueList
*la
, FcValueList
*lb
)
226 if (!FcValueEqual (la
->value
, lb
->value
))
237 FcValueListHash (FcValueList
*l
)
243 hash
= ((hash
<< 1) | (hash
>> 31)) ^ FcValueHash (l
->value
);
250 FcPatternDestroy (FcPattern
*p
)
254 if (p
->ref
== FC_REF_CONSTANT
|| --p
->ref
> 0)
257 for (i
= 0; i
< p
->num
; i
++)
258 FcValueListDestroy (p
->elts
[i
].values
);
263 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
268 FcMemFree (FC_MEM_PATTERN
, sizeof (FcPattern
));
272 #define FC_VALUE_LIST_HASH_SIZE 257
273 #define FC_PATTERN_HASH_SIZE 67
275 typedef struct _FcValueListEnt FcValueListEnt
;
277 struct _FcValueListEnt
{
278 FcValueListEnt
*next
;
283 typedef union _FcValueListAlign
{
288 static int FcValueListFrozenCount
[FcTypeLangSet
+ 1];
289 static int FcValueListFrozenBytes
[FcTypeLangSet
+ 1];
290 static char *FcValueListFrozenName
[] = {
303 FcValueListReport (void);
306 FcValueListReport (void)
310 printf ("Fc Frozen Values:\n");
311 printf ("\t%8s %9s %9s\n", "Type", "Count", "Bytes");
312 for (t
= FcTypeVoid
; t
<= FcTypeLangSet
; t
++)
313 printf ("\t%8s %9d %9d\n", FcValueListFrozenName
[t
],
314 FcValueListFrozenCount
[t
], FcValueListFrozenBytes
[t
]);
317 static FcValueListEnt
*
318 FcValueListEntCreate (FcValueList
*h
)
320 FcValueListAlign
*ea
;
322 FcValueList
*l
, *new;
327 for (l
= h
; l
; l
= l
->next
)
329 size
= sizeof (FcValueListAlign
) + n
* sizeof (FcValueList
);
330 FcValueListFrozenCount
[h
->value
.type
]++;
331 FcValueListFrozenBytes
[h
->value
.type
] += size
;
335 FcMemAlloc (FC_MEM_VALLIST
, size
);
337 e
->list
= (FcValueList
*) (ea
+ 1);
339 for (l
= h
; l
; l
= l
->next
, new++)
341 if (l
->value
.type
== FcTypeString
)
343 new->value
.type
= FcTypeString
;
344 new->value
.u
.s
= FcObjectStaticName (l
->value
.u
.s
);
348 new->value
= FcValueSave (l
->value
);
350 new->binding
= l
->binding
;
360 FcValueListEntDestroy (FcValueListEnt
*e
)
364 FcValueListFrozenCount
[e
->list
->value
.type
]--;
366 /* XXX: We should perform these two operations with "size" as
367 computed in FcValueListEntCreate, but we don't have access to
368 that value here. Without this, the FcValueListFrozenBytes
369 values will be wrong as will the FcMemFree counts.
371 FcValueListFrozenBytes[e->list->value.type] -= size;
372 FcMemFree (FC_MEM_VALLIST, size);
375 for (l
= e
->list
; l
; l
= l
->next
)
377 if (l
->value
.type
!= FcTypeString
)
378 FcValueDestroy (l
->value
);
380 /* XXX: Are we being too chummy with the implementation here to
381 free(e) when it was actually the enclosing FcValueListAlign
382 that was allocated? */
386 static int FcValueListTotal
;
387 static int FcValueListUsed
;
389 static FcValueListEnt
*FcValueListHashTable
[FC_VALUE_LIST_HASH_SIZE
];
392 FcValueListFreeze (FcValueList
*l
)
394 FcChar32 hash
= FcValueListHash (l
);
395 FcValueListEnt
**bucket
= &FcValueListHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
399 for (ent
= *bucket
; ent
; ent
= ent
->next
)
401 if (ent
->hash
== hash
&& FcValueListEqual (ent
->list
, l
))
405 ent
= FcValueListEntCreate (l
);
417 FcValueListThawAll (void)
420 FcValueListEnt
*ent
, *next
;
422 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
424 for (ent
= FcValueListHashTable
[i
]; ent
; ent
= next
)
427 FcValueListEntDestroy (ent
);
429 FcValueListHashTable
[i
] = 0;
432 FcValueListTotal
= 0;
437 FcPatternBaseHash (FcPattern
*b
)
439 FcChar32 hash
= b
->num
;
442 for (i
= 0; i
< b
->num
; i
++)
443 hash
= ((hash
<< 1) | (hash
>> 31)) ^ ((long) b
->elts
[i
].values
);
447 typedef struct _FcPatternEnt FcPatternEnt
;
449 struct _FcPatternEnt
{
455 static int FcPatternTotal
;
456 static int FcPatternUsed
;
458 static FcPatternEnt
*FcPatternHashTable
[FC_VALUE_LIST_HASH_SIZE
];
461 FcPatternBaseFreeze (FcPattern
*b
)
463 FcChar32 hash
= FcPatternBaseHash (b
);
464 FcPatternEnt
**bucket
= &FcPatternHashTable
[hash
% FC_VALUE_LIST_HASH_SIZE
];
470 for (ent
= *bucket
; ent
; ent
= ent
->next
)
472 if (ent
->hash
== hash
&& b
->num
== ent
->pattern
.num
)
474 for (i
= 0; i
< b
->num
; i
++)
476 if (b
->elts
[i
].object
!= ent
->pattern
.elts
[i
].object
)
478 if (b
->elts
[i
].values
!= ent
->pattern
.elts
[i
].values
)
482 return &ent
->pattern
;
487 * Compute size of pattern + elts
489 size
= sizeof (FcPatternEnt
) + b
->num
*sizeof (FcPatternElt
);
494 FcMemAlloc (FC_MEM_PATTERN
, size
);
497 ent
->pattern
.elts
= (FcPatternElt
*) (ent
+ 1);
498 ent
->pattern
.num
= b
->num
;
499 ent
->pattern
.size
= b
->num
;
500 ent
->pattern
.ref
= FC_REF_CONSTANT
;
502 for (i
= 0; i
< b
->num
; i
++)
504 ent
->pattern
.elts
[i
].values
= b
->elts
[i
].values
;
505 ent
->pattern
.elts
[i
].object
= b
->elts
[i
].object
;
511 return &ent
->pattern
;
515 FcPatternBaseThawAll (void)
518 FcPatternEnt
*ent
, *next
;
520 for (i
= 0; i
< FC_VALUE_LIST_HASH_SIZE
; i
++)
522 for (ent
= FcPatternHashTable
[i
]; ent
; ent
= next
)
527 FcPatternHashTable
[i
] = 0;
535 FcPatternFreeze (FcPattern
*p
)
537 FcPattern
*b
, *n
= 0;
541 if (p
->ref
== FC_REF_CONSTANT
)
544 size
= sizeof (FcPattern
) + p
->num
* sizeof (FcPatternElt
);
545 b
= (FcPattern
*) malloc (size
);
548 FcMemAlloc (FC_MEM_PATTERN
, size
);
552 b
->elts
= (FcPatternElt
*) (b
+ 1);
554 * Freeze object lists
556 for (i
= 0; i
< p
->num
; i
++)
558 b
->elts
[i
].object
= p
->elts
[i
].object
;
559 b
->elts
[i
].values
= FcValueListFreeze (p
->elts
[i
].values
);
560 if (!b
->elts
[i
].values
)
566 n
= FcPatternBaseFreeze (b
);
568 if (FcDebug() & FC_DBG_MEMORY
)
570 printf ("ValueLists: total %9d used %9d\n", FcValueListTotal
, FcValueListUsed
);
571 printf ("Patterns: total %9d used %9d\n", FcPatternTotal
, FcPatternUsed
);
577 assert (FcPatternEqual (n
, p
));
583 FcPatternThawAll (void)
585 FcPatternBaseThawAll ();
586 FcValueListThawAll ();
590 FcPatternPosition (const FcPattern
*p
, const char *object
)
592 int low
, high
, mid
, c
;
594 object
= FcObjectStaticName(object
);
601 mid
= (low
+ high
) >> 1;
602 c
= p
->elts
[mid
].object
- object
;
616 FcPatternFindElt (const FcPattern
*p
, const char *object
)
618 int i
= FcPatternPosition (p
, object
);
625 FcPatternInsertElt (FcPattern
*p
, const char *object
)
630 i
= FcPatternPosition (p
, object
);
636 if (p
->num
+ 1 >= p
->size
)
638 int s
= p
->size
+ 16;
640 e
= (FcPatternElt
*) realloc (p
->elts
, s
* sizeof (FcPatternElt
));
642 e
= (FcPatternElt
*) malloc (s
* sizeof (FcPatternElt
));
647 FcMemFree (FC_MEM_PATELT
, p
->size
* sizeof (FcPatternElt
));
648 FcMemAlloc (FC_MEM_PATELT
, s
* sizeof (FcPatternElt
));
651 p
->elts
[p
->size
].object
= 0;
652 p
->elts
[p
->size
].values
= 0;
658 memmove (p
->elts
+ i
+ 1,
660 sizeof (FcPatternElt
) *
666 p
->elts
[i
].object
= FcObjectStaticName (object
);
667 p
->elts
[i
].values
= 0;
674 FcPatternEqual (const FcPattern
*pa
, const FcPattern
*pb
)
681 if (pa
->num
!= pb
->num
)
683 for (i
= 0; i
< pa
->num
; i
++)
685 if (pa
->elts
[i
].object
!= pb
->elts
[i
].object
)
687 if (!FcValueListEqual (pa
->elts
[i
].values
, pb
->elts
[i
].values
))
694 FcPatternHash (const FcPattern
*p
)
699 for (i
= 0; i
< p
->num
; i
++)
701 h
= (((h
<< 1) | (h
>> 31)) ^
702 FcStringHash ((const FcChar8
*) p
->elts
[i
].object
) ^
703 FcValueListHash (p
->elts
[i
].values
));
709 FcPatternEqualSubset (const FcPattern
*pa
, const FcPattern
*pb
, const FcObjectSet
*os
)
711 FcPatternElt
*ea
, *eb
;
714 for (i
= 0; i
< os
->nobject
; i
++)
716 ea
= FcPatternFindElt (pa
, os
->objects
[i
]);
717 eb
= FcPatternFindElt (pb
, os
->objects
[i
]);
722 if (!FcValueListEqual (ea
->values
, eb
->values
))
735 FcPatternAddWithBinding (FcPattern
*p
,
738 FcValueBinding binding
,
742 FcValueList
*new, **prev
;
744 if (p
->ref
== FC_REF_CONSTANT
)
747 new = (FcValueList
*) malloc (sizeof (FcValueList
));
751 FcMemAlloc (FC_MEM_VALLIST
, sizeof (FcValueList
));
753 value
= FcValueSave (value
);
754 if (value
.type
== FcTypeVoid
)
758 new->binding
= binding
;
761 e
= FcPatternInsertElt (p
, object
);
767 for (prev
= &e
->values
; *prev
; prev
= &(*prev
)->next
);
772 new->next
= e
->values
;
779 switch (value
.type
) {
781 FcStrFree ((FcChar8
*) value
.u
.s
);
784 FcMatrixFree ((FcMatrix
*) value
.u
.m
);
787 FcCharSetDestroy ((FcCharSet
*) value
.u
.c
);
790 FcLangSetDestroy ((FcLangSet
*) value
.u
.l
);
796 FcMemFree (FC_MEM_VALLIST
, sizeof (FcValueList
));
803 FcPatternAdd (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
805 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingStrong
, append
);
809 FcPatternAddWeak (FcPattern
*p
, const char *object
, FcValue value
, FcBool append
)
811 return FcPatternAddWithBinding (p
, object
, value
, FcValueBindingWeak
, append
);
815 FcPatternDel (FcPattern
*p
, const char *object
)
820 e
= FcPatternFindElt (p
, object
);
827 FcValueListDestroy (e
->values
);
829 /* shuffle existing ones down */
830 memmove (e
, e
+1, (p
->elts
+ p
->num
- (e
+ 1)) * sizeof (FcPatternElt
));
832 p
->elts
[p
->num
].object
= 0;
833 p
->elts
[p
->num
].values
= 0;
838 FcPatternRemove (FcPattern
*p
, const char *object
, int id
)
841 FcValueList
**prev
, *l
;
843 e
= FcPatternFindElt (p
, object
);
846 for (prev
= &e
->values
; (l
= *prev
); prev
= &l
->next
)
852 FcValueListDestroy (l
);
854 FcPatternDel (p
, object
);
863 FcPatternAddInteger (FcPattern
*p
, const char *object
, int i
)
867 v
.type
= FcTypeInteger
;
869 return FcPatternAdd (p
, object
, v
, FcTrue
);
873 FcPatternAddDouble (FcPattern
*p
, const char *object
, double d
)
877 v
.type
= FcTypeDouble
;
879 return FcPatternAdd (p
, object
, v
, FcTrue
);
884 FcPatternAddString (FcPattern
*p
, const char *object
, const FcChar8
*s
)
888 v
.type
= FcTypeString
;
890 return FcPatternAdd (p
, object
, v
, FcTrue
);
894 FcPatternAddMatrix (FcPattern
*p
, const char *object
, const FcMatrix
*s
)
898 v
.type
= FcTypeMatrix
;
899 v
.u
.m
= (FcMatrix
*) s
;
900 return FcPatternAdd (p
, object
, v
, FcTrue
);
905 FcPatternAddBool (FcPattern
*p
, const char *object
, FcBool b
)
911 return FcPatternAdd (p
, object
, v
, FcTrue
);
915 FcPatternAddCharSet (FcPattern
*p
, const char *object
, const FcCharSet
*c
)
919 v
.type
= FcTypeCharSet
;
920 v
.u
.c
= (FcCharSet
*) c
;
921 return FcPatternAdd (p
, object
, v
, FcTrue
);
925 FcPatternAddFTFace (FcPattern
*p
, const char *object
, const FT_Face f
)
929 v
.type
= FcTypeFTFace
;
931 return FcPatternAdd (p
, object
, v
, FcTrue
);
935 FcPatternAddLangSet (FcPattern
*p
, const char *object
, const FcLangSet
*ls
)
939 v
.type
= FcTypeLangSet
;
940 v
.u
.l
= (FcLangSet
*) ls
;
941 return FcPatternAdd (p
, object
, v
, FcTrue
);
945 FcPatternGet (const FcPattern
*p
, const char *object
, int id
, FcValue
*v
)
950 e
= FcPatternFindElt (p
, object
);
952 return FcResultNoMatch
;
953 for (l
= e
->values
; l
; l
= l
->next
)
958 return FcResultMatch
;
966 FcPatternGetInteger (const FcPattern
*p
, const char *object
, int id
, int *i
)
971 r
= FcPatternGet (p
, object
, id
, &v
);
972 if (r
!= FcResultMatch
)
982 return FcResultTypeMismatch
;
984 return FcResultMatch
;
988 FcPatternGetDouble (const FcPattern
*p
, const char *object
, int id
, double *d
)
993 r
= FcPatternGet (p
, object
, id
, &v
);
994 if (r
!= FcResultMatch
)
1001 *d
= (double) v
.u
.i
;
1004 return FcResultTypeMismatch
;
1006 return FcResultMatch
;
1010 FcPatternGetString (const FcPattern
*p
, const char *object
, int id
, FcChar8
** s
)
1015 r
= FcPatternGet (p
, object
, id
, &v
);
1016 if (r
!= FcResultMatch
)
1018 if (v
.type
!= FcTypeString
)
1019 return FcResultTypeMismatch
;
1020 *s
= (FcChar8
*) v
.u
.s
;
1021 return FcResultMatch
;
1025 FcPatternGetMatrix(const FcPattern
*p
, const char *object
, int id
, FcMatrix
**m
)
1030 r
= FcPatternGet (p
, object
, id
, &v
);
1031 if (r
!= FcResultMatch
)
1033 if (v
.type
!= FcTypeMatrix
)
1034 return FcResultTypeMismatch
;
1035 *m
= (FcMatrix
*) v
.u
.m
;
1036 return FcResultMatch
;
1041 FcPatternGetBool(const FcPattern
*p
, const char *object
, int id
, FcBool
*b
)
1046 r
= FcPatternGet (p
, object
, id
, &v
);
1047 if (r
!= FcResultMatch
)
1049 if (v
.type
!= FcTypeBool
)
1050 return FcResultTypeMismatch
;
1052 return FcResultMatch
;
1056 FcPatternGetCharSet(const FcPattern
*p
, const char *object
, int id
, FcCharSet
**c
)
1061 r
= FcPatternGet (p
, object
, id
, &v
);
1062 if (r
!= FcResultMatch
)
1064 if (v
.type
!= FcTypeCharSet
)
1065 return FcResultTypeMismatch
;
1066 *c
= (FcCharSet
*) v
.u
.c
;
1067 return FcResultMatch
;
1071 FcPatternGetFTFace(const FcPattern
*p
, const char *object
, int id
, FT_Face
*f
)
1076 r
= FcPatternGet (p
, object
, id
, &v
);
1077 if (r
!= FcResultMatch
)
1079 if (v
.type
!= FcTypeFTFace
)
1080 return FcResultTypeMismatch
;
1081 *f
= (FT_Face
) v
.u
.f
;
1082 return FcResultMatch
;
1086 FcPatternGetLangSet(const FcPattern
*p
, const char *object
, int id
, FcLangSet
**ls
)
1091 r
= FcPatternGet (p
, object
, id
, &v
);
1092 if (r
!= FcResultMatch
)
1094 if (v
.type
!= FcTypeLangSet
)
1095 return FcResultTypeMismatch
;
1096 *ls
= (FcLangSet
*) v
.u
.l
;
1097 return FcResultMatch
;
1101 FcPatternDuplicate (const FcPattern
*orig
)
1107 new = FcPatternCreate ();
1111 for (i
= 0; i
< orig
->num
; i
++)
1113 for (l
= orig
->elts
[i
].values
; l
; l
= l
->next
)
1114 if (!FcPatternAdd (new, orig
->elts
[i
].object
, l
->value
, FcTrue
))
1121 FcPatternDestroy (new);
1127 FcPatternReference (FcPattern
*p
)
1129 if (p
->ref
!= FC_REF_CONSTANT
)
1134 FcPatternVaBuild (FcPattern
*orig
, va_list va
)
1138 FcPatternVapBuild (ret
, orig
, va
);
1143 FcPatternBuild (FcPattern
*orig
, ...)
1147 va_start (va
, orig
);
1148 FcPatternVapBuild (orig
, orig
, va
);
1154 * Add all of the elements in 's' to 'p'
1157 FcPatternAppend (FcPattern
*p
, FcPattern
*s
)
1163 for (i
= 0; i
< s
->num
; i
++)
1166 for (v
= e
->values
; v
; v
= v
->next
)
1168 if (!FcPatternAddWithBinding (p
, e
->object
,
1169 v
->value
, v
->binding
, FcTrue
))
1177 FcObjectStaticName (const char *name
)
1179 #define OBJECT_HASH_SIZE 31
1180 static struct objectBucket
{
1181 struct objectBucket
*next
;
1183 } *buckets
[OBJECT_HASH_SIZE
];
1184 FcChar32 hash
= FcStringHash ((const FcChar8
*) name
);
1185 struct objectBucket
**p
;
1186 struct objectBucket
*b
;
1189 for (p
= &buckets
[hash
% OBJECT_HASH_SIZE
]; (b
= *p
); p
= &(b
->next
))
1190 if (b
->hash
== hash
&& !strcmp (name
, (char *) (b
+ 1)))
1191 return (char *) (b
+ 1);
1192 size
= sizeof (struct objectBucket
) + strlen (name
) + 1;
1194 FcMemAlloc (FC_MEM_STATICSTR
, size
);
1199 strcpy ((char *) (b
+ 1), name
);
1201 return (char *) (b
+ 1);