Blame src/fccfg.c

Packit 352660
/*
Packit 352660
 * fontconfig/src/fccfg.c
Packit 352660
 *
Packit 352660
 * Copyright © 2000 Keith Packard
Packit 352660
 *
Packit 352660
 * Permission to use, copy, modify, distribute, and sell this software and its
Packit 352660
 * documentation for any purpose is hereby granted without fee, provided that
Packit 352660
 * the above copyright notice appear in all copies and that both that
Packit 352660
 * copyright notice and this permission notice appear in supporting
Packit 352660
 * documentation, and that the name of the author(s) not be used in
Packit 352660
 * advertising or publicity pertaining to distribution of the software without
Packit 352660
 * specific, written prior permission.  The authors make no
Packit 352660
 * representations about the suitability of this software for any purpose.  It
Packit 352660
 * is provided "as is" without express or implied warranty.
Packit 352660
 *
Packit 352660
 * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
Packit 352660
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
Packit 352660
 * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
Packit 352660
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
Packit 352660
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
Packit 352660
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
Packit 352660
 * PERFORMANCE OF THIS SOFTWARE.
Packit 352660
 */
Packit 352660
Packit 352660
/* Objects MT-safe for readonly access. */
Packit 352660
Packit 352660
#include "fcint.h"
Packit 352660
#include <dirent.h>
Packit 352660
#include <sys/types.h>
Packit 352660
Packit 352660
#if defined (_WIN32) && !defined (R_OK)
Packit 352660
#define R_OK 4
Packit 352660
#endif
Packit 352660
Packit 352660
static FcConfig    *_fcConfig; /* MT-safe */
Packit 352660
Packit 352660
static FcConfig *
Packit 352660
FcConfigEnsure (void)
Packit 352660
{
Packit 352660
    FcConfig	*config;
Packit 352660
retry:
Packit 352660
    config = fc_atomic_ptr_get (&_fcConfig);
Packit 352660
    if (!config)
Packit 352660
    {
Packit 352660
	config = FcInitLoadConfigAndFonts ();
Packit 352660
Packit 352660
	if (!fc_atomic_ptr_cmpexch (&_fcConfig, NULL, config)) {
Packit 352660
	    FcConfigDestroy (config);
Packit 352660
	    goto retry;
Packit 352660
	}
Packit 352660
    }
Packit 352660
    return config;
Packit 352660
}
Packit 352660
Packit 352660
static FcChar32
Packit 352660
FcHashAsStrIgnoreCase (const void *data)
Packit 352660
{
Packit 352660
    return FcStrHashIgnoreCase (data);
Packit 352660
}
Packit 352660
Packit 352660
static int
Packit 352660
FcCompareAsStr (const void *v1, const void *v2)
Packit 352660
{
Packit 352660
    return FcStrCmp (v1, v2);
Packit 352660
}
Packit 352660
Packit 352660
static void
Packit 352660
FcDestroyAsRule (void *data)
Packit 352660
{
Packit 352660
    FcRuleDestroy (data);
Packit 352660
}
Packit 352660
Packit 352660
static void
Packit 352660
FcDestroyAsRuleSet (void *data)
Packit 352660
{
Packit 352660
    FcRuleSetDestroy (data);
Packit 352660
}
Packit 352660
Packit 352660
static void
Packit 352660
FcDestroyAsStr (void *data)
Packit 352660
{
Packit 352660
    FcStrFree (data);
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcConfigInit (void)
Packit 352660
{
Packit 352660
  return FcConfigEnsure () ? FcTrue : FcFalse;
Packit 352660
}
Packit 352660
Packit 352660
void
Packit 352660
FcConfigFini (void)
Packit 352660
{
Packit 352660
    FcConfig *cfg = fc_atomic_ptr_get (&_fcConfig);
Packit 352660
    if (cfg && fc_atomic_ptr_cmpexch (&_fcConfig, cfg, NULL))
Packit 352660
	FcConfigDestroy (cfg);
Packit 352660
}
Packit 352660
Packit 352660
Packit 352660
FcConfig *
Packit 352660
FcConfigCreate (void)
Packit 352660
{
Packit 352660
    FcSetName	set;
Packit 352660
    FcConfig	*config;
Packit 352660
    FcMatchKind	k;
Packit 352660
    FcBool	err = FcFalse;
Packit 352660
Packit 352660
    config = malloc (sizeof (FcConfig));
Packit 352660
    if (!config)
Packit 352660
	goto bail0;
Packit 352660
Packit 352660
    config->configDirs = FcStrSetCreate ();
Packit 352660
    if (!config->configDirs)
Packit 352660
	goto bail1;
Packit 352660
Packit 352660
    config->configFiles = FcStrSetCreate ();
Packit 352660
    if (!config->configFiles)
Packit 352660
	goto bail2;
Packit 352660
Packit 352660
    config->fontDirs = FcStrSetCreate ();
Packit 352660
    if (!config->fontDirs)
Packit 352660
	goto bail3;
Packit 352660
Packit 352660
    config->acceptGlobs = FcStrSetCreate ();
Packit 352660
    if (!config->acceptGlobs)
Packit 352660
	goto bail4;
Packit 352660
Packit 352660
    config->rejectGlobs = FcStrSetCreate ();
Packit 352660
    if (!config->rejectGlobs)
Packit 352660
	goto bail5;
Packit 352660
Packit 352660
    config->acceptPatterns = FcFontSetCreate ();
Packit 352660
    if (!config->acceptPatterns)
Packit 352660
	goto bail6;
Packit 352660
Packit 352660
    config->rejectPatterns = FcFontSetCreate ();
Packit 352660
    if (!config->rejectPatterns)
Packit 352660
	goto bail7;
Packit 352660
Packit 352660
    config->cacheDirs = FcStrSetCreate ();
Packit 352660
    if (!config->cacheDirs)
Packit 352660
	goto bail8;
Packit 352660
Packit 352660
    for (k = FcMatchKindBegin; k < FcMatchKindEnd; k++)
Packit 352660
    {
Packit 352660
	config->subst[k] = FcPtrListCreate (FcDestroyAsRuleSet);
Packit 352660
	if (!config->subst[k])
Packit 352660
	    err = FcTrue;
Packit 352660
    }
Packit 352660
    if (err)
Packit 352660
	goto bail9;
Packit 352660
Packit 352660
    config->maxObjects = 0;
Packit 352660
    for (set = FcSetSystem; set <= FcSetApplication; set++)
Packit 352660
	config->fonts[set] = 0;
Packit 352660
Packit 352660
    config->rescanTime = time(0);
Packit 352660
    config->rescanInterval = 30;
Packit 352660
Packit 352660
    config->expr_pool = NULL;
Packit 352660
Packit 352660
    config->sysRoot = NULL;
Packit 352660
Packit 352660
    config->rulesetList = FcPtrListCreate (FcDestroyAsRuleSet);
Packit 352660
    if (!config->rulesetList)
Packit 352660
	goto bail9;
Packit 352660
    config->availConfigFiles = FcStrSetCreate ();
Packit 352660
    if (!config->availConfigFiles)
Packit 352660
	goto bail10;
Packit 352660
Packit 352660
    config->uuid_table = FcHashTableCreate (FcHashAsStrIgnoreCase,
Packit 352660
					    FcCompareAsStr,
Packit 352660
					    FcHashStrCopy,
Packit 352660
					    FcHashUuidCopy,
Packit 352660
					    FcDestroyAsStr,
Packit 352660
					    FcHashUuidFree);
Packit 352660
Packit 352660
    FcRefInit (&config->ref, 1);
Packit 352660
Packit 352660
    return config;
Packit 352660
Packit 352660
bail10:
Packit 352660
    FcPtrListDestroy (config->rulesetList);
Packit 352660
bail9:
Packit 352660
    for (k = FcMatchKindBegin; k < FcMatchKindEnd; k++)
Packit 352660
	if (config->subst[k])
Packit 352660
	    FcPtrListDestroy (config->subst[k]);
Packit 352660
    FcStrSetDestroy (config->cacheDirs);
Packit 352660
bail8:
Packit 352660
    FcFontSetDestroy (config->rejectPatterns);
Packit 352660
bail7:
Packit 352660
    FcFontSetDestroy (config->acceptPatterns);
Packit 352660
bail6:
Packit 352660
    FcStrSetDestroy (config->rejectGlobs);
Packit 352660
bail5:
Packit 352660
    FcStrSetDestroy (config->acceptGlobs);
Packit 352660
bail4:
Packit 352660
    FcStrSetDestroy (config->fontDirs);
Packit 352660
bail3:
Packit 352660
    FcStrSetDestroy (config->configFiles);
Packit 352660
bail2:
Packit 352660
    FcStrSetDestroy (config->configDirs);
Packit 352660
bail1:
Packit 352660
    free (config);
Packit 352660
bail0:
Packit 352660
    return 0;
Packit 352660
}
Packit 352660
Packit 352660
static FcFileTime
Packit 352660
FcConfigNewestFile (FcStrSet *files)
Packit 352660
{
Packit 352660
    FcStrList	    *list = FcStrListCreate (files);
Packit 352660
    FcFileTime	    newest = { 0, FcFalse };
Packit 352660
    FcChar8	    *file;
Packit 352660
    struct  stat    statb;
Packit 352660
Packit 352660
    if (list)
Packit 352660
    {
Packit 352660
	while ((file = FcStrListNext (list)))
Packit 352660
	    if (FcStat (file, &statb) == 0)
Packit 352660
		if (!newest.set || statb.st_mtime - newest.time > 0)
Packit 352660
		{
Packit 352660
		    newest.set = FcTrue;
Packit 352660
		    newest.time = statb.st_mtime;
Packit 352660
		}
Packit 352660
	FcStrListDone (list);
Packit 352660
    }
Packit 352660
    return newest;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcConfigUptoDate (FcConfig *config)
Packit 352660
{
Packit 352660
    FcFileTime	config_time, config_dir_time, font_time;
Packit 352660
    time_t	now = time(0);
Packit 352660
    if (!config)
Packit 352660
    {
Packit 352660
	config = FcConfigGetCurrent ();
Packit 352660
	if (!config)
Packit 352660
	    return FcFalse;
Packit 352660
    }
Packit 352660
    config_time = FcConfigNewestFile (config->configFiles);
Packit 352660
    config_dir_time = FcConfigNewestFile (config->configDirs);
Packit 352660
    font_time = FcConfigNewestFile (config->fontDirs);
Packit 352660
    if ((config_time.set && config_time.time - config->rescanTime > 0) ||
Packit 352660
	(config_dir_time.set && (config_dir_time.time - config->rescanTime) > 0) ||
Packit 352660
	(font_time.set && (font_time.time - config->rescanTime) > 0))
Packit 352660
    {
Packit 352660
	/* We need to check for potential clock problems here (OLPC ticket #6046) */
Packit 352660
	if ((config_time.set && (config_time.time - now) > 0) ||
Packit 352660
    	(config_dir_time.set && (config_dir_time.time - now) > 0) ||
Packit 352660
        (font_time.set && (font_time.time - now) > 0))
Packit 352660
	{
Packit 352660
	    fprintf (stderr,
Packit 352660
                    "Fontconfig warning: Directory/file mtime in the future. New fonts may not be detected.\n");
Packit 352660
	    config->rescanTime = now;
Packit 352660
	    return FcTrue;
Packit 352660
	}
Packit 352660
	else
Packit 352660
	    return FcFalse;
Packit 352660
    }
Packit 352660
    config->rescanTime = now;
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
FcExpr *
Packit 352660
FcConfigAllocExpr (FcConfig *config)
Packit 352660
{
Packit 352660
    if (!config->expr_pool || config->expr_pool->next == config->expr_pool->end)
Packit 352660
    {
Packit 352660
	FcExprPage *new_page;
Packit 352660
Packit 352660
	new_page = malloc (sizeof (FcExprPage));
Packit 352660
	if (!new_page)
Packit 352660
	    return 0;
Packit 352660
Packit 352660
	new_page->next_page = config->expr_pool;
Packit 352660
	new_page->next = new_page->exprs;
Packit 352660
	config->expr_pool = new_page;
Packit 352660
    }
Packit 352660
Packit 352660
    return config->expr_pool->next++;
Packit 352660
}
Packit 352660
Packit 352660
FcConfig *
Packit 352660
FcConfigReference (FcConfig *config)
Packit 352660
{
Packit 352660
    if (!config)
Packit 352660
    {
Packit 352660
	config = FcConfigGetCurrent ();
Packit 352660
	if (!config)
Packit 352660
	    return 0;
Packit 352660
    }
Packit 352660
Packit 352660
    FcRefInc (&config->ref);
Packit 352660
Packit 352660
    return config;
Packit 352660
}
Packit 352660
Packit 352660
void
Packit 352660
FcConfigDestroy (FcConfig *config)
Packit 352660
{
Packit 352660
    FcSetName	set;
Packit 352660
    FcExprPage	*page;
Packit 352660
    FcMatchKind	k;
Packit 352660
Packit 352660
    if (FcRefDec (&config->ref) != 1)
Packit 352660
	return;
Packit 352660
Packit 352660
    (void) fc_atomic_ptr_cmpexch (&_fcConfig, config, NULL);
Packit 352660
Packit 352660
    FcStrSetDestroy (config->configDirs);
Packit 352660
    FcStrSetDestroy (config->fontDirs);
Packit 352660
    FcStrSetDestroy (config->cacheDirs);
Packit 352660
    FcStrSetDestroy (config->configFiles);
Packit 352660
    FcStrSetDestroy (config->acceptGlobs);
Packit 352660
    FcStrSetDestroy (config->rejectGlobs);
Packit 352660
    FcFontSetDestroy (config->acceptPatterns);
Packit 352660
    FcFontSetDestroy (config->rejectPatterns);
Packit 352660
Packit 352660
    for (k = FcMatchKindBegin; k < FcMatchKindEnd; k++)
Packit 352660
	FcPtrListDestroy (config->subst[k]);
Packit 352660
    FcPtrListDestroy (config->rulesetList);
Packit 352660
    FcStrSetDestroy (config->availConfigFiles);
Packit 352660
    for (set = FcSetSystem; set <= FcSetApplication; set++)
Packit 352660
	if (config->fonts[set])
Packit 352660
	    FcFontSetDestroy (config->fonts[set]);
Packit 352660
Packit 352660
    page = config->expr_pool;
Packit 352660
    while (page)
Packit 352660
    {
Packit 352660
      FcExprPage *next = page->next_page;
Packit 352660
      free (page);
Packit 352660
      page = next;
Packit 352660
    }
Packit 352660
    if (config->sysRoot)
Packit 352660
	FcStrFree (config->sysRoot);
Packit 352660
Packit 352660
    FcHashTableDestroy (config->uuid_table);
Packit 352660
Packit 352660
    free (config);
Packit 352660
}
Packit 352660
Packit 352660
/*
Packit 352660
 * Add cache to configuration, adding fonts and directories
Packit 352660
 */
Packit 352660
Packit 352660
FcBool
Packit 352660
FcConfigAddCache (FcConfig *config, FcCache *cache,
Packit 352660
		  FcSetName set, FcStrSet *dirSet, FcChar8 *forDir)
Packit 352660
{
Packit 352660
    FcFontSet	*fs;
Packit 352660
    intptr_t	*dirs;
Packit 352660
    int		i;
Packit 352660
    FcBool      relocated = FcFalse;
Packit 352660
Packit 352660
    if (strcmp ((char *)FcCacheDir(cache), (char *)forDir) != 0)
Packit 352660
      relocated = FcTrue;
Packit 352660
Packit 352660
    /*
Packit 352660
     * Add fonts
Packit 352660
     */
Packit 352660
    fs = FcCacheSet (cache);
Packit 352660
    if (fs)
Packit 352660
    {
Packit 352660
	int	nref = 0;
Packit 352660
	
Packit 352660
	for (i = 0; i < fs->nfont; i++)
Packit 352660
	{
Packit 352660
	    FcPattern	*font = FcFontSetFont (fs, i);
Packit 352660
	    FcChar8	*font_file;
Packit 352660
	    FcChar8	*relocated_font_file = NULL;
Packit 352660
Packit 352660
	    if (FcPatternObjectGetString (font, FC_FILE_OBJECT,
Packit 352660
					  0, &font_file) == FcResultMatch)
Packit 352660
	    {
Packit 352660
		if (relocated)
Packit 352660
		  {
Packit 352660
		    FcChar8 *slash = FcStrLastSlash (font_file);
Packit 352660
		    relocated_font_file = FcStrBuildFilename (forDir, slash + 1, NULL);
Packit 352660
		    font_file = relocated_font_file;
Packit 352660
		  }
Packit 352660
Packit 352660
		/*
Packit 352660
		 * Check to see if font is banned by filename
Packit 352660
		 */
Packit 352660
		if (!FcConfigAcceptFilename (config, font_file))
Packit 352660
		{
Packit 352660
		    free (relocated_font_file);
Packit 352660
		    continue;
Packit 352660
		}
Packit 352660
	    }
Packit 352660
Packit 352660
	    /*
Packit 352660
	     * Check to see if font is banned by pattern
Packit 352660
	     */
Packit 352660
	    if (!FcConfigAcceptFont (config, font))
Packit 352660
	    {
Packit 352660
		free (relocated_font_file);
Packit 352660
		continue;
Packit 352660
	    }
Packit 352660
Packit 352660
	    if (relocated_font_file)
Packit 352660
	    {
Packit 352660
	      font = FcPatternCacheRewriteFile (font, cache, relocated_font_file);
Packit 352660
	      free (relocated_font_file);
Packit 352660
	    }
Packit 352660
Packit 352660
	    if (FcFontSetAdd (config->fonts[set], font))
Packit 352660
		nref++;
Packit 352660
	}
Packit 352660
	FcDirCacheReference (cache, nref);
Packit 352660
    }
Packit 352660
Packit 352660
    /*
Packit 352660
     * Add directories
Packit 352660
     */
Packit 352660
    dirs = FcCacheDirs (cache);
Packit 352660
    if (dirs)
Packit 352660
    {
Packit 352660
	for (i = 0; i < cache->dirs_count; i++)
Packit 352660
	{
Packit 352660
	    const FcChar8 *dir = FcCacheSubdir (cache, i);
Packit 352660
	    FcChar8 *s = NULL;
Packit 352660
Packit 352660
	    if (relocated)
Packit 352660
	    {
Packit 352660
		FcChar8 *base = FcStrBasename (dir);
Packit 352660
		dir = s = FcStrBuildFilename (forDir, base, NULL);
Packit 352660
		FcStrFree (base);
Packit 352660
	    }
Packit 352660
	    if (FcConfigAcceptFilename (config, dir))
Packit 352660
		FcStrSetAddFilename (dirSet, dir);
Packit 352660
	    if (s)
Packit 352660
		FcStrFree (s);
Packit 352660
	}
Packit 352660
    }
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
static FcBool
Packit 352660
FcConfigAddDirList (FcConfig *config, FcSetName set, FcStrSet *dirSet)
Packit 352660
{
Packit 352660
    FcStrList	    *dirlist;
Packit 352660
    FcChar8	    *dir;
Packit 352660
    FcCache	    *cache;
Packit 352660
Packit 352660
    dirlist = FcStrListCreate (dirSet);
Packit 352660
    if (!dirlist)
Packit 352660
        return FcFalse;
Packit 352660
	
Packit 352660
    while ((dir = FcStrListNext (dirlist)))
Packit 352660
    {
Packit 352660
	if (FcDebug () & FC_DBG_FONTSET)
Packit 352660
	    printf ("adding fonts from %s\n", dir);
Packit 352660
	cache = FcDirCacheRead (dir, FcFalse, config);
Packit 352660
	if (!cache)
Packit 352660
	    continue;
Packit 352660
	FcConfigAddCache (config, cache, set, dirSet, dir);
Packit 352660
	FcDirCacheUnload (cache);
Packit 352660
    }
Packit 352660
    FcStrListDone (dirlist);
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
/*
Packit 352660
 * Scan the current list of directories in the configuration
Packit 352660
 * and build the set of available fonts.
Packit 352660
 */
Packit 352660
Packit 352660
FcBool
Packit 352660
FcConfigBuildFonts (FcConfig *config)
Packit 352660
{
Packit 352660
    FcFontSet	    *fonts;
Packit 352660
Packit 352660
    if (!config)
Packit 352660
    {
Packit 352660
	config = FcConfigGetCurrent ();
Packit 352660
	if (!config)
Packit 352660
	    return FcFalse;
Packit 352660
    }
Packit 352660
	
Packit 352660
    fonts = FcFontSetCreate ();
Packit 352660
    if (!fonts)
Packit 352660
	return FcFalse;
Packit 352660
Packit 352660
    FcConfigSetFonts (config, fonts, FcSetSystem);
Packit 352660
Packit 352660
    if (!FcConfigAddDirList (config, FcSetSystem, config->fontDirs))
Packit 352660
	return FcFalse;
Packit 352660
    if (FcDebug () & FC_DBG_FONTSET)
Packit 352660
	FcFontSetPrint (fonts);
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcConfigSetCurrent (FcConfig *config)
Packit 352660
{
Packit 352660
    FcConfig *cfg;
Packit 352660
Packit 352660
retry:
Packit 352660
    cfg = fc_atomic_ptr_get (&_fcConfig);
Packit 352660
Packit 352660
    if (config == cfg)
Packit 352660
	return FcTrue;
Packit 352660
Packit 352660
    if (config && !config->fonts[FcSetSystem])
Packit 352660
	if (!FcConfigBuildFonts (config))
Packit 352660
	    return FcFalse;
Packit 352660
Packit 352660
    if (!fc_atomic_ptr_cmpexch (&_fcConfig, cfg, config))
Packit 352660
	goto retry;
Packit 352660
Packit 352660
    FcConfigReference (config);
Packit 352660
    if (cfg)
Packit 352660
	FcConfigDestroy (cfg);
Packit 352660
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
FcConfig *
Packit 352660
FcConfigGetCurrent (void)
Packit 352660
{
Packit 352660
    return FcConfigEnsure ();
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcConfigAddConfigDir (FcConfig	    *config,
Packit 352660
		      const FcChar8 *d)
Packit 352660
{
Packit 352660
    return FcStrSetAddFilename (config->configDirs, d);
Packit 352660
}
Packit 352660
Packit 352660
FcStrList *
Packit 352660
FcConfigGetConfigDirs (FcConfig   *config)
Packit 352660
{
Packit 352660
    if (!config)
Packit 352660
    {
Packit 352660
	config = FcConfigGetCurrent ();
Packit 352660
	if (!config)
Packit 352660
	    return 0;
Packit 352660
    }
Packit 352660
    return FcStrListCreate (config->configDirs);
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcConfigAddFontDir (FcConfig	    *config,
Packit 352660
		    const FcChar8   *d)
Packit 352660
{
Packit 352660
    return FcStrSetAddFilename (config->fontDirs, d);
Packit 352660
}
Packit 352660
Packit 352660
FcStrList *
Packit 352660
FcConfigGetFontDirs (FcConfig	*config)
Packit 352660
{
Packit 352660
    if (!config)
Packit 352660
    {
Packit 352660
	config = FcConfigGetCurrent ();
Packit 352660
	if (!config)
Packit 352660
	    return 0;
Packit 352660
    }
Packit 352660
    return FcStrListCreate (config->fontDirs);
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcConfigAddCacheDir (FcConfig	    *config,
Packit 352660
		     const FcChar8  *d)
Packit 352660
{
Packit 352660
    return FcStrSetAddFilename (config->cacheDirs, d);
Packit 352660
}
Packit 352660
Packit 352660
FcStrList *
Packit 352660
FcConfigGetCacheDirs (const FcConfig *config)
Packit 352660
{
Packit 352660
    if (!config)
Packit 352660
    {
Packit 352660
	config = FcConfigGetCurrent ();
Packit 352660
	if (!config)
Packit 352660
	    return 0;
Packit 352660
    }
Packit 352660
    return FcStrListCreate (config->cacheDirs);
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcConfigAddConfigFile (FcConfig	    *config,
Packit 352660
		       const FcChar8   *f)
Packit 352660
{
Packit 352660
    FcBool	ret;
Packit 352660
    FcChar8	*file = FcConfigFilename (f);
Packit 352660
Packit 352660
    if (!file)
Packit 352660
	return FcFalse;
Packit 352660
Packit 352660
    ret = FcStrSetAdd (config->configFiles, file);
Packit 352660
    FcStrFree (file);
Packit 352660
    return ret;
Packit 352660
}
Packit 352660
Packit 352660
FcStrList *
Packit 352660
FcConfigGetConfigFiles (FcConfig    *config)
Packit 352660
{
Packit 352660
    if (!config)
Packit 352660
    {
Packit 352660
	config = FcConfigGetCurrent ();
Packit 352660
	if (!config)
Packit 352660
	    return 0;
Packit 352660
    }
Packit 352660
    return FcStrListCreate (config->configFiles);
Packit 352660
}
Packit 352660
Packit 352660
FcChar8 *
Packit 352660
FcConfigGetCache (FcConfig  *config FC_UNUSED)
Packit 352660
{
Packit 352660
    return NULL;
Packit 352660
}
Packit 352660
Packit 352660
FcFontSet *
Packit 352660
FcConfigGetFonts (FcConfig	*config,
Packit 352660
		  FcSetName	set)
Packit 352660
{
Packit 352660
    if (!config)
Packit 352660
    {
Packit 352660
	config = FcConfigGetCurrent ();
Packit 352660
	if (!config)
Packit 352660
	    return 0;
Packit 352660
    }
Packit 352660
    return config->fonts[set];
Packit 352660
}
Packit 352660
Packit 352660
void
Packit 352660
FcConfigSetFonts (FcConfig	*config,
Packit 352660
		  FcFontSet	*fonts,
Packit 352660
		  FcSetName	set)
Packit 352660
{
Packit 352660
    if (config->fonts[set])
Packit 352660
	FcFontSetDestroy (config->fonts[set]);
Packit 352660
    config->fonts[set] = fonts;
Packit 352660
}
Packit 352660
Packit 352660
Packit 352660
FcBlanks *
Packit 352660
FcBlanksCreate (void)
Packit 352660
{
Packit 352660
    /* Deprecated. */
Packit 352660
    return NULL;
Packit 352660
}
Packit 352660
Packit 352660
void
Packit 352660
FcBlanksDestroy (FcBlanks *b FC_UNUSED)
Packit 352660
{
Packit 352660
    /* Deprecated. */
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcBlanksAdd (FcBlanks *b FC_UNUSED, FcChar32 ucs4 FC_UNUSED)
Packit 352660
{
Packit 352660
    /* Deprecated. */
Packit 352660
    return FcFalse;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcBlanksIsMember (FcBlanks *b FC_UNUSED, FcChar32 ucs4 FC_UNUSED)
Packit 352660
{
Packit 352660
    /* Deprecated. */
Packit 352660
    return FcFalse;
Packit 352660
}
Packit 352660
Packit 352660
FcBlanks *
Packit 352660
FcConfigGetBlanks (FcConfig	*config FC_UNUSED)
Packit 352660
{
Packit 352660
    /* Deprecated. */
Packit 352660
    return NULL;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcConfigAddBlank (FcConfig	*config FC_UNUSED,
Packit 352660
		  FcChar32    	blank FC_UNUSED)
Packit 352660
{
Packit 352660
    /* Deprecated. */
Packit 352660
    return FcFalse;
Packit 352660
}
Packit 352660
Packit 352660
Packit 352660
int
Packit 352660
FcConfigGetRescanInterval (FcConfig *config)
Packit 352660
{
Packit 352660
    if (!config)
Packit 352660
    {
Packit 352660
	config = FcConfigGetCurrent ();
Packit 352660
	if (!config)
Packit 352660
	    return 0;
Packit 352660
    }
Packit 352660
    return config->rescanInterval;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcConfigSetRescanInterval (FcConfig *config, int rescanInterval)
Packit 352660
{
Packit 352660
    if (!config)
Packit 352660
    {
Packit 352660
	config = FcConfigGetCurrent ();
Packit 352660
	if (!config)
Packit 352660
	    return FcFalse;
Packit 352660
    }
Packit 352660
    config->rescanInterval = rescanInterval;
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
/*
Packit 352660
 * A couple of typos escaped into the library
Packit 352660
 */
Packit 352660
int
Packit 352660
FcConfigGetRescanInverval (FcConfig *config)
Packit 352660
{
Packit 352660
    return FcConfigGetRescanInterval (config);
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcConfigSetRescanInverval (FcConfig *config, int rescanInterval)
Packit 352660
{
Packit 352660
    return FcConfigSetRescanInterval (config, rescanInterval);
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcConfigAddRule (FcConfig	*config,
Packit 352660
		 FcRule		*rule,
Packit 352660
		 FcMatchKind	kind)
Packit 352660
{
Packit 352660
    /* deprecated */
Packit 352660
    return FcFalse;
Packit 352660
}
Packit 352660
Packit 352660
static FcValue
Packit 352660
FcConfigPromote (FcValue v, FcValue u, FcValuePromotionBuffer *buf)
Packit 352660
{
Packit 352660
    if (v.type == FcTypeInteger)
Packit 352660
    {
Packit 352660
	v.type = FcTypeDouble;
Packit 352660
	v.u.d = (double) v.u.i;
Packit 352660
    }
Packit 352660
    else if (v.type == FcTypeVoid && u.type == FcTypeMatrix)
Packit 352660
    {
Packit 352660
	v.u.m = &FcIdentityMatrix;
Packit 352660
	v.type = FcTypeMatrix;
Packit 352660
    }
Packit 352660
    else if (buf && v.type == FcTypeString && u.type == FcTypeLangSet)
Packit 352660
    {
Packit 352660
	v.u.l = FcLangSetPromote (v.u.s, buf);
Packit 352660
	v.type = FcTypeLangSet;
Packit 352660
    }
Packit 352660
    else if (buf && v.type == FcTypeVoid && u.type == FcTypeLangSet)
Packit 352660
    {
Packit 352660
	v.u.l = FcLangSetPromote (NULL, buf);
Packit 352660
	v.type = FcTypeLangSet;
Packit 352660
    }
Packit 352660
    else if (buf && v.type == FcTypeVoid && u.type == FcTypeCharSet)
Packit 352660
    {
Packit 352660
	v.u.c = FcCharSetPromote (buf);
Packit 352660
	v.type = FcTypeCharSet;
Packit 352660
    }
Packit 352660
    if (buf && v.type == FcTypeDouble && u.type == FcTypeRange)
Packit 352660
    {
Packit 352660
	v.u.r = FcRangePromote (v.u.d, buf);
Packit 352660
	v.type = FcTypeRange;
Packit 352660
    }
Packit 352660
    return v;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcConfigCompareValue (const FcValue	*left_o,
Packit 352660
		      unsigned int      op_,
Packit 352660
		      const FcValue	*right_o)
Packit 352660
{
Packit 352660
    FcValue	left = FcValueCanonicalize(left_o);
Packit 352660
    FcValue	right = FcValueCanonicalize(right_o);
Packit 352660
    FcBool	ret = FcFalse;
Packit 352660
    FcOp	op = FC_OP_GET_OP (op_);
Packit 352660
    int		flags = FC_OP_GET_FLAGS (op_);
Packit 352660
    FcValuePromotionBuffer buf1, buf2;
Packit 352660
Packit 352660
    left = FcConfigPromote (left, right, &buf1);
Packit 352660
    right = FcConfigPromote (right, left, &buf2);
Packit 352660
    if (left.type == right.type)
Packit 352660
    {
Packit 352660
	switch (left.type) {
Packit 352660
	case FcTypeUnknown:
Packit 352660
	    break;	/* No way to guess how to compare for this object */
Packit 352660
	case FcTypeInteger:
Packit 352660
	    break;	/* FcConfigPromote prevents this from happening */
Packit 352660
	case FcTypeDouble:
Packit 352660
	    switch ((int) op) {
Packit 352660
	    case FcOpEqual:
Packit 352660
	    case FcOpContains:
Packit 352660
	    case FcOpListing:
Packit 352660
		ret = left.u.d == right.u.d;
Packit 352660
		break;
Packit 352660
	    case FcOpNotEqual:
Packit 352660
	    case FcOpNotContains:
Packit 352660
		ret = left.u.d != right.u.d;
Packit 352660
		break;
Packit 352660
	    case FcOpLess:
Packit 352660
		ret = left.u.d < right.u.d;
Packit 352660
		break;
Packit 352660
	    case FcOpLessEqual:
Packit 352660
		ret = left.u.d <= right.u.d;
Packit 352660
		break;
Packit 352660
	    case FcOpMore:
Packit 352660
		ret = left.u.d > right.u.d;
Packit 352660
		break;
Packit 352660
	    case FcOpMoreEqual:
Packit 352660
		ret = left.u.d >= right.u.d;
Packit 352660
		break;
Packit 352660
	    default:
Packit 352660
		break;
Packit 352660
	    }
Packit 352660
	    break;
Packit 352660
	case FcTypeBool:
Packit 352660
	    switch ((int) op) {
Packit 352660
	    case FcOpEqual:
Packit 352660
		ret = left.u.b == right.u.b;
Packit 352660
		break;
Packit 352660
	    case FcOpContains:
Packit 352660
	    case FcOpListing:
Packit 352660
		ret = left.u.b == right.u.b || left.u.b == FcDontCare;
Packit 352660
		break;
Packit 352660
	    case FcOpNotEqual:
Packit 352660
		ret = left.u.b != right.u.b;
Packit 352660
		break;
Packit 352660
	    case FcOpNotContains:
Packit 352660
		ret = !(left.u.b == right.u.b || left.u.b == FcDontCare);
Packit 352660
		break;
Packit 352660
	    case FcOpLess:
Packit 352660
		ret = left.u.b != right.u.b && right.u.b == FcDontCare;
Packit 352660
		break;
Packit 352660
	    case FcOpLessEqual:
Packit 352660
		ret = left.u.b == right.u.b || right.u.b == FcDontCare;
Packit 352660
		break;
Packit 352660
	    case FcOpMore:
Packit 352660
		ret = left.u.b != right.u.b && left.u.b == FcDontCare;
Packit 352660
		break;
Packit 352660
	    case FcOpMoreEqual:
Packit 352660
		ret = left.u.b == right.u.b || left.u.b == FcDontCare;
Packit 352660
		break;
Packit 352660
	    default:
Packit 352660
		break;
Packit 352660
	    }
Packit 352660
	    break;
Packit 352660
	case FcTypeString:
Packit 352660
	    switch ((int) op) {
Packit 352660
	    case FcOpEqual:
Packit 352660
	    case FcOpListing:
Packit 352660
		if (flags & FcOpFlagIgnoreBlanks)
Packit 352660
		    ret = FcStrCmpIgnoreBlanksAndCase (left.u.s, right.u.s) == 0;
Packit 352660
		else
Packit 352660
		    ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) == 0;
Packit 352660
		break;
Packit 352660
	    case FcOpContains:
Packit 352660
		ret = FcStrStrIgnoreCase (left.u.s, right.u.s) != 0;
Packit 352660
		break;
Packit 352660
	    case FcOpNotEqual:
Packit 352660
		if (flags & FcOpFlagIgnoreBlanks)
Packit 352660
		    ret = FcStrCmpIgnoreBlanksAndCase (left.u.s, right.u.s) != 0;
Packit 352660
		else
Packit 352660
		    ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) != 0;
Packit 352660
		break;
Packit 352660
	    case FcOpNotContains:
Packit 352660
		ret = FcStrStrIgnoreCase (left.u.s, right.u.s) == 0;
Packit 352660
		break;
Packit 352660
	    default:
Packit 352660
		break;
Packit 352660
	    }
Packit 352660
	    break;
Packit 352660
	case FcTypeMatrix:
Packit 352660
	    switch ((int) op) {
Packit 352660
	    case FcOpEqual:
Packit 352660
	    case FcOpContains:
Packit 352660
	    case FcOpListing:
Packit 352660
		ret = FcMatrixEqual (left.u.m, right.u.m);
Packit 352660
		break;
Packit 352660
	    case FcOpNotEqual:
Packit 352660
	    case FcOpNotContains:
Packit 352660
		ret = !FcMatrixEqual (left.u.m, right.u.m);
Packit 352660
		break;
Packit 352660
	    default:
Packit 352660
		break;
Packit 352660
	    }
Packit 352660
	    break;
Packit 352660
	case FcTypeCharSet:
Packit 352660
	    switch ((int) op) {
Packit 352660
	    case FcOpContains:
Packit 352660
	    case FcOpListing:
Packit 352660
		/* left contains right if right is a subset of left */
Packit 352660
		ret = FcCharSetIsSubset (right.u.c, left.u.c);
Packit 352660
		break;
Packit 352660
	    case FcOpNotContains:
Packit 352660
		/* left contains right if right is a subset of left */
Packit 352660
		ret = !FcCharSetIsSubset (right.u.c, left.u.c);
Packit 352660
		break;
Packit 352660
	    case FcOpEqual:
Packit 352660
		ret = FcCharSetEqual (left.u.c, right.u.c);
Packit 352660
		break;
Packit 352660
	    case FcOpNotEqual:
Packit 352660
		ret = !FcCharSetEqual (left.u.c, right.u.c);
Packit 352660
		break;
Packit 352660
	    default:
Packit 352660
		break;
Packit 352660
	    }
Packit 352660
	    break;
Packit 352660
	case FcTypeLangSet:
Packit 352660
	    switch ((int) op) {
Packit 352660
	    case FcOpContains:
Packit 352660
	    case FcOpListing:
Packit 352660
		ret = FcLangSetContains (left.u.l, right.u.l);
Packit 352660
		break;
Packit 352660
	    case FcOpNotContains:
Packit 352660
		ret = !FcLangSetContains (left.u.l, right.u.l);
Packit 352660
		break;
Packit 352660
	    case FcOpEqual:
Packit 352660
		ret = FcLangSetEqual (left.u.l, right.u.l);
Packit 352660
		break;
Packit 352660
	    case FcOpNotEqual:
Packit 352660
		ret = !FcLangSetEqual (left.u.l, right.u.l);
Packit 352660
		break;
Packit 352660
	    default:
Packit 352660
		break;
Packit 352660
	    }
Packit 352660
	    break;
Packit 352660
	case FcTypeVoid:
Packit 352660
	    switch ((int) op) {
Packit 352660
	    case FcOpEqual:
Packit 352660
	    case FcOpContains:
Packit 352660
	    case FcOpListing:
Packit 352660
		ret = FcTrue;
Packit 352660
		break;
Packit 352660
	    default:
Packit 352660
		break;
Packit 352660
	    }
Packit 352660
	    break;
Packit 352660
	case FcTypeFTFace:
Packit 352660
	    switch ((int) op) {
Packit 352660
	    case FcOpEqual:
Packit 352660
	    case FcOpContains:
Packit 352660
	    case FcOpListing:
Packit 352660
		ret = left.u.f == right.u.f;
Packit 352660
		break;
Packit 352660
	    case FcOpNotEqual:
Packit 352660
	    case FcOpNotContains:
Packit 352660
		ret = left.u.f != right.u.f;
Packit 352660
		break;
Packit 352660
	    default:
Packit 352660
		break;
Packit 352660
	    }
Packit 352660
	    break;
Packit 352660
	case FcTypeRange:
Packit 352660
	    ret = FcRangeCompare (op, left.u.r, right.u.r);
Packit 352660
	    break;
Packit 352660
	}
Packit 352660
    }
Packit 352660
    else
Packit 352660
    {
Packit 352660
	if (op == FcOpNotEqual || op == FcOpNotContains)
Packit 352660
	    ret = FcTrue;
Packit 352660
    }
Packit 352660
    return ret;
Packit 352660
}
Packit 352660
Packit 352660
Packit 352660
#define _FcDoubleFloor(d)	((int) (d))
Packit 352660
#define _FcDoubleCeil(d)	((double) (int) (d) == (d) ? (int) (d) : (int) ((d) + 1))
Packit 352660
#define FcDoubleFloor(d)	((d) >= 0 ? _FcDoubleFloor(d) : -_FcDoubleCeil(-(d)))
Packit 352660
#define FcDoubleCeil(d)		((d) >= 0 ? _FcDoubleCeil(d) : -_FcDoubleFloor(-(d)))
Packit 352660
#define FcDoubleRound(d)	FcDoubleFloor ((d) + 0.5)
Packit 352660
#define FcDoubleTrunc(d)	((d) >= 0 ? _FcDoubleFloor (d) : -_FcDoubleFloor (-(d)))
Packit 352660
Packit 352660
static FcValue
Packit 352660
FcConfigEvaluate (FcPattern *p, FcPattern *p_pat, FcMatchKind kind, FcExpr *e)
Packit 352660
{
Packit 352660
    FcValue	v, vl, vr, vle, vre;
Packit 352660
    FcMatrix	*m;
Packit 352660
    FcChar8     *str;
Packit 352660
    FcOp	op = FC_OP_GET_OP (e->op);
Packit 352660
    FcValuePromotionBuffer buf1, buf2;
Packit 352660
Packit 352660
    switch ((int) op) {
Packit 352660
    case FcOpInteger:
Packit 352660
	v.type = FcTypeInteger;
Packit 352660
	v.u.i = e->u.ival;
Packit 352660
	break;
Packit 352660
    case FcOpDouble:
Packit 352660
	v.type = FcTypeDouble;
Packit 352660
	v.u.d = e->u.dval;
Packit 352660
	break;
Packit 352660
    case FcOpString:
Packit 352660
	v.type = FcTypeString;
Packit 352660
	v.u.s = e->u.sval;
Packit 352660
	v = FcValueSave (v);
Packit 352660
	break;
Packit 352660
    case FcOpMatrix:
Packit 352660
	{
Packit 352660
	  FcMatrix m;
Packit 352660
	  FcValue xx, xy, yx, yy;
Packit 352660
	  v.type = FcTypeMatrix;
Packit 352660
	  xx = FcConfigPromote (FcConfigEvaluate (p, p_pat, kind, e->u.mexpr->xx), v, NULL);
Packit 352660
	  xy = FcConfigPromote (FcConfigEvaluate (p, p_pat, kind, e->u.mexpr->xy), v, NULL);
Packit 352660
	  yx = FcConfigPromote (FcConfigEvaluate (p, p_pat, kind, e->u.mexpr->yx), v, NULL);
Packit 352660
	  yy = FcConfigPromote (FcConfigEvaluate (p, p_pat, kind, e->u.mexpr->yy), v, NULL);
Packit 352660
	  if (xx.type == FcTypeDouble && xy.type == FcTypeDouble &&
Packit 352660
	      yx.type == FcTypeDouble && yy.type == FcTypeDouble)
Packit 352660
	  {
Packit 352660
	    m.xx = xx.u.d;
Packit 352660
	    m.xy = xy.u.d;
Packit 352660
	    m.yx = yx.u.d;
Packit 352660
	    m.yy = yy.u.d;
Packit 352660
	    v.u.m = &m;
Packit 352660
	  }
Packit 352660
	  else
Packit 352660
	    v.type = FcTypeVoid;
Packit 352660
	  v = FcValueSave (v);
Packit 352660
	}
Packit 352660
	break;
Packit 352660
    case FcOpCharSet:
Packit 352660
	v.type = FcTypeCharSet;
Packit 352660
	v.u.c = e->u.cval;
Packit 352660
	v = FcValueSave (v);
Packit 352660
	break;
Packit 352660
    case FcOpLangSet:
Packit 352660
	v.type = FcTypeLangSet;
Packit 352660
	v.u.l = e->u.lval;
Packit 352660
	v = FcValueSave (v);
Packit 352660
	break;
Packit 352660
    case FcOpRange:
Packit 352660
	v.type = FcTypeRange;
Packit 352660
	v.u.r = e->u.rval;
Packit 352660
	v = FcValueSave (v);
Packit 352660
	break;
Packit 352660
    case FcOpBool:
Packit 352660
	v.type = FcTypeBool;
Packit 352660
	v.u.b = e->u.bval;
Packit 352660
	break;
Packit 352660
    case FcOpField:
Packit 352660
	if (kind == FcMatchFont && e->u.name.kind == FcMatchPattern)
Packit 352660
	{
Packit 352660
	    if (FcResultMatch != FcPatternObjectGet (p_pat, e->u.name.object, 0, &v))
Packit 352660
		v.type = FcTypeVoid;
Packit 352660
	}
Packit 352660
	else if (kind == FcMatchPattern && e->u.name.kind == FcMatchFont)
Packit 352660
	{
Packit 352660
	    fprintf (stderr,
Packit 352660
                    "Fontconfig warning: <name> tag has target=\"font\" in a <match target=\"pattern\">.\n");
Packit 352660
	    v.type = FcTypeVoid;
Packit 352660
	}
Packit 352660
	else
Packit 352660
	{
Packit 352660
	    if (FcResultMatch != FcPatternObjectGet (p, e->u.name.object, 0, &v))
Packit 352660
		v.type = FcTypeVoid;
Packit 352660
	}
Packit 352660
	v = FcValueSave (v);
Packit 352660
	break;
Packit 352660
    case FcOpConst:
Packit 352660
	if (FcNameConstant (e->u.constant, &v.u.i))
Packit 352660
	    v.type = FcTypeInteger;
Packit 352660
	else
Packit 352660
	    v.type = FcTypeVoid;
Packit 352660
	break;
Packit 352660
    case FcOpQuest:
Packit 352660
	vl = FcConfigEvaluate (p, p_pat, kind, e->u.tree.left);
Packit 352660
	if (vl.type == FcTypeBool)
Packit 352660
	{
Packit 352660
	    if (vl.u.b)
Packit 352660
		v = FcConfigEvaluate (p, p_pat, kind, e->u.tree.right->u.tree.left);
Packit 352660
	    else
Packit 352660
		v = FcConfigEvaluate (p, p_pat, kind, e->u.tree.right->u.tree.right);
Packit 352660
	}
Packit 352660
	else
Packit 352660
	    v.type = FcTypeVoid;
Packit 352660
	FcValueDestroy (vl);
Packit 352660
	break;
Packit 352660
    case FcOpEqual:
Packit 352660
    case FcOpNotEqual:
Packit 352660
    case FcOpLess:
Packit 352660
    case FcOpLessEqual:
Packit 352660
    case FcOpMore:
Packit 352660
    case FcOpMoreEqual:
Packit 352660
    case FcOpContains:
Packit 352660
    case FcOpNotContains:
Packit 352660
    case FcOpListing:
Packit 352660
	vl = FcConfigEvaluate (p, p_pat, kind, e->u.tree.left);
Packit 352660
	vr = FcConfigEvaluate (p, p_pat, kind, e->u.tree.right);
Packit 352660
	v.type = FcTypeBool;
Packit 352660
	v.u.b = FcConfigCompareValue (&vl, e->op, &vr);
Packit 352660
	FcValueDestroy (vl);
Packit 352660
	FcValueDestroy (vr);
Packit 352660
	break;	
Packit 352660
    case FcOpOr:
Packit 352660
    case FcOpAnd:
Packit 352660
    case FcOpPlus:
Packit 352660
    case FcOpMinus:
Packit 352660
    case FcOpTimes:
Packit 352660
    case FcOpDivide:
Packit 352660
	vl = FcConfigEvaluate (p, p_pat, kind, e->u.tree.left);
Packit 352660
	vr = FcConfigEvaluate (p, p_pat, kind, e->u.tree.right);
Packit 352660
	vle = FcConfigPromote (vl, vr, &buf1);
Packit 352660
	vre = FcConfigPromote (vr, vle, &buf2);
Packit 352660
	if (vle.type == vre.type)
Packit 352660
	{
Packit 352660
	    switch ((int) vle.type) {
Packit 352660
	    case FcTypeDouble:
Packit 352660
		switch ((int) op) {
Packit 352660
		case FcOpPlus:	
Packit 352660
		    v.type = FcTypeDouble;
Packit 352660
		    v.u.d = vle.u.d + vre.u.d;
Packit 352660
		    break;
Packit 352660
		case FcOpMinus:
Packit 352660
		    v.type = FcTypeDouble;
Packit 352660
		    v.u.d = vle.u.d - vre.u.d;
Packit 352660
		    break;
Packit 352660
		case FcOpTimes:
Packit 352660
		    v.type = FcTypeDouble;
Packit 352660
		    v.u.d = vle.u.d * vre.u.d;
Packit 352660
		    break;
Packit 352660
		case FcOpDivide:
Packit 352660
		    v.type = FcTypeDouble;
Packit 352660
		    v.u.d = vle.u.d / vre.u.d;
Packit 352660
		    break;
Packit 352660
		default:
Packit 352660
		    v.type = FcTypeVoid;
Packit 352660
		    break;
Packit 352660
		}
Packit 352660
		if (v.type == FcTypeDouble &&
Packit 352660
		    v.u.d == (double) (int) v.u.d)
Packit 352660
		{
Packit 352660
		    v.type = FcTypeInteger;
Packit 352660
		    v.u.i = (int) v.u.d;
Packit 352660
		}
Packit 352660
		break;
Packit 352660
	    case FcTypeBool:
Packit 352660
		switch ((int) op) {
Packit 352660
		case FcOpOr:
Packit 352660
		    v.type = FcTypeBool;
Packit 352660
		    v.u.b = vle.u.b || vre.u.b;
Packit 352660
		    break;
Packit 352660
		case FcOpAnd:
Packit 352660
		    v.type = FcTypeBool;
Packit 352660
		    v.u.b = vle.u.b && vre.u.b;
Packit 352660
		    break;
Packit 352660
		default:
Packit 352660
		    v.type = FcTypeVoid;
Packit 352660
		    break;
Packit 352660
		}
Packit 352660
		break;
Packit 352660
	    case FcTypeString:
Packit 352660
		switch ((int) op) {
Packit 352660
		case FcOpPlus:
Packit 352660
		    v.type = FcTypeString;
Packit 352660
		    str = FcStrPlus (vle.u.s, vre.u.s);
Packit 352660
		    v.u.s = FcStrdup (str);
Packit 352660
		    FcStrFree (str);
Packit 352660
			
Packit 352660
		    if (!v.u.s)
Packit 352660
			v.type = FcTypeVoid;
Packit 352660
		    break;
Packit 352660
		default:
Packit 352660
		    v.type = FcTypeVoid;
Packit 352660
		    break;
Packit 352660
		}
Packit 352660
		break;
Packit 352660
	    case FcTypeMatrix:
Packit 352660
		switch ((int) op) {
Packit 352660
		case FcOpTimes:
Packit 352660
		    v.type = FcTypeMatrix;
Packit 352660
		    m = malloc (sizeof (FcMatrix));
Packit 352660
		    if (m)
Packit 352660
		    {
Packit 352660
			FcMatrixMultiply (m, vle.u.m, vre.u.m);
Packit 352660
			v.u.m = m;
Packit 352660
		    }
Packit 352660
		    else
Packit 352660
		    {
Packit 352660
			v.type = FcTypeVoid;
Packit 352660
		    }
Packit 352660
		    break;
Packit 352660
		default:
Packit 352660
		    v.type = FcTypeVoid;
Packit 352660
		    break;
Packit 352660
		}
Packit 352660
		break;
Packit 352660
	    case FcTypeCharSet:
Packit 352660
		switch ((int) op) {
Packit 352660
		case FcOpPlus:
Packit 352660
		    v.type = FcTypeCharSet;
Packit 352660
		    v.u.c = FcCharSetUnion (vle.u.c, vre.u.c);
Packit 352660
		    if (!v.u.c)
Packit 352660
			v.type = FcTypeVoid;
Packit 352660
		    break;
Packit 352660
		case FcOpMinus:
Packit 352660
		    v.type = FcTypeCharSet;
Packit 352660
		    v.u.c = FcCharSetSubtract (vle.u.c, vre.u.c);
Packit 352660
		    if (!v.u.c)
Packit 352660
			v.type = FcTypeVoid;
Packit 352660
		    break;
Packit 352660
		default:
Packit 352660
		    v.type = FcTypeVoid;
Packit 352660
		    break;
Packit 352660
		}
Packit 352660
		break;
Packit 352660
	    case FcTypeLangSet:
Packit 352660
		switch ((int) op) {
Packit 352660
		case FcOpPlus:
Packit 352660
		    v.type = FcTypeLangSet;
Packit 352660
		    v.u.l = FcLangSetUnion (vle.u.l, vre.u.l);
Packit 352660
		    if (!v.u.l)
Packit 352660
			v.type = FcTypeVoid;
Packit 352660
		    break;
Packit 352660
		case FcOpMinus:
Packit 352660
		    v.type = FcTypeLangSet;
Packit 352660
		    v.u.l = FcLangSetSubtract (vle.u.l, vre.u.l);
Packit 352660
		    if (!v.u.l)
Packit 352660
			v.type = FcTypeVoid;
Packit 352660
		    break;
Packit 352660
		default:
Packit 352660
		    v.type = FcTypeVoid;
Packit 352660
		    break;
Packit 352660
		}
Packit 352660
		break;
Packit 352660
	    default:
Packit 352660
		v.type = FcTypeVoid;
Packit 352660
		break;
Packit 352660
	    }
Packit 352660
	}
Packit 352660
	else
Packit 352660
	    v.type = FcTypeVoid;
Packit 352660
	FcValueDestroy (vl);
Packit 352660
	FcValueDestroy (vr);
Packit 352660
	break;
Packit 352660
    case FcOpNot:
Packit 352660
	vl = FcConfigEvaluate (p, p_pat, kind, e->u.tree.left);
Packit 352660
	switch ((int) vl.type) {
Packit 352660
	case FcTypeBool:
Packit 352660
	    v.type = FcTypeBool;
Packit 352660
	    v.u.b = !vl.u.b;
Packit 352660
	    break;
Packit 352660
	default:
Packit 352660
	    v.type = FcTypeVoid;
Packit 352660
	    break;
Packit 352660
	}
Packit 352660
	FcValueDestroy (vl);
Packit 352660
	break;
Packit 352660
    case FcOpFloor:
Packit 352660
	vl = FcConfigEvaluate (p, p_pat, kind, e->u.tree.left);
Packit 352660
	switch ((int) vl.type) {
Packit 352660
	case FcTypeInteger:
Packit 352660
	    v = vl;
Packit 352660
	    break;
Packit 352660
	case FcTypeDouble:
Packit 352660
	    v.type = FcTypeInteger;
Packit 352660
	    v.u.i = FcDoubleFloor (vl.u.d);
Packit 352660
	    break;
Packit 352660
	default:
Packit 352660
	    v.type = FcTypeVoid;
Packit 352660
	    break;
Packit 352660
	}
Packit 352660
	FcValueDestroy (vl);
Packit 352660
	break;
Packit 352660
    case FcOpCeil:
Packit 352660
	vl = FcConfigEvaluate (p, p_pat, kind, e->u.tree.left);
Packit 352660
	switch ((int) vl.type) {
Packit 352660
	case FcTypeInteger:
Packit 352660
	    v = vl;
Packit 352660
	    break;
Packit 352660
	case FcTypeDouble:
Packit 352660
	    v.type = FcTypeInteger;
Packit 352660
	    v.u.i = FcDoubleCeil (vl.u.d);
Packit 352660
	    break;
Packit 352660
	default:
Packit 352660
	    v.type = FcTypeVoid;
Packit 352660
	    break;
Packit 352660
	}
Packit 352660
	FcValueDestroy (vl);
Packit 352660
	break;
Packit 352660
    case FcOpRound:
Packit 352660
	vl = FcConfigEvaluate (p, p_pat, kind, e->u.tree.left);
Packit 352660
	switch ((int) vl.type) {
Packit 352660
	case FcTypeInteger:
Packit 352660
	    v = vl;
Packit 352660
	    break;
Packit 352660
	case FcTypeDouble:
Packit 352660
	    v.type = FcTypeInteger;
Packit 352660
	    v.u.i = FcDoubleRound (vl.u.d);
Packit 352660
	    break;
Packit 352660
	default:
Packit 352660
	    v.type = FcTypeVoid;
Packit 352660
	    break;
Packit 352660
	}
Packit 352660
	FcValueDestroy (vl);
Packit 352660
	break;
Packit 352660
    case FcOpTrunc:
Packit 352660
	vl = FcConfigEvaluate (p, p_pat, kind, e->u.tree.left);
Packit 352660
	switch ((int) vl.type) {
Packit 352660
	case FcTypeInteger:
Packit 352660
	    v = vl;
Packit 352660
	    break;
Packit 352660
	case FcTypeDouble:
Packit 352660
	    v.type = FcTypeInteger;
Packit 352660
	    v.u.i = FcDoubleTrunc (vl.u.d);
Packit 352660
	    break;
Packit 352660
	default:
Packit 352660
	    v.type = FcTypeVoid;
Packit 352660
	    break;
Packit 352660
	}
Packit 352660
	FcValueDestroy (vl);
Packit 352660
	break;
Packit 352660
    default:
Packit 352660
	v.type = FcTypeVoid;
Packit 352660
	break;
Packit 352660
    }
Packit 352660
    return v;
Packit 352660
}
Packit 352660
Packit 352660
static FcValueList *
Packit 352660
FcConfigMatchValueList (FcPattern	*p,
Packit 352660
			FcPattern	*p_pat,
Packit 352660
			FcMatchKind      kind,
Packit 352660
			FcTest		*t,
Packit 352660
			FcValueList	*values)
Packit 352660
{
Packit 352660
    FcValueList	    *ret = 0;
Packit 352660
    FcExpr	    *e = t->expr;
Packit 352660
    FcValue	    value;
Packit 352660
    FcValueList	    *v;
Packit 352660
Packit 352660
    while (e)
Packit 352660
    {
Packit 352660
	/* Compute the value of the match expression */
Packit 352660
	if (FC_OP_GET_OP (e->op) == FcOpComma)
Packit 352660
	{
Packit 352660
	    value = FcConfigEvaluate (p, p_pat, kind, e->u.tree.left);
Packit 352660
	    e = e->u.tree.right;
Packit 352660
	}
Packit 352660
	else
Packit 352660
	{
Packit 352660
	    value = FcConfigEvaluate (p, p_pat, kind, e);
Packit 352660
	    e = 0;
Packit 352660
	}
Packit 352660
Packit 352660
	for (v = values; v; v = FcValueListNext(v))
Packit 352660
	{
Packit 352660
	    /* Compare the pattern value to the match expression value */
Packit 352660
	    if (FcConfigCompareValue (&v->value, t->op, &value))
Packit 352660
	    {
Packit 352660
		if (!ret)
Packit 352660
		    ret = v;
Packit 352660
	    }
Packit 352660
	    else
Packit 352660
	    {
Packit 352660
		if (t->qual == FcQualAll)
Packit 352660
		{
Packit 352660
		    ret = 0;
Packit 352660
		    break;
Packit 352660
		}
Packit 352660
	    }
Packit 352660
	}
Packit 352660
	FcValueDestroy (value);
Packit 352660
    }
Packit 352660
    return ret;
Packit 352660
}
Packit 352660
Packit 352660
static FcValueList *
Packit 352660
FcConfigValues (FcPattern *p, FcPattern *p_pat, FcMatchKind kind, FcExpr *e, FcValueBinding binding)
Packit 352660
{
Packit 352660
    FcValueList	*l;
Packit 352660
Packit 352660
    if (!e)
Packit 352660
	return 0;
Packit 352660
    l = (FcValueList *) malloc (sizeof (FcValueList));
Packit 352660
    if (!l)
Packit 352660
	return 0;
Packit 352660
    if (FC_OP_GET_OP (e->op) == FcOpComma)
Packit 352660
    {
Packit 352660
	l->value = FcConfigEvaluate (p, p_pat, kind, e->u.tree.left);
Packit 352660
	l->next = FcConfigValues (p, p_pat, kind, e->u.tree.right, binding);
Packit 352660
    }
Packit 352660
    else
Packit 352660
    {
Packit 352660
	l->value = FcConfigEvaluate (p, p_pat, kind, e);
Packit 352660
	l->next = NULL;
Packit 352660
    }
Packit 352660
    l->binding = binding;
Packit 352660
    if (l->value.type == FcTypeVoid)
Packit 352660
    {
Packit 352660
	FcValueList  *next = FcValueListNext(l);
Packit 352660
Packit 352660
	free (l);
Packit 352660
	l = next;
Packit 352660
    }
Packit 352660
Packit 352660
    return l;
Packit 352660
}
Packit 352660
Packit 352660
static FcBool
Packit 352660
FcConfigAdd (FcValueListPtr *head,
Packit 352660
	     FcValueList    *position,
Packit 352660
	     FcBool	    append,
Packit 352660
	     FcValueList    *new,
Packit 352660
	     FcObject        object)
Packit 352660
{
Packit 352660
    FcValueListPtr  *prev, l, last, v;
Packit 352660
    FcValueBinding  sameBinding;
Packit 352660
Packit 352660
    /*
Packit 352660
     * Make sure the stored type is valid for built-in objects
Packit 352660
     */
Packit 352660
    for (l = new; l != NULL; l = FcValueListNext (l))
Packit 352660
    {
Packit 352660
	if (!FcObjectValidType (object, l->value.type))
Packit 352660
	{
Packit 352660
	    fprintf (stderr,
Packit 352660
		     "Fontconfig warning: FcPattern object %s does not accept value", FcObjectName (object));
Packit 352660
	    FcValuePrintFile (stderr, l->value);
Packit 352660
	    fprintf (stderr, "\n");
Packit 352660
Packit 352660
	    if (FcDebug () & FC_DBG_EDIT)
Packit 352660
	    {
Packit 352660
		printf ("Not adding\n");
Packit 352660
	    }
Packit 352660
Packit 352660
	    return FcFalse;
Packit 352660
	}
Packit 352660
    }
Packit 352660
Packit 352660
    if (position)
Packit 352660
	sameBinding = position->binding;
Packit 352660
    else
Packit 352660
	sameBinding = FcValueBindingWeak;
Packit 352660
    for (v = new; v != NULL; v = FcValueListNext(v))
Packit 352660
	if (v->binding == FcValueBindingSame)
Packit 352660
	    v->binding = sameBinding;
Packit 352660
    if (append)
Packit 352660
    {
Packit 352660
	if (position)
Packit 352660
	    prev = &position->next;
Packit 352660
	else
Packit 352660
	    for (prev = head; *prev != NULL;
Packit 352660
		 prev = &(*prev)->next)
Packit 352660
		;
Packit 352660
    }
Packit 352660
    else
Packit 352660
    {
Packit 352660
	if (position)
Packit 352660
	{
Packit 352660
	    for (prev = head; *prev != NULL;
Packit 352660
		 prev = &(*prev)->next)
Packit 352660
	    {
Packit 352660
		if (*prev == position)
Packit 352660
		    break;
Packit 352660
	    }
Packit 352660
	}
Packit 352660
	else
Packit 352660
	    prev = head;
Packit 352660
Packit 352660
	if (FcDebug () & FC_DBG_EDIT)
Packit 352660
	{
Packit 352660
	    if (*prev == NULL)
Packit 352660
		printf ("position not on list\n");
Packit 352660
	}
Packit 352660
    }
Packit 352660
Packit 352660
    if (FcDebug () & FC_DBG_EDIT)
Packit 352660
    {
Packit 352660
	printf ("%s list before ", append ? "Append" : "Prepend");
Packit 352660
	FcValueListPrintWithPosition (*head, *prev);
Packit 352660
	printf ("\n");
Packit 352660
    }
Packit 352660
Packit 352660
    if (new)
Packit 352660
    {
Packit 352660
	last = new;
Packit 352660
	while (last->next != NULL)
Packit 352660
	    last = last->next;
Packit 352660
Packit 352660
	last->next = *prev;
Packit 352660
	*prev = new;
Packit 352660
    }
Packit 352660
Packit 352660
    if (FcDebug () & FC_DBG_EDIT)
Packit 352660
    {
Packit 352660
	printf ("%s list after ", append ? "Append" : "Prepend");
Packit 352660
	FcValueListPrint (*head);
Packit 352660
	printf ("\n");
Packit 352660
    }
Packit 352660
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
static void
Packit 352660
FcConfigDel (FcValueListPtr *head,
Packit 352660
	     FcValueList    *position)
Packit 352660
{
Packit 352660
    FcValueListPtr *prev;
Packit 352660
Packit 352660
    for (prev = head; *prev != NULL; prev = &(*prev)->next)
Packit 352660
    {
Packit 352660
	if (*prev == position)
Packit 352660
	{
Packit 352660
	    *prev = position->next;
Packit 352660
	    position->next = NULL;
Packit 352660
	    FcValueListDestroy (position);
Packit 352660
	    break;
Packit 352660
	}
Packit 352660
    }
Packit 352660
}
Packit 352660
Packit 352660
static void
Packit 352660
FcConfigPatternAdd (FcPattern	*p,
Packit 352660
		    FcObject	object,
Packit 352660
		    FcValueList	*list,
Packit 352660
		    FcBool	append)
Packit 352660
{
Packit 352660
    if (list)
Packit 352660
    {
Packit 352660
	FcPatternElt    *e = FcPatternObjectInsertElt (p, object);
Packit 352660
Packit 352660
	if (!e)
Packit 352660
	    return;
Packit 352660
	FcConfigAdd (&e->values, 0, append, list, object);
Packit 352660
    }
Packit 352660
}
Packit 352660
Packit 352660
/*
Packit 352660
 * Delete all values associated with a field
Packit 352660
 */
Packit 352660
static void
Packit 352660
FcConfigPatternDel (FcPattern	*p,
Packit 352660
		    FcObject	object)
Packit 352660
{
Packit 352660
    FcPatternElt    *e = FcPatternObjectFindElt (p, object);
Packit 352660
    if (!e)
Packit 352660
	return;
Packit 352660
    while (e->values != NULL)
Packit 352660
	FcConfigDel (&e->values, e->values);
Packit 352660
}
Packit 352660
Packit 352660
static void
Packit 352660
FcConfigPatternCanon (FcPattern	    *p,
Packit 352660
		      FcObject	    object)
Packit 352660
{
Packit 352660
    FcPatternElt    *e = FcPatternObjectFindElt (p, object);
Packit 352660
    if (!e)
Packit 352660
	return;
Packit 352660
    if (e->values == NULL)
Packit 352660
	FcPatternObjectDel (p, object);
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcConfigSubstituteWithPat (FcConfig    *config,
Packit 352660
			   FcPattern   *p,
Packit 352660
			   FcPattern   *p_pat,
Packit 352660
			   FcMatchKind kind)
Packit 352660
{
Packit 352660
    FcValue v;
Packit 352660
    FcPtrList	    *s;
Packit 352660
    FcPtrListIter    iter, iter2;
Packit 352660
    FcRule          *r;
Packit 352660
    FcRuleSet	    *rs;
Packit 352660
    FcValueList	    *l, **value = NULL, *vl;
Packit 352660
    FcPattern	    *m;
Packit 352660
    FcStrSet	    *strs;
Packit 352660
    FcObject	    object = FC_INVALID_OBJECT;
Packit 352660
    FcPatternElt    **elt = NULL, *e;
Packit 352660
    int		    i, nobjs;
Packit 352660
    FcBool	    retval = FcTrue;
Packit 352660
    FcTest	    **tst = NULL;
Packit 352660
Packit 352660
    if (!config)
Packit 352660
    {
Packit 352660
	config = FcConfigGetCurrent ();
Packit 352660
	if (!config)
Packit 352660
	    return FcFalse;
Packit 352660
    }
Packit 352660
Packit 352660
    if (kind < FcMatchKindBegin || kind >= FcMatchKindEnd)
Packit 352660
	return FcFalse;
Packit 352660
    s = config->subst[kind];
Packit 352660
    if (kind == FcMatchPattern)
Packit 352660
    {
Packit 352660
	strs = FcGetDefaultLangs ();
Packit 352660
	if (strs)
Packit 352660
	{
Packit 352660
	    FcStrList *l = FcStrListCreate (strs);
Packit 352660
	    FcChar8 *lang;
Packit 352660
	    FcValue v;
Packit 352660
	    FcLangSet *lsund = FcLangSetCreate ();
Packit 352660
Packit 352660
	    FcLangSetAdd (lsund, (const FcChar8 *)"und");
Packit 352660
	    FcStrSetDestroy (strs);
Packit 352660
	    while (l && (lang = FcStrListNext (l)))
Packit 352660
	    {
Packit 352660
		FcPatternElt *e = FcPatternObjectFindElt (p, FC_LANG_OBJECT);
Packit 352660
Packit 352660
		if (e)
Packit 352660
		{
Packit 352660
		    FcValueListPtr ll;
Packit 352660
Packit 352660
		    for (ll = FcPatternEltValues (e); ll; ll = FcValueListNext (ll))
Packit 352660
		    {
Packit 352660
			FcValue vv = FcValueCanonicalize (&ll->value);
Packit 352660
Packit 352660
			if (vv.type == FcTypeLangSet)
Packit 352660
			{
Packit 352660
			    FcLangSet *ls = FcLangSetCreate ();
Packit 352660
			    FcBool b;
Packit 352660
Packit 352660
			    FcLangSetAdd (ls, lang);
Packit 352660
			    b = FcLangSetContains (vv.u.l, ls);
Packit 352660
			    FcLangSetDestroy (ls);
Packit 352660
			    if (b)
Packit 352660
				goto bail_lang;
Packit 352660
			    if (FcLangSetContains (vv.u.l, lsund))
Packit 352660
				goto bail_lang;
Packit 352660
			}
Packit 352660
			else
Packit 352660
			{
Packit 352660
			    if (FcStrCmpIgnoreCase (vv.u.s, lang) == 0)
Packit 352660
				goto bail_lang;
Packit 352660
			    if (FcStrCmpIgnoreCase (vv.u.s, (const FcChar8 *)"und") == 0)
Packit 352660
				goto bail_lang;
Packit 352660
			}
Packit 352660
		    }
Packit 352660
		}
Packit 352660
		v.type = FcTypeString;
Packit 352660
		v.u.s = lang;
Packit 352660
Packit 352660
		FcPatternObjectAddWithBinding (p, FC_LANG_OBJECT, v, FcValueBindingWeak, FcTrue);
Packit 352660
	    }
Packit 352660
	bail_lang:
Packit 352660
	    FcStrListDone (l);
Packit 352660
	    FcLangSetDestroy (lsund);
Packit 352660
	}
Packit 352660
	if (FcPatternObjectGet (p, FC_PRGNAME_OBJECT, 0, &v) == FcResultNoMatch)
Packit 352660
	{
Packit 352660
	    FcChar8 *prgname = FcGetPrgname ();
Packit 352660
	    if (prgname)
Packit 352660
		FcPatternObjectAddString (p, FC_PRGNAME_OBJECT, prgname);
Packit 352660
	}
Packit 352660
    }
Packit 352660
Packit 352660
    nobjs = FC_MAX_BASE_OBJECT + config->maxObjects + 2;
Packit 352660
    value = (FcValueList **) malloc (SIZEOF_VOID_P * nobjs);
Packit 352660
    if (!value)
Packit 352660
    {
Packit 352660
	retval = FcFalse;
Packit 352660
	goto bail1;
Packit 352660
    }
Packit 352660
    elt = (FcPatternElt **) malloc (SIZEOF_VOID_P * nobjs);
Packit 352660
    if (!elt)
Packit 352660
    {
Packit 352660
	retval = FcFalse;
Packit 352660
	goto bail1;
Packit 352660
    }
Packit 352660
    tst = (FcTest **) malloc (SIZEOF_VOID_P * nobjs);
Packit 352660
    if (!tst)
Packit 352660
    {
Packit 352660
	retval = FcFalse;
Packit 352660
	goto bail1;
Packit 352660
    }
Packit 352660
Packit 352660
    if (FcDebug () & FC_DBG_EDIT)
Packit 352660
    {
Packit 352660
	printf ("FcConfigSubstitute ");
Packit 352660
	FcPatternPrint (p);
Packit 352660
    }
Packit 352660
    FcPtrListIterInit (s, &iter);
Packit 352660
    for (; FcPtrListIterIsValid (s, &iter); FcPtrListIterNext (s, &iter))
Packit 352660
    {
Packit 352660
	rs = (FcRuleSet *) FcPtrListIterGetValue (s, &iter);
Packit 352660
	if (FcDebug () & FC_DBG_EDIT)
Packit 352660
	{
Packit 352660
	    printf ("\nRule Set: %s\n", rs->name);
Packit 352660
	}
Packit 352660
	FcPtrListIterInit (rs->subst[kind], &iter2);
Packit 352660
	for (; FcPtrListIterIsValid (rs->subst[kind], &iter2); FcPtrListIterNext (rs->subst[kind], &iter2))
Packit 352660
	{
Packit 352660
	    r = (FcRule *) FcPtrListIterGetValue (rs->subst[kind], &iter2);
Packit 352660
	    for (i = 0; i < nobjs; i++)
Packit 352660
	    {
Packit 352660
		elt[i] = NULL;
Packit 352660
		value[i] = NULL;
Packit 352660
		tst[i] = NULL;
Packit 352660
	    }
Packit 352660
	    for (; r; r = r->next)
Packit 352660
	    {
Packit 352660
		switch (r->type) {
Packit 352660
		case FcRuleUnknown:
Packit 352660
		    /* shouldn't be reached */
Packit 352660
		    break;
Packit 352660
		case FcRuleTest:
Packit 352660
		    object = FC_OBJ_ID (r->u.test->object);
Packit 352660
		    /*
Packit 352660
		     * Check the tests to see if
Packit 352660
		     * they all match the pattern
Packit 352660
		     */
Packit 352660
		    if (FcDebug () & FC_DBG_EDIT)
Packit 352660
		    {
Packit 352660
			printf ("FcConfigSubstitute test ");
Packit 352660
			FcTestPrint (r->u.test);
Packit 352660
		    }
Packit 352660
		    if (kind == FcMatchFont && r->u.test->kind == FcMatchPattern)
Packit 352660
			m = p_pat;
Packit 352660
		    else
Packit 352660
			m = p;
Packit 352660
		    if (m)
Packit 352660
			e = FcPatternObjectFindElt (m, r->u.test->object);
Packit 352660
		    else
Packit 352660
			e = NULL;
Packit 352660
		    /* different 'kind' won't be the target of edit */
Packit 352660
		    if (!elt[object] && kind == r->u.test->kind)
Packit 352660
		    {
Packit 352660
			elt[object] = e;
Packit 352660
			tst[object] = r->u.test;
Packit 352660
		    }
Packit 352660
		    /*
Packit 352660
		     * If there's no such field in the font,
Packit 352660
		     * then FcQualAll matches while FcQualAny does not
Packit 352660
		     */
Packit 352660
		    if (!e)
Packit 352660
		    {
Packit 352660
			if (r->u.test->qual == FcQualAll)
Packit 352660
			{
Packit 352660
			    value[object] = NULL;
Packit 352660
			    continue;
Packit 352660
			}
Packit 352660
			else
Packit 352660
			{
Packit 352660
			    if (FcDebug () & FC_DBG_EDIT)
Packit 352660
				printf ("No match\n");
Packit 352660
			    goto bail;
Packit 352660
			}
Packit 352660
		    }
Packit 352660
		    /*
Packit 352660
		     * Check to see if there is a match, mark the location
Packit 352660
		     * to apply match-relative edits
Packit 352660
		     */
Packit 352660
		    vl = FcConfigMatchValueList (m, p_pat, kind, r->u.test, e->values);
Packit 352660
		    /* different 'kind' won't be the target of edit */
Packit 352660
		    if (!value[object] && kind == r->u.test->kind)
Packit 352660
			value[object] = vl;
Packit 352660
		    if (!vl ||
Packit 352660
			(r->u.test->qual == FcQualFirst && vl != e->values) ||
Packit 352660
			(r->u.test->qual == FcQualNotFirst && vl == e->values))
Packit 352660
		    {
Packit 352660
			if (FcDebug () & FC_DBG_EDIT)
Packit 352660
			    printf ("No match\n");
Packit 352660
			goto bail;
Packit 352660
		    }
Packit 352660
		    break;
Packit 352660
		case FcRuleEdit:
Packit 352660
		    object = FC_OBJ_ID (r->u.edit->object);
Packit 352660
		    if (FcDebug () & FC_DBG_EDIT)
Packit 352660
		    {
Packit 352660
			printf ("Substitute ");
Packit 352660
			FcEditPrint (r->u.edit);
Packit 352660
			printf ("\n\n");
Packit 352660
		    }
Packit 352660
		    /*
Packit 352660
		     * Evaluate the list of expressions
Packit 352660
		     */
Packit 352660
		    l = FcConfigValues (p, p_pat,kind,  r->u.edit->expr, r->u.edit->binding);
Packit 352660
		    if (tst[object] && (tst[object]->kind == FcMatchFont || kind == FcMatchPattern))
Packit 352660
			elt[object] = FcPatternObjectFindElt (p, tst[object]->object);
Packit 352660
Packit 352660
		    switch (FC_OP_GET_OP (r->u.edit->op)) {
Packit 352660
		    case FcOpAssign:
Packit 352660
			/*
Packit 352660
			 * If there was a test, then replace the matched
Packit 352660
			 * value with the new list of values
Packit 352660
			 */
Packit 352660
			if (value[object])
Packit 352660
			{
Packit 352660
			    FcValueList	*thisValue = value[object];
Packit 352660
			    FcValueList	*nextValue = l;
Packit 352660
Packit 352660
			    /*
Packit 352660
			     * Append the new list of values after the current value
Packit 352660
			     */
Packit 352660
			    FcConfigAdd (&elt[object]->values, thisValue, FcTrue, l, r->u.edit->object);
Packit 352660
			    /*
Packit 352660
			     * Delete the marked value
Packit 352660
			     */
Packit 352660
			    if (thisValue)
Packit 352660
				FcConfigDel (&elt[object]->values, thisValue);
Packit 352660
			    /*
Packit 352660
			     * Adjust a pointer into the value list to ensure
Packit 352660
			     * future edits occur at the same place
Packit 352660
			     */
Packit 352660
			    value[object] = nextValue;
Packit 352660
			    break;
Packit 352660
			}
Packit 352660
			/* fall through ... */
Packit 352660
		    case FcOpAssignReplace:
Packit 352660
			/*
Packit 352660
			 * Delete all of the values and insert
Packit 352660
			 * the new set
Packit 352660
			 */
Packit 352660
			FcConfigPatternDel (p, r->u.edit->object);
Packit 352660
			FcConfigPatternAdd (p, r->u.edit->object, l, FcTrue);
Packit 352660
			/*
Packit 352660
			 * Adjust a pointer into the value list as they no
Packit 352660
			 * longer point to anything valid
Packit 352660
			 */
Packit 352660
			value[object] = NULL;
Packit 352660
			break;
Packit 352660
		    case FcOpPrepend:
Packit 352660
			if (value[object])
Packit 352660
			{
Packit 352660
			    FcConfigAdd (&elt[object]->values, value[object], FcFalse, l, r->u.edit->object);
Packit 352660
			    break;
Packit 352660
			}
Packit 352660
			/* fall through ... */
Packit 352660
		    case FcOpPrependFirst:
Packit 352660
			FcConfigPatternAdd (p, r->u.edit->object, l, FcFalse);
Packit 352660
			break;
Packit 352660
		    case FcOpAppend:
Packit 352660
			if (value[object])
Packit 352660
			{
Packit 352660
			    FcConfigAdd (&elt[object]->values, value[object], FcTrue, l, r->u.edit->object);
Packit 352660
			    break;
Packit 352660
			}
Packit 352660
			/* fall through ... */
Packit 352660
		    case FcOpAppendLast:
Packit 352660
			FcConfigPatternAdd (p, r->u.edit->object, l, FcTrue);
Packit 352660
			break;
Packit 352660
		    case FcOpDelete:
Packit 352660
			if (value[object])
Packit 352660
			{
Packit 352660
			    FcConfigDel (&elt[object]->values, value[object]);
Packit 352660
			    FcValueListDestroy (l);
Packit 352660
			    break;
Packit 352660
			}
Packit 352660
			/* fall through ... */
Packit 352660
		    case FcOpDeleteAll:
Packit 352660
			FcConfigPatternDel (p, r->u.edit->object);
Packit 352660
			FcValueListDestroy (l);
Packit 352660
			break;
Packit 352660
		    default:
Packit 352660
			FcValueListDestroy (l);
Packit 352660
			break;
Packit 352660
		    }
Packit 352660
		    /*
Packit 352660
		     * Now go through the pattern and eliminate
Packit 352660
		     * any properties without data
Packit 352660
		     */
Packit 352660
		    FcConfigPatternCanon (p, r->u.edit->object);
Packit 352660
Packit 352660
		    if (FcDebug () & FC_DBG_EDIT)
Packit 352660
		    {
Packit 352660
			printf ("FcConfigSubstitute edit");
Packit 352660
			FcPatternPrint (p);
Packit 352660
		    }
Packit 352660
		    break;
Packit 352660
		}
Packit 352660
	    }
Packit 352660
	bail:;
Packit 352660
	}
Packit 352660
    }
Packit 352660
    if (FcDebug () & FC_DBG_EDIT)
Packit 352660
    {
Packit 352660
	printf ("FcConfigSubstitute done");
Packit 352660
	FcPatternPrint (p);
Packit 352660
    }
Packit 352660
bail1:
Packit 352660
    if (elt)
Packit 352660
	free (elt);
Packit 352660
    if (value)
Packit 352660
	free (value);
Packit 352660
    if (tst)
Packit 352660
	free (tst);
Packit 352660
Packit 352660
    return retval;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcConfigSubstitute (FcConfig	*config,
Packit 352660
		    FcPattern	*p,
Packit 352660
		    FcMatchKind	kind)
Packit 352660
{
Packit 352660
    return FcConfigSubstituteWithPat (config, p, 0, kind);
Packit 352660
}
Packit 352660
Packit 352660
#if defined (_WIN32)
Packit 352660
Packit 352660
static FcChar8 fontconfig_path[1000] = ""; /* MT-dontcare */
Packit 352660
FcChar8 fontconfig_instprefix[1000] = ""; /* MT-dontcare */
Packit 352660
Packit 352660
#  if (defined (PIC) || defined (DLL_EXPORT))
Packit 352660
Packit 352660
BOOL WINAPI
Packit 352660
DllMain (HINSTANCE hinstDLL,
Packit 352660
	 DWORD     fdwReason,
Packit 352660
	 LPVOID    lpvReserved);
Packit 352660
Packit 352660
BOOL WINAPI
Packit 352660
DllMain (HINSTANCE hinstDLL,
Packit 352660
	 DWORD     fdwReason,
Packit 352660
	 LPVOID    lpvReserved)
Packit 352660
{
Packit 352660
  FcChar8 *p;
Packit 352660
Packit 352660
  switch (fdwReason) {
Packit 352660
  case DLL_PROCESS_ATTACH:
Packit 352660
      if (!GetModuleFileName ((HMODULE) hinstDLL, (LPCH) fontconfig_path,
Packit 352660
			      sizeof (fontconfig_path)))
Packit 352660
	  break;
Packit 352660
Packit 352660
      /* If the fontconfig DLL is in a "bin" or "lib" subfolder,
Packit 352660
       * assume it's a Unix-style installation tree, and use
Packit 352660
       * "etc/fonts" in there as FONTCONFIG_PATH. Otherwise use the
Packit 352660
       * folder where the DLL is as FONTCONFIG_PATH.
Packit 352660
       */
Packit 352660
      p = (FcChar8 *) strrchr ((const char *) fontconfig_path, '\\');
Packit 352660
      if (p)
Packit 352660
      {
Packit 352660
	  *p = '\0';
Packit 352660
	  p = (FcChar8 *) strrchr ((const char *) fontconfig_path, '\\');
Packit 352660
	  if (p && (FcStrCmpIgnoreCase (p + 1, (const FcChar8 *) "bin") == 0 ||
Packit 352660
		    FcStrCmpIgnoreCase (p + 1, (const FcChar8 *) "lib") == 0))
Packit 352660
	      *p = '\0';
Packit 352660
	  strcat ((char *) fontconfig_instprefix, (char *) fontconfig_path);
Packit 352660
	  strcat ((char *) fontconfig_path, "\\etc\\fonts");
Packit 352660
      }
Packit 352660
      else
Packit 352660
          fontconfig_path[0] = '\0';
Packit 352660
Packit 352660
      break;
Packit 352660
  }
Packit 352660
Packit 352660
  return TRUE;
Packit 352660
}
Packit 352660
Packit 352660
#  endif /* !PIC */
Packit 352660
Packit 352660
#undef FONTCONFIG_PATH
Packit 352660
#define FONTCONFIG_PATH fontconfig_path
Packit 352660
Packit 352660
#endif /* !_WIN32 */
Packit 352660
Packit 352660
#ifndef FONTCONFIG_FILE
Packit 352660
#define FONTCONFIG_FILE	"fonts.conf"
Packit 352660
#endif
Packit 352660
Packit 352660
static FcChar8 *
Packit 352660
FcConfigFileExists (const FcChar8 *dir, const FcChar8 *file)
Packit 352660
{
Packit 352660
    FcChar8    *path;
Packit 352660
    int         size, osize;
Packit 352660
Packit 352660
    if (!dir)
Packit 352660
	dir = (FcChar8 *) "";
Packit 352660
Packit 352660
    osize = strlen ((char *) dir) + 1 + strlen ((char *) file) + 1;
Packit 352660
    /*
Packit 352660
     * workaround valgrind warning because glibc takes advantage of how it knows memory is
Packit 352660
     * allocated to implement strlen by reading in groups of 4
Packit 352660
     */
Packit 352660
    size = (osize + 3) & ~3;
Packit 352660
Packit 352660
    path = malloc (size);
Packit 352660
    if (!path)
Packit 352660
	return 0;
Packit 352660
Packit 352660
    strcpy ((char *) path, (const char *) dir);
Packit 352660
    /* make sure there's a single separator */
Packit 352660
#ifdef _WIN32
Packit 352660
    if ((!path[0] || (path[strlen((char *) path)-1] != '/' &&
Packit 352660
		      path[strlen((char *) path)-1] != '\\')) &&
Packit 352660
	!(file[0] == '/' ||
Packit 352660
	  file[0] == '\\' ||
Packit 352660
	  (isalpha (file[0]) && file[1] == ':' && (file[2] == '/' || file[2] == '\\'))))
Packit 352660
	strcat ((char *) path, "\\");
Packit 352660
#else
Packit 352660
    if ((!path[0] || path[strlen((char *) path)-1] != '/') && file[0] != '/')
Packit 352660
	strcat ((char *) path, "/");
Packit 352660
    else
Packit 352660
	osize--;
Packit 352660
#endif
Packit 352660
    strcat ((char *) path, (char *) file);
Packit 352660
Packit 352660
    if (access ((char *) path, R_OK) == 0)
Packit 352660
	return path;
Packit 352660
Packit 352660
    FcStrFree (path);
Packit 352660
Packit 352660
    return 0;
Packit 352660
}
Packit 352660
Packit 352660
static FcChar8 **
Packit 352660
FcConfigGetPath (void)
Packit 352660
{
Packit 352660
    FcChar8    **path;
Packit 352660
    FcChar8    *env, *e, *colon;
Packit 352660
    FcChar8    *dir;
Packit 352660
    int	    npath;
Packit 352660
    int	    i;
Packit 352660
Packit 352660
    npath = 2;	/* default dir + null */
Packit 352660
    env = (FcChar8 *) getenv ("FONTCONFIG_PATH");
Packit 352660
    if (env)
Packit 352660
    {
Packit 352660
	e = env;
Packit 352660
	npath++;
Packit 352660
	while (*e)
Packit 352660
	    if (*e++ == FC_SEARCH_PATH_SEPARATOR)
Packit 352660
		npath++;
Packit 352660
    }
Packit 352660
    path = calloc (npath, sizeof (FcChar8 *));
Packit 352660
    if (!path)
Packit 352660
	goto bail0;
Packit 352660
    i = 0;
Packit 352660
Packit 352660
    if (env)
Packit 352660
    {
Packit 352660
	e = env;
Packit 352660
	while (*e)
Packit 352660
	{
Packit 352660
	    colon = (FcChar8 *) strchr ((char *) e, FC_SEARCH_PATH_SEPARATOR);
Packit 352660
	    if (!colon)
Packit 352660
		colon = e + strlen ((char *) e);
Packit 352660
	    path[i] = malloc (colon - e + 1);
Packit 352660
	    if (!path[i])
Packit 352660
		goto bail1;
Packit 352660
	    strncpy ((char *) path[i], (const char *) e, colon - e);
Packit 352660
	    path[i][colon - e] = '\0';
Packit 352660
	    if (*colon)
Packit 352660
		e = colon + 1;
Packit 352660
	    else
Packit 352660
		e = colon;
Packit 352660
	    i++;
Packit 352660
	}
Packit 352660
    }
Packit 352660
Packit 352660
#ifdef _WIN32
Packit 352660
	if (fontconfig_path[0] == '\0')
Packit 352660
	{
Packit 352660
		char *p;
Packit 352660
		if(!GetModuleFileName(NULL, (LPCH) fontconfig_path, sizeof(fontconfig_path)))
Packit 352660
			goto bail1;
Packit 352660
		p = strrchr ((const char *) fontconfig_path, '\\');
Packit 352660
		if (p) *p = '\0';
Packit 352660
		strcat ((char *) fontconfig_path, "\\fonts");
Packit 352660
	}
Packit 352660
#endif
Packit 352660
    dir = (FcChar8 *) FONTCONFIG_PATH;
Packit 352660
    path[i] = malloc (strlen ((char *) dir) + 1);
Packit 352660
    if (!path[i])
Packit 352660
	goto bail1;
Packit 352660
    strcpy ((char *) path[i], (const char *) dir);
Packit 352660
    return path;
Packit 352660
Packit 352660
bail1:
Packit 352660
    for (i = 0; path[i]; i++)
Packit 352660
	free (path[i]);
Packit 352660
    free (path);
Packit 352660
bail0:
Packit 352660
    return 0;
Packit 352660
}
Packit 352660
Packit 352660
static void
Packit 352660
FcConfigFreePath (FcChar8 **path)
Packit 352660
{
Packit 352660
    FcChar8    **p;
Packit 352660
Packit 352660
    for (p = path; *p; p++)
Packit 352660
	free (*p);
Packit 352660
    free (path);
Packit 352660
}
Packit 352660
Packit 352660
static FcBool	_FcConfigHomeEnabled = FcTrue; /* MT-goodenough */
Packit 352660
Packit 352660
FcChar8 *
Packit 352660
FcConfigHome (void)
Packit 352660
{
Packit 352660
    if (_FcConfigHomeEnabled)
Packit 352660
    {
Packit 352660
        char *home = getenv ("HOME");
Packit 352660
Packit 352660
#ifdef _WIN32
Packit 352660
	if (home == NULL)
Packit 352660
	    home = getenv ("USERPROFILE");
Packit 352660
#endif
Packit 352660
Packit 352660
	return (FcChar8 *) home;
Packit 352660
    }
Packit 352660
    return 0;
Packit 352660
}
Packit 352660
Packit 352660
FcChar8 *
Packit 352660
FcConfigXdgCacheHome (void)
Packit 352660
{
Packit 352660
    const char *env = getenv ("XDG_CACHE_HOME");
Packit 352660
    FcChar8 *ret = NULL;
Packit 352660
Packit 352660
    if (!_FcConfigHomeEnabled)
Packit 352660
	return NULL;
Packit 352660
    if (env)
Packit 352660
	ret = FcStrCopy ((const FcChar8 *)env);
Packit 352660
    else
Packit 352660
    {
Packit 352660
	const FcChar8 *home = FcConfigHome ();
Packit 352660
	size_t len = home ? strlen ((const char *)home) : 0;
Packit 352660
Packit 352660
	ret = malloc (len + 7 + 1);
Packit 352660
	if (ret)
Packit 352660
	{
Packit 352660
	    if (home)
Packit 352660
		memcpy (ret, home, len);
Packit 352660
	    memcpy (&ret[len], FC_DIR_SEPARATOR_S ".cache", 7);
Packit 352660
	    ret[len + 7] = 0;
Packit 352660
	}
Packit 352660
    }
Packit 352660
Packit 352660
    return ret;
Packit 352660
}
Packit 352660
Packit 352660
FcChar8 *
Packit 352660
FcConfigXdgConfigHome (void)
Packit 352660
{
Packit 352660
    const char *env = getenv ("XDG_CONFIG_HOME");
Packit 352660
    FcChar8 *ret = NULL;
Packit 352660
Packit 352660
    if (!_FcConfigHomeEnabled)
Packit 352660
	return NULL;
Packit 352660
    if (env)
Packit 352660
	ret = FcStrCopy ((const FcChar8 *)env);
Packit 352660
    else
Packit 352660
    {
Packit 352660
	const FcChar8 *home = FcConfigHome ();
Packit 352660
	size_t len = home ? strlen ((const char *)home) : 0;
Packit 352660
Packit 352660
	ret = malloc (len + 8 + 1);
Packit 352660
	if (ret)
Packit 352660
	{
Packit 352660
	    if (home)
Packit 352660
		memcpy (ret, home, len);
Packit 352660
	    memcpy (&ret[len], FC_DIR_SEPARATOR_S ".config", 8);
Packit 352660
	    ret[len + 8] = 0;
Packit 352660
	}
Packit 352660
    }
Packit 352660
Packit 352660
    return ret;
Packit 352660
}
Packit 352660
Packit 352660
FcChar8 *
Packit 352660
FcConfigXdgDataHome (void)
Packit 352660
{
Packit 352660
    const char *env = getenv ("XDG_DATA_HOME");
Packit 352660
    FcChar8 *ret = NULL;
Packit 352660
Packit 352660
    if (!_FcConfigHomeEnabled)
Packit 352660
	return NULL;
Packit 352660
    if (env)
Packit 352660
	ret = FcStrCopy ((const FcChar8 *)env);
Packit 352660
    else
Packit 352660
    {
Packit 352660
	const FcChar8 *home = FcConfigHome ();
Packit 352660
	size_t len = home ? strlen ((const char *)home) : 0;
Packit 352660
Packit 352660
	ret = malloc (len + 13 + 1);
Packit 352660
	if (ret)
Packit 352660
	{
Packit 352660
	    if (home)
Packit 352660
		memcpy (ret, home, len);
Packit 352660
	    memcpy (&ret[len], FC_DIR_SEPARATOR_S ".local" FC_DIR_SEPARATOR_S "share", 13);
Packit 352660
	    ret[len + 13] = 0;
Packit 352660
	}
Packit 352660
    }
Packit 352660
Packit 352660
    return ret;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcConfigEnableHome (FcBool enable)
Packit 352660
{
Packit 352660
    FcBool  prev = _FcConfigHomeEnabled;
Packit 352660
    _FcConfigHomeEnabled = enable;
Packit 352660
    return prev;
Packit 352660
}
Packit 352660
Packit 352660
FcChar8 *
Packit 352660
FcConfigFilename (const FcChar8 *url)
Packit 352660
{
Packit 352660
    FcChar8    *file, *dir, **path, **p;
Packit 352660
Packit 352660
    if (!url || !*url)
Packit 352660
    {
Packit 352660
	url = (FcChar8 *) getenv ("FONTCONFIG_FILE");
Packit 352660
	if (!url)
Packit 352660
	    url = (FcChar8 *) FONTCONFIG_FILE;
Packit 352660
    }
Packit 352660
    file = 0;
Packit 352660
Packit 352660
    if (FcStrIsAbsoluteFilename(url))
Packit 352660
	return FcConfigFileExists (0, url);
Packit 352660
Packit 352660
    if (*url == '~')
Packit 352660
    {
Packit 352660
	dir = FcConfigHome ();
Packit 352660
	if (dir)
Packit 352660
	    file = FcConfigFileExists (dir, url + 1);
Packit 352660
	else
Packit 352660
	    file = 0;
Packit 352660
    }
Packit 352660
Packit 352660
    path = FcConfigGetPath ();
Packit 352660
    if (!path)
Packit 352660
	return NULL;
Packit 352660
    for (p = path; *p; p++)
Packit 352660
    {
Packit 352660
	file = FcConfigFileExists (*p, url);
Packit 352660
	if (file)
Packit 352660
	    break;
Packit 352660
    }
Packit 352660
    FcConfigFreePath (path);
Packit 352660
    return file;
Packit 352660
}
Packit 352660
Packit 352660
FcChar8 *
Packit 352660
FcConfigRealFilename (FcConfig		*config,
Packit 352660
		      const FcChar8	*url)
Packit 352660
{
Packit 352660
    const FcChar8 *sysroot = FcConfigGetSysRoot (config);
Packit 352660
    FcChar8 *n = FcConfigFilename (url);
Packit 352660
    FcChar8 *nn = NULL;
Packit 352660
Packit 352660
    if (n)
Packit 352660
    {
Packit 352660
	FcChar8 buf[PATH_MAX];
Packit 352660
	ssize_t len;
Packit 352660
Packit 352660
	if (sysroot)
Packit 352660
	    nn = FcStrBuildFilename (sysroot, n, NULL);
Packit 352660
	else
Packit 352660
	    nn = FcStrdup (n);
Packit 352660
	FcStrFree (n);
Packit 352660
Packit 352660
	if ((len = FcReadLink (nn, buf, sizeof (buf) - 1)) != -1)
Packit 352660
	{
Packit 352660
	    buf[len] = 0;
Packit 352660
Packit 352660
	    if (!FcStrIsAbsoluteFilename (buf))
Packit 352660
	    {
Packit 352660
		FcChar8 *dirname = FcStrDirname (nn);
Packit 352660
		FcStrFree (nn);
Packit 352660
		if (!dirname)
Packit 352660
		    return NULL;
Packit 352660
Packit 352660
		FcChar8 *path = FcStrBuildFilename (dirname, buf, NULL);
Packit 352660
		FcStrFree (dirname);
Packit 352660
		if (!path)
Packit 352660
		    return NULL;
Packit 352660
Packit 352660
		nn = FcStrCanonFilename (path);
Packit 352660
		FcStrFree (path);
Packit 352660
	    }
Packit 352660
	    else
Packit 352660
	    {
Packit 352660
		FcStrFree (nn);
Packit 352660
		nn = FcStrdup (buf);
Packit 352660
	    }
Packit 352660
	}
Packit 352660
    }
Packit 352660
Packit 352660
    return nn;
Packit 352660
}
Packit 352660
Packit 352660
/*
Packit 352660
 * Manage the application-specific fonts
Packit 352660
 */
Packit 352660
Packit 352660
FcBool
Packit 352660
FcConfigAppFontAddFile (FcConfig    *config,
Packit 352660
			const FcChar8  *file)
Packit 352660
{
Packit 352660
    FcFontSet	*set;
Packit 352660
    FcStrSet	*subdirs;
Packit 352660
    FcStrList	*sublist;
Packit 352660
    FcChar8	*subdir;
Packit 352660
Packit 352660
    if (!config)
Packit 352660
    {
Packit 352660
	config = FcConfigGetCurrent ();
Packit 352660
	if (!config)
Packit 352660
	    return FcFalse;
Packit 352660
    }
Packit 352660
Packit 352660
    subdirs = FcStrSetCreateEx (FCSS_GROW_BY_64);
Packit 352660
    if (!subdirs)
Packit 352660
	return FcFalse;
Packit 352660
Packit 352660
    set = FcConfigGetFonts (config, FcSetApplication);
Packit 352660
    if (!set)
Packit 352660
    {
Packit 352660
	set = FcFontSetCreate ();
Packit 352660
	if (!set)
Packit 352660
	{
Packit 352660
	    FcStrSetDestroy (subdirs);
Packit 352660
	    return FcFalse;
Packit 352660
	}
Packit 352660
	FcConfigSetFonts (config, set, FcSetApplication);
Packit 352660
    }
Packit 352660
	
Packit 352660
    if (!FcFileScanConfig (set, subdirs, file, config))
Packit 352660
    {
Packit 352660
	FcStrSetDestroy (subdirs);
Packit 352660
	return FcFalse;
Packit 352660
    }
Packit 352660
    if ((sublist = FcStrListCreate (subdirs)))
Packit 352660
    {
Packit 352660
	while ((subdir = FcStrListNext (sublist)))
Packit 352660
	{
Packit 352660
	    FcConfigAppFontAddDir (config, subdir);
Packit 352660
	}
Packit 352660
	FcStrListDone (sublist);
Packit 352660
    }
Packit 352660
    FcStrSetDestroy (subdirs);
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcConfigAppFontAddDir (FcConfig	    *config,
Packit 352660
		       const FcChar8   *dir)
Packit 352660
{
Packit 352660
    FcFontSet	*set;
Packit 352660
    FcStrSet	*dirs;
Packit 352660
Packit 352660
    if (!config)
Packit 352660
    {
Packit 352660
	config = FcConfigGetCurrent ();
Packit 352660
	if (!config)
Packit 352660
	    return FcFalse;
Packit 352660
    }
Packit 352660
Packit 352660
    dirs = FcStrSetCreateEx (FCSS_GROW_BY_64);
Packit 352660
    if (!dirs)
Packit 352660
	return FcFalse;
Packit 352660
Packit 352660
    set = FcConfigGetFonts (config, FcSetApplication);
Packit 352660
    if (!set)
Packit 352660
    {
Packit 352660
	set = FcFontSetCreate ();
Packit 352660
	if (!set)
Packit 352660
	{
Packit 352660
	    FcStrSetDestroy (dirs);
Packit 352660
	    return FcFalse;
Packit 352660
	}
Packit 352660
	FcConfigSetFonts (config, set, FcSetApplication);
Packit 352660
    }
Packit 352660
Packit 352660
    FcStrSetAddFilename (dirs, dir);
Packit 352660
Packit 352660
    if (!FcConfigAddDirList (config, FcSetApplication, dirs))
Packit 352660
    {
Packit 352660
	FcStrSetDestroy (dirs);
Packit 352660
	return FcFalse;
Packit 352660
    }
Packit 352660
    FcStrSetDestroy (dirs);
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
void
Packit 352660
FcConfigAppFontClear (FcConfig	    *config)
Packit 352660
{
Packit 352660
    if (!config)
Packit 352660
    {
Packit 352660
	config = FcConfigGetCurrent ();
Packit 352660
	if (!config)
Packit 352660
	    return;
Packit 352660
    }
Packit 352660
Packit 352660
    FcConfigSetFonts (config, 0, FcSetApplication);
Packit 352660
}
Packit 352660
Packit 352660
/*
Packit 352660
 * Manage filename-based font source selectors
Packit 352660
 */
Packit 352660
Packit 352660
FcBool
Packit 352660
FcConfigGlobAdd (FcConfig	*config,
Packit 352660
		 const FcChar8  *glob,
Packit 352660
		 FcBool		accept)
Packit 352660
{
Packit 352660
    FcStrSet	*set = accept ? config->acceptGlobs : config->rejectGlobs;
Packit 352660
Packit 352660
    return FcStrSetAdd (set, glob);
Packit 352660
}
Packit 352660
Packit 352660
static FcBool
Packit 352660
FcConfigGlobsMatch (const FcStrSet	*globs,
Packit 352660
		    const FcChar8	*string)
Packit 352660
{
Packit 352660
    int	i;
Packit 352660
Packit 352660
    for (i = 0; i < globs->num; i++)
Packit 352660
	if (FcStrGlobMatch (globs->strs[i], string))
Packit 352660
	    return FcTrue;
Packit 352660
    return FcFalse;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcConfigAcceptFilename (FcConfig	*config,
Packit 352660
			const FcChar8	*filename)
Packit 352660
{
Packit 352660
    if (FcConfigGlobsMatch (config->acceptGlobs, filename))
Packit 352660
	return FcTrue;
Packit 352660
    if (FcConfigGlobsMatch (config->rejectGlobs, filename))
Packit 352660
	return FcFalse;
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
/*
Packit 352660
 * Manage font-pattern based font source selectors
Packit 352660
 */
Packit 352660
Packit 352660
FcBool
Packit 352660
FcConfigPatternsAdd (FcConfig	*config,
Packit 352660
		     FcPattern	*pattern,
Packit 352660
		     FcBool	accept)
Packit 352660
{
Packit 352660
    FcFontSet	*set = accept ? config->acceptPatterns : config->rejectPatterns;
Packit 352660
Packit 352660
    return FcFontSetAdd (set, pattern);
Packit 352660
}
Packit 352660
Packit 352660
static FcBool
Packit 352660
FcConfigPatternsMatch (const FcFontSet	*patterns,
Packit 352660
		       const FcPattern	*font)
Packit 352660
{
Packit 352660
    int i;
Packit 352660
Packit 352660
    for (i = 0; i < patterns->nfont; i++)
Packit 352660
	if (FcListPatternMatchAny (patterns->fonts[i], font))
Packit 352660
	    return FcTrue;
Packit 352660
    return FcFalse;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcConfigAcceptFont (FcConfig	    *config,
Packit 352660
		    const FcPattern *font)
Packit 352660
{
Packit 352660
    if (FcConfigPatternsMatch (config->acceptPatterns, font))
Packit 352660
	return FcTrue;
Packit 352660
    if (FcConfigPatternsMatch (config->rejectPatterns, font))
Packit 352660
	return FcFalse;
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
const FcChar8 *
Packit 352660
FcConfigGetSysRoot (const FcConfig *config)
Packit 352660
{
Packit 352660
    if (!config)
Packit 352660
    {
Packit 352660
	config = FcConfigGetCurrent ();
Packit 352660
	if (!config)
Packit 352660
	    return NULL;
Packit 352660
    }
Packit 352660
Packit 352660
    if (config->sysRoot)
Packit 352660
        return config->sysRoot;
Packit 352660
Packit 352660
    return (FcChar8 *) getenv ("FONTCONFIG_SYSROOT");
Packit 352660
}
Packit 352660
Packit 352660
void
Packit 352660
FcConfigSetSysRoot (FcConfig      *config,
Packit 352660
		    const FcChar8 *sysroot)
Packit 352660
{
Packit 352660
    FcChar8 *s = NULL;
Packit 352660
    FcBool init = FcFalse;
Packit 352660
Packit 352660
    if (!config)
Packit 352660
    {
Packit 352660
	/* We can't use FcConfigGetCurrent() here to ensure
Packit 352660
	 * the sysroot is set prior to initialize FcConfig,
Packit 352660
	 * to avoid loading caches from non-sysroot dirs.
Packit 352660
	 * So postpone the initialization later.
Packit 352660
	 */
Packit 352660
	config = fc_atomic_ptr_get (&_fcConfig);
Packit 352660
	if (!config)
Packit 352660
	{
Packit 352660
	    config = FcConfigCreate ();
Packit 352660
	    if (!config)
Packit 352660
		return;
Packit 352660
	    init = FcTrue;
Packit 352660
	}
Packit 352660
    }
Packit 352660
Packit 352660
    if (sysroot)
Packit 352660
    {
Packit 352660
	s = FcStrCopyFilename (sysroot);
Packit 352660
	if (!s)
Packit 352660
	    return;
Packit 352660
    }
Packit 352660
Packit 352660
    if (config->sysRoot)
Packit 352660
	FcStrFree (config->sysRoot);
Packit 352660
Packit 352660
    config->sysRoot = s;
Packit 352660
    if (init)
Packit 352660
    {
Packit 352660
	config = FcInitLoadOwnConfigAndFonts (config);
Packit 352660
	FcConfigSetCurrent (config);
Packit 352660
	/* FcConfigSetCurrent() increases the refcount.
Packit 352660
	 * decrease it here to avoid the memory leak.
Packit 352660
	 */
Packit 352660
	FcConfigDestroy (config);
Packit 352660
    }
Packit 352660
}
Packit 352660
Packit 352660
FcRuleSet *
Packit 352660
FcRuleSetCreate (const FcChar8 *name)
Packit 352660
{
Packit 352660
    FcRuleSet *ret = (FcRuleSet *) malloc (sizeof (FcRuleSet));
Packit 352660
    FcMatchKind k;
Packit 352660
    const FcChar8 *p;
Packit 352660
Packit 352660
    if (!name)
Packit 352660
	p = (const FcChar8 *)"";
Packit 352660
    else
Packit 352660
	p = name;
Packit 352660
Packit 352660
    if (ret)
Packit 352660
    {
Packit 352660
	ret->name = FcStrdup (p);
Packit 352660
	ret->description = NULL;
Packit 352660
	ret->domain = NULL;
Packit 352660
	for (k = FcMatchKindBegin; k < FcMatchKindEnd; k++)
Packit 352660
	    ret->subst[k] = FcPtrListCreate (FcDestroyAsRule);
Packit 352660
	FcRefInit (&ret->ref, 1);
Packit 352660
    }
Packit 352660
Packit 352660
    return ret;
Packit 352660
}
Packit 352660
Packit 352660
void
Packit 352660
FcRuleSetDestroy (FcRuleSet *rs)
Packit 352660
{
Packit 352660
    FcMatchKind k;
Packit 352660
Packit 352660
    if (!rs)
Packit 352660
	return;
Packit 352660
    if (FcRefDec (&rs->ref) != 1)
Packit 352660
	return;
Packit 352660
Packit 352660
    if (rs->name)
Packit 352660
	FcStrFree (rs->name);
Packit 352660
    if (rs->description)
Packit 352660
	FcStrFree (rs->description);
Packit 352660
    if (rs->domain)
Packit 352660
	FcStrFree (rs->domain);
Packit 352660
    for (k = FcMatchKindBegin; k < FcMatchKindEnd; k++)
Packit 352660
	FcPtrListDestroy (rs->subst[k]);
Packit 352660
Packit 352660
    free (rs);
Packit 352660
}
Packit 352660
Packit 352660
void
Packit 352660
FcRuleSetReference (FcRuleSet *rs)
Packit 352660
{
Packit 352660
    if (!FcRefIsConst (&rs->ref))
Packit 352660
	FcRefInc (&rs->ref);
Packit 352660
}
Packit 352660
Packit 352660
void
Packit 352660
FcRuleSetEnable (FcRuleSet	*rs,
Packit 352660
		 FcBool		flag)
Packit 352660
{
Packit 352660
    if (rs)
Packit 352660
    {
Packit 352660
	rs->enabled = flag;
Packit 352660
	/* XXX: we may want to provide a feature
Packit 352660
	 * to enable/disable rulesets through API
Packit 352660
	 * in the future?
Packit 352660
	 */
Packit 352660
    }
Packit 352660
}
Packit 352660
Packit 352660
void
Packit 352660
FcRuleSetAddDescription (FcRuleSet	*rs,
Packit 352660
			 const FcChar8	*domain,
Packit 352660
			 const FcChar8	*description)
Packit 352660
{
Packit 352660
    if (rs->domain)
Packit 352660
	FcStrFree (rs->domain);
Packit 352660
    if (rs->description)
Packit 352660
	FcStrFree (rs->description);
Packit 352660
Packit 352660
    rs->domain = domain ? FcStrdup (domain) : NULL;
Packit 352660
    rs->description = description ? FcStrdup (description) : NULL;
Packit 352660
}
Packit 352660
Packit 352660
int
Packit 352660
FcRuleSetAdd (FcRuleSet		*rs,
Packit 352660
	      FcRule		*rule,
Packit 352660
	      FcMatchKind	kind)
Packit 352660
{
Packit 352660
    FcPtrListIter iter;
Packit 352660
    FcRule *r;
Packit 352660
    int n = 0, ret;
Packit 352660
Packit 352660
    if (!rs ||
Packit 352660
       kind < FcMatchKindBegin || kind >= FcMatchKindEnd)
Packit 352660
	return -1;
Packit 352660
    FcPtrListIterInitAtLast (rs->subst[kind], &iter);
Packit 352660
    if (!FcPtrListIterAdd (rs->subst[kind], &iter, rule))
Packit 352660
	return -1;
Packit 352660
Packit 352660
    for (r = rule; r; r = r->next)
Packit 352660
    {
Packit 352660
	switch (r->type)
Packit 352660
	{
Packit 352660
	case FcRuleTest:
Packit 352660
	    if (r->u.test)
Packit 352660
	    {
Packit 352660
		if (r->u.test->kind == FcMatchDefault)
Packit 352660
		    r->u.test->kind = kind;
Packit 352660
		if (n < r->u.test->object)
Packit 352660
		    n = r->u.test->object;
Packit 352660
	    }
Packit 352660
	    break;
Packit 352660
	case FcRuleEdit:
Packit 352660
	    if (n < r->u.edit->object)
Packit 352660
		n = r->u.edit->object;
Packit 352660
	    break;
Packit 352660
	default:
Packit 352660
	    break;
Packit 352660
	}
Packit 352660
    }
Packit 352660
    if (FcDebug () & FC_DBG_EDIT)
Packit 352660
    {
Packit 352660
	printf ("Add Rule(kind:%d, name: %s) ", kind, rs->name);
Packit 352660
	FcRulePrint (rule);
Packit 352660
    }
Packit 352660
    ret = FC_OBJ_ID (n) - FC_MAX_BASE_OBJECT;
Packit 352660
Packit 352660
    return ret < 0 ? 0 : ret;
Packit 352660
}
Packit 352660
Packit 352660
void
Packit 352660
FcConfigFileInfoIterInit (FcConfig		*config,
Packit 352660
			  FcConfigFileInfoIter	*iter)
Packit 352660
{
Packit 352660
    FcConfig *c;
Packit 352660
    FcPtrListIter *i = (FcPtrListIter *)iter;
Packit 352660
Packit 352660
    if (!config)
Packit 352660
	c = FcConfigGetCurrent ();
Packit 352660
    else
Packit 352660
	c = config;
Packit 352660
    FcPtrListIterInit (c->rulesetList, i);
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcConfigFileInfoIterNext (FcConfig		*config,
Packit 352660
			  FcConfigFileInfoIter	*iter)
Packit 352660
{
Packit 352660
    FcConfig *c;
Packit 352660
    FcPtrListIter *i = (FcPtrListIter *)iter;
Packit 352660
Packit 352660
    if (!config)
Packit 352660
	c = FcConfigGetCurrent ();
Packit 352660
    else
Packit 352660
	c = config;
Packit 352660
    if (FcPtrListIterIsValid (c->rulesetList, i))
Packit 352660
    {
Packit 352660
	FcPtrListIterNext (c->rulesetList, i);
Packit 352660
    }
Packit 352660
    else
Packit 352660
	return FcFalse;
Packit 352660
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
FcBool
Packit 352660
FcConfigFileInfoIterGet (FcConfig		*config,
Packit 352660
			 FcConfigFileInfoIter	*iter,
Packit 352660
			 FcChar8		**name,
Packit 352660
			 FcChar8		**description,
Packit 352660
			 FcBool			*enabled)
Packit 352660
{
Packit 352660
    FcConfig *c;
Packit 352660
    FcRuleSet *r;
Packit 352660
    FcPtrListIter *i = (FcPtrListIter *)iter;
Packit 352660
Packit 352660
    if (!config)
Packit 352660
	c = FcConfigGetCurrent ();
Packit 352660
    else
Packit 352660
	c = config;
Packit 352660
    if (!FcPtrListIterIsValid (c->rulesetList, i))
Packit 352660
	return FcFalse;
Packit 352660
    r = FcPtrListIterGetValue (c->rulesetList, i);
Packit 352660
    if (name)
Packit 352660
	*name = FcStrdup (r->name && r->name[0] ? r->name : (const FcChar8 *) "fonts.conf");
Packit 352660
    if (description)
Packit 352660
	*description = FcStrdup (!r->description ? _("No description") :
Packit 352660
				 dgettext (r->domain ? (const char *) r->domain : GETTEXT_PACKAGE "-conf",
Packit 352660
					   (const char *) r->description));
Packit 352660
    if (enabled)
Packit 352660
	*enabled = r->enabled;
Packit 352660
Packit 352660
    return FcTrue;
Packit 352660
}
Packit 352660
Packit 352660
#define __fccfg__
Packit 352660
#include "fcaliastail.h"
Packit 352660
#undef __fccfg__