summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkira TAGOH <akira@tagoh.org>2021-03-29 21:25:21 +0900
committerAkira TAGOH <akira@tagoh.org>2021-03-30 15:08:17 +0900
commit6f27f42e6140030715075aa3bd3e5cc9e2fdc6f1 (patch)
tree3c01d36cd7dcfd1b1090ae4fb50e7a339d952e62
parentb03140c14ed71a8b29ae6d5f76f254a2adfc4f22 (diff)
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
-rw-r--r--src/fccfg.c59
-rw-r--r--src/fcint.h6
-rw-r--r--src/fcstr.c39
-rw-r--r--src/fcxml.c98
4 files changed, 166 insertions, 36 deletions
diff --git a/src/fccfg.c b/src/fccfg.c
index 462c423..21fc9b1 100644
--- a/src/fccfg.c
+++ b/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)
{
diff --git a/src/fcint.h b/src/fcint.h
index 2d4a2c4..4150a05 100644
--- a/src/fcint.h
+++ b/src/fcint.h
@@ -664,6 +664,9 @@ FcConfigXdgConfigHome (void);
FcPrivate FcChar8 *
FcConfigXdgDataHome (void);
+FcPrivate FcStrSet *
+FcConfigXdgDataDirs (void);
+
FcPrivate FcExpr *
FcConfigAllocExpr (FcConfig *config);
@@ -1258,6 +1261,9 @@ FcPrivate FcStrSet *
FcStrSetCreateEx (unsigned int control);
FcPrivate FcBool
+FcStrSetInsert (FcStrSet *set, const FcChar8 *s, int pos);
+
+FcPrivate FcBool
FcStrSetAddLangs (FcStrSet *strs, const char *languages);
FcPrivate void
diff --git a/src/fcstr.c b/src/fcstr.c
index 8971b71..765f711 100644
--- a/src/fcstr.c
+++ b/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;
diff --git a/src/fcxml.c b/src/fcxml.c
index 9efe157..0db318c 100644
--- a/src/fcxml.c
+++ b/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)
- {
- /* nop */
- }
- else if (!parse->scanOnly && (!FcStrUsesHome (prefix) || FcConfigHome ()))
+ prefix_dirs = _get_real_paths_from_prefix (parse, data, attr);
+ if (prefix_dirs)
{
- 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