/*
- * $XFree86: xc/lib/fontconfig/src/fccfg.c,v 1.5 2002/03/01 01:00:54 keithp Exp $
+ * $RCSId: xc/lib/fontconfig/src/fccfg.c,v 1.23 2002/08/31 22:17:32 keithp Exp $
*
- * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
+ * Copyright © 2000 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
goto bail3;
config->cache = 0;
- if (!FcConfigSetCache (config, (FcChar8 *) ("~/" FC_USER_CACHE_FILE)))
- goto bail4;
+ if (FcConfigHome())
+ if (!FcConfigSetCache (config, (FcChar8 *) ("~/" FC_USER_CACHE_FILE)))
+ goto bail4;
config->blanks = 0;
return 0;
}
-static time_t
+typedef struct _FcFileTime {
+ time_t time;
+ FcBool set;
+} FcFileTime;
+
+static FcFileTime
FcConfigNewestFile (FcStrSet *files)
{
FcStrList *list = FcStrListCreate (files);
- FcBool set = FcFalse;
- time_t newest = 0;
+ FcFileTime newest = { 0, FcFalse };
FcChar8 *file;
struct stat statb;
if (list)
{
while ((file = FcStrListNext (list)))
- {
if (stat ((char *) file, &statb) == 0)
- {
- if (!set)
- newest = statb.st_mtime;
- else if (statb.st_mtime - newest > 0)
- newest = statb.st_mtime;
- }
- }
+ if (!newest.set || statb.st_mtime - newest.time > 0)
+ newest.time = statb.st_mtime;
FcStrListDone (list);
}
return newest;
FcBool
FcConfigUptoDate (FcConfig *config)
{
- time_t config_time;
- time_t font_time;
- time_t now = time(0);
+ FcFileTime config_time, font_time;
+ time_t now = time(0);
if (!config)
{
config = FcConfigGetCurrent ();
}
config_time = FcConfigNewestFile (config->configFiles);
font_time = FcConfigNewestFile (config->configDirs);
- if (config_time - config->rescanTime > 0 ||
- font_time - config->rescanTime > 0)
+ if ((config_time.set && config_time.time - config->rescanTime > 0) ||
+ (font_time.set && font_time.time - config->rescanTime) > 0)
{
return FcFalse;
}
FcBool
FcConfigBuildFonts (FcConfig *config)
{
- FcFontSet *fonts;
- FcFileCache *cache;
- FcStrList *list;
- FcChar8 *dir;
+ 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)
if (FcDebug () & FC_DBG_FONTSET)
FcFontSetPrint (fonts);
- FcFileCacheSave (cache, config->cache);
- FcFileCacheDestroy (cache);
+ FcGlobalCacheSave (cache, config->cache);
+ FcGlobalCacheDestroy (cache);
FcConfigSetFonts (config, fonts, FcSetSystem);
subst = (FcSubst *) malloc (sizeof (FcSubst));
if (!subst)
return FcFalse;
+ FcMemAlloc (FC_MEM_SUBST, sizeof (FcSubst));
if (kind == FcMatchPattern)
prev = &config->substPattern;
else
subst->next = 0;
subst->test = test;
subst->edit = edit;
- if (FcDebug () & FC_DBG_EDIT)
- {
- printf ("Add Subst ");
- FcSubstPrint (subst);
- }
num = 0;
for (t = test; t; t = t->next)
+ {
+ if (t->kind == FcMatchDefault)
+ t->kind = kind;
num++;
+ }
if (config->maxObjects < num)
config->maxObjects = num;
+ if (FcDebug () & FC_DBG_EDIT)
+ {
+ printf ("Add Subst ");
+ FcSubstPrint (subst);
+ }
return FcTrue;
}
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;
}
+ else if (v.type == FcTypeString && u.type == FcTypeLangSet)
+ {
+ v.u.l = FcLangSetPromote (v.u.s);
+ v.type = FcTypeLangSet;
+ }
return v;
}
FcBool
-FcConfigCompareValue (FcValue m,
- FcOp op,
- FcValue v)
+FcConfigCompareValue (const FcValue m_o,
+ FcOp op,
+ const FcValue v_o)
{
- FcBool ret = FcFalse;
+ FcValue m = m_o;
+ FcValue v = v_o;
+ FcBool ret = FcFalse;
m = FcConfigPromote (m, v);
v = FcConfigPromote (v, m);
if (m.type == v.type)
{
- ret = FcFalse;
switch (m.type) {
case FcTypeInteger:
break; /* FcConfigPromote prevents this from happening */
case FcOpContains:
ret = m.u.d == v.u.d;
break;
- case FcOpNotEqual:
+ case FcOpNotEqual:
+ case FcOpNotContains:
ret = m.u.d != v.u.d;
break;
case FcOpLess:
case FcOpContains:
ret = m.u.b == v.u.b;
break;
- case FcOpNotEqual:
+ case FcOpNotEqual:
+ case FcOpNotContains:
ret = m.u.b != v.u.b;
break;
default:
case FcOpContains:
ret = FcStrCmpIgnoreCase (m.u.s, v.u.s) == 0;
break;
- case FcOpNotEqual:
+ case FcOpNotEqual:
+ case FcOpNotContains:
ret = FcStrCmpIgnoreCase (m.u.s, v.u.s) != 0;
break;
default:
ret = FcMatrixEqual (m.u.m, v.u.m);
break;
case FcOpNotEqual:
+ case FcOpNotContains:
ret = !FcMatrixEqual (m.u.m, v.u.m);
break;
default:
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 FcOpNotContains:
+ /* 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 FcTypeLangSet:
+ switch (op) {
+ case FcOpContains:
+ ret = FcLangSetContains (v.u.l, m.u.l);
+ break;
+ case FcOpNotContains:
+ ret = FcLangSetContains (v.u.l, m.u.l);
+ break;
+ case FcOpEqual:
+ ret = FcLangSetEqual (v.u.l, m.u.l);
+ break;
+ case FcOpNotEqual:
+ ret = !FcLangSetEqual (v.u.l, m.u.l);
+ break;
+ default:
+ break;
+ }
+ break;
case FcTypeVoid:
switch (op) {
case FcOpEqual:
break;
}
break;
+ case FcTypeFTFace:
+ switch (op) {
+ case FcOpEqual:
+ case FcOpContains:
+ ret = m.u.f == v.u.f;
+ break;
+ case FcOpNotEqual:
+ case FcOpNotContains:
+ ret = m.u.f != v.u.f;
+ break;
+ default:
+ break;
+ }
+ break;
}
}
else
{
- if (op == FcOpNotEqual)
+ if (op == FcOpNotEqual || op == FcOpNotContains)
ret = FcTrue;
}
return ret;
v.type = FcTypeVoid;
FcValueDestroy (vl);
break;
- case FcOpOr:
- case FcOpAnd:
case FcOpEqual:
- case FcOpContains:
case FcOpNotEqual:
case FcOpLess:
case FcOpLessEqual:
case FcOpMore:
case FcOpMoreEqual:
+ case FcOpContains:
+ case FcOpNotContains:
+ vl = FcConfigEvaluate (p, e->u.tree.left);
+ vr = FcConfigEvaluate (p, e->u.tree.right);
+ v.type = FcTypeBool;
+ v.u.b = FcConfigCompareValue (vl, e->op, vr);
+ FcValueDestroy (vl);
+ FcValueDestroy (vr);
+ break;
+ case FcOpOr:
+ case FcOpAnd:
case FcOpPlus:
case FcOpMinus:
case FcOpTimes:
v.type = FcTypeDouble;
v.u.d = vl.u.d / vr.u.d;
break;
- case FcOpEqual:
- case FcOpContains:
- v.type = FcTypeBool;
- v.u.b = vl.u.d == vr.u.d;
- break;
- case FcOpNotEqual:
- v.type = FcTypeBool;
- v.u.b = vl.u.d != vr.u.d;
- break;
- case FcOpLess:
- v.type = FcTypeBool;
- v.u.b = vl.u.d < vr.u.d;
- break;
- case FcOpLessEqual:
- v.type = FcTypeBool;
- v.u.b = vl.u.d <= vr.u.d;
- break;
- case FcOpMore:
- v.type = FcTypeBool;
- v.u.b = vl.u.d > vr.u.d;
- break;
- case FcOpMoreEqual:
- v.type = FcTypeBool;
- v.u.b = vl.u.d >= vr.u.d;
- break;
default:
v.type = FcTypeVoid;
break;
v.type = FcTypeBool;
v.u.b = vl.u.b && vr.u.b;
break;
- case FcOpEqual:
- case FcOpContains:
- v.type = FcTypeBool;
- v.u.b = vl.u.b == vr.u.b;
- break;
- case FcOpNotEqual:
- v.type = FcTypeBool;
- v.u.b = vl.u.b != vr.u.b;
- break;
default:
v.type = FcTypeVoid;
break;
break;
case FcTypeString:
switch (e->op) {
- case FcOpEqual:
- case FcOpContains:
- v.type = FcTypeBool;
- v.u.b = FcStrCmpIgnoreCase (vl.u.s, vr.u.s) == 0;
- break;
- case FcOpNotEqual:
- v.type = FcTypeBool;
- v.u.b = FcStrCmpIgnoreCase (vl.u.s, vr.u.s) != 0;
- break;
case FcOpPlus:
v.type = FcTypeString;
v.u.s = FcStrPlus (vl.u.s, vr.u.s);
v.type = FcTypeVoid;
break;
}
+ break;
case FcTypeMatrix:
switch (e->op) {
- case FcOpEqual:
- case FcOpContains:
- v.type = FcTypeBool;
- v.u.b = FcMatrixEqual (vl.u.m, vr.u.m);
- break;
- case FcOpNotEqual:
- v.type = FcTypeBool;
- v.u.b = FcMatrixEqual (vl.u.m, vr.u.m);
- break;
case FcOpTimes:
v.type = FcTypeMatrix;
m = malloc (sizeof (FcMatrix));
break;
}
break;
- case FcTypeCharSet:
- switch (e->op) {
- case FcOpContains:
- /* vl contains vr if vr - vl is empty */
- v.type = FcTypeBool;
- v.u.b = FcCharSetSubtractCount (vr.u.c, vl.u.c) == 0;
- break;
- case FcOpEqual:
- v.type = FcTypeBool;
- v.u.b = FcCharSetEqual (vl.u.c, vr.u.c);
- break;
- case FcOpNotEqual:
- v.type = FcTypeBool;
- v.u.b = !FcCharSetEqual (vl.u.c, vr.u.c);
- break;
- default:
- v.type = FcTypeVoid;
- break;
- }
- break;
default:
v.type = FcTypeVoid;
break;
static FcValueList *
FcConfigMatchValueList (FcPattern *p,
FcTest *t,
- FcValueList *v)
+ FcValueList *values)
{
FcValueList *ret = 0;
FcExpr *e = t->expr;
FcValue value;
+ FcValueList *v;
while (e)
{
e = 0;
}
- for (; v; v = v->next)
+ for (v = values; v; v = v->next)
{
if (FcConfigCompareValue (v->value, t->op, value))
{
}
}
}
+ FcValueDestroy (value);
}
- FcValueDestroy (value);
return ret;
}
static FcValueList *
-FcConfigValues (FcPattern *p, FcExpr *e)
+FcConfigValues (FcPattern *p, FcExpr *e, FcValueBinding binding)
{
FcValueList *l;
if (e->op == FcOpComma)
{
l->value = FcConfigEvaluate (p, e->u.tree.left);
- l->next = FcConfigValues (p, e->u.tree.right);
+ l->next = FcConfigValues (p, e->u.tree.right, binding);
}
else
{
l->value = FcConfigEvaluate (p, e);
l->next = 0;
}
+ l->binding = binding;
while (l && l->value.type == FcTypeVoid)
{
FcValueList *next = l->next;
FcBool append,
FcValueList *new)
{
- FcValueList **prev, *last;
+ FcValueList **prev, *last, *v;
+ FcValueBinding sameBinding;
+ if (position)
+ sameBinding = position->binding;
+ else
+ sameBinding = FcValueBindingWeak;
+ for (v = new; v; v = v->next)
+ if (v->binding == FcValueBindingSame)
+ v->binding = sameBinding;
if (append)
{
if (position)
{
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)
}
FcBool
-FcConfigSubstitute (FcConfig *config,
- FcPattern *p,
- FcMatchKind kind)
+FcConfigSubstituteWithPat (FcConfig *config,
+ FcPattern *p,
+ FcPattern *p_pat,
+ FcMatchKind kind)
{
FcSubst *s;
FcSubState *st;
FcTest *t;
FcEdit *e;
FcValueList *l;
+ FcPattern *m;
if (!config)
{
printf ("FcConfigSubstitute test ");
FcTestPrint (t);
}
- st[i].elt = FcPatternFind (p, t->field, FcFalse);
+ st[i].elt = 0;
+ if (kind == FcMatchFont && t->kind == FcMatchPattern)
+ m = p_pat;
+ else
+ m = p;
+ if (m)
+ st[i].elt = FcPatternFindElt (m, t->field);
+ else
+ st[i].elt = 0;
/*
* If there's no such field in the font,
* then FcQualAll matches while FcQualAny does not
* Check to see if there is a match, mark the location
* to apply match-relative edits
*/
- st[i].value = FcConfigMatchValueList (p, t, st[i].elt->values);
+ st[i].value = FcConfigMatchValueList (m, 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)
{
/*
* Evaluate the list of expressions
*/
- l = FcConfigValues (p, e->expr);
+ l = FcConfigValues (p, e->expr, e->binding);
/*
- * Locate any test associated with this field
+ * Locate any test associated with this field, skipping
+ * tests associated with the pattern when substituting in
+ * the font
*/
for (t = s->test, i = 0; t; t = t->next, i++)
- if (!FcStrCmpIgnoreCase ((FcChar8 *) t->field, (FcChar8 *) e->field))
+ {
+ if ((t->kind == FcMatchFont || kind == FcMatchPattern) &&
+ !FcStrCmpIgnoreCase ((FcChar8 *) t->field,
+ (FcChar8 *) e->field))
+ {
+ if (!st[i].elt)
+ t = 0;
break;
+ }
+ }
switch (e->op) {
case FcOpAssign:
/*
return FcTrue;
}
+FcBool
+FcConfigSubstitute (FcConfig *config,
+ FcPattern *p,
+ FcMatchKind kind)
+{
+ return FcConfigSubstituteWithPat (config, p, 0, kind);
+}
+
#ifndef FONTCONFIG_PATH
#define FONTCONFIG_PATH "/etc/fonts"
#endif
strcat ((char *) path, "/");
strcat ((char *) path, (char *) file);
+ FcMemAlloc (FC_MEM_STRING, strlen ((char *) path) + 1);
if (access ((char *) path, R_OK) == 0)
return path;
- free (path);
+ FcStrFree (path);
return 0;
}
free (path);
}
+static FcBool _FcConfigHomeEnabled = FcTrue;
+
+FcChar8 *
+FcConfigHome (void)
+{
+ if (_FcConfigHomeEnabled)
+ return getenv ("HOME");
+ return 0;
+}
+
+FcBool
+FcConfigEnableHome (FcBool enable)
+{
+ FcBool prev = _FcConfigHomeEnabled;
+ _FcConfigHomeEnabled = enable;
+ return prev;
+}
+
FcChar8 *
FcConfigFilename (const FcChar8 *url)
{
file = 0;
switch (*url) {
case '~':
- dir = (FcChar8 *) getenv ("HOME");
+ dir = FcConfigHome ();
if (dir)
file = FcConfigFileExists (dir, url + 1);
else