2 * $RCSId: xc/lib/fontconfig/src/fccfg.c,v 1.23 2002/08/31 22:17:32 keithp Exp $
4 * Copyright © 2000 Keith Packard
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. Keith Packard makes no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
27 #if defined (_WIN32) && defined (PIC)
41 config = malloc (sizeof (FcConfig));
44 FcMemAlloc (FC_MEM_CONFIG, sizeof (FcConfig));
46 config->configDirs = FcStrSetCreate ();
47 if (!config->configDirs)
50 config->configFiles = FcStrSetCreate ();
51 if (!config->configFiles)
54 config->fontDirs = FcStrSetCreate ();
55 if (!config->fontDirs)
60 if (!FcConfigSetCache (config, (FcChar8 *) ("~/" FC_USER_CACHE_FILE)))
65 config->substPattern = 0;
66 config->substFont = 0;
67 config->maxObjects = 0;
68 for (set = FcSetSystem; set <= FcSetApplication; set++)
69 config->fonts[set] = 0;
71 config->rescanTime = time(0);
72 config->rescanInterval = 30;
77 FcStrSetDestroy (config->fontDirs);
79 FcStrSetDestroy (config->configFiles);
81 FcStrSetDestroy (config->configDirs);
84 FcMemFree (FC_MEM_CONFIG, sizeof (FcConfig));
89 typedef struct _FcFileTime {
95 FcConfigNewestFile (FcStrSet *files)
97 FcStrList *list = FcStrListCreate (files);
98 FcFileTime newest = { 0, FcFalse };
104 while ((file = FcStrListNext (list)))
105 if (stat ((char *) file, &statb) == 0)
106 if (!newest.set || statb.st_mtime - newest.time > 0)
107 newest.time = statb.st_mtime;
108 FcStrListDone (list);
114 FcConfigUptoDate (FcConfig *config)
116 FcFileTime config_time, font_time;
117 time_t now = time(0);
120 config = FcConfigGetCurrent ();
124 config_time = FcConfigNewestFile (config->configFiles);
125 font_time = FcConfigNewestFile (config->configDirs);
126 if ((config_time.set && config_time.time - config->rescanTime > 0) ||
127 (font_time.set && font_time.time - config->rescanTime) > 0)
131 config->rescanTime = now;
136 FcSubstDestroy (FcSubst *s)
144 FcTestDestroy (s->test);
146 FcEditDestroy (s->edit);
152 FcConfigDestroy (FcConfig *config)
156 if (config == _fcConfig)
159 FcStrSetDestroy (config->configDirs);
160 FcStrSetDestroy (config->fontDirs);
161 FcStrSetDestroy (config->configFiles);
163 FcStrFree (config->cache);
165 FcSubstDestroy (config->substPattern);
166 FcSubstDestroy (config->substFont);
167 for (set = FcSetSystem; set <= FcSetApplication; set++)
168 if (config->fonts[set])
169 FcFontSetDestroy (config->fonts[set]);
171 FcMemFree (FC_MEM_CONFIG, sizeof (FcConfig));
175 * Scan the current list of directories in the configuration
176 * and build the set of available fonts. Update the
177 * per-user cache file to reflect the new configuration
181 FcConfigBuildFonts (FcConfig *config)
184 FcGlobalCache *cache;
188 fonts = FcFontSetCreate ();
192 cache = FcGlobalCacheCreate ();
196 FcGlobalCacheLoad (cache, config->cache);
198 list = FcConfigGetFontDirs (config);
202 while ((dir = FcStrListNext (list)))
204 if (FcDebug () & FC_DBG_FONTSET)
205 printf ("scan dir %s\n", dir);
206 FcDirScan (fonts, config->fontDirs, cache, config->blanks, dir, FcFalse);
209 FcStrListDone (list);
211 if (FcDebug () & FC_DBG_FONTSET)
212 FcFontSetPrint (fonts);
214 FcGlobalCacheSave (cache, config->cache);
215 FcGlobalCacheDestroy (cache);
217 FcConfigSetFonts (config, fonts, FcSetSystem);
221 FcFontSetDestroy (fonts);
227 FcConfigSetCurrent (FcConfig *config)
230 if (!FcConfigBuildFonts (config))
234 FcConfigDestroy (_fcConfig);
240 FcConfigGetCurrent (void)
249 FcConfigAddConfigDir (FcConfig *config,
252 return FcStrSetAddFilename (config->configDirs, d);
256 FcConfigGetConfigDirs (FcConfig *config)
260 config = FcConfigGetCurrent ();
264 return FcStrListCreate (config->configDirs);
268 FcConfigAddFontDir (FcConfig *config,
271 return FcStrSetAddFilename (config->fontDirs, d);
275 FcConfigAddDir (FcConfig *config,
278 return (FcConfigAddConfigDir (config, d) &&
279 FcConfigAddFontDir (config, d));
283 FcConfigGetFontDirs (FcConfig *config)
287 config = FcConfigGetCurrent ();
291 return FcStrListCreate (config->fontDirs);
295 FcConfigAddConfigFile (FcConfig *config,
299 FcChar8 *file = FcConfigFilename (f);
304 ret = FcStrSetAdd (config->configFiles, file);
310 FcConfigGetConfigFiles (FcConfig *config)
314 config = FcConfigGetCurrent ();
318 return FcStrListCreate (config->configFiles);
322 FcConfigSetCache (FcConfig *config,
325 FcChar8 *new = FcStrCopyFilename (c);
330 FcStrFree (config->cache);
336 FcConfigGetCache (FcConfig *config)
340 config = FcConfigGetCurrent ();
344 return config->cache;
348 FcConfigGetFonts (FcConfig *config,
353 config = FcConfigGetCurrent ();
357 return config->fonts[set];
361 FcConfigSetFonts (FcConfig *config,
365 if (config->fonts[set])
366 FcFontSetDestroy (config->fonts[set]);
367 config->fonts[set] = fonts;
373 FcConfigGetBlanks (FcConfig *config)
377 config = FcConfigGetCurrent ();
381 return config->blanks;
385 FcConfigAddBlank (FcConfig *config,
393 b = FcBlanksCreate ();
397 if (!FcBlanksAdd (b, blank))
404 FcConfigGetRescanInverval (FcConfig *config)
408 config = FcConfigGetCurrent ();
412 return config->rescanInterval;
416 FcConfigSetRescanInverval (FcConfig *config, int rescanInterval)
420 config = FcConfigGetCurrent ();
424 config->rescanInterval = rescanInterval;
429 FcConfigAddEdit (FcConfig *config,
434 FcSubst *subst, **prev;
438 subst = (FcSubst *) malloc (sizeof (FcSubst));
441 FcMemAlloc (FC_MEM_SUBST, sizeof (FcSubst));
442 if (kind == FcMatchPattern)
443 prev = &config->substPattern;
445 prev = &config->substFont;
446 for (; *prev; prev = &(*prev)->next);
452 for (t = test; t; t = t->next)
454 if (t->kind == FcMatchDefault)
458 if (config->maxObjects < num)
459 config->maxObjects = num;
460 if (FcDebug () & FC_DBG_EDIT)
462 printf ("Add Subst ");
463 FcSubstPrint (subst);
468 typedef struct _FcSubState {
474 FcConfigPromote (FcValue v, FcValue u)
476 if (v.type == FcTypeInteger)
478 v.type = FcTypeDouble;
479 v.u.d = (double) v.u.i;
481 else if (v.type == FcTypeVoid && u.type == FcTypeMatrix)
483 v.u.m = &FcIdentityMatrix;
484 v.type = FcTypeMatrix;
486 else if (v.type == FcTypeString && u.type == FcTypeLangSet)
488 v.u.l = FcLangSetPromote (v.u.s);
489 v.type = FcTypeLangSet;
495 FcConfigCompareValue (const FcValue m_o,
501 FcBool ret = FcFalse;
503 m = FcConfigPromote (m, v);
504 v = FcConfigPromote (v, m);
505 if (m.type == v.type)
509 break; /* FcConfigPromote prevents this from happening */
514 ret = m.u.d == v.u.d;
517 case FcOpNotContains:
518 ret = m.u.d != v.u.d;
524 ret = m.u.d <= v.u.d;
530 ret = m.u.d >= v.u.d;
540 ret = m.u.b == v.u.b;
543 case FcOpNotContains:
544 ret = m.u.b != v.u.b;
554 ret = FcStrCmpIgnoreCase (m.u.s, v.u.s) == 0;
557 case FcOpNotContains:
558 ret = FcStrCmpIgnoreCase (m.u.s, v.u.s) != 0;
568 ret = FcMatrixEqual (m.u.m, v.u.m);
571 case FcOpNotContains:
572 ret = !FcMatrixEqual (m.u.m, v.u.m);
581 /* m contains v if v is a subset of m */
582 ret = FcCharSetIsSubset (v.u.c, m.u.c);
584 case FcOpNotContains:
585 /* m contains v if v is a subset of m */
586 ret = !FcCharSetIsSubset (v.u.c, m.u.c);
589 ret = FcCharSetEqual (m.u.c, v.u.c);
592 ret = !FcCharSetEqual (m.u.c, v.u.c);
601 ret = FcLangSetContains (v.u.l, m.u.l);
603 case FcOpNotContains:
604 ret = FcLangSetContains (v.u.l, m.u.l);
607 ret = FcLangSetEqual (v.u.l, m.u.l);
610 ret = !FcLangSetEqual (v.u.l, m.u.l);
630 ret = m.u.f == v.u.f;
633 case FcOpNotContains:
634 ret = m.u.f != v.u.f;
644 if (op == FcOpNotEqual || op == FcOpNotContains)
652 FcConfigEvaluate (FcPattern *p, FcExpr *e)
660 v.type = FcTypeInteger;
664 v.type = FcTypeDouble;
668 v.type = FcTypeString;
673 v.type = FcTypeMatrix;
678 v.type = FcTypeCharSet;
687 r = FcPatternGet (p, e->u.field, 0, &v);
688 if (r != FcResultMatch)
692 if (FcNameConstant (e->u.constant, &v.u.i))
693 v.type = FcTypeInteger;
698 vl = FcConfigEvaluate (p, e->u.tree.left);
699 if (vl.type == FcTypeBool)
702 v = FcConfigEvaluate (p, e->u.tree.right->u.tree.left);
704 v = FcConfigEvaluate (p, e->u.tree.right->u.tree.right);
717 case FcOpNotContains:
718 vl = FcConfigEvaluate (p, e->u.tree.left);
719 vr = FcConfigEvaluate (p, e->u.tree.right);
721 v.u.b = FcConfigCompareValue (vl, e->op, vr);
731 vl = FcConfigEvaluate (p, e->u.tree.left);
732 vr = FcConfigEvaluate (p, e->u.tree.right);
733 vl = FcConfigPromote (vl, vr);
734 vr = FcConfigPromote (vr, vl);
735 if (vl.type == vr.type)
741 v.type = FcTypeDouble;
742 v.u.d = vl.u.d + vr.u.d;
745 v.type = FcTypeDouble;
746 v.u.d = vl.u.d - vr.u.d;
749 v.type = FcTypeDouble;
750 v.u.d = vl.u.d * vr.u.d;
753 v.type = FcTypeDouble;
754 v.u.d = vl.u.d / vr.u.d;
760 if (v.type == FcTypeDouble &&
761 v.u.d == (double) (int) v.u.d)
763 v.type = FcTypeInteger;
771 v.u.b = vl.u.b || vr.u.b;
775 v.u.b = vl.u.b && vr.u.b;
785 v.type = FcTypeString;
786 v.u.s = FcStrPlus (vl.u.s, vr.u.s);
798 v.type = FcTypeMatrix;
799 m = malloc (sizeof (FcMatrix));
802 FcMemAlloc (FC_MEM_MATRIX, sizeof (FcMatrix));
803 FcMatrixMultiply (m, vl.u.m, vr.u.m);
827 vl = FcConfigEvaluate (p, e->u.tree.left);
847 FcConfigMatchValueList (FcPattern *p,
851 FcValueList *ret = 0;
858 if (e->op == FcOpComma)
860 value = FcConfigEvaluate (p, e->u.tree.left);
865 value = FcConfigEvaluate (p, e);
869 for (v = values; v; v = v->next)
871 if (FcConfigCompareValue (v->value, t->op, value))
878 if (t->qual == FcQualAll)
885 FcValueDestroy (value);
891 FcConfigValues (FcPattern *p, FcExpr *e, FcValueBinding binding)
897 l = (FcValueList *) malloc (sizeof (FcValueList));
900 FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList));
901 if (e->op == FcOpComma)
903 l->value = FcConfigEvaluate (p, e->u.tree.left);
904 l->next = FcConfigValues (p, e->u.tree.right, binding);
908 l->value = FcConfigEvaluate (p, e);
911 l->binding = binding;
912 while (l && l->value.type == FcTypeVoid)
914 FcValueList *next = l->next;
916 FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
924 FcConfigAdd (FcValueList **head,
925 FcValueList *position,
929 FcValueList **prev, *last, *v;
930 FcValueBinding sameBinding;
933 sameBinding = position->binding;
935 sameBinding = FcValueBindingWeak;
936 for (v = new; v; v = v->next)
937 if (v->binding == FcValueBindingSame)
938 v->binding = sameBinding;
942 prev = &position->next;
944 for (prev = head; *prev; prev = &(*prev)->next)
951 for (prev = head; *prev; prev = &(*prev)->next)
953 if (*prev == position)
960 if (FcDebug () & FC_DBG_EDIT)
963 printf ("position not on list\n");
967 if (FcDebug () & FC_DBG_EDIT)
969 printf ("%s list before ", append ? "Append" : "Prepend");
970 FcValueListPrint (*head);
984 if (FcDebug () & FC_DBG_EDIT)
986 printf ("%s list after ", append ? "Append" : "Prepend");
987 FcValueListPrint (*head);
995 FcConfigDel (FcValueList **head,
996 FcValueList *position)
1000 for (prev = head; *prev; prev = &(*prev)->next)
1002 if (*prev == position)
1004 *prev = position->next;
1006 FcValueListDestroy (position);
1013 FcConfigPatternAdd (FcPattern *p,
1020 FcPatternElt *e = FcPatternInsertElt (p, object);
1024 FcConfigAdd (&e->values, 0, append, list);
1029 * Delete all values associated with a field
1032 FcConfigPatternDel (FcPattern *p,
1035 FcPatternElt *e = FcPatternFindElt (p, object);
1039 FcConfigDel (&e->values, e->values);
1043 FcConfigPatternCanon (FcPattern *p,
1046 FcPatternElt *e = FcPatternFindElt (p, object);
1050 FcPatternDel (p, object);
1054 FcConfigSubstituteWithPat (FcConfig *config,
1069 config = FcConfigGetCurrent ();
1074 st = (FcSubState *) malloc (config->maxObjects * sizeof (FcSubState));
1075 if (!st && config->maxObjects)
1077 FcMemAlloc (FC_MEM_SUBSTATE, config->maxObjects * sizeof (FcSubState));
1079 if (FcDebug () & FC_DBG_EDIT)
1081 printf ("FcConfigSubstitute ");
1084 if (kind == FcMatchPattern)
1085 s = config->substPattern;
1087 s = config->substFont;
1088 for (; s; s = s->next)
1091 * Check the tests to see if
1092 * they all match the pattern
1094 for (t = s->test, i = 0; t; t = t->next, i++)
1096 if (FcDebug () & FC_DBG_EDIT)
1098 printf ("FcConfigSubstitute test ");
1102 if (kind == FcMatchFont && t->kind == FcMatchPattern)
1107 st[i].elt = FcPatternFindElt (m, t->field);
1111 * If there's no such field in the font,
1112 * then FcQualAll matches while FcQualAny does not
1116 if (t->qual == FcQualAll)
1125 * Check to see if there is a match, mark the location
1126 * to apply match-relative edits
1128 st[i].value = FcConfigMatchValueList (m, t, st[i].elt->values);
1131 if (t->qual == FcQualFirst && st[i].value != st[i].elt->values)
1133 if (t->qual == FcQualNotFirst && st[i].value == st[i].elt->values)
1138 if (FcDebug () & FC_DBG_EDIT)
1139 printf ("No match\n");
1142 if (FcDebug () & FC_DBG_EDIT)
1144 printf ("Substitute ");
1147 for (e = s->edit; e; e = e->next)
1150 * Evaluate the list of expressions
1152 l = FcConfigValues (p, e->expr, e->binding);
1154 * Locate any test associated with this field, skipping
1155 * tests associated with the pattern when substituting in
1158 for (t = s->test, i = 0; t; t = t->next, i++)
1160 if ((t->kind == FcMatchFont || kind == FcMatchPattern) &&
1161 !FcStrCmpIgnoreCase ((FcChar8 *) t->field,
1162 (FcChar8 *) e->field))
1172 * If there was a test, then replace the matched
1173 * value with the new list of values
1177 FcValueList *thisValue = st[i].value;
1178 FcValueList *nextValue = thisValue ? thisValue->next : 0;
1181 * Append the new list of values after the current value
1183 FcConfigAdd (&st[i].elt->values, thisValue, FcTrue, l);
1185 * Delete the marked value
1187 FcConfigDel (&st[i].elt->values, thisValue);
1189 * Adjust any pointers into the value list to ensure
1190 * future edits occur at the same place
1192 for (t = s->test, i = 0; t; t = t->next, i++)
1194 if (st[i].value == thisValue)
1195 st[i].value = nextValue;
1199 /* fall through ... */
1200 case FcOpAssignReplace:
1202 * Delete all of the values and insert
1205 FcConfigPatternDel (p, e->field);
1206 FcConfigPatternAdd (p, e->field, l, FcTrue);
1208 * Adjust any pointers into the value list as they no
1209 * longer point to anything valid
1213 FcPatternElt *thisElt = st[i].elt;
1214 for (t = s->test, i = 0; t; t = t->next, i++)
1216 if (st[i].elt == thisElt)
1224 FcConfigAdd (&st[i].elt->values, st[i].value, FcFalse, l);
1227 /* fall through ... */
1228 case FcOpPrependFirst:
1229 FcConfigPatternAdd (p, e->field, l, FcFalse);
1234 FcConfigAdd (&st[i].elt->values, st[i].value, FcTrue, l);
1237 /* fall through ... */
1238 case FcOpAppendLast:
1239 FcConfigPatternAdd (p, e->field, l, FcTrue);
1246 * Now go through the pattern and eliminate
1247 * any properties without data
1249 for (e = s->edit; e; e = e->next)
1250 FcConfigPatternCanon (p, e->field);
1252 if (FcDebug () & FC_DBG_EDIT)
1254 printf ("FcConfigSubstitute edit");
1258 FcMemFree (FC_MEM_SUBSTATE, config->maxObjects * sizeof (FcSubState));
1260 if (FcDebug () & FC_DBG_EDIT)
1262 printf ("FcConfigSubstitute done");
1269 FcConfigSubstitute (FcConfig *config,
1273 return FcConfigSubstituteWithPat (config, p, 0, kind);
1276 #if defined (_WIN32) && defined (PIC)
1278 static FcChar8 fontconfig_path[1000] = "";
1281 DllMain (HINSTANCE hinstDLL,
1287 switch (fdwReason) {
1288 case DLL_PROCESS_ATTACH:
1289 if (!GetModuleFileName ((HMODULE) hinstDLL, fontconfig_path,
1290 sizeof (fontconfig_path)))
1293 /* If the fontconfig DLL is in a "bin" or "lib" subfolder,
1294 * assume it's a Unix-style installation tree, and use
1295 * "etc/fonts" in there as FONTCONFIG_PATH. Otherwise use the
1296 * folder where the DLL is as FONTCONFIG_PATH.
1298 p = strrchr (fontconfig_path, '\\');
1302 p = strrchr (fontconfig_path, '\\');
1303 if (p && (FcStrCmpIgnoreCase (p + 1, "bin") == 0 ||
1304 FcStrCmpIgnoreCase (p + 1, "lib") == 0))
1306 strcat (fontconfig_path, "\\etc\\fonts");
1309 fontconfig_path[0] = '\0';
1317 #undef FONTCONFIG_PATH
1318 #define FONTCONFIG_PATH fontconfig_path
1320 #else /* !(_WIN32 && PIC) */
1322 #ifndef FONTCONFIG_PATH
1323 #define FONTCONFIG_PATH "/etc/fonts"
1326 #endif /* !(_WIN32 && PIC) */
1328 #ifndef FONTCONFIG_FILE
1329 #define FONTCONFIG_FILE "fonts.conf"
1333 FcConfigFileExists (const FcChar8 *dir, const FcChar8 *file)
1338 dir = (FcChar8 *) "";
1339 path = malloc (strlen ((char *) dir) + 1 + strlen ((char *) file) + 1);
1343 strcpy ((char *) path, (const char *) dir);
1344 /* make sure there's a single separator */
1346 if ((!path[0] || (path[strlen((char *) path)-1] != '/' &&
1347 path[strlen((char *) path)-1] != '\\')) &&
1348 (file[0] != '/' && file[0] != '\\'))
1349 strcat ((char *) path, "\\");
1351 if ((!path[0] || path[strlen((char *) path)-1] != '/') && file[0] != '/')
1352 strcat ((char *) path, "/");
1354 strcat ((char *) path, (char *) file);
1356 FcMemAlloc (FC_MEM_STRING, strlen ((char *) path) + 1);
1357 if (access ((char *) path, R_OK) == 0)
1365 FcConfigGetPath (void)
1368 FcChar8 *env, *e, *colon;
1373 npath = 2; /* default dir + null */
1374 env = (FcChar8 *) getenv ("FONTCONFIG_PATH");
1380 if (*e++ == FC_SEARCH_PATH_SEPARATOR)
1383 path = calloc (npath, sizeof (FcChar8 *));
1393 colon = (FcChar8 *) strchr ((char *) e, FC_SEARCH_PATH_SEPARATOR);
1395 colon = e + strlen ((char *) e);
1396 path[i] = malloc (colon - e + 1);
1399 strncpy ((char *) path[i], (const char *) e, colon - e);
1400 path[i][colon - e] = '\0';
1409 dir = (FcChar8 *) FONTCONFIG_PATH;
1410 path[i] = malloc (strlen ((char *) dir) + 1);
1413 strcpy ((char *) path[i], (const char *) dir);
1417 for (i = 0; path[i]; i++)
1425 FcConfigFreePath (FcChar8 **path)
1429 for (p = path; *p; p++)
1434 static FcBool _FcConfigHomeEnabled = FcTrue;
1439 if (_FcConfigHomeEnabled)
1441 char *home = getenv ("HOME");
1445 home = getenv ("USERPROFILE");
1454 FcConfigEnableHome (FcBool enable)
1456 FcBool prev = _FcConfigHomeEnabled;
1457 _FcConfigHomeEnabled = enable;
1462 FcConfigFilename (const FcChar8 *url)
1464 FcChar8 *file, *dir, **path, **p;
1468 url = (FcChar8 *) getenv ("FONTCONFIG_FILE");
1470 url = (FcChar8 *) FONTCONFIG_FILE;
1475 if (isalpha (*url) &&
1477 (url[2] == '/' || url[2] == '\\'))
1483 dir = FcConfigHome ();
1485 file = FcConfigFileExists (dir, url + 1);
1494 file = FcConfigFileExists (0, url);
1497 path = FcConfigGetPath ();
1500 for (p = path; *p; p++)
1502 file = FcConfigFileExists (*p, url);
1506 FcConfigFreePath (path);
1513 * Manage the application-specific fonts
1517 FcConfigAppFontAddFile (FcConfig *config,
1518 const FcChar8 *file)
1527 config = FcConfigGetCurrent ();
1532 subdirs = FcStrSetCreate ();
1536 set = FcConfigGetFonts (config, FcSetApplication);
1539 set = FcFontSetCreate ();
1542 FcStrSetDestroy (subdirs);
1545 FcConfigSetFonts (config, set, FcSetApplication);
1548 if (!FcFileScan (set, subdirs, 0, config->blanks, file, FcFalse))
1550 FcStrSetDestroy (subdirs);
1553 if ((sublist = FcStrListCreate (subdirs)))
1555 while ((subdir = FcStrListNext (sublist)))
1557 FcConfigAppFontAddDir (config, subdir);
1559 FcStrListDone (sublist);
1565 FcConfigAppFontAddDir (FcConfig *config,
1575 config = FcConfigGetCurrent ();
1579 subdirs = FcStrSetCreate ();
1583 set = FcConfigGetFonts (config, FcSetApplication);
1586 set = FcFontSetCreate ();
1589 FcStrSetDestroy (subdirs);
1592 FcConfigSetFonts (config, set, FcSetApplication);
1595 if (!FcDirScan (set, subdirs, 0, config->blanks, dir, FcFalse))
1597 FcStrSetDestroy (subdirs);
1600 if ((sublist = FcStrListCreate (subdirs)))
1602 while ((subdir = FcStrListNext (sublist)))
1604 FcConfigAppFontAddDir (config, subdir);
1606 FcStrListDone (sublist);
1612 FcConfigAppFontClear (FcConfig *config)
1614 FcConfigSetFonts (config, 0, FcSetApplication);