]> git.pld-linux.org Git - packages/fontconfig.git/blob - fontconfig-git.patch
- rel 3; fixes from git
[packages/fontconfig.git] / fontconfig-git.patch
1 diff --git a/conf.d/30-metric-aliases.conf b/conf.d/30-metric-aliases.conf
2 index 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>
51 diff --git a/conf.d/45-latin.conf b/conf.d/45-latin.conf
52 index 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   -->
78 diff --git a/configure.ac b/configure.ac
79 index 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
186 diff --git a/fontconfig.pc.in b/fontconfig.pc.in
187 index 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@
201 diff --git a/fontconfig/fcprivate.h b/fontconfig/fcprivate.h
202 index 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:                                         \
216 diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h
217 index 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,
228 diff --git a/src/fccache.c b/src/fccache.c
229 index 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)
267 diff --git a/src/fccfg.c b/src/fccfg.c
268 index 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
779 diff --git a/src/fccompat.c b/src/fccompat.c
780 index 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 +}
814 diff --git a/src/fcdbg.c b/src/fcdbg.c
815 index 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  }
889 diff --git a/src/fcdir.c b/src/fcdir.c
890 index 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,
910 diff --git a/src/fchash.c b/src/fchash.c
911 index 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 */
955 diff --git a/src/fcint.h b/src/fcint.h
956 index 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,
1092 diff --git a/src/fclist.c b/src/fclist.c
1093 index 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:
1104 diff --git a/src/fcmatch.c b/src/fcmatch.c
1105 index 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,
1117 diff --git a/src/fcname.c b/src/fcname.c
1118 index 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:
1160 diff --git a/src/fcobjs.c b/src/fcobjs.c
1161 index 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  
1182 diff --git a/src/fcobjs.h b/src/fcobjs.h
1183 index 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)
1204 diff --git a/src/fcpat.c b/src/fcpat.c
1205 index 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
1234 diff --git a/src/fcstat.c b/src/fcstat.c
1235 index 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)
1260 diff --git a/src/fcxml.c b/src/fcxml.c
1261 index 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.435564 seconds and 3 git commands to generate.