Unverified Commit 65c37f6d authored by Apteryks's avatar Apteryks
Browse files

Add support for XDG_DATA_DIRS.

parent d243bb3f
Pipeline #248808 passed with stage
in 8 minutes and 51 seconds
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* fontconfig/src/fccfg.c * fontconfig/src/fccfg.c
* *
* Copyright © 2000 Keith Packard * Copyright © 2000 Keith Packard
* Copyright © 2020 Maxim Cournoyer
* *
* Permission to use, copy, modify, distribute, and sell this software and its * Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that * documentation for any purpose is hereby granted without fee, provided that
...@@ -2621,6 +2622,63 @@ FcConfigEnableHome (FcBool enable) ...@@ -2621,6 +2622,63 @@ FcConfigEnableHome (FcBool enable)
return prev; return prev;
} }
/* TODO: Refactor to share common code with FcConfigGetPath */
FcChar8 **
FcConfigXdgDataDirs (size_t *size)
{
FcChar8 **path;
FcChar8 *env, *e, *colon;
int npath;
int i;
npath = 1; /* null */
env = (FcChar8 *) getenv ("XDG_DATA_DIRS");
if (env)
{
e = env;
npath++;
while (*e)
if (*e++ == FC_SEARCH_PATH_SEPARATOR)
npath++;
}
path = calloc (npath, sizeof (FcChar8 *));
if (!path)
goto bail0;
i = 0;
if (env)
{
e = env;
while (*e)
{
colon = (FcChar8 *) strchr ((char *) e, FC_SEARCH_PATH_SEPARATOR);
if (!colon)
colon = e + strlen ((char *) e);
path[i] = malloc (colon - e + 1);
if (!path[i])
goto bail1;
strncpy ((char *) path[i], (const char *) e, colon - e);
path[i][colon - e] = '\0';
if (*colon)
e = colon + 1;
else
e = colon;
i++;
}
}
*size = npath;
return path;
bail1:
for (i = 0; path[i]; i++)
free (path[i]);
free (path);
bail0:
return 0;
}
FcChar8 * FcChar8 *
FcConfigGetFilename (FcConfig *config, FcConfigGetFilename (FcConfig *config,
const FcChar8 *url) const FcChar8 *url)
......
...@@ -664,6 +664,9 @@ FcConfigXdgConfigHome (void); ...@@ -664,6 +664,9 @@ FcConfigXdgConfigHome (void);
FcPrivate FcChar8 * FcPrivate FcChar8 *
FcConfigXdgDataHome (void); FcConfigXdgDataHome (void);
FcPrivate FcChar8 **
FcConfigXdgDataDirs (size_t *size);
FcPrivate FcExpr * FcPrivate FcExpr *
FcConfigAllocExpr (FcConfig *config); FcConfigAllocExpr (FcConfig *config);
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* fontconfig/src/fcxml.c * fontconfig/src/fcxml.c
* *
* Copyright © 2002 Keith Packard * Copyright © 2002 Keith Packard
* Copyright © 2020 Maxim Cournoyer
* *
* Permission to use, copy, modify, distribute, and sell this software and its * Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that * documentation for any purpose is hereby granted without fee, provided that
...@@ -1285,24 +1286,68 @@ FcConfigGetAttribute (FcConfigParse *parse, const char *attr) ...@@ -1285,24 +1286,68 @@ FcConfigGetAttribute (FcConfigParse *parse, const char *attr)
return 0; return 0;
} }
static FcChar8 * static FcChar8 **
_get_real_path_from_prefix(FcConfigParse *parse, const FcChar8 *path, const FcChar8 *prefix) _get_real_paths_from_prefix(FcConfigParse *parse, const FcChar8 *path, const FcChar8 *prefix)
{ {
#ifdef _WIN32 #ifdef _WIN32
FcChar8 buffer[1000] = { 0 }; FcChar8 buffer[1000] = { 0 };
#endif #endif
FcChar8 *parent = NULL, *retval = NULL; FcChar8 **paths = NULL;
FcChar8 **parents = NULL;
FcChar8 **tmp_ptr = NULL;
size_t parents_length = 2; /* one item followed by zero */
/* Allocate a default size of one value for the parents array. */
tmp_ptr = calloc(parents_length, sizeof (FcChar8 *));
if (tmp_ptr == NULL)
{
free (parents);
fprintf(stderr, "Out of Memory\n");
return NULL;
}
else
{
parents = tmp_ptr;
}
if (prefix) if (prefix)
{ {
if (FcStrCmp (prefix, (const FcChar8 *) "xdg") == 0) if (FcStrCmp (prefix, (const FcChar8 *) "xdg") == 0)
{ {
parent = FcConfigXdgDataHome (); size_t data_dirs_length = 0;
if (!parent) FcChar8 *data_home = FcConfigXdgDataHome ();
FcChar8 **data_dirs = FcConfigXdgDataDirs (&data_dirs_length);
if (!data_home && !data_dirs)
{ {
/* Home directory might be disabled */ /* Home directory might be disabled and XDG_DATA_DIRS is unset */
return NULL; return NULL;
} }
else if (data_home)
{
/* Resize the zero-terminated data_dirs array so that
data_home can be appended to it. */
parents_length = data_dirs_length + 1;
tmp_ptr = realloc(data_dirs,
parents_length * sizeof (FcChar8 *));
if (tmp_ptr == NULL)
{
for (int i = 0; data_dirs[i]; i++)
free (data_dirs[i]);
free (data_dirs);
fprintf(stderr, "Out of Memory\n");
return NULL;
}
else
{
// Append the XDG_DATA_HOME prefix.
free (parents); /* clear default allocated memory */
parents = tmp_ptr;
parents[data_dirs_length - 1] = data_home;
/* Ensure the array is terminated by zero. */
parents[data_dirs_length] = 0;
}
}
} }
else if (FcStrCmp (prefix, (const FcChar8 *) "default") == 0 || else if (FcStrCmp (prefix, (const FcChar8 *) "default") == 0 ||
FcStrCmp (prefix, (const FcChar8 *) "cwd") == 0) FcStrCmp (prefix, (const FcChar8 *) "cwd") == 0)
...@@ -1311,8 +1356,8 @@ _get_real_path_from_prefix(FcConfigParse *parse, const FcChar8 *path, const FcCh ...@@ -1311,8 +1356,8 @@ _get_real_path_from_prefix(FcConfigParse *parse, const FcChar8 *path, const FcCh
} }
else if (FcStrCmp (prefix, (const FcChar8 *) "relative") == 0) else if (FcStrCmp (prefix, (const FcChar8 *) "relative") == 0)
{ {
parent = FcStrDirname (parse->name); parents[0] = FcStrDirname (parse->name);
if (!parent) if (!parents[0])
return NULL; return NULL;
} }
} }
...@@ -1379,17 +1424,29 @@ _get_real_path_from_prefix(FcConfigParse *parse, const FcChar8 *path, const FcCh ...@@ -1379,17 +1424,29 @@ _get_real_path_from_prefix(FcConfigParse *parse, const FcChar8 *path, const FcCh
} }
} }
#endif #endif
if (parent)
/* Allocate the 'paths' array used as the return value. */
paths = calloc(parents_length, sizeof (FcChar8 *));
if (paths == NULL) {
fprintf(stderr, "Out of Memory\n");
return NULL;
}
if (*parents)
{ {
retval = FcStrBuildFilename (parent, path, NULL); /* Copy the parents-prefixed paths into the paths array. */
FcStrFree (parent); for (int i = 0; parents[i]; i++) {
paths[i] = FcStrBuildFilename (parents[i], path, NULL);
FcStrFree(parents[i]);
}
free (parents);
} }
else else
{ {
retval = FcStrdup (path); paths[0] = FcStrdup (path);
} }
return retval; return paths;
} }
static void static void
...@@ -2062,7 +2119,7 @@ static void ...@@ -2062,7 +2119,7 @@ static void
FcParseRemapDir (FcConfigParse *parse) FcParseRemapDir (FcConfigParse *parse)
{ {
const FcChar8 *path, *attr, *data, *salt; const FcChar8 *path, *attr, *data, *salt;
FcChar8 *prefix = NULL; FcChar8 **prefixes = NULL;
data = FcStrBufDoneStatic (&parse->pstack->str); data = FcStrBufDoneStatic (&parse->pstack->str);
if (!data) if (!data)
...@@ -2083,20 +2140,25 @@ FcParseRemapDir (FcConfigParse *parse) ...@@ -2083,20 +2140,25 @@ FcParseRemapDir (FcConfigParse *parse)
} }
attr = FcConfigGetAttribute (parse, "prefix"); attr = FcConfigGetAttribute (parse, "prefix");
salt = FcConfigGetAttribute (parse, "salt"); salt = FcConfigGetAttribute (parse, "salt");
prefix = _get_real_path_from_prefix (parse, data, attr); prefixes = _get_real_paths_from_prefix (parse, data, attr);
if (!prefix || prefix[0] == 0) for (FcChar8 **p = prefixes; *p; p++)
{ {
/* nop */ FcChar8 *prefix = *p;
} if (!prefix || prefix[0] == 0)
else if (!parse->scanOnly && (!FcStrUsesHome (prefix) || FcConfigHome ())) {
{ /* nop */
if (!FcConfigAddFontDir (parse->config, prefix, path, salt)) }
FcConfigMessage (parse, FcSevereError, "out of memory; cannot create remap data for %s as %s", prefix, path); else if (!parse->scanOnly && (!FcStrUsesHome (prefix) || FcConfigHome ()))
} {
FcStrBufDestroy (&parse->pstack->str); 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);
if (prefix) if (prefix)
FcStrFree (prefix); FcStrFree (prefix);
}
free (prefixes);
} }
static void static void
...@@ -2250,7 +2312,7 @@ static void ...@@ -2250,7 +2312,7 @@ static void
FcParseDir (FcConfigParse *parse) FcParseDir (FcConfigParse *parse)
{ {
const FcChar8 *attr, *data, *salt; const FcChar8 *attr, *data, *salt;
FcChar8 *prefix = NULL; FcChar8 **prefixes = NULL;
data = FcStrBufDoneStatic (&parse->pstack->str); data = FcStrBufDoneStatic (&parse->pstack->str);
if (!data) if (!data)
...@@ -2265,20 +2327,25 @@ FcParseDir (FcConfigParse *parse) ...@@ -2265,20 +2327,25 @@ FcParseDir (FcConfigParse *parse)
} }
attr = FcConfigGetAttribute (parse, "prefix"); attr = FcConfigGetAttribute (parse, "prefix");
salt = FcConfigGetAttribute (parse, "salt"); salt = FcConfigGetAttribute (parse, "salt");
prefix = _get_real_path_from_prefix (parse, data, attr); prefixes = _get_real_paths_from_prefix (parse, data, attr);
if (!prefix || prefix[0] == 0) for (FcChar8 **p = prefixes; *p; p++)
{
/* nop */
}
else if (!parse->scanOnly && (!FcStrUsesHome (prefix) || FcConfigHome ()))
{ {
if (!FcConfigAddFontDir (parse->config, prefix, NULL, salt)) FcChar8 *prefix = *p;
FcConfigMessage (parse, FcSevereError, "out of memory; cannot add directory %s", prefix); if (!prefix || prefix[0] == 0)
} {
FcStrBufDestroy (&parse->pstack->str); /* 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);
if (prefix) if (prefix)
FcStrFree (prefix); FcStrFree (prefix);
}
free (prefixes);
} }
static void static void
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment