conf.d/50-user.conf | 7 doc/fontconfig-user.sgml | 37 ++--- fonts.conf.in | 4 fonts.dtd | 10 + src/fccfg.c | 78 ++++++++++ src/fcinit.c | 20 ++ src/fcint.h | 11 + src/fcstr.c | 5 src/fcxml.c | 344 ++++++++++++++++++++++++++++++----------------- 9 files changed, 366 insertions(+), 150 deletions(-) New commits: commit 8c255fb185d5651b57380b0a9443001e8051b29d Author: Akira TAGOH <akira at tagoh.org> Date: Mon Mar 12 19:18:19 2012 +0900 Bug 20411 - fontconfig doesn''t match FreeDesktop directories specs Allows reading configuration files, fonts and cache files from the directories where the XDG Base Directory Specification defines. the old directories are still in the configuration files for the backward compatibility. diff --git a/conf.d/50-user.conf b/conf.d/50-user.conf index 3f89012..2f10408 100644 --- a/conf.d/50-user.conf +++ b/conf.d/50-user.conf @@ -2,6 +2,9 @@ <!DOCTYPE fontconfig SYSTEM "fonts.dtd"> <fontconfig> <!-- Load per-user customization file --> - <include ignore_missing="yes">~/.fonts.conf.d</include> - <include ignore_missing="yes">~/.fonts.conf</include> + <include ignore_missing="yes" prefix="xdg">fontconfig/conf.d</include> + <include ignore_missing="yes" prefix="xdg">fontconfig/fonts.conf</include> + <!-- the following elements will be removed in the future --> + <include ignore_missing="yes" deprecated="yes">~/.fonts.conf.d</include> + <include ignore_missing="yes" deprecated="yes">~/.fonts.conf</include> </fontconfig> diff --git a/doc/fontconfig-user.sgml b/doc/fontconfig-user.sgml index 22d2ad3..5c9d362 100644 --- a/doc/fontconfig-user.sgml +++ b/doc/fontconfig-user.sgml @@ -37,6 +37,8 @@ &confdir;/fonts.conf &confdir;/fonts.dtd &confdir;/conf.d + $XDG_CONFIG_HOME/fontconfig/conf.d + $XDG_CONFIG_HOME/fontconfig/fonts.conf ~/.fonts.conf.d ~/.fonts.conf </synopsis> @@ -299,21 +301,22 @@ following structure: This is the top level element for a font configuration and can contain <literal><dir></literal>, <literal><cachedir></literal>, <literal><include></literal>, <literal><match></literal> and <literal><alias></literal> elements in any order. </para></refsect2> - <refsect2><title><literal><dir></literal></title><para> + <refsect2><title><literal><dir prefix="default"></literal></title><para> This element contains a directory name which will be scanned for font files -to include in the set of available fonts. +to include in the set of available fonts. If ''prefix'' is set to "xdg", the value in the XDG_DATA_HOME environment variable will be added as the path prefix. please see XDG Base Directory Specification for more details. </para></refsect2> - <refsect2><title><literal><cachedir></literal></title><para> + <refsect2><title><literal><cachedir prefix="default"></literal></title><para> This element contains a directory name that is supposed to be stored or read the cache of font information. If multiple elements are specified in the configuration file, the directory that can be accessed first in the list will be used to store the cache files. If it starts with ''~'', it refers to -a directory in the users home directory. The default directory is ``~/.fontconfig'''' -and it contains the cache files named ``<literal><hash value></literal>-<literal><architecture></literal>.cache-<literal><version</literal>'''', +a directory in the users home directory. If ''prefix'' is set to "xdg", the value in the XDG_CACHE_HOME environment variable will be added as the path prefix. please see XDG Base Directory Specification for more details. +The default directory is ``$XDG_CACHE_HOME/fontconfig'''' and it contains the cache files +named ``<literal><hash value></literal>-<literal><architecture></literal>.cache-<literal><version</literal>'''', where <literal><version></literal> is the font configureation file version number (currently 3). </para></refsect2> - <refsect2><title><literal><include ignore_missing="no"></literal></title><para> + <refsect2><title><literal><include ignore_missing="no" prefix="default"></literal></title><para> This element contains the name of an additional configuration file or directory. If a directory, every file within that directory starting with an ASCII digit (U+0030 - U+0039) and ending with the string ``.conf'''' will be processed in sorted order. When @@ -321,7 +324,7 @@ the XML datatype is traversed by FcConfigParse, the contents of the file(s) will also be incorporated into the configuration by passing the filename(s) to FcConfigLoadAndParse. If ''ignore_missing'' is set to "yes" instead of the default "no", a missing file or directory will elicit no warning message from -the library. +the library. If ''prefix'' is set to "xdg", the value in the XDG_CONFIG_HOME environment variable will be added as the path prefix. please see XDG Base Directory Specification for more details. </para></refsect2> <refsect2><title><literal><config></literal></title><para> This element provides a place to consolidate additional configuration @@ -577,7 +580,7 @@ This is an example of a system-wide configuration file Load per-user customization file, but don''t complain if it doesn''t exist --> -<include ignore_missing="yes">~/.fonts.conf</include> +<include ignore_missing="yes" prefix="xdg">fontconfig/fonts.conf</include> <!-- Load local customization files, but don''t complain @@ -630,18 +633,18 @@ This is an example of a system-wide configuration file <refsect2><title>User configuration file</title> <para> This is an example of a per-user configuration file that lives in -~/.fonts.conf +$XDG_CONFIG_HOME/fontconfig/fonts.conf </para> <programlisting> <?xml version="1.0"?> <!DOCTYPE fontconfig SYSTEM "fonts.dtd"> -<!-- ~/.fonts.conf for per-user font configuration --> +<!-- $XDG_CONFIG_HOME/fontconfig/fonts.conf for per-user font configuration --> <fontconfig> <!-- Private font directory --> -<dir>~/.fonts</dir> +<dir prefix="xdg">fonts</dir> <!-- use rgb sub-pixel ordering to improve glyph appearance on @@ -677,20 +680,20 @@ format. The master fonts.conf file references this directory in an is a DTD that describes the format of the configuration files. </para> <para> -<emphasis>~/.fonts.conf.d</emphasis> +<emphasis>$XDG_CONFIG_HOME/fontconfig/conf.d</emphasis> and <emphasis>~/.fonts.conf.d</emphasis> is the conventional name for a per-user directory of (typically auto-generated) configuration files, although the -actual location is specified in the global fonts.conf file. +actual location is specified in the global fonts.conf file. please note that ~/.fonts.conf.d is deprecated now. it will not be read by default in the future version. </para> <para> -<emphasis>~/.fonts.conf</emphasis> +<emphasis>$XDG_CONFIG_HOME/fontconfig/fonts.conf</emphasis> and <emphasis>~/.fonts.conf</emphasis> is the conventional location for per-user font configuration, although the -actual location is specified in the global fonts.conf file. +actual location is specified in the global fonts.conf file. please note that ~/.fonts.conf is deprecated now. it will not be read by default in the future version. </para> <para> -<emphasis> ~/.fontconfig/*.cache-*</emphasis> +<emphasis>$XDG_CACHE_HOME/fontconfig/*.cache-*</emphasis> and <emphasis> ~/.fontconfig/*.cache-*</emphasis> is the conventional repository of font information that isn''t found in the -per-directory caches. This file is automatically maintained by fontconfig. +per-directory caches. This file is automatically maintained by fontconfig. please note that ~/.fontconfig/*.cache-* is deprecated now. it will not be read by default in the future version. </para> </refsect1> <refsect1><title>Environment variables</title> diff --git a/fonts.conf.in b/fonts.conf.in index 8f9fb88..6a8753d 100644 --- a/fonts.conf.in +++ b/fonts.conf.in @@ -25,6 +25,8 @@ <dir>@FC_DEFAULT_FONTS@</dir> @FC_FONTPATH@ + <dir prefix="xdg">fonts</dir> + <!-- the following element will be removed in the future --> <dir>~/.fonts</dir> <!-- @@ -71,6 +73,8 @@ <!-- Font cache directory list --> <cachedir>@FC_CACHEDIR@</cachedir> + <cachedir prefix="xdg">fontconfig</cachedir> + <!-- the following element will be removed in the future --> <cachedir>~/.fontconfig</cachedir> <config> diff --git a/fonts.dtd b/fonts.dtd index 255367c..782e592 100644 --- a/fonts.dtd +++ b/fonts.dtd @@ -12,7 +12,9 @@ Add a directory that provides fonts --> <!ELEMENT dir (#PCDATA)> -<!ATTLIST dir xml:space (default|preserve) ''preserve''> +<!ATTLIST dir + prefix (#PCDATA) "default" + xml:space (default|preserve) ''preserve''> <!-- Define the per-user file that holds cache font information. @@ -33,7 +35,9 @@ home directory path. --> <!ELEMENT cachedir (#PCDATA)> -<!ATTLIST cachedir xml:space (default|preserve) ''preserve''> +<!ATTLIST cachedir + prefix (#PCDATA) "default" + xml:space (default|preserve) ''preserve''> <!-- Reference another configuration file; note that this @@ -48,6 +52,8 @@ <!ELEMENT include (#PCDATA)> <!ATTLIST include ignore_missing (no|yes) "no" + prefix (#PCDATA) "default" + deprecated (#PCDATA) "no" xml:space (default|preserve) "preserve"> <!-- diff --git a/src/fccfg.c b/src/fccfg.c index 31c4276..5b72492 100644 --- a/src/fccfg.c +++ b/src/fccfg.c @@ -1837,6 +1837,81 @@ FcConfigHome (void) return 0; } +FcChar8 * +FcConfigXdgCacheHome (void) +{ + const char *env = getenv ("XDG_CACHE_HOME"); + FcChar8 *ret = NULL; + + if (env) + ret = FcStrCopy ((const FcChar8 *)env); + else + { + const FcChar8 *home = FcConfigHome (); + size_t len = home ? strlen ((const char *)home) : 0; + + ret = malloc (len + 7 + 1); + if (ret) + { + memcpy (ret, home, len); + memcpy (&ret[len], FC_DIR_SEPARATOR_S ".cache", 7); + ret[len + 7] = 0; + } + } + + return ret; +} + +FcChar8 * +FcConfigXdgConfigHome (void) +{ + const char *env = getenv ("XDG_CONFIG_HOME"); + FcChar8 *ret = NULL; + + if (env) + ret = FcStrCopy ((const FcChar8 *)env); + else + { + const FcChar8 *home = FcConfigHome (); + size_t len = home ? strlen ((const char *)home) : 0; + + ret = malloc (len + 8 + 1); + if (ret) + { + memcpy (ret, home, len); + memcpy (&ret[len], FC_DIR_SEPARATOR_S ".config", 8); + ret[len + 8] = 0; + } + } + + return ret; +} + +FcChar8 * +FcConfigXdgDataHome (void) +{ + const char *env = getenv ("XDG_DATA_HOME"); + FcChar8 *ret = NULL; + + if (env) + ret = FcStrCopy ((const FcChar8 *)env); + else + { + const FcChar8 *home = FcConfigHome (); + size_t len = home ? strlen ((const char *)home) : 0; + + ret = malloc (len + 13 + 1); + if (ret) + { + memcpy (ret, home, len); + memcpy (&ret[len], FC_DIR_SEPARATOR_S ".local" FC_DIR_SEPARATOR_S "share", 13); + ret[len + 13] = 0; + } + } + + return ret; +} + FcBool FcConfigEnableHome (FcBool enable) { @@ -1883,7 +1958,7 @@ FcConfigFilename (const FcChar8 *url) default: path = FcConfigGetPath (); if (!path) - return 0; + return NULL; for (p = path; *p; p++) { file = FcConfigFileExists (*p, url); @@ -1893,6 +1968,7 @@ FcConfigFilename (const FcChar8 *url) FcConfigFreePath (path); break; } + return file; } diff --git a/src/fcinit.c b/src/fcinit.c index abf64b5..ab64012 100644 --- a/src/fcinit.c +++ b/src/fcinit.c @@ -72,21 +72,37 @@ FcInitLoadConfig (void) if (config->cacheDirs && config->cacheDirs->num == 0) { + FcChar8 *prefix; + size_t plen; + fprintf (stderr, "Fontconfig warning: no <cachedir> elements found. Check configuration.\n"); fprintf (stderr, "Fontconfig warning: adding <cachedir>%s</cachedir>\n", FC_CACHEDIR); + prefix = FcConfigXdgCacheHome (); + plen = prefix ? strlen ((const char *)prefix) : 0; + if (!prefix) + goto bail; + prefix = realloc (prefix, plen + 12); + if (!prefix) + goto bail; + memcpy (&prefix[plen], FC_DIR_SEPARATOR_S "fontconfig", 11); + prefix[plen + 11] = 0; fprintf (stderr, - "Fontconfig warning: adding <cachedir>~/.fontconfig</cachedir>\n"); + "Fontconfig warning: adding <cachedir prefix=\"xdg\">fontconfig</cachedir>\n"); + if (!FcConfigAddCacheDir (config, (FcChar8 *) FC_CACHEDIR) || - !FcConfigAddCacheDir (config, (FcChar8 *) "~/.fontconfig")) + !FcConfigAddCacheDir (config, (FcChar8 *) prefix)) { + bail: fprintf (stderr, "Fontconfig error: out of memory"); + free (prefix); FcConfigDestroy (config); return FcInitFallbackConfig (); } + free (prefix); } return config; diff --git a/src/fcint.h b/src/fcint.h index a89aae1..ad9db8a 100644 --- a/src/fcint.h +++ b/src/fcint.h @@ -64,9 +64,11 @@ typedef HRESULT (WINAPI *pfnSHGetFolderPathA)(HWND, int, HANDLE, DWORD, LPSTR); extern pfnGetSystemWindowsDirectory pGetSystemWindowsDirectory; extern pfnSHGetFolderPathA pSHGetFolderPathA; # define FC_SEARCH_PATH_SEPARATOR '';'' +# define FC_DIR_SEPARATOR ''\\'' # define FC_DIR_SEPARATOR_S "\\" #else # define FC_SEARCH_PATH_SEPARATOR '':'' +# define FC_DIR_SEPARATOR ''/'' # define FC_DIR_SEPARATOR_S "/" #endif @@ -570,6 +572,15 @@ FcStat (const FcChar8 *file, struct stat *statb); /* fccfg.c */ +FcPrivate FcChar8 * +FcConfigXdgCacheHome (void); + +FcPrivate FcChar8 * +FcConfigXdgConfigHome (void); + +FcPrivate FcChar8 * +FcConfigXdgDataHome (void); + FcPrivate FcExpr * FcConfigAllocExpr (FcConfig *config); diff --git a/src/fcstr.c b/src/fcstr.c index ae37ff0..f20d05e 100644 --- a/src/fcstr.c +++ b/src/fcstr.c @@ -896,11 +896,11 @@ FcStrCopyFilename (const FcChar8 *s) FcChar8 *full; int size; if (!home) - return 0; + return NULL; size = strlen ((char *) home) + strlen ((char *) s); full = (FcChar8 *) malloc (size); if (!full) - return 0; + return NULL; strcpy ((char *) full, (char *) home); strcat ((char *) full, (char *) s + 1); new = FcStrCanonFilename (full); @@ -908,6 +908,7 @@ FcStrCopyFilename (const FcChar8 *s) } else new = FcStrCanonFilename (s); + return new; } diff --git a/src/fcxml.c b/src/fcxml.c index c49529a..f027270 100644 --- a/src/fcxml.c +++ b/src/fcxml.c @@ -1844,24 +1844,238 @@ FcParseUnary (FcConfigParse *parse, FcOp op) } static void +FcParseDir (FcConfigParse *parse) +{ + const FcChar8 *attr, *data; + FcChar8 *prefix = NULL; + + attr = FcConfigGetAttribute (parse, "prefix"); + if (attr && FcStrCmp (attr, (const FcChar8 *)"xdg") == 0) + prefix = FcConfigXdgDataHome (); + data = FcStrBufDoneStatic (&parse->pstack->str); + if (!data) + { + FcConfigMessage (parse, FcSevereError, "out of memory"); + goto bail; + } + if (prefix) + { + size_t plen = strlen ((const char *)prefix); + size_t dlen = strlen ((const char *)data); + + prefix = realloc (prefix, plen + 1 + dlen + 1); + if (!prefix) + { + FcConfigMessage (parse, FcSevereError, "out of memory"); + goto bail; + } + prefix[plen] = FC_DIR_SEPARATOR; + memcpy (&prefix[plen + 1], data, dlen); + prefix[plen + 1 + dlen] = 0; + data = prefix; + } +#ifdef _WIN32 + if (strcmp (data, "CUSTOMFONTDIR") == 0) + { + char *p; + data = buffer; + if (!GetModuleFileName (NULL, buffer, sizeof (buffer) - 20)) + { + FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed"); + break; + } + /* + * Must use the multi-byte aware function to search + * for backslash because East Asian double-byte code + * pages have characters with backslash as the second + * byte. + */ + p = _mbsrchr (data, ''\\''); + if (p) *p = ''\0''; + strcat (data, "\\fonts"); + } + else if (strcmp (data, "APPSHAREFONTDIR") == 0) + { + char *p; + data = buffer; + if (!GetModuleFileName (NULL, buffer, sizeof (buffer) - 20)) + { + FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed"); + break; + } + p = _mbsrchr (data, ''\\''); + if (p) *p = ''\0''; + strcat (data, "\\..\\share\\fonts"); + } + else if (strcmp (data, "WINDOWSFONTDIR") == 0) + { + int rc; + data = buffer; + rc = pGetSystemWindowsDirectory (buffer, sizeof (buffer) - 20); + if (rc == 0 || rc > sizeof (buffer) - 20) + { + FcConfigMessage (parse, FcSevereError, "GetSystemWindowsDirectory failed"); + break; + } + if (data [strlen (data) - 1] != ''\\'') + strcat (data, "\\"); + strcat (data, "fonts"); + } +#endif + if (strlen ((char *) data) == 0) + FcConfigMessage (parse, FcSevereWarning, "empty font directory name ignored"); + else if (!FcStrUsesHome (data) || FcConfigHome ()) + { + if (!FcConfigAddDir (parse->config, data)) + FcConfigMessage (parse, FcSevereError, "out of memory; cannot add directory %s", data); + } + FcStrBufDestroy (&parse->pstack->str); + + bail: + if (prefix) + free (prefix); +} + +static void +FcParseCacheDir (FcConfigParse *parse) +{ + const FcChar8 *attr; + FcChar8 *prefix = NULL, *data; + + attr = FcConfigGetAttribute (parse, "prefix"); + if (attr && FcStrCmp (attr, (const FcChar8 *)"xdg") == 0) + prefix = FcConfigXdgCacheHome (); + data = FcStrBufDone (&parse->pstack->str); + if (!data) + { + FcConfigMessage (parse, FcSevereError, "out of memory"); + goto bail; + } + if (prefix) + { + size_t plen = strlen ((const char *)prefix); + size_t dlen = strlen ((const char *)data); + + prefix = realloc (prefix, plen + 1 + dlen + 1); + if (!prefix) + { + FcConfigMessage (parse, FcSevereError, "out of memory"); + goto bail; + } + prefix[plen] = FC_DIR_SEPARATOR; + memcpy (&prefix[plen + 1], data, dlen); + prefix[plen + 1 + dlen] = 0; + FcStrFree (data); + data = prefix; + } +#ifdef _WIN32 + if (strcmp (data, "WINDOWSTEMPDIR_FONTCONFIG_CACHE") == 0) + { + int rc; + FcStrFree (data); + data = malloc (1000); + if (!data) + { + FcConfigMessage (parse, FcSevereError, "out of memory"); + goto bail; + } + FcMemAlloc (FC_MEM_STRING, 1000); + rc = GetTempPath (800, data); + if (rc == 0 || rc > 800) + { + FcConfigMessage (parse, FcSevereError, "GetTempPath failed"); + goto bail; + } + if (data [strlen (data) - 1] != ''\\'') + strcat (data, "\\"); + strcat (data, "fontconfig\\cache"); + } + else if (strcmp (data, "LOCAL_APPDATA_FONTCONFIG_CACHE") == 0) + { + char szFPath[MAX_PATH + 1]; + size_t len; + + if (!(pSHGetFolderPathA && SUCCEEDED(pSHGetFolderPathA(NULL, /* CSIDL_LOCAL_APPDATA */ 28, NULL, 0, szFPath)))) + { + FcConfigMessage (parse, FcSevereError, "SHGetFolderPathA failed"); + goto bail; + } + strncat(szFPath, "\\fontconfig\\cache", MAX_PATH - 1 - strlen(szFPath)); + len = strlen(szFPath) + 1; + FcStrFree (data); + data = malloc(len); + if (!data) + { + FcConfigMessage (parse, FcSevereError, "out of memory"); + goto bail; + } + FcMemAlloc (FC_MEM_STRING, len); + strncpy(data, szFPath, len); + } +#endif + if (strlen ((char *) data) == 0) + FcConfigMessage (parse, FcSevereWarning, "empty cache directory name ignored"); + else if (!FcStrUsesHome (data) || FcConfigHome ()) + { + if (!FcConfigAddCacheDir (parse->config, data)) + FcConfigMessage (parse, FcSevereError, "out of memory; cannot add cache directory %s", data); + } + FcStrBufDestroy (&parse->pstack->str); + + bail: + if (data) + FcStrFree (data); +} + +static void FcParseInclude (FcConfigParse *parse) { FcChar8 *s; - const FcChar8 *i; + const FcChar8 *attr; FcBool ignore_missing = FcFalse; + FcChar8 *prefix = NULL; s = FcStrBufDoneStatic (&parse->pstack->str); if (!s) { FcConfigMessage (parse, FcSevereError, "out of memory"); - return; + goto bail; } - i = FcConfigGetAttribute (parse, "ignore_missing"); - if (i && FcConfigLexBool (parse, (FcChar8 *) i) == FcTrue) + attr = FcConfigGetAttribute (parse, "ignore_missing"); + if (attr && FcConfigLexBool (parse, (FcChar8 *) attr) == FcTrue) ignore_missing = FcTrue; + attr = FcConfigGetAttribute (parse, "prefix"); + if (attr && FcStrCmp (attr, (const FcChar8 *)"xdg") == 0) + prefix = FcConfigXdgConfigHome (); + if (prefix) + { + size_t plen = strlen ((const char *)prefix); + size_t dlen = strlen ((const char *)s); + + prefix = realloc (prefix, plen + 1 + dlen + 1); + if (!prefix) + { + FcConfigMessage (parse, FcSevereError, "out of memory"); + goto bail; + } + prefix[plen] = FC_DIR_SEPARATOR; + memcpy (&prefix[plen + 1], s, dlen); + prefix[plen + 1 + dlen] = 0; + s = prefix; + } if (!FcConfigParseAndLoad (parse->config, s, !ignore_missing)) parse->error = FcTrue; + else + { + attr = FcConfigGetAttribute (parse, "deprecated"); + if (attr && FcConfigLexBool (parse, (FcChar8 *) attr) == FcTrue) + FcConfigMessage (parse, FcSevereWarning, "reading configurations from %s is deprecated.\n", s); + } FcStrBufDestroy (&parse->pstack->str); + + bail: + if (prefix) + free (prefix); } typedef struct _FcOpMap { @@ -2296,129 +2510,11 @@ FcEndElement(void *userData, const XML_Char *name) case FcElementFontconfig: break; case FcElementDir: - data = FcStrBufDoneStatic (&parse->pstack->str); - if (!data) - { - FcConfigMessage (parse, FcSevereError, "out of memory"); - break; - } -#ifdef _WIN32 - if (strcmp (data, "CUSTOMFONTDIR") == 0) - { - char *p; - data = buffer; - if (!GetModuleFileName (NULL, buffer, sizeof (buffer) - 20)) - { - FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed"); - break; - } - /* - * Must use the multi-byte aware function to search - * for backslash because East Asian double-byte code - * pages have characters with backslash as the second - * byte. - */ - p = _mbsrchr (data, ''\\''); - if (p) *p = ''\0''; - strcat (data, "\\fonts"); - } - else if (strcmp (data, "APPSHAREFONTDIR") == 0) - { - char *p; - data = buffer; - if (!GetModuleFileName (NULL, buffer, sizeof (buffer) - 20)) - { - FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed"); - break; - } - p = _mbsrchr (data, ''\\''); - if (p) *p = ''\0''; - strcat (data, "\\..\\share\\fonts"); - } - else if (strcmp (data, "WINDOWSFONTDIR") == 0) - { - int rc; - data = buffer; - rc = pGetSystemWindowsDirectory (buffer, sizeof (buffer) - 20); - if (rc == 0 || rc > sizeof (buffer) - 20) - { - FcConfigMessage (parse, FcSevereError, "GetSystemWindowsDirectory failed"); - break; - } - if (data [strlen (data) - 1] != ''\\'') - strcat (data, "\\"); - strcat (data, "fonts"); - } -#endif - if (strlen ((char *) data) == 0) - FcConfigMessage (parse, FcSevereWarning, "empty font directory name ignored"); - else if (!FcStrUsesHome (data) || FcConfigHome ()) - { - if (!FcConfigAddDir (parse->config, data)) - FcConfigMessage (parse, FcSevereError, "out of memory; cannot add directory %s", data); - } - FcStrBufDestroy (&parse->pstack->str); + FcParseDir (parse); break; case FcElementCacheDir: - data = FcStrBufDone (&parse->pstack->str); - if (!data) - { - FcConfigMessage (parse, FcSevereError, "out of memory"); - break; - } -#ifdef _WIN32 - if (strcmp (data, "WINDOWSTEMPDIR_FONTCONFIG_CACHE") == 0) - { - int rc; - FcStrFree (data); - data = malloc (1000); - if (!data) - { - FcConfigMessage (parse, FcSevereError, "out of memory"); - break; - } - FcMemAlloc (FC_MEM_STRING, 1000); - rc = GetTempPath (800, data); - if (rc == 0 || rc > 800) - { - FcConfigMessage (parse, FcSevereError, "GetTempPath failed"); - FcStrFree (data); - break; - } - if (data [strlen (data) - 1] != ''\\'') - strcat (data, "\\"); - strcat (data, "fontconfig\\cache"); - } - else if (strcmp (data, "LOCAL_APPDATA_FONTCONFIG_CACHE") == 0) - { - char szFPath[MAX_PATH + 1]; - size_t len; - FcStrFree (data); - if (!(pSHGetFolderPathA && SUCCEEDED(pSHGetFolderPathA(NULL, /* CSIDL_LOCAL_APPDATA */ 28, NULL, 0, szFPath)))) - { - FcConfigMessage (parse, FcSevereError, "SHGetFolderPathA failed"); - break; - } - strncat(szFPath, "\\fontconfig\\cache", MAX_PATH - 1 - strlen(szFPath)); - len = strlen(szFPath) + 1; - data = malloc(len); - if (!data) - { - FcConfigMessage (parse, FcSevereError, "out of memory"); - break; - } - FcMemAlloc (FC_MEM_STRING, len); - strncpy(data, szFPath, len); - } -#endif - if (!FcStrUsesHome (data) || FcConfigHome ()) - { - if (!FcConfigAddCacheDir (parse->config, data)) - FcConfigMessage (parse, FcSevereError, "out of memory; cannot add cache directory %s", data); - } - FcStrFree (data); + FcParseCacheDir (parse); break; - case FcElementCache: data = FcStrBufDoneStatic (&parse->pstack->str); if (!data)