12c393a42Smrg/*
2a6844aabSmrg * fontconfig/fc-match/fc-match.c
32c393a42Smrg *
42c393a42Smrg * Copyright © 2003 Keith Packard
52c393a42Smrg *
62c393a42Smrg * Permission to use, copy, modify, distribute, and sell this software and its
72c393a42Smrg * documentation for any purpose is hereby granted without fee, provided that
82c393a42Smrg * the above copyright notice appear in all copies and that both that
92c393a42Smrg * copyright notice and this permission notice appear in supporting
10ca08ab68Smrg * documentation, and that the name of the author(s) not be used in
112c393a42Smrg * advertising or publicity pertaining to distribution of the software without
12ca08ab68Smrg * specific, written prior permission.  The authors make no
132c393a42Smrg * representations about the suitability of this software for any purpose.  It
142c393a42Smrg * is provided "as is" without express or implied warranty.
152c393a42Smrg *
16a6844aabSmrg * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
172c393a42Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18a6844aabSmrg * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
192c393a42Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
202c393a42Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
212c393a42Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
222c393a42Smrg * PERFORMANCE OF THIS SOFTWARE.
232c393a42Smrg */
242c393a42Smrg
252c393a42Smrg#ifdef HAVE_CONFIG_H
262c393a42Smrg#include <config.h>
272c393a42Smrg#else
282c393a42Smrg#ifdef linux
292c393a42Smrg#define HAVE_GETOPT_LONG 1
302c393a42Smrg#endif
312c393a42Smrg#define HAVE_GETOPT 1
322c393a42Smrg#endif
332c393a42Smrg
342c393a42Smrg#include <fontconfig/fontconfig.h>
352c393a42Smrg#include <stdio.h>
362c393a42Smrg#include <stdlib.h>
372c393a42Smrg#include <string.h>
38a32e9e42Smrg#include <locale.h>
39a32e9e42Smrg
40a4e54154Smrg#ifdef HAVE_UNISTD_H
41a4e54154Smrg#include <unistd.h>
42a4e54154Smrg#endif
43a4e54154Smrg
44a32e9e42Smrg#ifdef ENABLE_NLS
45a32e9e42Smrg#include <libintl.h>
46a32e9e42Smrg#define _(x)		(dgettext(GETTEXT_PACKAGE, x))
47a32e9e42Smrg#else
48a32e9e42Smrg#define dgettext(d, s)	(s)
49a32e9e42Smrg#define _(x)		(x)
50a32e9e42Smrg#endif
512c393a42Smrg
522c393a42Smrg#ifndef HAVE_GETOPT
532c393a42Smrg#define HAVE_GETOPT 0
542c393a42Smrg#endif
552c393a42Smrg#ifndef HAVE_GETOPT_LONG
562c393a42Smrg#define HAVE_GETOPT_LONG 0
572c393a42Smrg#endif
582c393a42Smrg
592c393a42Smrg#if HAVE_GETOPT_LONG
602c393a42Smrg#undef  _GNU_SOURCE
612c393a42Smrg#define _GNU_SOURCE
622c393a42Smrg#include <getopt.h>
632c393a42Smrgstatic const struct option longopts[] = {
642c393a42Smrg    {"sort", 0, 0, 's'},
652c393a42Smrg    {"all", 0, 0, 'a'},
662c393a42Smrg    {"verbose", 0, 0, 'v'},
67a32e9e42Smrg    {"brief", 0, 0, 'b'},
68a6844aabSmrg    {"format", 1, 0, 'f'},
69a6844aabSmrg    {"version", 0, 0, 'V'},
70a6844aabSmrg    {"help", 0, 0, 'h'},
712c393a42Smrg    {NULL,0,0,0},
722c393a42Smrg};
732c393a42Smrg#else
742c393a42Smrg#if HAVE_GETOPT
752c393a42Smrgextern char *optarg;
762c393a42Smrgextern int optind, opterr, optopt;
772c393a42Smrg#endif
782c393a42Smrg#endif
792c393a42Smrg
80a6844aabSmrgstatic void
81a6844aabSmrgusage (char *program, int error)
822c393a42Smrg{
83a6844aabSmrg    FILE *file = error ? stderr : stdout;
842c393a42Smrg#if HAVE_GETOPT_LONG
85a32e9e42Smrg    fprintf (file, _("usage: %s [-savbVh] [-f FORMAT] [--sort] [--all] [--verbose] [--brief] [--format=FORMAT] [--version] [--help] [pattern] {element...}\n"),
862c393a42Smrg	     program);
872c393a42Smrg#else
88a32e9e42Smrg    fprintf (file, _("usage: %s [-savVh] [-f FORMAT] [pattern] {element...}\n"),
892c393a42Smrg	     program);
902c393a42Smrg#endif
91a32e9e42Smrg    fprintf (file, _("List best font matching [pattern]\n"));
92a6844aabSmrg    fprintf (file, "\n");
932c393a42Smrg#if HAVE_GETOPT_LONG
94a32e9e42Smrg    fprintf (file, _("  -s, --sort           display sorted list of matches\n"));
95a32e9e42Smrg    fprintf (file, _("  -a, --all            display unpruned sorted list of matches\n"));
96a32e9e42Smrg    fprintf (file, _("  -v, --verbose        display entire font pattern verbosely\n"));
97a32e9e42Smrg    fprintf (file, _("  -b, --brief          display entire font pattern briefly\n"));
98a32e9e42Smrg    fprintf (file, _("  -f, --format=FORMAT  use the given output format\n"));
99a32e9e42Smrg    fprintf (file, _("  -V, --version        display font config version and exit\n"));
100a32e9e42Smrg    fprintf (file, _("  -h, --help           display this help and exit\n"));
1012c393a42Smrg#else
102a32e9e42Smrg    fprintf (file, _("  -s,        (sort)    display sorted list of matches\n"));
103a32e9e42Smrg    fprintf (file, _("  -a         (all)     display unpruned sorted list of matches\n"));
104a32e9e42Smrg    fprintf (file, _("  -v         (verbose) display entire font pattern verbosely\n"));
105a32e9e42Smrg    fprintf (file, _("  -b         (brief)   display entire font pattern briefly\n"));
106a32e9e42Smrg    fprintf (file, _("  -f FORMAT  (format)  use the given output format\n"));
107a32e9e42Smrg    fprintf (file, _("  -V         (version) display font config version and exit\n"));
108a32e9e42Smrg    fprintf (file, _("  -h         (help)    display this help and exit\n"));
1092c393a42Smrg#endif
110a6844aabSmrg    exit (error);
1112c393a42Smrg}
1122c393a42Smrg
1132c393a42Smrgint
1142c393a42Smrgmain (int argc, char **argv)
1152c393a42Smrg{
116ca08ab68Smrg    int			verbose = 0;
117a32e9e42Smrg    int			brief = 0;
118ca08ab68Smrg    int			sort = 0, all = 0;
119ca08ab68Smrg    const FcChar8	*format = NULL;
120a4e54154Smrg    const FcChar8	*format_optarg = NULL;
121ca08ab68Smrg    int			i;
122ca08ab68Smrg    FcObjectSet		*os = 0;
123ca08ab68Smrg    FcFontSet		*fs;
124ca08ab68Smrg    FcPattern		*pat;
125ca08ab68Smrg    FcResult		result;
1262c393a42Smrg#if HAVE_GETOPT_LONG || HAVE_GETOPT
127ca08ab68Smrg    int			c;
1282c393a42Smrg
129a32e9e42Smrg    setlocale (LC_ALL, "");
1302c393a42Smrg#if HAVE_GETOPT_LONG
131a32e9e42Smrg    while ((c = getopt_long (argc, argv, "asvbf:Vh", longopts, NULL)) != -1)
1322c393a42Smrg#else
133a32e9e42Smrg    while ((c = getopt (argc, argv, "asvbf:Vh")) != -1)
1342c393a42Smrg#endif
1352c393a42Smrg    {
1362c393a42Smrg	switch (c) {
1372c393a42Smrg	case 'a':
1382c393a42Smrg	    all = 1;
1392c393a42Smrg	    break;
1402c393a42Smrg	case 's':
1412c393a42Smrg	    sort = 1;
1422c393a42Smrg	    break;
143a6844aabSmrg	case 'v':
144a6844aabSmrg	    verbose = 1;
145a6844aabSmrg	    break;
146a32e9e42Smrg	case 'b':
147a32e9e42Smrg	    brief = 1;
148a32e9e42Smrg	    break;
149a6844aabSmrg	case 'f':
150a4e54154Smrg	    format = format_optarg = (FcChar8 *) strdup (optarg);
151a6844aabSmrg	    break;
1522c393a42Smrg	case 'V':
1532c393a42Smrg	    fprintf (stderr, "fontconfig version %d.%d.%d\n",
1542c393a42Smrg		     FC_MAJOR, FC_MINOR, FC_REVISION);
1552c393a42Smrg	    exit (0);
156a6844aabSmrg	case 'h':
157a6844aabSmrg	    usage (argv[0], 0);
1582c393a42Smrg	default:
159a6844aabSmrg	    usage (argv[0], 1);
1602c393a42Smrg	}
1612c393a42Smrg    }
1622c393a42Smrg    i = optind;
1632c393a42Smrg#else
1642c393a42Smrg    i = 1;
1652c393a42Smrg#endif
1662c393a42Smrg
1672c393a42Smrg    if (argv[i])
168a6844aabSmrg    {
1692c393a42Smrg	pat = FcNameParse ((FcChar8 *) argv[i]);
1706fc018e4Smrg	if (!pat)
1716fc018e4Smrg	{
172a32e9e42Smrg	    fprintf (stderr, _("Unable to parse the pattern\n"));
1736fc018e4Smrg	    return 1;
1746fc018e4Smrg	}
175a6844aabSmrg	while (argv[++i])
176a6844aabSmrg	{
177a6844aabSmrg	    if (!os)
178a6844aabSmrg		os = FcObjectSetCreate ();
179a6844aabSmrg	    FcObjectSetAdd (os, argv[i]);
180a6844aabSmrg	}
181a6844aabSmrg    }
1822c393a42Smrg    else
1832c393a42Smrg	pat = FcPatternCreate ();
1842c393a42Smrg
1852c393a42Smrg    if (!pat)
1862c393a42Smrg	return 1;
1872c393a42Smrg
1882c393a42Smrg    FcConfigSubstitute (0, pat, FcMatchPattern);
1892c393a42Smrg    FcDefaultSubstitute (pat);
1902c393a42Smrg
1912c393a42Smrg    fs = FcFontSetCreate ();
1922c393a42Smrg
1932c393a42Smrg    if (sort || all)
1942c393a42Smrg    {
1952c393a42Smrg	FcFontSet	*font_patterns;
1962c393a42Smrg	int	j;
1972c393a42Smrg	font_patterns = FcFontSort (0, pat, all ? FcFalse : FcTrue, 0, &result);
1982c393a42Smrg
199ca08ab68Smrg	if (!font_patterns || font_patterns->nfont == 0)
200ca08ab68Smrg	{
201a32e9e42Smrg	    fprintf (stderr, _("No fonts installed on the system\n"));
202ca08ab68Smrg	    return 1;
203ca08ab68Smrg	}
2042c393a42Smrg	for (j = 0; j < font_patterns->nfont; j++)
2052c393a42Smrg	{
2062c393a42Smrg	    FcPattern  *font_pattern;
2072c393a42Smrg
2082c393a42Smrg	    font_pattern = FcFontRenderPrepare (NULL, pat, font_patterns->fonts[j]);
2092c393a42Smrg	    if (font_pattern)
2102c393a42Smrg		FcFontSetAdd (fs, font_pattern);
2112c393a42Smrg	}
2122c393a42Smrg
2132c393a42Smrg	FcFontSetSortDestroy (font_patterns);
2142c393a42Smrg    }
2152c393a42Smrg    else
2162c393a42Smrg    {
2172c393a42Smrg	FcPattern   *match;
2182c393a42Smrg	match = FcFontMatch (0, pat, &result);
2192c393a42Smrg	if (match)
2202c393a42Smrg	    FcFontSetAdd (fs, match);
2212c393a42Smrg    }
2222c393a42Smrg    FcPatternDestroy (pat);
2232c393a42Smrg
224ca08ab68Smrg    if (!format)
225ca08ab68Smrg    {
226ca08ab68Smrg	if (os)
227ca08ab68Smrg	    format = (const FcChar8 *) "%{=unparse}\n";
228ca08ab68Smrg	else
229ca08ab68Smrg	    format = (const FcChar8 *) "%{=fcmatch}\n";
230ca08ab68Smrg    }
231ca08ab68Smrg
2322c393a42Smrg    if (fs)
2332c393a42Smrg    {
2342c393a42Smrg	int	j;
2352c393a42Smrg
2362c393a42Smrg	for (j = 0; j < fs->nfont; j++)
2372c393a42Smrg	{
238a6844aabSmrg	    FcPattern *font;
239a6844aabSmrg
240a6844aabSmrg	    font = FcPatternFilter (fs->fonts[j], os);
241a6844aabSmrg
242a32e9e42Smrg	    if (verbose || brief)
2432c393a42Smrg	    {
244a32e9e42Smrg		if (brief)
245a32e9e42Smrg		{
246a32e9e42Smrg		    FcPatternDel (font, FC_CHARSET);
247a32e9e42Smrg		    FcPatternDel (font, FC_LANG);
248a32e9e42Smrg		}
249a6844aabSmrg		FcPatternPrint (font);
250a6844aabSmrg	    }
251ca08ab68Smrg	    else
252a6844aabSmrg	    {
253a6844aabSmrg	        FcChar8 *s;
254a6844aabSmrg
255a6844aabSmrg		s = FcPatternFormat (font, format);
256a6844aabSmrg		if (s)
257a6844aabSmrg		{
258a6844aabSmrg		    printf ("%s", s);
259ca08ab68Smrg		    FcStrFree (s);
260a6844aabSmrg		}
261a6844aabSmrg	    }
262a6844aabSmrg
263a6844aabSmrg	    FcPatternDestroy (font);
2642c393a42Smrg	}
2652c393a42Smrg	FcFontSetDestroy (fs);
2662c393a42Smrg    }
267a6844aabSmrg
268a6844aabSmrg    if (os)
269a6844aabSmrg	FcObjectSetDestroy (os);
270a6844aabSmrg
2712c393a42Smrg    FcFini ();
272a6844aabSmrg
273a4e54154Smrg    if (format_optarg) {
274a4e54154Smrg	free ((void*)format_optarg);
275a4e54154Smrg	format_optarg = NULL;
276a4e54154Smrg    }
277a4e54154Smrg
2782c393a42Smrg    return 0;
2792c393a42Smrg}
280