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 @@
* fontconfig/src/fccfg.c
*
* Copyright © 2000 Keith Packard
* Copyright © 2020 Maxim Cournoyer
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
......@@ -2621,6 +2622,63 @@ FcConfigEnableHome (FcBool enable)
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 *
FcConfigGetFilename (FcConfig *config,
const FcChar8 *url)
......
......@@ -664,6 +664,9 @@ FcConfigXdgConfigHome (void);
FcPrivate FcChar8 *
FcConfigXdgDataHome (void);
FcPrivate FcChar8 **
FcConfigXdgDataDirs (size_t *size);
FcPrivate FcExpr *
FcConfigAllocExpr (FcConfig *config);
......
......@@ -2,6 +2,7 @@
* fontconfig/src/fcxml.c
*
* Copyright © 2002 Keith Packard
* Copyright © 2020 Maxim Cournoyer
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
......@@ -1285,24 +1286,68 @@ FcConfigGetAttribute (FcConfigParse *parse, const char *attr)
return 0;
}
static FcChar8 *
_get_real_path_from_prefix(FcConfigParse *parse, const FcChar8 *path, const FcChar8 *prefix)
static FcChar8 **
_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;
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 (FcStrCmp (prefix, (const FcChar8 *) "xdg") == 0)
{
parent = FcConfigXdgDataHome ();
if (!parent)
size_t data_dirs_length = 0;
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;
}
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 ||
FcStrCmp (prefix, (const FcChar8 *) "cwd") == 0)
......@@ -1311,8 +1356,8 @@ _get_real_path_from_prefix(FcConfigParse *parse, const FcChar8 *path, const FcCh
}
else if (FcStrCmp (prefix, (const FcChar8 *) "relative") == 0)
{
parent = FcStrDirname (parse->name);
if (!parent)
parents[0] = FcStrDirname (parse->name);
if (!parents[0])
return NULL;
}
}
......@@ -1379,17 +1424,29 @@ _get_real_path_from_prefix(FcConfigParse *parse, const FcChar8 *path, const FcCh
}
}
#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);
FcStrFree (parent);
/* Copy the parents-prefixed paths into the paths array. */
for (int i = 0; parents[i]; i++) {
paths[i] = FcStrBuildFilename (parents[i], path, NULL);
FcStrFree(parents[i]);
}
free (parents);
}
else
{
retval = FcStrdup (path);
paths[0] = FcStrdup (path);
}
return retval;
return paths;
}
static void
......@@ -2062,7 +2119,7 @@ static void
FcParseRemapDir (FcConfigParse *parse)
{
const FcChar8 *path, *attr, *data, *salt;
FcChar8 *prefix = NULL;
FcChar8 **prefixes = NULL;
data = FcStrBufDoneStatic (&parse->pstack->str);
if (!data)
......@@ -2083,7 +2140,10 @@ FcParseRemapDir (FcConfigParse *parse)
}
attr = FcConfigGetAttribute (parse, "prefix");
salt = FcConfigGetAttribute (parse, "salt");
prefix = _get_real_path_from_prefix (parse, data, attr);
prefixes = _get_real_paths_from_prefix (parse, data, attr);
for (FcChar8 **p = prefixes; *p; p++)
{
FcChar8 *prefix = *p;
if (!prefix || prefix[0] == 0)
{
/* nop */
......@@ -2097,6 +2157,8 @@ FcParseRemapDir (FcConfigParse *parse)
if (prefix)
FcStrFree (prefix);
}
free (prefixes);
}
static void
......@@ -2250,7 +2312,7 @@ static void
FcParseDir (FcConfigParse *parse)
{
const FcChar8 *attr, *data, *salt;
FcChar8 *prefix = NULL;
FcChar8 **prefixes = NULL;
data = FcStrBufDoneStatic (&parse->pstack->str);
if (!data)
......@@ -2265,7 +2327,10 @@ FcParseDir (FcConfigParse *parse)
}
attr = FcConfigGetAttribute (parse, "prefix");
salt = FcConfigGetAttribute (parse, "salt");
prefix = _get_real_path_from_prefix (parse, data, attr);
prefixes = _get_real_paths_from_prefix (parse, data, attr);
for (FcChar8 **p = prefixes; *p; p++)
{
FcChar8 *prefix = *p;
if (!prefix || prefix[0] == 0)
{
/* nop */
......@@ -2279,6 +2344,8 @@ FcParseDir (FcConfigParse *parse)
if (prefix)
FcStrFree (prefix);
}
free (prefixes);
}
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