FcBool
FcDirCacheUnlink (const FcChar8 *dir, FcConfig *config)
{
    FcChar8	*cache_hashed = NULL;
    FcChar8	cache_base[CACHEBASE_LEN];
    FcStrList	*list;
    FcChar8	*cache_dir;
    const FcChar8 *sysroot = FcConfigGetSysRoot (config);

    FcDirCacheBasename (dir, cache_base);

    list = FcStrListCreate (config->cacheDirs);
    if (!list)
        return FcFalse;
	
    while ((cache_dir = FcStrListNext (list)))
    {
	if (sysroot)
	    cache_hashed = FcStrBuildFilename (sysroot, cache_dir, cache_base, NULL);
	else
	    cache_hashed = FcStrBuildFilename (cache_dir, cache_base, NULL);
        if (!cache_hashed)
	    break;
	(void) unlink ((char *) cache_hashed);
	FcStrFree (cache_hashed);
    }
    FcStrListDone (list);
    /* return FcFalse if something went wrong */
    if (cache_dir)
	return FcFalse;
    return FcTrue;
}
static void
xfce_xsettings_helper_fc_monitor (XfceXSettingsHelper *helper,
                                  FcStrList           *files)
{
    const gchar  *path;
    GFile        *file;
    GFileMonitor *monitor;

    if (G_UNLIKELY (files == NULL))
        return;

    for (;;)
    {
        path = (const gchar *) FcStrListNext (files);
        if (G_UNLIKELY (path == NULL))
            break;

        file = g_file_new_for_path (path);
        monitor = g_file_monitor (file, G_FILE_MONITOR_NONE, NULL, NULL);
        g_object_unref (G_OBJECT (file));

        if (G_LIKELY (monitor != NULL))
        {
            g_ptr_array_add (helper->fc_monitors, monitor);
            g_signal_connect_swapped (G_OBJECT (monitor), "changed",
                G_CALLBACK (xfce_xsettings_helper_fc_changed), helper);

            xfsettings_dbg_filtered (XFSD_DEBUG_FONTCONFIG, "monitoring \"%s\"",
                                     path);
        }
    }

    FcStrListDone (files);
}
/*
 * Look for a cache file for the specified dir. Attempt
 * to use each one we find, stopping when the callback
 * indicates success
 */
static FcBool
FcDirCacheProcess (FcConfig *config, const FcChar8 *dir,
		   FcBool (*callback) (FcConfig *config, int fd, struct stat *fd_stat,
				       struct stat *dir_stat, void *closure),
		   void *closure, FcChar8 **cache_file_ret)
{
    int		fd = -1;
    FcChar8	cache_base[CACHEBASE_LEN];
    FcStrList	*list;
    FcChar8	*cache_dir, *d;
    struct stat file_stat, dir_stat;
    FcBool	ret = FcFalse;
    const FcChar8 *sysroot = FcConfigGetSysRoot (config);

    if (sysroot)
	d = FcStrBuildFilename (sysroot, dir, NULL);
    else
	d = FcStrdup (dir);
    if (FcStatChecksum (d, &dir_stat) < 0)
    {
	FcStrFree (d);
        return FcFalse;
    }
    FcStrFree (d);

    FcDirCacheBasename (dir, cache_base);

    list = FcStrListCreate (config->cacheDirs);
    if (!list)
        return FcFalse;
	
    while ((cache_dir = FcStrListNext (list)))
    {
        FcChar8	*cache_hashed;

	if (sysroot)
	    cache_hashed = FcStrBuildFilename (sysroot, cache_dir, cache_base, NULL);
	else
	    cache_hashed = FcStrBuildFilename (cache_dir, cache_base, NULL);
        if (!cache_hashed)
	    break;
        fd = FcDirCacheOpenFile (cache_hashed, &file_stat);
        if (fd >= 0) {
	    ret = (*callback) (config, fd, &file_stat, &dir_stat, closure);
	    close (fd);
	    if (ret)
	    {
		if (cache_file_ret)
		    *cache_file_ret = cache_hashed;
		else
		    FcStrFree (cache_hashed);
		break;
	    }
	}
    	FcStrFree (cache_hashed);
    }
    FcStrListDone (list);

    return ret;
}
Exemple #4
0
static void
create_file_monitors (FontViewModel *self)
{
    FcConfig *config;
    FcStrList *str_list;
    FcChar8 *path;
    GFile *file;
    GFileMonitor *monitor;

    config = FcConfigGetCurrent ();
    str_list = FcConfigGetFontDirs (config);

    while ((path = FcStrListNext (str_list)) != NULL) {
        file = g_file_new_for_path ((const gchar *) path);
        monitor = g_file_monitor (file, G_FILE_MONITOR_NONE,
                                  NULL, NULL);

        if (monitor != NULL) {
            self->priv->monitors = g_list_prepend (self->priv->monitors, monitor);
            g_signal_connect (monitor, "changed",
                              G_CALLBACK (file_monitor_changed_cb), self);
        }

        g_object_unref (file);
    }

    FcStrListDone (str_list);
}
static void
monitor_files (GPtrArray *monitors,
               FcStrList *list,
               gpointer   data)
{
        const char *str;

        while ((str = (const char *) FcStrListNext (list))) {
                GFile *file;
                GFileMonitor *monitor;

                file = g_file_new_for_path (str);

                monitor = g_file_monitor (file, G_FILE_MONITOR_NONE, NULL, NULL);

                g_object_unref (file);

                if (!monitor)
                        continue;

                g_signal_connect (monitor, "changed", G_CALLBACK (stuff_changed), data);

                g_ptr_array_add (monitors, monitor);
        }

        FcStrListDone (list);
}
Exemple #6
0
static FcBool
FcConfigAddDirList (FcConfig *config, FcSetName set, FcStrSet *dirSet)
{
    FcStrList	    *dirlist;
    FcChar8	    *dir;
    FcCache	    *cache;
    FcBool	     ret = FcFalse;

    dirlist = FcStrListCreate (dirSet);
    if (!dirlist)
        return FcFalse;
	
    while ((dir = FcStrListNext (dirlist)))
    {
	if (FcDebug () & FC_DBG_FONTSET)
	    printf ("adding fonts from %s\n", dir);
	cache = FcDirCacheRead (dir, FcFalse, config);
	if (!cache)
	    continue;
	FcConfigAddCache (config, cache, set, dirSet);
	FcDirCacheUnload (cache);
	ret = FcTrue;
    }
    FcStrListDone (dirlist);
    return ret;
}
static FcBool
cache_print_set (FcFontSet *set, FcStrSet *dirs, const FcChar8 *base_name, FcBool verbose)
{
    FcChar8	    *dir;
    const FcChar8   *base;
    int		    n;
    int		    ndir = 0;
    FcStrList	    *list;

    list = FcStrListCreate (dirs);
    if (!list)
	goto bail2;
    
    while ((dir = FcStrListNext (list)))
    {
	base = file_base_name (base_name, dir);
	if (!write_string (stdout, base))
	    goto bail3;
	if (PUTC (' ', stdout) == EOF)
	    goto bail3;
	if (!write_int (stdout, 0))
	    goto bail3;
        if (PUTC (' ', stdout) == EOF)
	    goto bail3;
	if (!write_string (stdout, FC_FONT_FILE_DIR))
	    goto bail3;
	if (PUTC ('\n', stdout) == EOF)
	    goto bail3;
	ndir++;
    }
    
    for (n = 0; n < set->nfont; n++)
    {
	FcPattern   *font = set->fonts[n];
	FcChar8 *s;

	s = FcPatternFormat (font, (const FcChar8 *) "%{=fccat}\n");
	if (s)
	{
	    printf ("%s", s);
	    FcStrFree (s);
	}
    }
    if (verbose && !set->nfont && !ndir)
	printf ("<empty>\n");

    FcStrListDone (list);

    return FcTrue;

bail3:
    FcStrListDone (list);
bail2:
    return FcFalse;
}
Exemple #8
0
GeeArrayList *
FcListUserDirs(void)
{
    FcChar8      * directory;
    FcStrList    * fdlist;
    GeeArrayList * dirlist = gee_array_list_new(G_TYPE_STRING,
                                              (GBoxedCopyFunc) g_strdup,
                                              (GDestroyNotify) g_free0,
                                              NULL,
                                              NULL,
                                              NULL);
    g_assert(FcInit());
    fdlist = FcConfigGetConfigDirs(NULL);
    while ((directory = FcStrListNext(fdlist)))
        if (get_file_owner((const gchar *) directory) == 0)
            gee_abstract_collection_add((GeeAbstractCollection *) dirlist, directory);
    FcStrListDone(fdlist);
    return dirlist;
}
Exemple #9
0
//
// Obtain location of config file to use.
//
// For system, prefer the following:
//
//     <...>/config.d/00kde.conf   = preferred method from FCConfig >= 2.3
//     <...>/local.conf
//
// Non-system, prefer:
//
//     $HOME/<...>/.fonts.conf
//     $HOME/<...>/fonts.conf
//
QString getConfigFile(bool system)
{
#if (FC_VERSION>=20300)
    static const char constKdeRootFcFile[] = "00kde.conf";
#endif

    FcStrList   *list=FcConfigGetConfigFiles(FcConfigGetCurrent());
    QStringList files;
    FcChar8     *file;
    QString     home(Misc::dirSyntax(QDir::homePath()));

    while((file=FcStrListNext(list)))
    {
        QString f((const char *)file);

        if(Misc::fExists(f))
        {
            // For nonsystem, only consider file within $HOME
            if(system || 0==Misc::fileSyntax(f).indexOf(home))
                files.append(f);
        }
#if (FC_VERSION>=20300)
        if(system && Misc::dExists(f) && (f.contains(QRegExp("/conf\\.d/?$")) ||
                                          f.contains(QRegExp("/conf\\.d?$"))) )
            return Misc::dirSyntax(f)+constKdeRootFcFile;   // This ones good enough for me!
#endif
    }

    //
    // Go through list of files, looking for the preferred one...
    if(files.count())
    {
        QStringList::const_iterator it(files.begin()),
                              end(files.end());

        for(; it!=end; ++it)
            if(-1!=(*it).indexOf(QRegExp(system ? "/local\\.conf$" : "/\\.?fonts\\.conf$")))
                return *it;
        return files.front();  // Just return the 1st one...
    }
    else // Hmmm... no known files?
        return system ? "/etc/fonts/local.conf" : Misc::fileSyntax(home+"/.fonts.conf");
}
Exemple #10
0
static FcBool
cleanCacheDirectories (FcConfig *config, FcBool verbose)
{
    FcStrList	*cache_dirs = FcConfigGetCacheDirs (config);
    FcChar8	*cache_dir;
    FcBool	ret = FcTrue;

    if (!cache_dirs)
	return FcFalse;
    while ((cache_dir = FcStrListNext (cache_dirs)))
    {
	if (!FcDirCacheClean (cache_dir, verbose))
	{
	    ret = FcFalse;
	    break;
	}
    }
    FcStrListDone (cache_dirs);
    return ret;
}
Exemple #11
0
GeeArrayList *
FcListDirs(gboolean recursive)
{
    FcChar8      * directory;
    FcStrList    * fdlist;
    GeeArrayList * dirlist = gee_array_list_new(G_TYPE_STRING,
                                              (GBoxedCopyFunc) g_strdup,
                                              (GDestroyNotify) g_free0,
                                              NULL,
                                              NULL,
                                              NULL);
    g_assert(FcInit());
    if (recursive)
        fdlist = FcConfigGetFontDirs(NULL);
    else
        fdlist = FcConfigGetConfigDirs(NULL);
    while ((directory = FcStrListNext(fdlist)))
        gee_abstract_collection_add((GeeAbstractCollection *) dirlist, directory);
    FcStrListDone(fdlist);
    return dirlist;
}
Exemple #12
0
static FcFileTime
FcConfigNewestFile (FcStrSet *files)
{
    FcStrList	    *list = FcStrListCreate (files);
    FcFileTime	    newest = { 0, FcFalse };
    FcChar8	    *file;
    struct  stat    statb;

    if (list)
    {
	while ((file = FcStrListNext (list)))
	    if (FcStat (file, &statb) == 0)
		if (!newest.set || statb.st_mtime - newest.time > 0)
		{
		    newest.set = FcTrue;
		    newest.time = statb.st_mtime;
		}
	FcStrListDone (list);
    }
    return newest;
}
Exemple #13
0
FcStrSet *fcinfo_languages(const FcPattern *filter)
{
  FcObjectSet *objectset;
  FcFontSet *fontset;
  FcLangSet *union_langset;
  FcStrSet *result;
  int f;

  FcInit();
  objectset = FcObjectSetBuild(FC_LANG, NULL);
  fontset = FcFontList(NULL, (FcPattern *)filter, objectset);
  FcObjectSetDestroy(objectset);

  union_langset = FcLangSetCreate();
  for (f = 0; f < fontset->nfont; f++)
  {
    FcLangSet *langset;
    FcStrList *strlist;
    FcChar8 *lang;

    if (FcPatternGetLangSet(fontset->fonts[f], FC_LANG, 0, &langset)
        != FcResultMatch)
      continue;
    if (! langset)
      continue;

    strlist = FcStrListCreate(FcLangSetGetLangs(langset));
    while ((lang = FcStrListNext(strlist)))
      if (FcLangSetHasLang(union_langset, lang))
       FcLangSetAdd(union_langset, FcStrCopy(lang));
  }

  result = FcLangSetGetLangs(union_langset);
  
  FcFontSetDestroy(fontset);
  FcLangSetDestroy(union_langset);
  return result;
}
Exemple #14
0
int main(int argc, char *argv[])
{
#ifdef HAVE_GETOPT_H
    static struct option options[]=
    {
        { "configure_x",    0, 0, 'x' },
        { "configure_gs",   0, 0, 'g' },
        { "add_to_fc_cfg",  0, 0, 'f' },
        { "add_to_x_cfg",   0, 0, 'a' },
        { "refresh_x",      0, 0, 'r' },
        { "refresh_xfs",    0, 0, 's' },
        { 0,                0, 0, 0   }
    };
#endif

    int  c=0,
         rv=0;
    bool doX=false,
         doGs=false,
         addToX=false,
         addToFc=false,
         refreshX=false,
         refreshXfs=false,
         root=KFI::Misc::root();

#ifdef HAVE_GETOPT_H
    int optIndex;
    while(-1!=(c=getopt_long(argc, argv, "xgfars", options, &optIndex)))
#else
    while(-1!=(c=getopt(argc, argv, "xgfars")))
#endif
        switch(c)
        {
            case 'x':
                doX=true;
                break;
            case 'g':
                doGs=true;
                break;
            case 'f':
                addToFc=true;
                break;
            case 'a':
                addToX=true;
                break;
            case 'r':
                refreshX=true;
                break;
            case 's':
                refreshXfs=true;
                break;
            case '?':
                usage(argv[0]);
                break;
        }

    int  left=argc-optind;
    bool folderRequired=doX || addToX || addToFc || (!root && doGs);

    if (left>1 || (0==left && folderRequired) || (!doX && !doGs && !addToX && !addToFc))
        usage(argv[0]);
    else
    {
        QString folder;

        if(folderRequired)
        {
            folder=argv[optind];
            unsigned int len=folder.length();

            // Remove quotes...
            if( (folder[0]==QChar('\'') || folder[0]==QChar('\"')) &&
                (folder[len-1]==QChar('\'') || folder[len-1]==QChar('\"')))
                folder=folder.mid(1, len-2);
            folder=KFI::Misc::dirSyntax(folder);
        }

        if(folderRequired && !KFI::Misc::dExists(folder))
        {
            std::cerr << "ERROR: " << QFile::encodeName(folder) << " does not exist!" << std::endl;
            rv=-2;
        }
        else
        {
            if(!folder.isEmpty())
            {
                if(0==rv && addToFc)
                {
                    //
                    // Only add folder to fontconfig's config if its not already there...
                    FcStrList *list=FcConfigGetFontDirs(FcConfigGetCurrent());
                    FcChar8   *dir;
                    bool      found=false;

                    while((dir=FcStrListNext(list)))
                        if(0==KFI::Misc::dirSyntax((const char *)dir).find(folder))
                            found=true;

                    if(!found)
                    {
                        KXftConfig *xft=new KXftConfig(KXftConfig::Dirs, root);

                        xft->addDir(folder);
                        rv=xft->apply() ? 0 : -3;
                        delete xft;
                   }
                }

                if(0==rv && addToX && root)
                {
                    KFI::CXConfig *x=NULL;

                    if((x=getXCfg(true)))
                    {
                        x->addPath(folder);
                        rv=x->writeConfig() ? 0 : -4;
                        delete x;
                    }
                    else
                        rv=-5;
                }
            }

            if(0==rv && (doX || doGs))
            {
                if(0==rv && doX)
                    rv=KFI::CXConfig::configureDir(folder) ? 0 : -5;

                refresh(refreshX, refreshXfs, root);

                if(0==rv && doGs)
                {
                    KFI::CFontEngine fe;
                    rv=KFI::Fontmap::create(root ? QString::null : folder, fe) ? 0 : -6;
                }
            }
            else if(0==rv)
                refresh(refreshX, refreshXfs, root);
        }
    }

    return rv;
}
Exemple #15
0
int
main (int argc, char **argv)
{
    int		i;
    int		ret = 0;
    FcFontSet	*fs;
    FcStrSet    *dirs;
    FcStrSet	*args = NULL;
    FcStrList	*arglist;
    FcCache	*cache;
    FcConfig	*config;
    FcChar8	*arg;
    int		verbose = 0;
    int		recurse = 0;
    FcBool	first = FcTrue;
#if HAVE_GETOPT_LONG || HAVE_GETOPT
    int		c;

#if HAVE_GETOPT_LONG
    while ((c = getopt_long (argc, argv, "Vvrh", longopts, NULL)) != -1)
#else
    while ((c = getopt (argc, argv, "Vvrh")) != -1)
#endif
    {
	switch (c) {
	case 'V':
	    fprintf (stderr, "fontconfig version %d.%d.%d\n", 
		     FC_MAJOR, FC_MINOR, FC_REVISION);
	    exit (0);
	case 'v':
	    verbose++;
	    break;
	case 'r':
	    recurse++;
	    break;
	case 'h':
	    usage (argv[0], 0);
	default:
	    usage (argv[0], 1);
	}
    }
    i = optind;
#else
    i = 1;
#endif

    config = FcInitLoadConfig ();
    if (!config)
    {
	fprintf (stderr, "%s: Can't init font config library\n", argv[0]);
	return 1;
    }
    FcConfigSetCurrent (config);
    
    args = FcStrSetCreate ();
    if (!args)
    {
	fprintf (stderr, "%s: malloc failure\n", argv[0]);
	return 1;
    }
    if (i < argc)
    {
	for (; i < argc; i++)
	{
	    if (!FcStrSetAddFilename (args, (const FcChar8 *) argv[i]))
	    {
		fprintf (stderr, "%s: malloc failure\n", argv[0]);
		return 1;
	    }
	}
	arglist = FcStrListCreate (args);
	if (!arglist)
	{
	    fprintf (stderr, "%s: malloc failure\n", argv[0]);
	    return 1;
	}
    }
    else
    {
	recurse++;
	arglist = FcConfigGetFontDirs (config);
	while ((arg = FcStrListNext (arglist)))
	    if (!FcStrSetAdd (args, arg))
	    {
		fprintf (stderr, "%s: malloc failure\n", argv[0]);
		return 1;
	    }
	FcStrListDone (arglist);
    }
    arglist = FcStrListCreate (args);
    if (!arglist)
    {
	fprintf (stderr, "%s: malloc failure\n", argv[0]);
	return 1;
    }

    while ((arg = FcStrListNext (arglist)))
    {
	int	    j;
	FcChar8	    *cache_file = NULL;
	struct stat file_stat;
	
	if (FcFileIsDir (arg))
	    cache = FcDirCacheLoad (arg, config, &cache_file);
	else
	    cache = FcDirCacheLoadFile (arg, &file_stat);
	if (!cache)
	{
	    perror ((char *) arg);
	    ret++;
	    continue;
	}
	
	dirs = FcStrSetCreate ();
	fs = FcCacheCopySet (cache);
	for (j = 0; j < FcCacheNumSubdir (cache); j++) 
	{
	    FcStrSetAdd (dirs, FcCacheSubdir (cache, j));
	    if (recurse)
		FcStrSetAdd (args, FcCacheSubdir (cache, j));
	}

	if (verbose)
	{
	    if (!first)
		printf ("\n");
	    printf ("Directory: %s\nCache: %s\n--------\n",
		    FcCacheDir(cache), cache_file ? cache_file : arg);
	    first = FcFalse;
	}
        cache_print_set (fs, dirs, FcCacheDir (cache), verbose);

	FcStrSetDestroy (dirs);

	FcFontSetDestroy (fs);
	FcDirCacheUnload (cache);
	if (cache_file)
	    FcStrFree (cache_file);
    }

    FcFini ();
    return 0;
}
Exemple #16
0
static int
scanDirs (FcStrList *list, FcConfig *config, FcBool force, FcBool really_force, FcBool verbose, int *changed)
{
    int		    ret = 0;
    const FcChar8   *dir;
    FcStrSet	    *subdirs;
    FcStrList	    *sublist;
    FcCache	    *cache;
    struct stat	    statb;
    FcBool	    was_valid;
    int		    i;
    
    /*
     * Now scan all of the directories into separate databases
     * and write out the results
     */
    while ((dir = FcStrListNext (list)))
    {
	if (verbose)
	{
	    printf ("%s: ", dir);
	    fflush (stdout);
	}
	
	if (!dir)
	{
	    if (verbose)
		printf ("skipping, no such directory\n");
	    continue;
	}
	
	if (FcStrSetMember (processed_dirs, dir))
	{
	    if (verbose)
		printf ("skipping, looped directory detected\n");
	    continue;
	}

	if (stat ((char *) dir, &statb) == -1)
	{
	    switch (errno) {
	    case ENOENT:
	    case ENOTDIR:
		if (verbose)
		    printf ("skipping, no such directory\n");
		break;
	    default:
		fprintf (stderr, "\"%s\": ", dir);
		perror ("");
		ret++;
		break;
	    }
	    continue;
	}

	if (!S_ISDIR (statb.st_mode))
	{
	    fprintf (stderr, "\"%s\": not a directory, skipping\n", dir);
	    continue;
	}

	if (really_force)
	    FcDirCacheUnlink (dir, config);

	cache = NULL;
	was_valid = FcFalse;
	if (!force) {
	    cache = FcDirCacheLoad (dir, config, NULL);
	    if (cache)
		was_valid = FcTrue;
	}
	
	if (!cache)
	{
	    (*changed)++;
	    cache = FcDirCacheRead (dir, FcTrue, config);
	    if (!cache)
	    {
		fprintf (stderr, "%s: error scanning\n", dir);
		ret++;
		continue;
	    }
	}

	if (was_valid)
	{
	    if (verbose)
		printf ("skipping, existing cache is valid: %d fonts, %d dirs\n",
			FcCacheNumFont (cache), FcCacheNumSubdir (cache));
	}
	else
	{
	    if (verbose)
		printf ("caching, new cache contents: %d fonts, %d dirs\n", 
			FcCacheNumFont (cache), FcCacheNumSubdir (cache));

	    if (!FcDirCacheValid (dir))
	    {
		fprintf (stderr, "%s: failed to write cache\n", dir);
		(void) FcDirCacheUnlink (dir, config);
		ret++;
	    }
	}
	
	subdirs = FcStrSetCreate ();
	if (!subdirs)
	{
	    fprintf (stderr, "%s: Can't create subdir set\n", dir);
	    ret++;
	    FcDirCacheUnload (cache);
	    continue;
	}
	for (i = 0; i < FcCacheNumSubdir (cache); i++)
	    FcStrSetAdd (subdirs, FcCacheSubdir (cache, i));
	
	FcDirCacheUnload (cache);
	
	sublist = FcStrListCreate (subdirs);
	FcStrSetDestroy (subdirs);
	if (!sublist)
	{
	    fprintf (stderr, "%s: Can't create subdir list\n", dir);
	    ret++;
	    continue;
	}
	FcStrSetAdd (processed_dirs, dir);
	ret += scanDirs (sublist, config, force, really_force, verbose, changed);
    }
    FcStrListDone (list);
    return ret;
}
int
main (int argc, char **argv)
{
    int         brief = 0;
    FcChar8     *format = NULL;
    int		i;
    FcFontSet   *fs;
#if HAVE_GETOPT_LONG || HAVE_GETOPT
    int		c;

    setlocale (LC_ALL, "");
#if HAVE_GETOPT_LONG
    while ((c = getopt_long (argc, argv, "bf:Vh", longopts, NULL)) != -1)
#else
    while ((c = getopt (argc, argv, "bf:Vh")) != -1)
#endif
    {
	switch (c) {
	case 'b':
	    brief = 1;
	    break;
	case 'f':
	    format = (FcChar8 *) strdup (optarg);
	    break;
	case 'V':
	    fprintf (stderr, "fontconfig version %d.%d.%d\n",
		     FC_MAJOR, FC_MINOR, FC_REVISION);
	    exit (0);
	case 'h':
	    usage (argv[0], 0);
	default:
	    usage (argv[0], 1);
	}
    }
    i = optind;
#else
    i = 1;
#endif

    if (i == argc)
	usage (argv[0], 1);

    fs = FcFontSetCreate ();

    for (; i < argc; i++)
    {
	const FcChar8 *file = (FcChar8*) argv[i];

	if (!FcFileIsDir (file))
	    FcFileScan (fs, NULL, NULL, NULL, file, FcTrue);
	else
	{
	    FcStrSet *dirs = FcStrSetCreate ();
	    FcStrList *strlist = FcStrListCreate (dirs);
	    do
	    {
		FcDirScan (fs, dirs, NULL, NULL, file, FcTrue);
	    }
	    while ((file = FcStrListNext (strlist)));
	    FcStrListDone (strlist);
	    FcStrSetDestroy (dirs);
	}
    }

    for (i = 0; i < fs->nfont; i++)
    {
	FcPattern *pat = fs->fonts[i];

	if (brief)
	{
	    FcPatternDel (pat, FC_CHARSET);
	    FcPatternDel (pat, FC_LANG);
	}

	if (format)
	{
	    FcChar8 *s;

	    s = FcPatternFormat (pat, format);
	    if (s)
	    {
		printf ("%s", s);
		FcStrFree (s);
	    }
	}
	else
	{
	    FcPatternPrint (pat);
	}
    }

    FcFontSetDestroy (fs);

    FcFini ();
    return i > 0 ? 0 : 1;
}
void
font_config_magic_class::
add_entry(FcPattern *p)
{
  FcMagicValue<FcChar8*> family_name, file_name, foundary_name, font_style;
  FcMagicValue<int> font_index, font_weight, font_slant;
  FcMagicValue<FcLangSet*> lang;
  
  FcGetMagicValue(p, FC_FILE, file_name);
  if(file_name.m_exists)
    {
      FontEntry entry_key;
      WRATHFontConfig::FontSpecification entry;
      
      GetPairFromFcMagicValue(entry_key.m_filename, file_name);
      
      FcGetMagicValue(p, FC_INDEX, font_index);
      GetPairFromFcMagicValue(entry_key.m_face_index, font_index);
      
      entry.font()=WRATHFontDatabase::fetch_font_entry(entry_key.m_filename, entry_key.m_face_index);
      
      FcGetMagicValue(p, FC_FAMILY, family_name);
      GetPairFromFcMagicValue(entry.m_fontconfig_details.m_family_name, family_name);
      
      FcGetMagicValue(p, FC_FOUNDRY, foundary_name);
      GetPairFromFcMagicValue(entry.m_fontconfig_details.m_foundary_name, foundary_name);
      
      FcGetMagicValue(p, FC_WEIGHT, font_weight);
      GetPairFromFcMagicValue(entry.m_fontconfig_details.m_weight, font_weight);
      
      FcGetMagicValue(p, FC_SLANT, font_slant);
      GetPairFromFcMagicValue(entry.m_fontconfig_details.m_slant, font_slant);
      
      FcGetMagicValue(p, FC_STYLE, font_style);
      GetPairFromFcMagicValue(entry.m_fontconfig_details.m_style, font_style);
      
      #if (FC_MAJOR>=2 && FC_MINOR>=7) || (FC_MAJOR>=3)   
      {        
        FcGetMagicValue(p, FC_LANG, lang);
        if(lang.m_exists)
          {
            FcStrSet *langs_as_strs;
            FcStrList *iter;
            FcChar8 *current;
            
            langs_as_strs=FcLangSetGetLangs(lang.m_value); //do we need to free this thing??
            iter=FcStrListCreate(langs_as_strs);
            
            for(current=FcStrListNext(iter); current; current=FcStrListNext(iter))
              {
                const char *str(reinterpret_cast<const char*>(current));
                entry.m_fontconfig_details.m_languages.insert(std::string(str));
              }
            FcStrListDone(iter);
            FcStrSetDestroy(langs_as_strs);
          }
      }
      #endif
              
      WRATHassert(m_font_list.find(entry.font())==m_font_list.end());
      m_font_list[entry.font()]=entry;
    }
}