]> git.wh0rd.org - fontconfig.git/blame - src/fclang.c
Add FcGetLangs() and FcLangGetCharSet().
[fontconfig.git] / src / fclang.c
CommitLineData
3de8881e 1/*
793e946c 2 * $RCSId: xc/lib/fontconfig/src/fclang.c,v 1.7 2002/08/26 23:34:31 keithp Exp $
3de8881e 3 *
46b51147 4 * Copyright © 2002 Keith Packard
3de8881e
KP
5 *
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.
15 *
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.
23 */
24
25#include "fcint.h"
26
27typedef struct {
e85789a9 28 const FcChar8 lang[8];
21696e5b 29 const FcCharSet charset;
3de8881e
KP
30} FcLangCharSet;
31
793e946c
KP
32typedef struct {
33 int begin;
34 int end;
35} FcLangCharSetRange;
36
e50b9ae7 37#include "../fc-lang/fclang.h"
3de8881e 38
d8d73958
KP
39struct _FcLangSet {
40 FcChar32 map[NUM_LANG_SET_MAP];
4262e0b3 41 FcStrSet *extra;
d8d73958
KP
42};
43
44#define FcLangSetBitSet(ls, id) ((ls)->map[(id)>>5] |= ((FcChar32) 1 << ((id) & 0x1f)))
45#define FcLangSetBitGet(ls, id) (((ls)->map[(id)>>5] >> ((id) & 0x1f)) & 1)
46
47FcLangSet *
48FcFreeTypeLangSet (const FcCharSet *charset,
e50b9ae7 49 const FcChar8 *exclusiveLang)
3de8881e 50{
cd2ec1a9 51 int i, j;
e50b9ae7 52 FcChar32 missing;
e50b9ae7 53 const FcCharSet *exclusiveCharset = 0;
d8d73958 54 FcLangSet *ls;
82f35f8b 55
e50b9ae7 56 if (exclusiveLang)
cf223cc7 57 exclusiveCharset = FcLangGetCharSet (exclusiveLang);
d8d73958
KP
58 ls = FcLangSetCreate ();
59 if (!ls)
60 return 0;
7ce19673
KP
61 if (FcDebug() & FC_DBG_LANGSET)
62 {
63 printf ("font charset\n");
64 FcCharSetPrint (charset);
65 printf ("\n");
66 }
3de8881e
KP
67 for (i = 0; i < NUM_LANG_CHAR_SET; i++)
68 {
7ce19673
KP
69 if (FcDebug() & FC_DBG_LANGSET)
70 {
71 printf ("%s charset\n", fcLangCharSets[i].lang);
72 FcCharSetPrint (&fcLangCharSets[i].charset);
73 printf ("\n");
74 }
75
e50b9ae7
KP
76 /*
77 * Check for Han charsets to make fonts
78 * which advertise support for a single language
79 * not support other Han languages
80 */
81 if (exclusiveCharset &&
cd2ec1a9 82 FcFreeTypeIsExclusiveLang (fcLangCharSets[i].lang))
e50b9ae7 83 {
cd2ec1a9
PL
84 if (fcLangCharSets[i].charset.num != exclusiveCharset->num)
85 continue;
86
87 for (j = 0; j < fcLangCharSets[i].charset.num; j++)
7ce19673
KP
88 if (FcCharSetLeaf(&fcLangCharSets[i].charset, j) !=
89 FcCharSetLeaf(exclusiveCharset, j))
cd2ec1a9 90 continue;
e50b9ae7 91 }
3de8881e
KP
92 missing = FcCharSetSubtractCount (&fcLangCharSets[i].charset, charset);
93 if (FcDebug() & FC_DBG_SCANV)
c80d2ac4
KP
94 {
95 if (missing && missing < 10)
96 {
97 FcCharSet *missed = FcCharSetSubtract (&fcLangCharSets[i].charset,
98 charset);
99 FcChar32 ucs4;
100 FcChar32 map[FC_CHARSET_MAP_SIZE];
101 FcChar32 next;
102
0d745819 103 printf ("\n%s(%u) ", fcLangCharSets[i].lang, missing);
c80d2ac4
KP
104 printf ("{");
105 for (ucs4 = FcCharSetFirstPage (missed, map, &next);
106 ucs4 != FC_CHARSET_DONE;
107 ucs4 = FcCharSetNextPage (missed, map, &next))
108 {
109 int i, j;
110 for (i = 0; i < FC_CHARSET_MAP_SIZE; i++)
111 if (map[i])
112 {
113 for (j = 0; j < 32; j++)
114 if (map[i] & (1 << j))
115 printf (" %04x", ucs4 + i * 32 + j);
116 }
117 }
118 printf (" }\n\t");
119 FcCharSetDestroy (missed);
120 }
121 else
0d745819 122 printf ("%s(%u) ", fcLangCharSets[i].lang, missing);
c80d2ac4 123 }
e50b9ae7 124 if (!missing)
d8d73958 125 FcLangSetBitSet (ls, i);
3de8881e 126 }
e50b9ae7 127
3de8881e
KP
128 if (FcDebug() & FC_DBG_SCANV)
129 printf ("\n");
d8d73958
KP
130
131
132 return ls;
3de8881e
KP
133}
134
d8d73958 135#define FcLangEnd(c) ((c) == '-' || (c) == '\0')
3de8881e
KP
136
137FcLangResult
138FcLangCompare (const FcChar8 *s1, const FcChar8 *s2)
139{
3de8881e 140 FcChar8 c1, c2;
d8d73958
KP
141 FcLangResult result = FcLangDifferentLang;
142
3de8881e
KP
143 for (;;)
144 {
145 c1 = *s1++;
146 c2 = *s2++;
d8d73958 147
3de8881e
KP
148 c1 = FcToLower (c1);
149 c2 = FcToLower (c2);
150 if (c1 != c2)
d8d73958
KP
151 {
152 if (FcLangEnd (c1) && FcLangEnd (c2))
c833409f 153 result = FcLangDifferentTerritory;
d8d73958
KP
154 return result;
155 }
156 else if (!c1)
157 return FcLangEqual;
158 else if (c1 == '-')
c833409f 159 result = FcLangDifferentTerritory;
3de8881e 160 }
3de8881e
KP
161}
162
793e946c 163/*
74a623e0 164 * Return FcTrue when super contains sub.
793e946c 165 *
74a623e0
KP
166 * super contains sub if super and sub have the same
167 * language and either the same country or one
168 * is missing the country
793e946c
KP
169 */
170
171static FcBool
74a623e0 172FcLangContains (const FcChar8 *super, const FcChar8 *sub)
793e946c
KP
173{
174 FcChar8 c1, c2;
175
176 for (;;)
177 {
74a623e0
KP
178 c1 = *super++;
179 c2 = *sub++;
793e946c
KP
180
181 c1 = FcToLower (c1);
182 c2 = FcToLower (c2);
183 if (c1 != c2)
184 {
74a623e0 185 /* see if super has a country while sub is mising one */
793e946c
KP
186 if (c1 == '-' && c2 == '\0')
187 return FcTrue;
74a623e0
KP
188 /* see if sub has a country while super is mising one */
189 if (c1 == '\0' && c2 == '-')
190 return FcTrue;
793e946c
KP
191 return FcFalse;
192 }
193 else if (!c1)
194 return FcTrue;
195 }
196}
197
3de8881e 198const FcCharSet *
cf223cc7 199FcLangGetCharSet (const FcChar8 *lang)
3de8881e
KP
200{
201 int i;
202 int country = -1;
82f35f8b 203
3de8881e
KP
204 for (i = 0; i < NUM_LANG_CHAR_SET; i++)
205 {
206 switch (FcLangCompare (lang, fcLangCharSets[i].lang)) {
207 case FcLangEqual:
208 return &fcLangCharSets[i].charset;
c833409f 209 case FcLangDifferentTerritory:
3de8881e
KP
210 if (country == -1)
211 country = i;
212 default:
213 break;
214 }
215 }
216 if (country == -1)
217 return 0;
b36f2a39 218 return &fcLangCharSets[country].charset;
3de8881e 219}
d8d73958 220
cf223cc7
BE
221FcStrSet *
222FcGetLangs (void)
223{
224 FcStrSet *langs;
225 int i;
226
227 langs = FcStrSetCreate();
228 if (!langs)
229 return 0;
230
231 for (i = 0; i < NUM_LANG_CHAR_SET; i++)
232 FcStrSetAdd (langs, fcLangCharSets[i].lang);
233
234 return langs;
235}
236
d8d73958
KP
237FcLangSet *
238FcLangSetCreate (void)
239{
240 FcLangSet *ls;
241
242 ls = malloc (sizeof (FcLangSet));
243 if (!ls)
244 return 0;
245 FcMemAlloc (FC_MEM_LANGSET, sizeof (FcLangSet));
246 memset (ls->map, '\0', sizeof (ls->map));
4262e0b3 247 ls->extra = 0;
d8d73958
KP
248 return ls;
249}
250
251void
252FcLangSetDestroy (FcLangSet *ls)
253{
4262e0b3
PL
254 if (ls->extra)
255 FcStrSetDestroy (ls->extra);
d8d73958
KP
256 FcMemFree (FC_MEM_LANGSET, sizeof (FcLangSet));
257 free (ls);
258}
259
260FcLangSet *
261FcLangSetCopy (const FcLangSet *ls)
262{
263 FcLangSet *new;
264
265 new = FcLangSetCreate ();
266 if (!new)
267 goto bail0;
268 memcpy (new->map, ls->map, sizeof (new->map));
4262e0b3 269 if (ls->extra)
d8d73958
KP
270 {
271 FcStrList *list;
272 FcChar8 *extra;
273
4262e0b3
PL
274 new->extra = FcStrSetCreate ();
275 if (!new->extra)
d8d73958
KP
276 goto bail1;
277
4262e0b3 278 list = FcStrListCreate (ls->extra);
d8d73958
KP
279 if (!list)
280 goto bail1;
281
282 while ((extra = FcStrListNext (list)))
4262e0b3 283 if (!FcStrSetAdd (new->extra, extra))
d8d73958
KP
284 {
285 FcStrListDone (list);
286 goto bail1;
287 }
288 FcStrListDone (list);
289 }
290 return new;
291bail1:
292 FcLangSetDestroy (new);
293bail0:
294 return 0;
295}
296
297static int
298FcLangSetIndex (const FcChar8 *lang)
299{
12d49d3c
CW
300 int low, high, mid = 0;
301 int cmp = 0;
793e946c 302 FcChar8 firstChar = FcToLower(lang[0]);
947afeb5 303 FcChar8 secondChar = firstChar ? FcToLower(lang[1]) : '\0';
793e946c
KP
304
305 if (firstChar < 'a')
306 {
307 low = 0;
308 high = fcLangCharSetRanges[0].begin;
309 }
310 else if(firstChar > 'z')
311 {
312 low = fcLangCharSetRanges[25].begin;
313 high = NUM_LANG_CHAR_SET - 1;
314 }
315 else
316 {
317 low = fcLangCharSetRanges[firstChar - 'a'].begin;
318 high = fcLangCharSetRanges[firstChar - 'a'].end;
319 /* no matches */
320 if (low > high)
321 return -low; /* next entry after where it would be */
322 }
d8d73958 323
d8d73958
KP
324 while (low <= high)
325 {
326 mid = (high + low) >> 1;
793e946c
KP
327 if(fcLangCharSets[mid].lang[0] != firstChar)
328 cmp = FcStrCmpIgnoreCase(fcLangCharSets[mid].lang, lang);
329 else
330 { /* fast path for resolving 2-letter languages (by far the most common) after
331 * finding the first char (probably already true because of the hash table) */
947afeb5
KP
332 cmp = fcLangCharSets[mid].lang[1] - secondChar;
333 if (cmp == 0 &&
334 (fcLangCharSets[mid].lang[2] != '\0' ||
335 lang[2] != '\0'))
793e946c 336 {
947afeb5
KP
337 cmp = FcStrCmpIgnoreCase(fcLangCharSets[mid].lang+2,
338 lang+2);
793e946c 339 }
793e946c
KP
340 }
341 if (cmp == 0)
d8d73958
KP
342 return mid;
343 if (cmp < 0)
344 low = mid + 1;
345 else
346 high = mid - 1;
347 }
348 if (cmp < 0)
349 mid++;
350 return -(mid + 1);
351}
352
353FcBool
354FcLangSetAdd (FcLangSet *ls, const FcChar8 *lang)
355{
356 int id;
357
358 id = FcLangSetIndex (lang);
359 if (id >= 0)
360 {
361 FcLangSetBitSet (ls, id);
362 return FcTrue;
363 }
4262e0b3 364 if (!ls->extra)
d8d73958 365 {
4262e0b3
PL
366 ls->extra = FcStrSetCreate ();
367 if (!ls->extra)
d8d73958
KP
368 return FcFalse;
369 }
4262e0b3 370 return FcStrSetAdd (ls->extra, lang);
d8d73958
KP
371}
372
373FcLangResult
374FcLangSetHasLang (const FcLangSet *ls, const FcChar8 *lang)
375{
376 int id;
377 FcLangResult best, r;
378 int i;
379
380 id = FcLangSetIndex (lang);
2458a6d8
KP
381 if (id < 0)
382 id = -id - 1;
383 else if (FcLangSetBitGet (ls, id))
d8d73958 384 return FcLangEqual;
d8d73958
KP
385 best = FcLangDifferentLang;
386 for (i = id - 1; i >= 0; i--)
387 {
388 r = FcLangCompare (lang, fcLangCharSets[i].lang);
389 if (r == FcLangDifferentLang)
390 break;
391 if (FcLangSetBitGet (ls, i) && r < best)
392 best = r;
393 }
394 for (i = id; i < NUM_LANG_CHAR_SET; i++)
395 {
396 r = FcLangCompare (lang, fcLangCharSets[i].lang);
397 if (r == FcLangDifferentLang)
398 break;
399 if (FcLangSetBitGet (ls, i) && r < best)
400 best = r;
401 }
4262e0b3 402 if (ls->extra)
d8d73958 403 {
4262e0b3 404 FcStrList *list = FcStrListCreate (ls->extra);
d8d73958 405 FcChar8 *extra;
d8d73958
KP
406
407 if (list)
408 {
409 while (best > FcLangEqual && (extra = FcStrListNext (list)))
410 {
411 r = FcLangCompare (lang, extra);
412 if (r < best)
413 best = r;
414 }
415 FcStrListDone (list);
416 }
417 }
418 return best;
419}
420
421static FcLangResult
422FcLangSetCompareStrSet (const FcLangSet *ls, FcStrSet *set)
423{
424 FcStrList *list = FcStrListCreate (set);
425 FcLangResult r, best = FcLangDifferentLang;
426 FcChar8 *extra;
427
428 if (list)
429 {
430 while (best > FcLangEqual && (extra = FcStrListNext (list)))
431 {
432 r = FcLangSetHasLang (ls, extra);
433 if (r < best)
434 best = r;
435 }
436 FcStrListDone (list);
437 }
438 return best;
439}
440
441FcLangResult
442FcLangSetCompare (const FcLangSet *lsa, const FcLangSet *lsb)
443{
234397b4 444 int i, j;
d8d73958
KP
445 FcLangResult best, r;
446
447 for (i = 0; i < NUM_LANG_SET_MAP; i++)
448 if (lsa->map[i] & lsb->map[i])
449 return FcLangEqual;
450 best = FcLangDifferentLang;
234397b4
DD
451 for (j = 0; j < NUM_COUNTRY_SET; j++)
452 for (i = 0; i < NUM_LANG_SET_MAP; i++)
453 if ((lsa->map[i] & fcLangCountrySets[j][i]) &&
454 (lsb->map[i] & fcLangCountrySets[j][i]))
455 {
c833409f 456 best = FcLangDifferentTerritory;
234397b4
DD
457 break;
458 }
4262e0b3 459 if (lsa->extra)
d8d73958 460 {
4262e0b3 461 r = FcLangSetCompareStrSet (lsb, lsa->extra);
d8d73958
KP
462 if (r < best)
463 best = r;
464 }
4262e0b3 465 if (best > FcLangEqual && lsb->extra)
d8d73958 466 {
4262e0b3 467 r = FcLangSetCompareStrSet (lsa, lsb->extra);
d8d73958
KP
468 if (r < best)
469 best = r;
470 }
471 return best;
472}
473
474/*
475 * Used in computing values -- mustn't allocate any storage
476 */
477FcLangSet *
478FcLangSetPromote (const FcChar8 *lang)
479{
480 static FcLangSet ls;
481 static FcStrSet strs;
482 static FcChar8 *str;
483 int id;
484
485 memset (ls.map, '\0', sizeof (ls.map));
4262e0b3 486 ls.extra = 0;
d8d73958
KP
487 id = FcLangSetIndex (lang);
488 if (id > 0)
489 {
490 FcLangSetBitSet (&ls, id);
491 }
492 else
493 {
4262e0b3 494 ls.extra = &strs;
d8d73958
KP
495 strs.num = 1;
496 strs.size = 1;
4262e0b3 497 strs.strs = &str;
47d4f950 498 strs.ref = 1;
d8d73958
KP
499 str = (FcChar8 *) lang;
500 }
501 return &ls;
502}
503
504FcChar32
505FcLangSetHash (const FcLangSet *ls)
506{
507 FcChar32 h = 0;
508 int i;
509
510 for (i = 0; i < NUM_LANG_SET_MAP; i++)
511 h ^= ls->map[i];
4262e0b3
PL
512 if (ls->extra)
513 h ^= ls->extra->num;
d8d73958
KP
514 return h;
515}
516
517FcLangSet *
518FcNameParseLangSet (const FcChar8 *string)
519{
793e946c
KP
520 FcChar8 lang[32],c;
521 int i;
d8d73958
KP
522 FcLangSet *ls;
523
524 ls = FcLangSetCreate ();
525 if (!ls)
526 goto bail0;
527
793e946c 528 for(;;)
d8d73958 529 {
793e946c 530 for(i = 0; i < 31;i++)
d8d73958 531 {
793e946c
KP
532 c = *string++;
533 if(c == '\0' || c == '|')
534 break; /* end of this code */
535 lang[i] = c;
d8d73958 536 }
793e946c
KP
537 lang[i] = '\0';
538 if (!FcLangSetAdd (ls, lang))
539 goto bail1;
540 if(c == '\0')
541 break;
d8d73958
KP
542 }
543 return ls;
544bail1:
545 FcLangSetDestroy (ls);
546bail0:
547 return 0;
548}
549
550FcBool
551FcNameUnparseLangSet (FcStrBuf *buf, const FcLangSet *ls)
552{
553 int i, bit;
554 FcChar32 bits;
555 FcBool first = FcTrue;
556
557 for (i = 0; i < NUM_LANG_SET_MAP; i++)
558 {
559 if ((bits = ls->map[i]))
560 {
561 for (bit = 0; bit <= 31; bit++)
562 if (bits & (1 << bit))
563 {
564 int id = (i << 5) | bit;
565 if (!first)
566 if (!FcStrBufChar (buf, '|'))
567 return FcFalse;
568 if (!FcStrBufString (buf, fcLangCharSets[id].lang))
569 return FcFalse;
570 first = FcFalse;
571 }
572 }
573 }
4262e0b3 574 if (ls->extra)
d8d73958 575 {
4262e0b3 576 FcStrList *list = FcStrListCreate (ls->extra);
d8d73958
KP
577 FcChar8 *extra;
578
579 if (!list)
580 return FcFalse;
581 while ((extra = FcStrListNext (list)))
582 {
583 if (!first)
584 if (!FcStrBufChar (buf, '|'))
04f7d3e7
PL
585 {
586 FcStrListDone (list);
d8d73958 587 return FcFalse;
04f7d3e7 588 }
793e946c 589 if (!FcStrBufString (buf, extra))
04f7d3e7
PL
590 {
591 FcStrListDone (list);
592 return FcFalse;
593 }
d8d73958
KP
594 first = FcFalse;
595 }
2de24638 596 FcStrListDone (list);
d8d73958
KP
597 }
598 return FcTrue;
599}
600
601FcBool
602FcLangSetEqual (const FcLangSet *lsa, const FcLangSet *lsb)
603{
604 int i;
605
606 for (i = 0; i < NUM_LANG_SET_MAP; i++)
607 {
608 if (lsa->map[i] != lsb->map[i])
609 return FcFalse;
610 }
4262e0b3 611 if (!lsa->extra && !lsb->extra)
d8d73958 612 return FcTrue;
4262e0b3
PL
613 if (lsa->extra && lsb->extra)
614 return FcStrSetEqual (lsa->extra, lsb->extra);
d8d73958
KP
615 return FcFalse;
616}
793e946c
KP
617
618static FcBool
619FcLangSetContainsLang (const FcLangSet *ls, const FcChar8 *lang)
620{
621 int id;
793e946c
KP
622 int i;
623
624 id = FcLangSetIndex (lang);
625 if (id < 0)
626 id = -id - 1;
627 else if (FcLangSetBitGet (ls, id))
628 return FcTrue;
629 /*
630 * search up and down among equal languages for a match
631 */
632 for (i = id - 1; i >= 0; i--)
633 {
634 if (FcLangCompare (fcLangCharSets[i].lang, lang) == FcLangDifferentLang)
635 break;
636 if (FcLangSetBitGet (ls, i) &&
637 FcLangContains (fcLangCharSets[i].lang, lang))
638 return FcTrue;
639 }
640 for (i = id; i < NUM_LANG_CHAR_SET; i++)
641 {
642 if (FcLangCompare (fcLangCharSets[i].lang, lang) == FcLangDifferentLang)
643 break;
644 if (FcLangSetBitGet (ls, i) &&
645 FcLangContains (fcLangCharSets[i].lang, lang))
646 return FcTrue;
647 }
4262e0b3 648 if (ls->extra)
793e946c 649 {
4262e0b3 650 FcStrList *list = FcStrListCreate (ls->extra);
793e946c 651 FcChar8 *extra;
793e946c
KP
652
653 if (list)
654 {
655 while ((extra = FcStrListNext (list)))
656 {
657 if (FcLangContains (extra, lang))
658 break;
659 }
660 FcStrListDone (list);
661 if (extra)
662 return FcTrue;
663 }
664 }
665 return FcFalse;
666}
667
668/*
669 * return FcTrue if lsa contains every language in lsb
670 */
671FcBool
672FcLangSetContains (const FcLangSet *lsa, const FcLangSet *lsb)
673{
674 int i, j;
675 FcChar32 missing;
676
677 if (FcDebug() & FC_DBG_MATCHV)
678 {
679 printf ("FcLangSet "); FcLangSetPrint (lsa);
680 printf (" contains "); FcLangSetPrint (lsb);
681 printf ("\n");
682 }
683 /*
684 * check bitmaps for missing language support
685 */
686 for (i = 0; i < NUM_LANG_SET_MAP; i++)
687 {
688 missing = lsb->map[i] & ~lsa->map[i];
689 if (missing)
690 {
691 for (j = 0; j < 32; j++)
692 if (missing & (1 << j))
693 {
694 if (!FcLangSetContainsLang (lsa,
695 fcLangCharSets[i*32 + j].lang))
696 {
697 if (FcDebug() & FC_DBG_MATCHV)
698 printf ("\tMissing bitmap %s\n", fcLangCharSets[i*32+j].lang);
699 return FcFalse;
700 }
701 }
702 }
703 }
4262e0b3 704 if (lsb->extra)
793e946c 705 {
4262e0b3 706 FcStrList *list = FcStrListCreate (lsb->extra);
793e946c
KP
707 FcChar8 *extra;
708
709 if (list)
710 {
711 while ((extra = FcStrListNext (list)))
712 {
713 if (!FcLangSetContainsLang (lsa, extra))
714 {
715 if (FcDebug() & FC_DBG_MATCHV)
716 printf ("\tMissing string %s\n", extra);
717 break;
718 }
719 }
720 FcStrListDone (list);
721 if (extra)
722 return FcFalse;
723 }
724 }
725 return FcTrue;
726}
cd2ec1a9 727
7ce19673
KP
728FcBool
729FcLangSetSerializeAlloc (FcSerialize *serialize, const FcLangSet *l)
cd2ec1a9 730{
7ce19673
KP
731 if (!FcSerializeAlloc (serialize, l, sizeof (FcLangSet)))
732 return FcFalse;
4262e0b3 733 return FcTrue;
cd2ec1a9 734}
212c9f43 735
4262e0b3 736FcLangSet *
7ce19673 737FcLangSetSerialize(FcSerialize *serialize, const FcLangSet *l)
4262e0b3 738{
7ce19673 739 FcLangSet *l_serialize = FcSerializePtr (serialize, l);
4262e0b3 740
7ce19673
KP
741 if (!l_serialize)
742 return NULL;
743 *l_serialize = *l;
744 return l_serialize;
212c9f43 745}
23816bf9
KP
746#define __fclang__
747#include "fcaliastail.h"
748#undef __fclang__