/*
- * $XFree86: $
+ * $XFree86: xc/lib/fontconfig/src/fccfg.c,v 1.15 2002/06/21 06:14:45 keithp Exp $
*
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
*
* PERFORMANCE OF THIS SOFTWARE.
*/
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
#include "fcint.h"
-static FcConfig *fcConfig;
+FcConfig *_fcConfig;
FcConfig *
FcConfigCreate (void)
config = malloc (sizeof (FcConfig));
if (!config)
goto bail0;
+ FcMemAlloc (FC_MEM_CONFIG, sizeof (FcConfig));
- config->dirs = malloc (sizeof (char *));
- if (!config->dirs)
+ config->configDirs = FcStrSetCreate ();
+ if (!config->configDirs)
goto bail1;
- config->dirs[0] = 0;
- config->configFiles = malloc (sizeof (char *));
+ config->configFiles = FcStrSetCreate ();
if (!config->configFiles)
goto bail2;
- config->configFiles[0] = 0;
+
+ config->fontDirs = FcStrSetCreate ();
+ if (!config->fontDirs)
+ goto bail3;
config->cache = 0;
if (!FcConfigSetCache (config, (FcChar8 *) ("~/" FC_USER_CACHE_FILE)))
- goto bail3;
+ goto bail4;
config->blanks = 0;
config->maxObjects = 0;
for (set = FcSetSystem; set <= FcSetApplication; set++)
config->fonts[set] = 0;
+
+ config->rescanTime = time(0);
+ config->rescanInterval = 30;
return config;
+bail4:
+ FcStrSetDestroy (config->fontDirs);
bail3:
- free (config->configFiles);
+ FcStrSetDestroy (config->configFiles);
bail2:
- free (config->dirs);
+ FcStrSetDestroy (config->configDirs);
bail1:
free (config);
+ FcMemFree (FC_MEM_CONFIG, sizeof (FcConfig));
bail0:
return 0;
}
+typedef struct _FcFileTime {
+ time_t time;
+ FcBool set;
+} FcFileTime;
+
+static FcFileTime
+FcConfigNewestFile (FcStrSet *files)
+{
+ FcStrList *list = FcStrListCreate (files);
+ FcFileTime newest = { 0, FcFalse };
+ FcChar8 *file;
+ struct stat statb;
+
+ if (list)
+ {
+ while ((file = FcStrListNext (list)))
+ if (stat ((char *) file, &statb) == 0)
+ if (!newest.set || statb.st_mtime - newest.time > 0)
+ newest.time = statb.st_mtime;
+ FcStrListDone (list);
+ }
+ return newest;
+}
+
+FcBool
+FcConfigUptoDate (FcConfig *config)
+{
+ FcFileTime config_time, font_time;
+ time_t now = time(0);
+ if (!config)
+ {
+ config = FcConfigGetCurrent ();
+ if (!config)
+ return FcFalse;
+ }
+ config_time = FcConfigNewestFile (config->configFiles);
+ font_time = FcConfigNewestFile (config->configDirs);
+ if ((config_time.set && config_time.time - config->rescanTime > 0) ||
+ (font_time.set && font_time.time - config->rescanTime) > 0)
+ {
+ return FcFalse;
+ }
+ config->rescanTime = now;
+ return FcTrue;
+}
+
static void
FcSubstDestroy (FcSubst *s)
{
}
}
-static void
-FcConfigDestroyStrings (FcChar8 **strings)
-{
- FcChar8 **s;
-
- for (s = strings; s && *s; s++)
- free (*s);
- if (strings)
- free (strings);
-}
-
-static FcBool
-FcConfigAddString (FcChar8 ***strings, FcChar8 *string)
-{
- int n;
- FcChar8 **s;
-
- n = 0;
- for (s = *strings; s && *s; s++)
- n++;
- s = malloc ((n + 2) * sizeof (FcChar8 *));
- if (!s)
- return FcFalse;
- s[n] = string;
- s[n+1] = 0;
- memcpy (s, *strings, n * sizeof (FcChar8 *));
- free (*strings);
- *strings = s;
- return FcTrue;
-}
-
void
FcConfigDestroy (FcConfig *config)
{
FcSetName set;
- FcConfigDestroyStrings (config->dirs);
- FcConfigDestroyStrings (config->configFiles);
- free (config->cache);
+ if (config == _fcConfig)
+ _fcConfig = 0;
+
+ FcStrSetDestroy (config->configDirs);
+ FcStrSetDestroy (config->fontDirs);
+ FcStrSetDestroy (config->configFiles);
+
+ FcStrFree (config->cache);
FcSubstDestroy (config->substPattern);
FcSubstDestroy (config->substFont);
for (set = FcSetSystem; set <= FcSetApplication; set++)
if (config->fonts[set])
FcFontSetDestroy (config->fonts[set]);
+ free (config);
+ FcMemFree (FC_MEM_CONFIG, sizeof (FcConfig));
}
/*
FcBool
FcConfigBuildFonts (FcConfig *config)
{
- FcFontSet *fonts;
- FcFileCache *cache;
- FcChar8 **d;
+ FcFontSet *fonts;
+ FcGlobalCache *cache;
+ FcStrList *list;
+ FcChar8 *dir;
fonts = FcFontSetCreate ();
if (!fonts)
goto bail0;
- cache = FcFileCacheCreate ();
+ cache = FcGlobalCacheCreate ();
if (!cache)
goto bail1;
- FcFileCacheLoad (cache, config->cache);
+ FcGlobalCacheLoad (cache, config->cache);
+
+ list = FcConfigGetFontDirs (config);
+ if (!list)
+ goto bail1;
- for (d = config->dirs; d && *d; d++)
+ while ((dir = FcStrListNext (list)))
{
if (FcDebug () & FC_DBG_FONTSET)
- printf ("scan dir %s\n", *d);
- FcDirScan (fonts, cache, config->blanks, *d, FcFalse);
+ printf ("scan dir %s\n", dir);
+ FcDirScan (fonts, config->fontDirs, cache, config->blanks, dir, FcFalse);
}
+ FcStrListDone (list);
+
if (FcDebug () & FC_DBG_FONTSET)
FcFontSetPrint (fonts);
- FcFileCacheSave (cache, config->cache);
- FcFileCacheDestroy (cache);
+ FcGlobalCacheSave (cache, config->cache);
+ FcGlobalCacheDestroy (cache);
FcConfigSetFonts (config, fonts, FcSetSystem);
if (!FcConfigBuildFonts (config))
return FcFalse;
- if (fcConfig)
- FcConfigDestroy (fcConfig);
- fcConfig = config;
+ if (_fcConfig)
+ FcConfigDestroy (_fcConfig);
+ _fcConfig = config;
return FcTrue;
}
FcConfig *
FcConfigGetCurrent (void)
{
- return fcConfig;
+ if (!_fcConfig)
+ if (!FcInit ())
+ return 0;
+ return _fcConfig;
}
FcBool
-FcConfigAddDir (FcConfig *config,
- const FcChar8 *d)
+FcConfigAddConfigDir (FcConfig *config,
+ const FcChar8 *d)
{
- FcChar8 *dir;
- FcChar8 *h;
+ return FcStrSetAddFilename (config->configDirs, d);
+}
- if (*d == '~')
- {
- h = (FcChar8 *) getenv ("HOME");
- if (!h)
- return FcFalse;
- dir = (FcChar8 *) malloc (strlen ((char *) h) + strlen ((char *) d));
- if (!dir)
- return FcFalse;
- strcpy ((char *) dir, (char *) h);
- strcat ((char *) dir, (char *) d+1);
- }
- else
- {
- dir = (FcChar8 *) malloc (strlen ((char *) d) + 1);
- if (!dir)
- return FcFalse;
- strcpy (dir, d);
- }
- if (!FcConfigAddString (&config->dirs, dir))
+FcStrList *
+FcConfigGetConfigDirs (FcConfig *config)
+{
+ if (!config)
{
- free (dir);
- return FcFalse;
+ config = FcConfigGetCurrent ();
+ if (!config)
+ return 0;
}
- return FcTrue;
+ return FcStrListCreate (config->configDirs);
+}
+
+FcBool
+FcConfigAddFontDir (FcConfig *config,
+ const FcChar8 *d)
+{
+ return FcStrSetAddFilename (config->fontDirs, d);
+}
+
+FcBool
+FcConfigAddDir (FcConfig *config,
+ const FcChar8 *d)
+{
+ return (FcConfigAddConfigDir (config, d) &&
+ FcConfigAddFontDir (config, d));
}
-FcChar8 **
-FcConfigGetDirs (FcConfig *config)
+FcStrList *
+FcConfigGetFontDirs (FcConfig *config)
{
if (!config)
{
if (!config)
return 0;
}
- return config->dirs;
+ return FcStrListCreate (config->fontDirs);
}
FcBool
FcConfigAddConfigFile (FcConfig *config,
const FcChar8 *f)
{
- FcChar8 *file;
- file = FcConfigFilename (f);
+ FcBool ret;
+ FcChar8 *file = FcConfigFilename (f);
+
if (!file)
return FcFalse;
- if (!FcConfigAddString (&config->configFiles, file))
- {
- free (file);
- return FcFalse;
- }
- return FcTrue;
+
+ ret = FcStrSetAdd (config->configFiles, file);
+ FcStrFree (file);
+ return ret;
}
-FcChar8 **
+FcStrList *
FcConfigGetConfigFiles (FcConfig *config)
{
if (!config)
if (!config)
return 0;
}
- return config->configFiles;
+ return FcStrListCreate (config->configFiles);
}
FcBool
FcConfigSetCache (FcConfig *config,
const FcChar8 *c)
{
- FcChar8 *new;
- FcChar8 *h;
-
- if (*c == '~')
- {
- h = (FcChar8 *) getenv ("HOME");
- if (!h)
- return FcFalse;
- new = (FcChar8 *) malloc (strlen ((char *) h) + strlen ((char *) c));
- if (!new)
- return FcFalse;
- strcpy ((char *) new, (char *) h);
- strcat ((char *) new, (char *) c+1);
- }
- else
- {
- new = FcStrCopy (c);
- }
+ FcChar8 *new = FcStrCopyFilename (c);
+
+ if (!new)
+ return FcFalse;
if (config->cache)
- free (config->cache);
+ FcStrFree (config->cache);
config->cache = new;
return FcTrue;
}
config->fonts[set] = fonts;
}
+
+
FcBlanks *
FcConfigGetBlanks (FcConfig *config)
{
return FcTrue;
}
+int
+FcConfigGetRescanInverval (FcConfig *config)
+{
+ if (!config)
+ {
+ config = FcConfigGetCurrent ();
+ if (!config)
+ return 0;
+ }
+ return config->rescanInterval;
+}
+
+FcBool
+FcConfigSetRescanInverval (FcConfig *config, int rescanInterval)
+{
+ if (!config)
+ {
+ config = FcConfigGetCurrent ();
+ if (!config)
+ return FcFalse;
+ }
+ config->rescanInterval = rescanInterval;
+ return FcTrue;
+}
+
FcBool
FcConfigAddEdit (FcConfig *config,
FcTest *test,
FcValueList *value;
} FcSubState;
-static const FcMatrix FcIdentityMatrix = { 1, 0, 0, 1 };
-
static FcValue
FcConfigPromote (FcValue v, FcValue u)
{
}
else if (v.type == FcTypeVoid && u.type == FcTypeMatrix)
{
- v.u.m = (FcMatrix *) &FcIdentityMatrix;
+ v.u.m = &FcIdentityMatrix;
v.type = FcTypeMatrix;
}
return v;
case FcTypeCharSet:
switch (op) {
case FcOpContains:
- /* m contains v if v - m is empty */
- ret = FcCharSetSubtractCount (v.u.c, m.u.c) == 0;
+ /* m contains v if v is a subset of m */
+ ret = FcCharSetIsSubset (v.u.c, m.u.c);
break;
case FcOpEqual:
ret = FcCharSetEqual (m.u.c, v.u.c);
break;
}
break;
+ case FcTypeFTFace:
+ switch (op) {
+ case FcOpEqual:
+ ret = m.u.f == v.u.f;
+ break;
+ case FcOpNotEqual:
+ ret = m.u.f != v.u.f;
+ break;
+ default:
+ break;
+ }
}
}
else
v.type = FcTypeVoid;
break;
}
+ break;
case FcTypeMatrix:
switch (e->op) {
case FcOpEqual:
case FcTypeCharSet:
switch (e->op) {
case FcOpContains:
- /* vl contains vr if vr - vl is empty */
+ /* vl contains vr if vr is a subset of vl */
v.type = FcTypeBool;
- v.u.b = FcCharSetSubtractCount (vr.u.c, vl.u.c) == 0;
+ v.u.b = FcCharSetIsSubset (vr.u.c, vl.u.c);
break;
case FcOpEqual:
v.type = FcTypeBool;
static FcValueList *
FcConfigMatchValueList (FcPattern *p,
FcTest *t,
- FcValueList *v)
+ FcValueList *values)
{
- FcValueList *ret = 0;
- FcValue value = FcConfigEvaluate (p, t->expr);
+ FcValueList *ret = 0;
+ FcExpr *e = t->expr;
+ FcValue value;
+ FcValueList *v;
- for (; v; v = v->next)
+ while (e)
{
- if (FcConfigCompareValue (v->value, t->op, value))
+ if (e->op == FcOpComma)
{
- if (!ret)
- ret = v;
+ value = FcConfigEvaluate (p, e->u.tree.left);
+ e = e->u.tree.right;
}
else
{
- if (t->qual == FcQualAll)
+ value = FcConfigEvaluate (p, e);
+ e = 0;
+ }
+
+ for (v = values; v; v = v->next)
+ {
+ if (FcConfigCompareValue (v->value, t->op, value))
{
- ret = 0;
- break;
+ if (!ret)
+ ret = v;
+ }
+ else
+ {
+ if (t->qual == FcQualAll)
+ {
+ ret = 0;
+ break;
+ }
}
}
+ FcValueDestroy (value);
}
- FcValueDestroy (value);
return ret;
}
l->value = FcConfigEvaluate (p, e);
l->next = 0;
}
- while (l->value.type == FcTypeVoid)
+ l->binding = FcValueBindingWeak;
+ while (l && l->value.type == FcTypeVoid)
{
FcValueList *next = l->next;
{
if (list)
{
- FcPatternElt *e = FcPatternFind (p, object, FcTrue);
+ FcPatternElt *e = FcPatternInsertElt (p, object);
if (!e)
return;
FcConfigPatternDel (FcPattern *p,
const char *object)
{
- FcPatternElt *e = FcPatternFind (p, object, FcFalse);
+ FcPatternElt *e = FcPatternFindElt (p, object);
if (!e)
return;
while (e->values)
FcConfigPatternCanon (FcPattern *p,
const char *object)
{
- FcPatternElt *e = FcPatternFind (p, object, FcFalse);
+ FcPatternElt *e = FcPatternFindElt (p, object);
if (!e)
return;
if (!e->values)
printf ("FcConfigSubstitute test ");
FcTestPrint (t);
}
- st[i].elt = FcPatternFind (p, t->field, FcFalse);
+ st[i].elt = FcPatternFindElt (p, t->field);
/*
* If there's no such field in the font,
* then FcQualAll matches while FcQualAny does not
st[i].value = FcConfigMatchValueList (p, t, st[i].elt->values);
if (!st[i].value)
break;
+ if (t->qual == FcQualFirst && st[i].value != st[i].elt->values)
+ break;
+ if (t->qual == FcQualNotFirst && st[i].value == st[i].elt->values)
+ break;
}
if (t)
{
if (!path)
return 0;
- strcpy (path, dir);
+ strcpy ((char *) path, (const char *) dir);
/* make sure there's a single separating / */
if ((!path[0] || path[strlen((char *) path)-1] != '/') && file[0] != '/')
strcat ((char *) path, "/");
path[i] = malloc (colon - e + 1);
if (!path[i])
goto bail1;
- strncpy (path[i], e, colon - e);
+ strncpy ((char *) path[i], (const char *) e, colon - e);
path[i][colon - e] = '\0';
if (*colon)
e = colon + 1;
path[i] = malloc (strlen ((char *) dir) + 1);
if (!path[i])
goto bail1;
- strcpy (path[i], dir);
+ strcpy ((char *) path[i], (const char *) dir);
return path;
bail1:
const FcChar8 *file)
{
FcFontSet *set;
+ FcStrSet *subdirs;
+ FcStrList *sublist;
+ FcChar8 *subdir;
if (!config)
{
return FcFalse;
}
+ subdirs = FcStrSetCreate ();
+ if (!subdirs)
+ return FcFalse;
+
set = FcConfigGetFonts (config, FcSetApplication);
if (!set)
{
set = FcFontSetCreate ();
if (!set)
+ {
+ FcStrSetDestroy (subdirs);
return FcFalse;
+ }
FcConfigSetFonts (config, set, FcSetApplication);
}
- return FcFileScan (set, 0, config->blanks, file, FcFalse);
+
+ if (!FcFileScan (set, subdirs, 0, config->blanks, file, FcFalse))
+ {
+ FcStrSetDestroy (subdirs);
+ return FcFalse;
+ }
+ if ((sublist = FcStrListCreate (subdirs)))
+ {
+ while ((subdir = FcStrListNext (sublist)))
+ {
+ FcConfigAppFontAddDir (config, subdir);
+ }
+ FcStrListDone (sublist);
+ }
+ return FcTrue;
}
FcBool
const FcChar8 *dir)
{
FcFontSet *set;
+ FcStrSet *subdirs;
+ FcStrList *sublist;
+ FcChar8 *subdir;
if (!config)
{
if (!config)
return FcFalse;
}
+ subdirs = FcStrSetCreate ();
+ if (!subdirs)
+ return FcFalse;
+
set = FcConfigGetFonts (config, FcSetApplication);
if (!set)
{
set = FcFontSetCreate ();
if (!set)
+ {
+ FcStrSetDestroy (subdirs);
return FcFalse;
+ }
FcConfigSetFonts (config, set, FcSetApplication);
}
- return FcDirScan (set, 0, config->blanks, dir, FcFalse);
+
+ if (!FcDirScan (set, subdirs, 0, config->blanks, dir, FcFalse))
+ {
+ FcStrSetDestroy (subdirs);
+ return FcFalse;
+ }
+ if ((sublist = FcStrListCreate (subdirs)))
+ {
+ while ((subdir = FcStrListNext (sublist)))
+ {
+ FcConfigAppFontAddDir (config, subdir);
+ }
+ FcStrListDone (sublist);
+ }
+ return FcTrue;
}
void