Add support for XDG_DATA_DIRS
Add dirs from XDG_DATA_DIRS when <dir prefix="xdg"> appears in fonts.conf Fixes https://gitlab.freedesktop.org/fontconfig/fontconfig/-/issues/271
This commit is contained in:
parent
b03140c14e
commit
6f27f42e61
59
src/fccfg.c
59
src/fccfg.c
|
@ -2614,6 +2614,65 @@ FcConfigXdgDataHome (void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
FcStrSet *
|
||||
FcConfigXdgDataDirs (void)
|
||||
{
|
||||
const char *env = getenv ("XDG_DATA_DIRS");
|
||||
FcStrSet *ret = FcStrSetCreate ();
|
||||
|
||||
if (env)
|
||||
{
|
||||
FcChar8 *ee, *e = ee = FcStrCopy ((const FcChar8 *) env);
|
||||
|
||||
/* We don't intentionally use FC_SEARCH_PATH_SEPARATOR here because of:
|
||||
* The directories in $XDG_DATA_DIRS should be seperated with a colon ':'.
|
||||
* in doc.
|
||||
*/
|
||||
while (e)
|
||||
{
|
||||
FcChar8 *p = (FcChar8 *) strchr ((const char *) e, ':');
|
||||
FcChar8 *s;
|
||||
size_t len;
|
||||
|
||||
if (!p)
|
||||
{
|
||||
s = FcStrCopy (e);
|
||||
e = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
*p = 0;
|
||||
s = FcStrCopy (e);
|
||||
e = p + 1;
|
||||
}
|
||||
len = strlen ((const char *) s);
|
||||
if (s[len - 1] == FC_DIR_SEPARATOR)
|
||||
{
|
||||
do
|
||||
{
|
||||
len--;
|
||||
}
|
||||
while (len > 1 && s[len - 1] == FC_DIR_SEPARATOR);
|
||||
s[len] = 0;
|
||||
}
|
||||
FcStrSetAdd (ret, s);
|
||||
FcStrFree (s);
|
||||
}
|
||||
FcStrFree (ee);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* From spec doc at https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html#variables
|
||||
*
|
||||
* If $XDG_DATA_DIRS is either not set or empty, a value equal to /usr/local/share/:/usr/share/ should be used.
|
||||
*/
|
||||
FcStrSetAdd (ret, (const FcChar8 *) "/usr/local/share");
|
||||
FcStrSetAdd (ret, (const FcChar8 *) "/usr/share");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
FcBool
|
||||
FcConfigEnableHome (FcBool enable)
|
||||
{
|
||||
|
|
|
@ -664,6 +664,9 @@ FcConfigXdgConfigHome (void);
|
|||
FcPrivate FcChar8 *
|
||||
FcConfigXdgDataHome (void);
|
||||
|
||||
FcPrivate FcStrSet *
|
||||
FcConfigXdgDataDirs (void);
|
||||
|
||||
FcPrivate FcExpr *
|
||||
FcConfigAllocExpr (FcConfig *config);
|
||||
|
||||
|
@ -1257,6 +1260,9 @@ FcIsFsMtimeBroken (const FcChar8 *dir);
|
|||
FcPrivate FcStrSet *
|
||||
FcStrSetCreateEx (unsigned int control);
|
||||
|
||||
FcPrivate FcBool
|
||||
FcStrSetInsert (FcStrSet *set, const FcChar8 *s, int pos);
|
||||
|
||||
FcPrivate FcBool
|
||||
FcStrSetAddLangs (FcStrSet *strs, const char *languages);
|
||||
|
||||
|
|
39
src/fcstr.c
39
src/fcstr.c
|
@ -1252,7 +1252,7 @@ _FcStrSetGrow (FcStrSet *set, int growElements)
|
|||
}
|
||||
|
||||
static FcBool
|
||||
_FcStrSetAppend (FcStrSet *set, FcChar8 *s)
|
||||
_FcStrSetInsert (FcStrSet *set, FcChar8 *s, int pos)
|
||||
{
|
||||
if (!FcStrSetHasControlBit (set, FCSS_ALLOW_DUPLICATES))
|
||||
{
|
||||
|
@ -1268,8 +1268,21 @@ _FcStrSetAppend (FcStrSet *set, FcChar8 *s)
|
|||
if (!_FcStrSetGrow(set, growElements))
|
||||
return FcFalse;
|
||||
}
|
||||
set->strs[set->num++] = s;
|
||||
set->strs[set->num] = 0;
|
||||
if (pos >= set->num)
|
||||
{
|
||||
set->strs[set->num++] = s;
|
||||
set->strs[set->num] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
|
||||
set->num++;
|
||||
set->strs[set->num] = 0;
|
||||
for (i = set->num - 1; i > pos; i--)
|
||||
set->strs[i] = set->strs[i - 1];
|
||||
set->strs[pos] = s;
|
||||
}
|
||||
return FcTrue;
|
||||
}
|
||||
|
||||
|
@ -1354,7 +1367,21 @@ FcStrSetAdd (FcStrSet *set, const FcChar8 *s)
|
|||
FcChar8 *new = FcStrCopy (s);
|
||||
if (!new)
|
||||
return FcFalse;
|
||||
if (!_FcStrSetAppend (set, new))
|
||||
if (!_FcStrSetInsert (set, new, set->num))
|
||||
{
|
||||
FcStrFree (new);
|
||||
return FcFalse;
|
||||
}
|
||||
return FcTrue;
|
||||
}
|
||||
|
||||
FcBool
|
||||
FcStrSetInsert (FcStrSet *set, const FcChar8 *s, int pos)
|
||||
{
|
||||
FcChar8 *new = FcStrCopy (s);
|
||||
if (!new)
|
||||
return FcFalse;
|
||||
if (!_FcStrSetInsert (set, new, pos))
|
||||
{
|
||||
FcStrFree (new);
|
||||
return FcFalse;
|
||||
|
@ -1368,7 +1395,7 @@ FcStrSetAddTriple (FcStrSet *set, const FcChar8 *a, const FcChar8 *b, const FcCh
|
|||
FcChar8 *new = FcStrMakeTriple (a, b, c);
|
||||
if (!new)
|
||||
return FcFalse;
|
||||
if (!_FcStrSetAppend (set, new))
|
||||
if (!_FcStrSetInsert (set, new, set->num))
|
||||
{
|
||||
FcStrFree (new);
|
||||
return FcFalse;
|
||||
|
@ -1403,7 +1430,7 @@ FcStrSetAddFilename (FcStrSet *set, const FcChar8 *s)
|
|||
FcChar8 *new = FcStrCopyFilename (s);
|
||||
if (!new)
|
||||
return FcFalse;
|
||||
if (!_FcStrSetAppend (set, new))
|
||||
if (!_FcStrSetInsert (set, new, set->num))
|
||||
{
|
||||
FcStrFree (new);
|
||||
return FcFalse;
|
||||
|
|
98
src/fcxml.c
98
src/fcxml.c
|
@ -1285,20 +1285,22 @@ FcConfigGetAttribute (FcConfigParse *parse, const char *attr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static FcChar8 *
|
||||
_get_real_path_from_prefix(FcConfigParse *parse, const FcChar8 *path, const FcChar8 *prefix)
|
||||
static FcStrSet *
|
||||
_get_real_paths_from_prefix(FcConfigParse *parse, const FcChar8 *path, const FcChar8 *prefix)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
FcChar8 buffer[1000] = { 0 };
|
||||
#endif
|
||||
FcChar8 *parent = NULL, *retval = NULL;
|
||||
FcStrSet *e = NULL;
|
||||
|
||||
if (prefix)
|
||||
{
|
||||
if (FcStrCmp (prefix, (const FcChar8 *) "xdg") == 0)
|
||||
{
|
||||
parent = FcConfigXdgDataHome ();
|
||||
if (!parent)
|
||||
e = FcConfigXdgDataDirs ();
|
||||
if (!parent || !e)
|
||||
{
|
||||
/* Home directory might be disabled */
|
||||
return NULL;
|
||||
|
@ -1388,8 +1390,28 @@ _get_real_path_from_prefix(FcConfigParse *parse, const FcChar8 *path, const FcCh
|
|||
{
|
||||
retval = FcStrdup (path);
|
||||
}
|
||||
if (!e)
|
||||
e = FcStrSetCreate ();
|
||||
else
|
||||
{
|
||||
FcChar8 *s;
|
||||
int i;
|
||||
|
||||
return retval;
|
||||
for (i = 0; i < e->num; i++)
|
||||
{
|
||||
s = FcStrBuildFilename (e->strs[i], path, NULL);
|
||||
FcStrFree (e->strs[i]);
|
||||
e->strs[i] = s;
|
||||
}
|
||||
}
|
||||
if (!FcStrSetInsert (e, retval, 0))
|
||||
{
|
||||
FcStrSetDestroy (e);
|
||||
e = NULL;
|
||||
}
|
||||
FcStrFree (retval);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2062,7 +2084,7 @@ static void
|
|||
FcParseRemapDir (FcConfigParse *parse)
|
||||
{
|
||||
const FcChar8 *path, *attr, *data, *salt;
|
||||
FcChar8 *prefix = NULL;
|
||||
FcStrSet *prefix_dirs = NULL;
|
||||
|
||||
data = FcStrBufDoneStatic (&parse->pstack->str);
|
||||
if (!data)
|
||||
|
@ -2083,20 +2105,28 @@ FcParseRemapDir (FcConfigParse *parse)
|
|||
}
|
||||
attr = FcConfigGetAttribute (parse, "prefix");
|
||||
salt = FcConfigGetAttribute (parse, "salt");
|
||||
prefix = _get_real_path_from_prefix (parse, data, attr);
|
||||
if (!prefix || prefix[0] == 0)
|
||||
prefix_dirs = _get_real_paths_from_prefix (parse, data, attr);
|
||||
if (prefix_dirs)
|
||||
{
|
||||
/* nop */
|
||||
}
|
||||
else if (!parse->scanOnly && (!FcStrUsesHome (prefix) || FcConfigHome ()))
|
||||
{
|
||||
if (!FcConfigAddFontDir (parse->config, prefix, path, salt))
|
||||
FcConfigMessage (parse, FcSevereError, "out of memory; cannot create remap data for %s as %s", prefix, path);
|
||||
}
|
||||
FcStrBufDestroy (&parse->pstack->str);
|
||||
FcStrList *l = FcStrListCreate (prefix_dirs);
|
||||
FcChar8 *prefix;
|
||||
|
||||
if (prefix)
|
||||
FcStrFree (prefix);
|
||||
FcStrSetDestroy (prefix_dirs);
|
||||
while ((prefix = FcStrListNext (l)))
|
||||
{
|
||||
if (!prefix || prefix[0] == 0)
|
||||
{
|
||||
/* nop */
|
||||
}
|
||||
else if (!parse->scanOnly && (!FcStrUsesHome (prefix) || FcConfigHome ()))
|
||||
{
|
||||
if (!FcConfigAddFontDir (parse->config, prefix, path, salt))
|
||||
FcConfigMessage (parse, FcSevereError, "out of memory; cannot create remap data for %s as %s", prefix, path);
|
||||
}
|
||||
FcStrBufDestroy (&parse->pstack->str);
|
||||
}
|
||||
FcStrListDone (l);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2250,7 +2280,7 @@ static void
|
|||
FcParseDir (FcConfigParse *parse)
|
||||
{
|
||||
const FcChar8 *attr, *data, *salt;
|
||||
FcChar8 *prefix = NULL;
|
||||
FcStrSet *prefix_dirs = NULL;
|
||||
|
||||
data = FcStrBufDoneStatic (&parse->pstack->str);
|
||||
if (!data)
|
||||
|
@ -2265,20 +2295,28 @@ FcParseDir (FcConfigParse *parse)
|
|||
}
|
||||
attr = FcConfigGetAttribute (parse, "prefix");
|
||||
salt = FcConfigGetAttribute (parse, "salt");
|
||||
prefix = _get_real_path_from_prefix (parse, data, attr);
|
||||
if (!prefix || prefix[0] == 0)
|
||||
prefix_dirs = _get_real_paths_from_prefix (parse, data, attr);
|
||||
if (prefix_dirs)
|
||||
{
|
||||
/* nop */
|
||||
}
|
||||
else if (!parse->scanOnly && (!FcStrUsesHome (prefix) || FcConfigHome ()))
|
||||
{
|
||||
if (!FcConfigAddFontDir (parse->config, prefix, NULL, salt))
|
||||
FcConfigMessage (parse, FcSevereError, "out of memory; cannot add directory %s", prefix);
|
||||
}
|
||||
FcStrBufDestroy (&parse->pstack->str);
|
||||
FcStrList *l = FcStrListCreate (prefix_dirs);
|
||||
FcChar8 *prefix;
|
||||
|
||||
if (prefix)
|
||||
FcStrFree (prefix);
|
||||
FcStrSetDestroy (prefix_dirs);
|
||||
while ((prefix = FcStrListNext (l)))
|
||||
{
|
||||
if (!prefix || prefix[0] == 0)
|
||||
{
|
||||
/* nop */
|
||||
}
|
||||
else if (!parse->scanOnly && (!FcStrUsesHome (prefix) || FcConfigHome ()))
|
||||
{
|
||||
if (!FcConfigAddFontDir (parse->config, prefix, NULL, salt))
|
||||
FcConfigMessage (parse, FcSevereError, "out of memory; cannot add directory %s", prefix);
|
||||
}
|
||||
FcStrBufDestroy (&parse->pstack->str);
|
||||
}
|
||||
FcStrListDone (l);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
Loading…
Reference in New Issue