]> git.pld-linux.org Git - packages/fontconfig.git/blame - fontconfig-git.patch
- rel 3; fixes from git
[packages/fontconfig.git] / fontconfig-git.patch
CommitLineData
3ea8a859
AM
1diff --git a/conf.d/30-metric-aliases.conf b/conf.d/30-metric-aliases.conf
2index f25052a..0fd0b8a 100644
3--- a/conf.d/30-metric-aliases.conf
4+++ b/conf.d/30-metric-aliases.conf
5@@ -230,6 +230,7 @@
6 <alias binding="same">
7 <family>Helvetica</family>
8 <accept>
9+ <family>TeX Gyre Heros</family>
10 <family>Nimbus Sans L</family>
11 </accept>
12 </alias>
13@@ -237,6 +238,7 @@
14 <alias binding="same">
15 <family>Times</family>
16 <accept>
17+ <family>TeX Gyre Termes</family>
18 <family>Nimbus Roman No9 L</family>
19 </accept>
20 </alias>
21@@ -253,6 +255,7 @@
22 <alias binding="same">
23 <family>Arial</family>
24 <accept>
25+ <family>TeX Gyre Heros</family>
26 <family>Arimo</family>
27 <family>Liberation Sans</family>
28 <family>Albany</family>
29@@ -270,6 +273,7 @@
30 <alias binding="same">
31 <family>Times New Roman</family>
32 <accept>
33+ <family>TeX Gyre Termes</family>
34 <family>Tinos</family>
35 <family>Liberation Serif</family>
36 <family>Thorndale</family>
37@@ -278,6 +282,13 @@
38 </alias>
39
40 <alias binding="same">
41+ <family>Georgia</family>
42+ <accept>
43+ <family>Gelasio</family>
44+ </accept>
45+ </alias>
46+
47+ <alias binding="same">
48 <family>Courier New</family>
49 <accept>
50 <family>Cousine</family>
51diff --git a/conf.d/45-latin.conf b/conf.d/45-latin.conf
52index 09fd526..aa62ed4 100644
53--- a/conf.d/45-latin.conf
54+++ b/conf.d/45-latin.conf
55@@ -45,6 +45,22 @@
56 <family>Thorndale</family>
57 <default><family>serif</family></default>
58 </alias>
59+ <alias>
60+ <family>Georgia</family>
61+ <default><family>serif</family></default>
62+ </alias>
63+ <alias>
64+ <family>Garamond</family>
65+ <default><family>serif</family></default>
66+ </alias>
67+ <alias>
68+ <family>Palatino Linotype</family>
69+ <default><family>serif</family></default>
70+ </alias>
71+ <alias>
72+ <family>Trebuchet MS</family>
73+ <default><family>serif</family></default>
74+ </alias>
75 <!--
76 Sans-serif faces
77 -->
78diff --git a/configure.ac b/configure.ac
79index 0f129db..321fece 100644
80--- a/configure.ac
81+++ b/configure.ac
82@@ -54,6 +54,9 @@ AC_SUBST(LIBT_VERSION_INFO)
83 LIBT_CURRENT_MINUS_AGE=`expr $LIBT_CURRENT - $LIBT_AGE`
84 AC_SUBST(LIBT_CURRENT_MINUS_AGE)
85
86+PKGCONFIG_REQUIRES=
87+PKGCONFIG_REQUIRES_PRIVATELY=
88+
89 dnl ==========================================================================
90
91 AC_CONFIG_HEADERS(config.h)
92@@ -161,6 +164,37 @@ AC_LINK_IFELSE([AC_LANG_SOURCE([[
93 AC_MSG_RESULT([yes])
94 AC_DEFINE([HAVE_POSIX_FADVISE], [1], [Define to 1 if you have the 'posix_fadvise' function.])
95 ],[AC_MSG_RESULT([no])])
96+if test "$os_win32" = "no"; then
97+ AC_MSG_CHECKING([for scandir])
98+ AC_LINK_IFELSE([AC_LANG_SOURCE([[
99+ #include <dirent.h>
100+ int comp(const struct dirent **, const struct dirent **);
101+ int comp(const struct dirent **a, const struct dirent **b) { return 0; }
102+ int main(void) {
103+ struct dirent **d;
104+ return scandir(".", &d, 0, &comp) >= 0;
105+ }
106+ ]])],[
107+ AC_MSG_RESULT([yes])
108+ AC_DEFINE([HAVE_SCANDIR], [1], [Define to 1 if you have the 'scandir' function.])
109+ ],[
110+ AC_LINK_IFELSE([AC_LANG_SOURCE([[
111+ #include <dirent.h>
112+ int comp(const void *, const void *);
113+ int comp(const void *a, const void *b) { return 0; }
114+ int main(void) {
115+ struct dirent **d;
116+ return scandir(".", &d, 0, &comp) >= 0;
117+ }
118+ ]])],[
119+ AC_MSG_RESULT([yes])
120+ AC_DEFINE([HAVE_SCANDIR_VOID_P], [1], [Define to 1 if you have the 'scandir' function with int (* compar)(const void *, const void *)])
121+ ],[
122+ AC_MSG_ERROR([
123+*** No scandir function available.])
124+ ])
125+ ])
126+fi
127 CFLAGS="$fc_saved_CFLAGS"
128
129 #
130@@ -251,13 +285,14 @@ if test "x$enable_iconv" != "xno"; then
131 AC_TRY_LINK([#include <iconv.h>],
132 [iconv_open ("from", "to");],
133 [iconv_type="libiconv"
134- use_iconv=1],
135+ use_iconv=1
136+ ICONV_CFLAGS="$libiconv_cflags"
137+ ICONV_LIBS="$libiconv_libs"
138+ ],
139 [use_iconv=0])
140
141 CFLAGS="$iconvsaved_CFLAGS"
142 LIBS="$iconvsaved_LIBS"
143- ICONV_CFLAGS="$libiconv_cflags"
144- ICONV_LIBS="$libiconv_libs"
145 fi
146 if test "x$use_iconv" = "x0"; then
147 AC_TRY_LINK([#include <iconv.h>],
148@@ -277,6 +312,7 @@ AC_DEFINE_UNQUOTED(USE_ICONV,$use_iconv,[Use iconv.])
149 # Checks for FreeType
150 #
151 PKG_CHECK_MODULES(FREETYPE, freetype2)
152+PKGCONFIG_REQUIRES="$PKGCONFIG_REQUIRES freetype2"
153
154 AC_SUBST(FREETYPE_LIBS)
155 AC_SUBST(FREETYPE_CFLAGS)
156@@ -336,6 +372,8 @@ if test "$enable_libxml2" != "yes"; then
157 else
158 EXPAT_LIBS="-lexpat"
159 fi
160+ else
161+ PKGCONFIG_REQUIRES_PRIVATELY="$PKGCONFIG_REQUIRES_PRIVATELY expat"
162 fi
163
164 expatsaved_CPPFLAGS="$CPPFLAGS"
165@@ -377,6 +415,7 @@ AC_ARG_ENABLE(libxml2,
166
167 if test "$enable_libxml2" = "yes"; then
168 PKG_CHECK_MODULES([LIBXML2], [libxml-2.0 >= 2.6])
169+ PKGCONFIG_REQUIRES_PRIVATELY="$PKGCONFIG_REQUIRES_PRIVATELY libxml-2.0"
170 AC_DEFINE_UNQUOTED(ENABLE_LIBXML2,1,[Use libxml2 instead of Expat])
171
172 AC_SUBST(LIBXML2_CFLAGS)
173@@ -684,6 +723,12 @@ dnl include the header file for workaround of miscalculating size on autoconf
174 dnl particularly for fat binaries
175 AH_BOTTOM([#include "config-fixups.h"])
176
177+dnl
178+dnl
179+AC_SUBST(PKGCONFIG_REQUIRES)
180+AC_SUBST(PKGCONFIG_REQUIRES_PRIVATELY)
181+
182+dnl
183 AC_CONFIG_FILES([
184 Makefile
185 fontconfig/Makefile
186diff --git a/fontconfig.pc.in b/fontconfig.pc.in
187index 9ef2c27..6e112bb 100644
188--- a/fontconfig.pc.in
189+++ b/fontconfig.pc.in
190@@ -11,6 +11,8 @@ cachedir=@fc_cachedir@
191 Name: Fontconfig
192 Description: Font configuration and customization library
193 Version: @VERSION@
194+Requires: @PKGCONFIG_REQUIRES@
195+Requires.private: @PKGCONFIG_REQUIRES_PRIVATELY@
196 Libs: -L${libdir} -lfontconfig
197-Libs.private: @LIBXML2_LIBS@ @EXPAT_LIBS@ @FREETYPE_LIBS@ @ICONV_LIBS@
198-Cflags: -I${includedir}
199+Libs.private: @EXPAT_LIBS@ @FREETYPE_LIBS@ @ICONV_LIBS@ @LIBXML2_LIBS@
200+Cflags: -I${includedir} @EXPAT_CFLAGS@ @FREETYPE_CFLAGS@ @ICONV_CFLAGS@ @LIBXML2_CFLAGS@
201diff --git a/fontconfig/fcprivate.h b/fontconfig/fcprivate.h
202index 18b8c08..210c1d8 100644
203--- a/fontconfig/fcprivate.h
204+++ b/fontconfig/fcprivate.h
205@@ -48,8 +48,9 @@
206 __o__ = va_arg (va, const char *); \
207 if (!__o__) \
208 break; \
209- __v__.type = va_arg (va, FcType); \
210+ __v__.type = va_arg (va, int); \
211 switch (__v__.type) { \
212+ case FcTypeUnknown: \
213 case FcTypeVoid: \
214 goto _FcPatternVapBuild_bail1; \
215 case FcTypeInteger: \
216diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h
217index 422187b..39d1b1b 100644
218--- a/fontconfig/fontconfig.h
219+++ b/fontconfig/fontconfig.h
220@@ -185,6 +185,7 @@ typedef int FcBool;
221 #define FC_LCD_LEGACY 3
222
223 typedef enum _FcType {
224+ FcTypeUnknown = -1,
225 FcTypeVoid,
226 FcTypeInteger,
227 FcTypeDouble,
228diff --git a/src/fccache.c b/src/fccache.c
229index 9f1c298..e02d49e 100644
230--- a/src/fccache.c
231+++ b/src/fccache.c
232@@ -830,34 +830,6 @@ bail1:
233 return NULL;
234 }
235
236-
237-#ifdef _WIN32
238-#include <direct.h>
239-#define mkdir(path,mode) _mkdir(path)
240-#endif
241-
242-static FcBool
243-FcMakeDirectory (const FcChar8 *dir)
244-{
245- FcChar8 *parent;
246- FcBool ret;
247-
248- if (strlen ((char *) dir) == 0)
249- return FcFalse;
250-
251- parent = FcStrDirname (dir);
252- if (!parent)
253- return FcFalse;
254- if (access ((char *) parent, F_OK) == 0)
255- ret = mkdir ((char *) dir, 0755) == 0 && chmod ((char *) dir, 0755) == 0;
256- else if (access ((char *) parent, F_OK) == -1)
257- ret = FcMakeDirectory (parent) && (mkdir ((char *) dir, 0755) == 0) && chmod ((char *) dir, 0755) == 0;
258- else
259- ret = FcFalse;
260- FcStrFree (parent);
261- return ret;
262-}
263-
264 /* write serialized state to the cache file */
265 FcBool
266 FcDirCacheWrite (FcCache *cache, FcConfig *config)
267diff --git a/src/fccfg.c b/src/fccfg.c
268index fcdf73e..be738d5 100644
269--- a/src/fccfg.c
270+++ b/src/fccfg.c
271@@ -214,10 +214,8 @@ FcSubstDestroy (FcSubst *s)
272 while (s)
273 {
274 n = s->next;
275- if (s->test)
276- FcTestDestroy (s->test);
277- if (s->edit)
278- FcEditDestroy (s->edit);
279+ if (s->rule)
280+ FcRuleDestroy (s->rule);
281 free (s);
282 s = n;
283 }
284@@ -226,20 +224,20 @@ FcSubstDestroy (FcSubst *s)
285 FcExpr *
286 FcConfigAllocExpr (FcConfig *config)
287 {
288- if (!config->expr_pool || config->expr_pool->next == config->expr_pool->end)
289- {
290- FcExprPage *new_page;
291+ if (!config->expr_pool || config->expr_pool->next == config->expr_pool->end)
292+ {
293+ FcExprPage *new_page;
294
295- new_page = malloc (sizeof (FcExprPage));
296- if (!new_page)
297- return 0;
298+ new_page = malloc (sizeof (FcExprPage));
299+ if (!new_page)
300+ return 0;
301
302- new_page->next_page = config->expr_pool;
303- new_page->next = new_page->exprs;
304- config->expr_pool = new_page;
305- }
306+ new_page->next_page = config->expr_pool;
307+ new_page->next = new_page->exprs;
308+ config->expr_pool = new_page;
309+ }
310
311- return config->expr_pool->next++;
312+ return config->expr_pool->next++;
313 }
314
315 FcConfig *
316@@ -644,15 +642,13 @@ FcConfigSetRescanInverval (FcConfig *config, int rescanInterval)
317 return FcConfigSetRescanInterval (config, rescanInterval);
318 }
319
320-
321 FcBool
322-FcConfigAddEdit (FcConfig *config,
323- FcTest *test,
324- FcEdit *edit,
325+FcConfigAddRule (FcConfig *config,
326+ FcRule *rule,
327 FcMatchKind kind)
328 {
329 FcSubst *subst, **prev;
330- FcTest *t;
331+ FcRule *r;
332 int num;
333
334 switch (kind) {
335@@ -673,15 +669,27 @@ FcConfigAddEdit (FcConfig *config,
336 return FcFalse;
337 for (; *prev; prev = &(*prev)->next);
338 *prev = subst;
339- subst->next = 0;
340- subst->test = test;
341- subst->edit = edit;
342+ subst->next = NULL;
343+ subst->rule = rule;
344 num = 0;
345- for (t = test; t; t = t->next)
346+ for (r = rule; r; r = r->next)
347 {
348- if (t->kind == FcMatchDefault)
349- t->kind = kind;
350- num++;
351+ switch (r->type)
352+ {
353+ case FcRuleTest:
354+ if (r->u.test &&
355+ r->u.test->kind == FcMatchDefault)
356+ r->u.test->kind = kind;
357+ if (r->u.test->object > FC_MAX_BASE_OBJECT)
358+ num++;
359+ break;
360+ case FcRuleEdit:
361+ if (r->u.edit->object > FC_MAX_BASE_OBJECT)
362+ num++;
363+ break;
364+ default:
365+ break;
366+ }
367 }
368 if (config->maxObjects < num)
369 config->maxObjects = num;
370@@ -721,7 +729,7 @@ FcConfigPromote (FcValue v, FcValue u, FcValuePromotionBuffer *buf)
371
372 FcBool
373 FcConfigCompareValue (const FcValue *left_o,
374- FcOp op_,
375+ unsigned int op_,
376 const FcValue *right_o)
377 {
378 FcValue left = FcValueCanonicalize(left_o);
379@@ -736,6 +744,8 @@ FcConfigCompareValue (const FcValue *left_o,
380 if (left.type == right.type)
381 {
382 switch (left.type) {
383+ case FcTypeUnknown:
384+ break; /* No way to guess how to compare for this object */
385 case FcTypeInteger:
386 break; /* FcConfigPromote prevents this from happening */
387 case FcTypeDouble:
388@@ -1484,13 +1494,16 @@ FcConfigSubstituteWithPat (FcConfig *config,
389 {
390 FcValue v;
391 FcSubst *s;
392- FcSubState *st;
393- int i;
394- FcTest *t;
395- FcEdit *e;
396- FcValueList *l;
397+ FcRule *r;
398+ FcValueList *l, **value = NULL;
399 FcPattern *m;
400 FcStrSet *strs;
401+ FcObject object = FC_INVALID_OBJECT;
402+ FcPatternElt **elt = NULL;
403+ int i, nobjs;
404+ FcBool retval = FcTrue;
405+
406+#define FC_OBJ_ID(_n_) ((_n_) > FC_MAX_BASE_OBJECT ? ((_n_) - FC_EXT_OBJ_INDEX) : (_n_))
407
408 if (!config)
409 {
410@@ -1535,9 +1548,19 @@ FcConfigSubstituteWithPat (FcConfig *config,
411 return FcFalse;
412 }
413
414- st = (FcSubState *) malloc (config->maxObjects * sizeof (FcSubState));
415- if (!st && config->maxObjects)
416- return FcFalse;
417+ nobjs = FC_MAX_BASE_OBJECT + config->maxObjects + 2;
418+ value = (FcValueList **) malloc (SIZEOF_VOID_P * nobjs);
419+ if (!value)
420+ {
421+ retval = FcFalse;
422+ goto bail1;
423+ }
424+ elt = (FcPatternElt **) malloc (SIZEOF_VOID_P * nobjs);
425+ if (!elt)
426+ {
427+ retval = FcFalse;
428+ goto bail1;
429+ }
430
431 if (FcDebug () & FC_DBG_EDIT)
432 {
433@@ -1546,200 +1569,185 @@ FcConfigSubstituteWithPat (FcConfig *config,
434 }
435 for (; s; s = s->next)
436 {
437- /*
438- * Check the tests to see if
439- * they all match the pattern
440- */
441- for (t = s->test, i = 0; t; t = t->next, i++)
442+ r = s->rule;
443+ for (i = 0; i < nobjs; i++)
444 {
445- if (FcDebug () & FC_DBG_EDIT)
446- {
447- printf ("FcConfigSubstitute test ");
448- FcTestPrint (t);
449- }
450- st[i].elt = 0;
451- if (kind == FcMatchFont && t->kind == FcMatchPattern)
452- m = p_pat;
453- else
454- m = p;
455- if (m)
456- st[i].elt = FcPatternObjectFindElt (m, t->object);
457- else
458- st[i].elt = 0;
459- /*
460- * If there's no such field in the font,
461- * then FcQualAll matches while FcQualAny does not
462- */
463- if (!st[i].elt)
464- {
465- if (t->qual == FcQualAll)
466+ elt[i] = NULL;
467+ value[i] = NULL;
468+ }
469+ for (; r; r = r->next)
470+ {
471+ switch (r->type) {
472+ case FcRuleUnknown:
473+ /* shouldn't be reached */
474+ break;
475+ case FcRuleTest:
476+ object = FC_OBJ_ID (r->u.test->object);
477+ /*
478+ * Check the tests to see if
479+ * they all match the pattern
480+ */
481+ if (FcDebug () & FC_DBG_EDIT)
482 {
483- st[i].value = 0;
484- continue;
485+ printf ("FcConfigSubstitute test ");
486+ FcTestPrint (r->u.test);
487 }
488+ if (kind == FcMatchFont && r->u.test->kind == FcMatchPattern)
489+ m = p_pat;
490 else
491- break;
492- }
493- /*
494- * Check to see if there is a match, mark the location
495- * to apply match-relative edits
496- */
497- st[i].value = FcConfigMatchValueList (m, p_pat, kind, t, st[i].elt->values);
498- if (!st[i].value)
499- break;
500- if (t->qual == FcQualFirst && st[i].value != st[i].elt->values)
501- break;
502- if (t->qual == FcQualNotFirst && st[i].value == st[i].elt->values)
503- break;
504- }
505- if (t)
506- {
507- if (FcDebug () & FC_DBG_EDIT)
508- printf ("No match\n");
509- continue;
510- }
511- if (FcDebug () & FC_DBG_EDIT)
512- {
513- printf ("Substitute ");
514- FcSubstPrint (s);
515- }
516- for (e = s->edit; e; e = e->next)
517- {
518- /*
519- * Evaluate the list of expressions
520- */
521- l = FcConfigValues (p, p_pat,kind, e->expr, e->binding);
522- /*
523- * Locate any test associated with this field, skipping
524- * tests associated with the pattern when substituting in
525- * the font
526- */
527- for (t = s->test, i = 0; t; t = t->next, i++)
528- {
529- if ((t->kind == FcMatchFont || kind == FcMatchPattern) &&
530- t->object == e->object)
531+ m = p;
532+ if (m)
533+ elt[object] = FcPatternObjectFindElt (m, r->u.test->object);
534+ /*
535+ * If there's no such field in the font,
536+ * then FcQualAll matches while FcQualAny does not
537+ */
538+ if (!elt[object])
539 {
540- /*
541- * KLUDGE - the pattern may have been reallocated or
542- * things may have been inserted or deleted above
543- * this element by other edits. Go back and find
544- * the element again
545- */
546- if (e != s->edit && st[i].elt)
547- st[i].elt = FcPatternObjectFindElt (p, t->object);
548- if (!st[i].elt)
549- t = 0;
550- break;
551+ if (r->u.test->qual == FcQualAll)
552+ {
553+ value[object] = NULL;
554+ continue;
555+ }
556+ else
557+ {
558+ if (FcDebug () & FC_DBG_EDIT)
559+ printf ("No match\n");
560+ goto bail;
561+ }
562 }
563- }
564- switch (FC_OP_GET_OP (e->op)) {
565- case FcOpAssign:
566 /*
567- * If there was a test, then replace the matched
568- * value with the new list of values
569+ * Check to see if there is a match, mark the location
570+ * to apply match-relative edits
571 */
572- if (t)
573+ value[object] = FcConfigMatchValueList (m, p_pat, kind, r->u.test, elt[object]->values);
574+ if (!value[object] ||
575+ (r->u.test->qual == FcQualFirst && value[object] != elt[object]->values) ||
576+ (r->u.test->qual == FcQualNotFirst && value[object] == elt[object]->values))
577 {
578- FcValueList *thisValue = st[i].value;
579- FcValueList *nextValue = thisValue;
580-
581+ if (FcDebug () & FC_DBG_EDIT)
582+ printf ("No match\n");
583+ goto bail;
584+ }
585+ break;
586+ case FcRuleEdit:
587+ object = FC_OBJ_ID (r->u.edit->object);
588+ if (FcDebug () & FC_DBG_EDIT)
589+ {
590+ printf ("Substitute ");
591+ FcEditPrint (r->u.edit);
592+ printf ("\n\n");
593+ }
594+ /*
595+ * Evaluate the list of expressions
596+ */
597+ l = FcConfigValues (p, p_pat,kind, r->u.edit->expr, r->u.edit->binding);
598+
599+ switch (FC_OP_GET_OP (r->u.edit->op)) {
600+ case FcOpAssign:
601 /*
602- * Append the new list of values after the current value
603+ * If there was a test, then replace the matched
604+ * value with the new list of values
605 */
606- FcConfigAdd (&st[i].elt->values, thisValue, FcTrue, l, e->object);
607+ if (value[object])
608+ {
609+ FcValueList *thisValue = value[object];
610+ FcValueList *nextValue = l;
611+
612+ /*
613+ * Append the new list of values after the current value
614+ */
615+ FcConfigAdd (&elt[object]->values, thisValue, FcTrue, l, r->u.edit->object);
616+ /*
617+ * Delete the marked value
618+ */
619+ if (thisValue)
620+ FcConfigDel (&elt[object]->values, thisValue);
621+ /*
622+ * Adjust a pointer into the value list to ensure
623+ * future edits occur at the same place
624+ */
625+ value[object] = nextValue;
626+ break;
627+ }
628+ /* fall through ... */
629+ case FcOpAssignReplace:
630 /*
631- * Delete the marked value
632+ * Delete all of the values and insert
633+ * the new set
634 */
635- if (thisValue)
636- FcConfigDel (&st[i].elt->values, thisValue);
637+ FcConfigPatternDel (p, r->u.edit->object);
638+ FcConfigPatternAdd (p, r->u.edit->object, l, FcTrue);
639 /*
640- * Adjust any pointers into the value list to ensure
641- * future edits occur at the same place
642+ * Adjust a pointer into the value list as they no
643+ * longer point to anything valid
644 */
645- for (t = s->test, i = 0; t; t = t->next, i++)
646+ value[object] = NULL;
647+ break;
648+ case FcOpPrepend:
649+ if (value[object])
650 {
651- if (st[i].value == thisValue)
652- st[i].value = nextValue;
653+ FcConfigAdd (&elt[object]->values, value[object], FcFalse, l, r->u.edit->object);
654+ break;
655 }
656+ /* fall through ... */
657+ case FcOpPrependFirst:
658+ FcConfigPatternAdd (p, r->u.edit->object, l, FcFalse);
659 break;
660- }
661- /* fall through ... */
662- case FcOpAssignReplace:
663- /*
664- * Delete all of the values and insert
665- * the new set
666- */
667- FcConfigPatternDel (p, e->object);
668- FcConfigPatternAdd (p, e->object, l, FcTrue);
669- /*
670- * Adjust any pointers into the value list as they no
671- * longer point to anything valid
672- */
673- if (t)
674- {
675- FcPatternElt *thisElt = st[i].elt;
676- for (t = s->test, i = 0; t; t = t->next, i++)
677+ case FcOpAppend:
678+ if (value[object])
679 {
680- if (st[i].elt == thisElt)
681- st[i].value = 0;
682+ FcConfigAdd (&elt[object]->values, value[object], FcTrue, l, r->u.edit->object);
683+ break;
684 }
685- }
686- break;
687- case FcOpPrepend:
688- if (t)
689- {
690- FcConfigAdd (&st[i].elt->values, st[i].value, FcFalse, l, e->object);
691+ /* fall through ... */
692+ case FcOpAppendLast:
693+ FcConfigPatternAdd (p, r->u.edit->object, l, FcTrue);
694 break;
695- }
696- /* fall through ... */
697- case FcOpPrependFirst:
698- FcConfigPatternAdd (p, e->object, l, FcFalse);
699- break;
700- case FcOpAppend:
701- if (t)
702- {
703- FcConfigAdd (&st[i].elt->values, st[i].value, FcTrue, l, e->object);
704+ case FcOpDelete:
705+ if (value[object])
706+ {
707+ FcConfigDel (&elt[object]->values, value[object]);
708+ break;
709+ }
710+ /* fall through ... */
711+ case FcOpDeleteAll:
712+ FcConfigPatternDel (p, r->u.edit->object);
713+ break;
714+ default:
715+ FcValueListDestroy (l);
716 break;
717 }
718- /* fall through ... */
719- case FcOpAppendLast:
720- FcConfigPatternAdd (p, e->object, l, FcTrue);
721- break;
722- case FcOpDelete:
723- if (t)
724+ /*
725+ * Now go through the pattern and eliminate
726+ * any properties without data
727+ */
728+ FcConfigPatternCanon (p, r->u.edit->object);
729+
730+ if (FcDebug () & FC_DBG_EDIT)
731 {
732- FcConfigDel (&st[i].elt->values, st[i].value);
733- break;
734+ printf ("FcConfigSubstitute edit");
735+ FcPatternPrint (p);
736 }
737- /* fall through ... */
738- case FcOpDeleteAll:
739- FcConfigPatternDel (p, e->object);
740- break;
741- default:
742- FcValueListDestroy (l);
743 break;
744 }
745 }
746- /*
747- * Now go through the pattern and eliminate
748- * any properties without data
749- */
750- for (e = s->edit; e; e = e->next)
751- FcConfigPatternCanon (p, e->object);
752-
753- if (FcDebug () & FC_DBG_EDIT)
754- {
755- printf ("FcConfigSubstitute edit");
756- FcPatternPrint (p);
757- }
758+ bail:;
759 }
760- free (st);
761 if (FcDebug () & FC_DBG_EDIT)
762 {
763 printf ("FcConfigSubstitute done");
764 FcPatternPrint (p);
765 }
766- return FcTrue;
767+bail1:
768+ if (elt)
769+ free (elt);
770+ if (value)
771+ free (value);
772+
773+#undef FC_OBJ_ID
774+
775+ return retval;
776 }
777
778 FcBool
779diff --git a/src/fccompat.c b/src/fccompat.c
780index a217160..d4f88c8 100644
781--- a/src/fccompat.c
782+++ b/src/fccompat.c
783@@ -219,3 +219,30 @@ FcRandom(void)
784
785 return result;
786 }
787+
788+#ifdef _WIN32
789+#include <direct.h>
790+#define mkdir(path,mode) _mkdir(path)
791+#endif
792+
793+FcBool
794+FcMakeDirectory (const FcChar8 *dir)
795+{
796+ FcChar8 *parent;
797+ FcBool ret;
798+
799+ if (strlen ((char *) dir) == 0)
800+ return FcFalse;
801+
802+ parent = FcStrDirname (dir);
803+ if (!parent)
804+ return FcFalse;
805+ if (access ((char *) parent, F_OK) == 0)
806+ ret = mkdir ((char *) dir, 0755) == 0 && chmod ((char *) dir, 0755) == 0;
807+ else if (access ((char *) parent, F_OK) == -1)
808+ ret = FcMakeDirectory (parent) && (mkdir ((char *) dir, 0755) == 0) && chmod ((char *) dir, 0755) == 0;
809+ else
810+ ret = FcFalse;
811+ FcStrFree (parent);
812+ return ret;
813+}
814diff --git a/src/fcdbg.c b/src/fcdbg.c
815index 9d02f5a..d74bc27 100644
816--- a/src/fcdbg.c
817+++ b/src/fcdbg.c
818@@ -30,6 +30,9 @@ static void
819 _FcValuePrintFile (FILE *f, const FcValue v)
820 {
821 switch (v.type) {
822+ case FcTypeUnknown:
823+ fprintf (f, "<unknown>");
824+ break;
825 case FcTypeVoid:
826 fprintf (f, "<void>");
827 break;
828@@ -98,6 +101,10 @@ FcValueBindingPrint (const FcValueListPtr l)
829 case FcValueBindingSame:
830 printf ("(=)");
831 break;
832+ default:
833+ /* shouldn't be reached */
834+ printf ("(?)");
835+ break;
836 }
837 }
838
839@@ -420,21 +427,38 @@ FcEditPrint (const FcEdit *edit)
840 void
841 FcSubstPrint (const FcSubst *subst)
842 {
843- FcEdit *e;
844- FcTest *t;
845+ FcRule *r;
846+ FcRuleType last_type = FcRuleUnknown;
847
848 printf ("match\n");
849- for (t = subst->test; t; t = t->next)
850- {
851- printf ("\t");
852- FcTestPrint (t);
853- }
854- printf ("edit\n");
855- for (e = subst->edit; e; e = e->next)
856+ for (r = subst->rule; r; r = r->next)
857 {
858+ if (last_type != r->type)
859+ {
860+ switch (r->type) {
861+ case FcRuleTest:
862+ printf ("[test]\n");
863+ break;
864+ case FcRuleEdit:
865+ printf ("[edit]\n");
866+ break;
867+ default:
868+ break;
869+ }
870+ last_type = r->type;
871+ }
872 printf ("\t");
873- FcEditPrint (e);
874- printf (";\n");
875+ switch (r->type) {
876+ case FcRuleTest:
877+ FcTestPrint (r->u.test);
878+ break;
879+ case FcRuleEdit:
880+ FcEditPrint (r->u.edit);
881+ printf (";\n");
882+ break;
883+ default:
884+ break;
885+ }
886 }
887 printf ("\n");
888 }
889diff --git a/src/fcdir.c b/src/fcdir.c
890index dc580bb..b040a28 100644
891--- a/src/fcdir.c
892+++ b/src/fcdir.c
893@@ -49,6 +49,16 @@ FcFileIsLink (const FcChar8 *file)
894 #endif
895 }
896
897+FcBool
898+FcFileIsFile (const FcChar8 *file)
899+{
900+ struct stat statb;
901+
902+ if (FcStat (file, &statb) != 0)
903+ return FcFalse;
904+ return S_ISREG (statb.st_mode);
905+}
906+
907 static FcBool
908 FcFileScanFontConfig (FcFontSet *set,
909 FcBlanks *blanks,
910diff --git a/src/fchash.c b/src/fchash.c
911index 92585a6..7216bee 100644
912--- a/src/fchash.c
913+++ b/src/fchash.c
914@@ -190,14 +190,14 @@ FcHashGetSHA256Digest (const FcChar8 *input_strings,
915 }
916 /* set input size at the end */
917 len *= 8;
918- block[63 - 0] = len & 0xff;
919- block[63 - 1] = (len >> 8) & 0xff;
920- block[63 - 2] = (len >> 16) & 0xff;
921- block[63 - 3] = (len >> 24) & 0xff;
922- block[63 - 4] = (len >> 32) & 0xff;
923- block[63 - 5] = (len >> 40) & 0xff;
924- block[63 - 6] = (len >> 48) & 0xff;
925- block[63 - 7] = (len >> 56) & 0xff;
926+ block[63 - 0] = (uint64_t)len & 0xff;
927+ block[63 - 1] = ((uint64_t)len >> 8) & 0xff;
928+ block[63 - 2] = ((uint64_t)len >> 16) & 0xff;
929+ block[63 - 3] = ((uint64_t)len >> 24) & 0xff;
930+ block[63 - 4] = ((uint64_t)len >> 32) & 0xff;
931+ block[63 - 5] = ((uint64_t)len >> 40) & 0xff;
932+ block[63 - 6] = ((uint64_t)len >> 48) & 0xff;
933+ block[63 - 7] = ((uint64_t)len >> 56) & 0xff;
934 FcHashComputeSHA256Digest (ret, block);
935
936 return FcHashSHA256ToString (ret);
937@@ -226,7 +226,7 @@ FcHashGetSHA256DigestFromFile (const FcChar8 *filename)
938 {
939 if ((len = fread (ibuf, sizeof (char), 64, fp)) < 64)
940 {
941- long v;
942+ uint64_t v;
943
944 /* add a padding */
945 memset (&ibuf[len], 0, 64 - len);
946@@ -281,7 +281,7 @@ FcHashGetSHA256DigestFromMemory (const char *fontdata,
947 {
948 if ((length - i) < 64)
949 {
950- long v;
951+ uint64_t v;
952 size_t n;
953
954 /* add a padding */
955diff --git a/src/fcint.h b/src/fcint.h
956index 65bf333..ec0c674 100644
957--- a/src/fcint.h
958+++ b/src/fcint.h
959@@ -37,6 +37,7 @@
960 #include <ctype.h>
961 #include <assert.h>
962 #include <errno.h>
963+#include <limits.h>
964 #include <unistd.h>
965 #include <stddef.h>
966 #include <sys/types.h>
967@@ -85,7 +86,7 @@ extern pfnSHGetFolderPathA pSHGetFolderPathA;
968 #define FC_DBG_CONFIG 1024
969 #define FC_DBG_LANGSET 2048
970
971-#define _FC_ASSERT_STATIC1(_line, _cond) typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1]
972+#define _FC_ASSERT_STATIC1(_line, _cond) typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1] FC_UNUSED
973 #define _FC_ASSERT_STATIC0(_line, _cond) _FC_ASSERT_STATIC1 (_line, (_cond))
974 #define FC_ASSERT_STATIC(_cond) _FC_ASSERT_STATIC0 (__LINE__, (_cond))
975
976@@ -107,7 +108,9 @@ extern pfnSHGetFolderPathA pSHGetFolderPathA;
977 FC_ASSERT_STATIC (sizeof (FcRef) == sizeof (int));
978
979 typedef enum _FcValueBinding {
980- FcValueBindingWeak, FcValueBindingStrong, FcValueBindingSame
981+ FcValueBindingWeak, FcValueBindingStrong, FcValueBindingSame,
982+ /* to make sure sizeof (FcValueBinding) == 4 even with -fshort-enums */
983+ FcValueBindingEnd = INT_MAX
984 } FcValueBinding;
985
986 #define FcStrdup(s) ((FcChar8 *) strdup ((const char *) (s)))
987@@ -171,6 +174,11 @@ typedef struct _FcValueList {
988
989 typedef int FcObject;
990
991+/* The 1000 is to leave some room for future added internal objects, such
992+ * that caches from newer fontconfig can still be used with older fontconfig
993+ * without getting confused. */
994+#define FC_EXT_OBJ_INDEX 1000
995+
996 typedef struct _FcPatternElt *FcPatternEltPtr;
997
998 /*
999@@ -271,7 +279,6 @@ typedef enum _FcQual {
1000 #define FcMatchDefault ((FcMatchKind) -1)
1001
1002 typedef struct _FcTest {
1003- struct _FcTest *next;
1004 FcMatchKind kind;
1005 FcQual qual;
1006 FcObject object;
1007@@ -280,17 +287,28 @@ typedef struct _FcTest {
1008 } FcTest;
1009
1010 typedef struct _FcEdit {
1011- struct _FcEdit *next;
1012 FcObject object;
1013 FcOp op;
1014 FcExpr *expr;
1015 FcValueBinding binding;
1016 } FcEdit;
1017
1018+typedef enum _FcRuleType {
1019+ FcRuleUnknown, FcRuleTest, FcRuleEdit
1020+} FcRuleType;
1021+
1022+typedef struct _FcRule {
1023+ struct _FcRule *next;
1024+ FcRuleType type;
1025+ union {
1026+ FcTest *test;
1027+ FcEdit *edit;
1028+ } u;
1029+} FcRule;
1030+
1031 typedef struct _FcSubst {
1032 struct _FcSubst *next;
1033- FcTest *test;
1034- FcEdit *edit;
1035+ FcRule *rule;
1036 } FcSubst;
1037
1038 typedef struct _FcCharLeaf {
1039@@ -610,10 +628,9 @@ FcPrivate FcBool
1040 FcConfigAddBlank (FcConfig *config,
1041 FcChar32 blank);
1042
1043-FcPrivate FcBool
1044-FcConfigAddEdit (FcConfig *config,
1045- FcTest *test,
1046- FcEdit *edit,
1047+FcBool
1048+FcConfigAddRule (FcConfig *config,
1049+ FcRule *rule,
1050 FcMatchKind kind);
1051
1052 FcPrivate void
1053@@ -623,7 +640,7 @@ FcConfigSetFonts (FcConfig *config,
1054
1055 FcPrivate FcBool
1056 FcConfigCompareValue (const FcValue *m,
1057- FcOp op,
1058+ unsigned int op_,
1059 const FcValue *v);
1060
1061 FcPrivate FcBool
1062@@ -730,6 +747,9 @@ FcMakeTempfile (char *template);
1063 FcPrivate int32_t
1064 FcRandom (void);
1065
1066+FcPrivate FcBool
1067+FcMakeDirectory (const FcChar8 *dir);
1068+
1069 /* fcdbg.c */
1070
1071 FcPrivate void
1072@@ -788,6 +808,9 @@ FcPrivate FcBool
1073 FcFileIsLink (const FcChar8 *file);
1074
1075 FcPrivate FcBool
1076+FcFileIsFile (const FcChar8 *file);
1077+
1078+FcPrivate FcBool
1079 FcFileScanConfig (FcFontSet *set,
1080 FcStrSet *dirs,
1081 FcBlanks *blanks,
1082@@ -840,6 +863,9 @@ FcTestDestroy (FcTest *test);
1083 FcPrivate void
1084 FcEditDestroy (FcEdit *e);
1085
1086+void
1087+FcRuleDestroy (FcRule *rule);
1088+
1089 /* fclang.c */
1090 FcPrivate FcLangSet *
1091 FcFreeTypeLangSet (const FcCharSet *charset,
1092diff --git a/src/fclist.c b/src/fclist.c
1093index b7ae899..c56e24c 100644
1094--- a/src/fclist.c
1095+++ b/src/fclist.c
1096@@ -252,6 +252,7 @@ FcListValueHash (FcValue *value)
1097 {
1098 FcValue v = FcValueCanonicalize(value);
1099 switch (v.type) {
1100+ case FcTypeUnknown:
1101 case FcTypeVoid:
1102 return 0;
1103 case FcTypeInteger:
1104diff --git a/src/fcmatch.c b/src/fcmatch.c
1105index 10976d6..dec92b9 100644
1106--- a/src/fcmatch.c
1107+++ b/src/fcmatch.c
1108@@ -245,6 +245,8 @@ typedef enum _FcMatcherPriorityDummy {
1109 typedef enum _FcMatcherPriority {
1110 PRI1(HASH),
1111 PRI1(FILE),
1112+ PRI1(FONTFORMAT),
1113+ PRI1(SCALABLE),
1114 PRI1(FOUNDRY),
1115 PRI1(CHARSET),
1116 PRI_FAMILY_STRONG,
1117diff --git a/src/fcname.c b/src/fcname.c
1118index 6dd4d49..712b2fa 100644
1119--- a/src/fcname.c
1120+++ b/src/fcname.c
1121@@ -76,6 +76,8 @@ FcObjectValidType (FcObject object, FcType type)
1122
1123 if (t) {
1124 switch ((int) t->type) {
1125+ case FcTypeUnknown:
1126+ return FcTrue;
1127 case FcTypeDouble:
1128 case FcTypeInteger:
1129 if (type == FcTypeDouble || type == FcTypeInteger)
1130@@ -86,7 +88,7 @@ FcObjectValidType (FcObject object, FcType type)
1131 return FcTrue;
1132 break;
1133 default:
1134- if (t->type == (unsigned int) -1 || type == t->type)
1135+ if (type == t->type)
1136 return FcTrue;
1137 break;
1138 }
1139@@ -318,6 +320,12 @@ FcNameFindNext (const FcChar8 *cur, const char *delim, FcChar8 *save, FcChar8 *l
1140
1141 while ((c = *cur))
1142 {
1143+ if (!isspace (c))
1144+ break;
1145+ ++cur;
1146+ }
1147+ while ((c = *cur))
1148+ {
1149 if (c == '\\')
1150 {
1151 ++cur;
1152@@ -468,6 +476,7 @@ FcNameUnparseValue (FcStrBuf *buf,
1153 FcValue v = FcValueCanonicalize(v0);
1154
1155 switch (v.type) {
1156+ case FcTypeUnknown:
1157 case FcTypeVoid:
1158 return FcTrue;
1159 case FcTypeInteger:
1160diff --git a/src/fcobjs.c b/src/fcobjs.c
1161index 146ca70..bad9824 100644
1162--- a/src/fcobjs.c
1163+++ b/src/fcobjs.c
1164@@ -37,7 +37,7 @@ FcObjectTypeLookup (register const char *str, register unsigned int len);
1165 /* The 1000 is to leave some room for future added internal objects, such
1166 * that caches from newer fontconfig can still be used with older fontconfig
1167 * without getting confused. */
1168-static fc_atomic_int_t next_id = FC_MAX_BASE_OBJECT + 1000;
1169+static fc_atomic_int_t next_id = FC_MAX_BASE_OBJECT + FC_EXT_OBJ_INDEX;
1170 struct FcObjectOtherTypeInfo {
1171 struct FcObjectOtherTypeInfo *next;
1172 FcObjectType object;
1173@@ -63,7 +63,7 @@ retry:
1174 return NULL;
1175
1176 ot->object.object = (const char *) FcStrdup (str);
1177- ot->object.type = -1;
1178+ ot->object.type = FcTypeUnknown;
1179 ot->id = fc_atomic_int_add (next_id, +1);
1180 ot->next = ots;
1181
1182diff --git a/src/fcobjs.h b/src/fcobjs.h
1183index 682fe6a..87c7319 100644
1184--- a/src/fcobjs.h
1185+++ b/src/fcobjs.h
1186@@ -23,7 +23,7 @@ FC_OBJECT (FILE, FcTypeString, FcCompareFilename)
1187 FC_OBJECT (INDEX, FcTypeInteger, NULL)
1188 FC_OBJECT (RASTERIZER, FcTypeString, FcCompareString)
1189 FC_OBJECT (OUTLINE, FcTypeBool, FcCompareBool)
1190-FC_OBJECT (SCALABLE, FcTypeBool, NULL)
1191+FC_OBJECT (SCALABLE, FcTypeBool, FcCompareBool)
1192 FC_OBJECT (DPI, FcTypeDouble, NULL)
1193 FC_OBJECT (RGBA, FcTypeInteger, NULL)
1194 FC_OBJECT (SCALE, FcTypeDouble, NULL)
1195@@ -35,7 +35,7 @@ FC_OBJECT (CHARSET, FcTypeCharSet, FcCompareCharSet)
1196 FC_OBJECT (LANG, FcTypeLangSet, FcCompareLang)
1197 FC_OBJECT (FONTVERSION, FcTypeInteger, FcCompareNumber)
1198 FC_OBJECT (CAPABILITY, FcTypeString, NULL)
1199-FC_OBJECT (FONTFORMAT, FcTypeString, NULL)
1200+FC_OBJECT (FONTFORMAT, FcTypeString, FcCompareString)
1201 FC_OBJECT (EMBOLDEN, FcTypeBool, NULL)
1202 FC_OBJECT (EMBEDDED_BITMAP, FcTypeBool, NULL)
1203 FC_OBJECT (DECORATIVE, FcTypeBool, FcCompareBool)
1204diff --git a/src/fcpat.c b/src/fcpat.c
1205index 25bff64..0614ac2 100644
1206--- a/src/fcpat.c
1207+++ b/src/fcpat.c
1208@@ -246,6 +246,8 @@ FcValueEqual (FcValue va, FcValue vb)
1209 return FcFalse;
1210 }
1211 switch (va.type) {
1212+ case FcTypeUnknown:
1213+ return FcFalse; /* don't know how to compare this object */
1214 case FcTypeVoid:
1215 return FcTrue;
1216 case FcTypeInteger:
1217@@ -294,6 +296,7 @@ static FcChar32
1218 FcValueHash (const FcValue *v)
1219 {
1220 switch (v->type) {
1221+ case FcTypeUnknown:
1222 case FcTypeVoid:
1223 return 0;
1224 case FcTypeInteger:
1225@@ -317,7 +320,7 @@ FcValueHash (const FcValue *v)
1226 case FcTypeLangSet:
1227 return FcLangSetHash (FcValueLangSet(v));
1228 }
1229- return FcFalse;
1230+ return 0;
1231 }
1232
1233 static FcBool
1234diff --git a/src/fcstat.c b/src/fcstat.c
1235index 390f45c..ab56aca 100644
1236--- a/src/fcstat.c
1237+++ b/src/fcstat.c
1238@@ -164,11 +164,21 @@ FcDirChecksumScandirFilter(const struct dirent *entry)
1239 }
1240 #endif
1241
1242+#ifdef HAVE_SCANDIR
1243 static int
1244 FcDirChecksumScandirSorter(const struct dirent **lhs, const struct dirent **rhs)
1245 {
1246 return strcmp((*lhs)->d_name, (*rhs)->d_name);
1247 }
1248+#elif HAVE_SCANDIR_VOID_P
1249+static int
1250+FcDirChecksumScandirSorter(const void *a, const void *b)
1251+{
1252+ const struct dirent *lhs = a, *rhs = b;
1253+
1254+ return strcmp(lhs->d_name, rhs->d_name);
1255+}
1256+#endif
1257
1258 static int
1259 FcDirChecksum (const FcChar8 *dir, time_t *checksum)
1260diff --git a/src/fcxml.c b/src/fcxml.c
1261index 470e44f..2cdf0ad 100644
1262--- a/src/fcxml.c
1263+++ b/src/fcxml.c
1264@@ -62,12 +62,30 @@ FcExprDestroy (FcExpr *e);
1265 void
1266 FcTestDestroy (FcTest *test)
1267 {
1268- if (test->next)
1269- FcTestDestroy (test->next);
1270 FcExprDestroy (test->expr);
1271 free (test);
1272 }
1273
1274+void
1275+FcRuleDestroy (FcRule *rule)
1276+{
1277+ FcRule *n = rule->next;
1278+
1279+ switch (rule->type) {
1280+ case FcRuleTest:
1281+ FcTestDestroy (rule->u.test);
1282+ break;
1283+ case FcRuleEdit:
1284+ FcEditDestroy (rule->u.edit);
1285+ break;
1286+ default:
1287+ break;
1288+ }
1289+ free (rule);
1290+ if (n)
1291+ FcRuleDestroy (n);
1292+}
1293+
1294 static FcExpr *
1295 FcExprCreateInteger (FcConfig *config, int i)
1296 {
1297@@ -300,8 +318,6 @@ FcExprDestroy (FcExpr *e)
1298 void
1299 FcEditDestroy (FcEdit *e)
1300 {
1301- if (e->next)
1302- FcEditDestroy (e->next);
1303 if (e->expr)
1304 FcExprDestroy (e->expr);
1305 free (e);
1306@@ -705,7 +721,7 @@ FcTestCreate (FcConfigParse *parse,
1307 FcMatchKind kind,
1308 FcQual qual,
1309 const FcChar8 *field,
1310- FcOp compare,
1311+ unsigned int compare,
1312 FcExpr *expr)
1313 {
1314 FcTest *test = (FcTest *) malloc (sizeof (FcTest));
1315@@ -714,7 +730,6 @@ FcTestCreate (FcConfigParse *parse,
1316 {
1317 const FcObjectType *o;
1318
1319- test->next = 0;
1320 test->kind = kind;
1321 test->qual = qual;
1322 test->object = FcObjectFromName ((const char *) field);
1323@@ -740,7 +755,6 @@ FcEditCreate (FcConfigParse *parse,
1324 {
1325 const FcObjectType *o;
1326
1327- e->next = 0;
1328 e->object = object;
1329 e->op = op;
1330 e->expr = expr;
1331@@ -752,6 +766,34 @@ FcEditCreate (FcConfigParse *parse,
1332 return e;
1333 }
1334
1335+static FcRule *
1336+FcRuleCreate (FcRuleType type,
1337+ void *p)
1338+{
1339+ FcRule *r = (FcRule *) malloc (sizeof (FcRule));
1340+
1341+ if (!r)
1342+ return NULL;
1343+
1344+ r->next = NULL;
1345+ r->type = type;
1346+ switch (type)
1347+ {
1348+ case FcRuleTest:
1349+ r->u.test = (FcTest *) p;
1350+ break;
1351+ case FcRuleEdit:
1352+ r->u.edit = (FcEdit *) p;
1353+ break;
1354+ default:
1355+ free (r);
1356+ r = NULL;
1357+ break;
1358+ }
1359+
1360+ return r;
1361+}
1362+
1363 static FcVStack *
1364 FcVStackCreateAndPush (FcConfigParse *parse)
1365 {
1366@@ -1657,9 +1699,9 @@ static void
1367 FcParseAlias (FcConfigParse *parse)
1368 {
1369 FcExpr *family = 0, *accept = 0, *prefer = 0, *def = 0, *new = 0;
1370- FcEdit *edit = 0, *next;
1371+ FcEdit *edit = 0;
1372 FcVStack *vstack;
1373- FcTest *test = NULL;
1374+ FcRule *rule = NULL, *r;
1375 FcValueBinding binding;
1376
1377 if (!FcConfigLexBinding (parse, FcConfigGetAttribute (parse, "binding"), &binding))
1378@@ -1704,8 +1746,14 @@ FcParseAlias (FcConfigParse *parse)
1379 vstack->tag = FcVStackNone;
1380 break;
1381 case FcVStackTest:
1382- vstack->u.test->next = test;
1383- test = vstack->u.test;
1384+ if (rule)
1385+ {
1386+ r = FcRuleCreate (FcRuleTest, vstack->u.test);
1387+ r->next = rule;
1388+ rule = r;
1389+ }
1390+ else
1391+ rule = FcRuleCreate (FcRuleTest, vstack->u.test);
1392 vstack->tag = FcVStackNone;
1393 break;
1394 default:
1395@@ -1723,8 +1771,35 @@ FcParseAlias (FcConfigParse *parse)
1396 FcExprDestroy (accept);
1397 if (def)
1398 FcExprDestroy (def);
1399+ if (rule)
1400+ FcRuleDestroy (rule);
1401 return;
1402 }
1403+ if (!prefer &&
1404+ !accept &&
1405+ !def)
1406+ {
1407+ FcExprDestroy (family);
1408+ return;
1409+ }
1410+ else
1411+ {
1412+ FcTest *t = FcTestCreate (parse, FcMatchPattern,
1413+ FcQualAny,
1414+ (FcChar8 *) FC_FAMILY,
1415+ FC_OP (FcOpEqual, FcOpFlagIgnoreBlanks),
1416+ family);
1417+ if (rule)
1418+ {
1419+ for (r = rule; r->next; r = r->next);
1420+ r->next = FcRuleCreate (FcRuleTest, t);
1421+ r = r->next;
1422+ }
1423+ else
1424+ {
1425+ r = rule = FcRuleCreate (FcRuleTest, t);
1426+ }
1427+ }
1428 if (prefer)
1429 {
1430 edit = FcEditCreate (parse,
1431@@ -1732,60 +1807,46 @@ FcParseAlias (FcConfigParse *parse)
1432 FcOpPrepend,
1433 prefer,
1434 binding);
1435- if (edit)
1436- edit->next = 0;
1437- else
1438+ if (!edit)
1439 FcExprDestroy (prefer);
1440+ else
1441+ {
1442+ r->next = FcRuleCreate (FcRuleEdit, edit);
1443+ r = r->next;
1444+ }
1445 }
1446 if (accept)
1447 {
1448- next = edit;
1449 edit = FcEditCreate (parse,
1450 FC_FAMILY_OBJECT,
1451 FcOpAppend,
1452 accept,
1453 binding);
1454- if (edit)
1455- edit->next = next;
1456- else
1457+ if (!edit)
1458 FcExprDestroy (accept);
1459+ else
1460+ {
1461+ r->next = FcRuleCreate (FcRuleEdit, edit);
1462+ r = r->next;
1463+ }
1464 }
1465 if (def)
1466 {
1467- next = edit;
1468 edit = FcEditCreate (parse,
1469 FC_FAMILY_OBJECT,
1470 FcOpAppendLast,
1471 def,
1472 binding);
1473- if (edit)
1474- edit->next = next;
1475- else
1476+ if (!edit)
1477 FcExprDestroy (def);
1478- }
1479- if (edit)
1480- {
1481- FcTest *t = FcTestCreate (parse, FcMatchPattern,
1482- FcQualAny,
1483- (FcChar8 *) FC_FAMILY,
1484- FC_OP (FcOpEqual, FcOpFlagIgnoreBlanks),
1485- family);
1486- if (test)
1487+ else
1488 {
1489- FcTest *p = test;
1490-
1491- while (p->next)
1492- p = p->next;
1493- p->next = t;
1494+ r->next = FcRuleCreate (FcRuleEdit, edit);
1495+ r = r->next;
1496 }
1497- else
1498- test = t;
1499- if (test)
1500- if (!FcConfigAddEdit (parse->config, test, edit, FcMatchPattern))
1501- FcTestDestroy (test);
1502 }
1503- else
1504- FcExprDestroy (family);
1505+ if (!FcConfigAddRule (parse->config, rule, FcMatchPattern))
1506+ FcRuleDestroy (rule);
1507 }
1508
1509 static FcExpr *
1510@@ -2121,6 +2182,8 @@ FcParseInclude (FcConfigParse *parse)
1511 FcBool ignore_missing = FcFalse;
1512 FcBool deprecated = FcFalse;
1513 FcChar8 *prefix = NULL, *p;
1514+ static FcChar8 *userdir = NULL;
1515+ static FcChar8 *userconf = NULL;
1516
1517 s = FcStrBufDoneStatic (&parse->pstack->str);
1518 if (!s)
1519@@ -2153,23 +2216,78 @@ FcParseInclude (FcConfigParse *parse)
1520 memcpy (&prefix[plen + 1], s, dlen);
1521 prefix[plen + 1 + dlen] = 0;
1522 s = prefix;
1523+ if (FcFileIsDir (s))
1524+ {
1525+ userdir:
1526+ if (!userdir)
1527+ userdir = FcStrdup (s);
1528+ }
1529+ else if (FcFileIsFile (s))
1530+ {
1531+ userconf:
1532+ if (!userconf)
1533+ userconf = FcStrdup (s);
1534+ }
1535+ else
1536+ {
1537+ /* No config dir nor file on the XDG directory spec compliant place
1538+ * so need to guess what it is supposed to be.
1539+ */
1540+ FcChar8 *parent = FcStrDirname (s);
1541+
1542+ if (!FcFileIsDir (parent))
1543+ FcMakeDirectory (parent);
1544+ FcStrFree (parent);
1545+ if (FcStrStr (s, (const FcChar8 *)"conf.d") != NULL)
1546+ goto userdir;
1547+ else
1548+ goto userconf;
1549+ }
1550 }
1551 if (!FcConfigParseAndLoad (parse->config, s, !ignore_missing))
1552 parse->error = FcTrue;
1553+#ifndef _WIN32
1554 else
1555 {
1556 FcChar8 *filename;
1557+ static FcBool warn_conf = FcFalse, warn_confd = FcFalse;
1558
1559 filename = FcConfigFilename(s);
1560 if (deprecated == FcTrue &&
1561 filename != NULL &&
1562 !FcFileIsLink (filename))
1563 {
1564- FcConfigMessage (parse, FcSevereWarning, "reading configurations from %s is deprecated.", s);
1565+ if (FcFileIsDir (filename))
1566+ {
1567+ if (FcFileIsDir (userdir) ||
1568+ rename ((const char *)filename, (const char *)userdir) != 0 ||
1569+ symlink ((const char *)userdir, (const char *)filename) != 0)
1570+ {
1571+ if (!warn_confd)
1572+ {
1573+ FcConfigMessage (parse, FcSevereWarning, "reading configurations from %s is deprecated. please move it to %s manually", s, userdir);
1574+ warn_confd = FcTrue;
1575+ }
1576+ }
1577+ }
1578+ else
1579+ {
1580+ if (FcFileIsFile (userconf) ||
1581+ rename ((const char *)filename, (const char *)userconf) != 0 ||
1582+ symlink ((const char *)userconf, (const char *)filename) != 0)
1583+ {
1584+ if (!warn_conf)
1585+ {
1586+ FcConfigMessage (parse, FcSevereWarning, "reading configurations from %s is deprecated. please move it to %s manually", s, userconf);
1587+ warn_conf = FcTrue;
1588+ }
1589+ }
1590+ }
1591 }
1592 if(filename)
1593 FcStrFree(filename);
1594 }
1595+#endif
1596 FcStrBufDestroy (&parse->pstack->str);
1597
1598 bail:
1599@@ -2386,22 +2504,14 @@ FcParseEdit (FcConfigParse *parse)
1600 FcEditDestroy (edit);
1601 }
1602
1603-typedef struct FcSubstStack {
1604- FcTest *test;
1605- FcEdit *edit;
1606-} FcSubstStack;
1607-
1608 static void
1609 FcParseMatch (FcConfigParse *parse)
1610 {
1611 const FcChar8 *kind_name;
1612 FcMatchKind kind;
1613- FcTest *test = 0;
1614 FcEdit *edit = 0;
1615 FcVStack *vstack;
1616- FcBool tested = FcFalse;
1617- FcSubstStack *sstack = NULL;
1618- int len, pos = 0;
1619+ FcRule *rule = NULL, *r;
1620
1621 kind_name = FcConfigGetAttribute (parse, "target");
1622 if (!kind_name)
1623@@ -2420,48 +2530,29 @@ FcParseMatch (FcConfigParse *parse)
1624 return;
1625 }
1626 }
1627- len = FcVStackElements(parse);
1628- if (len > 0)
1629- {
1630- sstack = malloc (sizeof (FcSubstStack) * (len + 1));
1631- if (!sstack)
1632- {
1633- FcConfigMessage (parse, FcSevereError, "out of memory");
1634- return;
1635- }
1636- }
1637 while ((vstack = FcVStackPeek (parse)))
1638 {
1639 switch ((int) vstack->tag) {
1640 case FcVStackTest:
1641- vstack->u.test->next = test;
1642- test = vstack->u.test;
1643+ r = FcRuleCreate (FcRuleTest, vstack->u.test);
1644+ if (rule)
1645+ r->next = rule;
1646+ rule = r;
1647 vstack->tag = FcVStackNone;
1648- tested = FcTrue;
1649 break;
1650 case FcVStackEdit:
1651- /* due to the reverse traversal, <edit> node appears faster than
1652- * <test> node if any. so we have to deal with it here rather than
1653- * the above in FcVStackTest, and put recipes in reverse order.
1654- */
1655- if (tested)
1656- {
1657- sstack[pos].test = test;
1658- sstack[pos].edit = edit;
1659- pos++;
1660- test = NULL;
1661- edit = NULL;
1662- tested = FcFalse;
1663- }
1664- vstack->u.edit->next = edit;
1665- edit = vstack->u.edit;
1666- vstack->tag = FcVStackNone;
1667- if (kind == FcMatchScan && edit->object > FC_MAX_BASE_OBJECT)
1668+ if (kind == FcMatchScan && vstack->u.edit->object > FC_MAX_BASE_OBJECT)
1669 {
1670 FcConfigMessage (parse, FcSevereError,
1671 "<match target=\"scan\"> cannot edit user-defined object \"%s\"",
1672 FcObjectName(edit->object));
1673+ break;
1674 }
1675+ r = FcRuleCreate (FcRuleEdit, vstack->u.edit);
1676+ if (rule)
1677+ r->next = rule;
1678+ rule = r;
1679+ vstack->tag = FcVStackNone;
1680 break;
1681 default:
1682 FcConfigMessage (parse, FcSevereWarning, "invalid match element");
1683@@ -2469,22 +2560,8 @@ FcParseMatch (FcConfigParse *parse)
1684 }
1685 FcVStackPopAndDestroy (parse);
1686 }
1687- if (!FcConfigAddEdit (parse->config, test, edit, kind))
1688+ if (!FcConfigAddRule (parse->config, rule, kind))
1689 FcConfigMessage (parse, FcSevereError, "out of memory");
1690- if (sstack)
1691- {
1692- int i;
1693-
1694- for (i = 0; i < pos; i++)
1695- {
1696- if (!FcConfigAddEdit (parse->config, sstack[pos - i - 1].test, sstack[pos - i - 1].edit, kind))
1697- {
1698- FcConfigMessage (parse, FcSevereError, "out of memory");
1699- return;
1700- }
1701- }
1702- free (sstack);
1703- }
1704 }
1705
1706 static void
This page took 0.471749 seconds and 4 git commands to generate.