Include <sys/types.h> and "config.h".
[m17n/libotf.git] / example / otflist.c
1 /* otflist.c -- List OpenType fonts.
2
3 Copyright (C) 2003, 2004
4   National Institute of Advanced Industrial Science and Technology (AIST)
5   Registration Number H15PRO167
6
7 This file is part of libotf.
8
9 Libotf is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published
11 by the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
13
14 Libotf is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
17 License for more details.
18
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library, in a file named COPYING; if not,
21 write to the Free Software Foundation, Inc., 59 Temple Place, Suite
22 330, Boston, MA 02111-1307, USA.  */
23
24 #include <stdio.h>
25 #include <unistd.h>
26 #include <string.h>
27 #include <sys/types.h>
28 #include <dirent.h>
29
30 #include <ft2build.h>
31 #include FT_FREETYPE_H
32
33 #include "config.h"
34 #include <otf.h>
35
36 /* Format MSG by FMT and print the result to the stderr, and exit.  */
37
38 #define FATAL_ERROR(fmt, arg)   \
39   do {                          \
40     fprintf (stderr, fmt, arg); \
41     exit (1);                   \
42   } while (0)
43
44
45 void
46 print_tag (OTF_Tag tag)
47 {
48   char name[5];
49
50   OTF_tag_name (tag, name);
51   printf ("%s", name);
52 }
53
54 void
55 print_gsub_gpos_info (OTF *otf, char *table)
56 {
57   int i, j;
58
59   if (OTF_get_table (otf, table) == 0)
60     {
61       OTF_ScriptList *scripts;
62       OTF_FeatureList *features;
63
64       if (! strcmp (table, "GSUB"))
65         scripts = &otf->gsub->ScriptList, features = &otf->gsub->FeatureList;
66       else
67         scripts = &otf->gpos->ScriptList, features = &otf->gpos->FeatureList;
68
69       printf ("  %s scripts: ", table);
70       for (i = 0; i < scripts->ScriptCount; i++)
71         {
72           OTF_Script *script = scripts->Script + i;
73
74           if (i > 0)
75             printf (", ");
76           print_tag (script->ScriptTag);
77           if (script->LangSysCount > 0)
78             {
79               printf (" (");
80               for (j = 0; j < script->LangSysCount; j++)
81                 {
82                   if (j > 0)
83                     printf (", ");
84                   print_tag (script->LangSysRecord[j].LangSysTag);
85                 }
86               printf (" )");
87             }
88         }
89       printf ("\n");
90
91       printf ("  %s features: ", table);
92       for (i = 0; i < features->FeatureCount; i++)
93         {
94           if (i > 0)
95             printf (",");
96           print_tag (features->Feature[i].FeatureTag);
97         }
98       printf ("\n");
99     }
100 }
101 void
102 help_and_exit (char *prog)
103 {
104   printf ("otflist %s\n", LIBOTF_VERSION);
105   printf ("Usage: %s [-l] [-h] [DIR]\n", prog);
106   printf ("List information about OpenType font files in the directory DIR.\n");
107   printf ("It actually lists all fonts that can be handled by Freetype.\n");
108   printf ("  -h         print this help, then exit\n");
109   printf ("  -l         use a long listing mode\n");
110   exit (0);
111 }
112
113 int
114 filter (const struct dirent *direntry)
115 {
116   int len = strlen (direntry->d_name);
117   const char *ext = direntry->d_name + (len - 4);
118
119   return (len >= 5
120           && (! strncmp (ext, ".ttf", 4)
121               || ! strncmp (ext, ".TTF", 4)
122               || ! strncmp (ext, ".otf", 4)
123               || ! strncmp (ext, ".OTF", 4)
124               || ! strncmp (ext, ".PFA", 4)
125               || ! strncmp (ext, ".pfa", 4)
126               || ! strncmp (ext, ".PFB", 4)
127               || ! strncmp (ext, ".pfb", 4)));
128 }
129
130 int dir_index = 0;
131
132 #ifdef HAVE_SCANDIR
133
134 struct dirent **namelist = NULL;
135 int num_files = 0;
136
137 char *
138 next_file (char *dirname)
139 {
140   if (dir_index == 0)
141     {
142 #ifdef HAVE_ALPHASORT
143       num_files = scandir (".", &namelist, filter, alphasort);
144 #else
145       num_files = scandir (".", &namelist, filter, NULL);
146 #endif
147     }
148   if (dir_index == num_files)
149     return NULL;
150   return namelist[dir_index++]->d_name;
151 }
152
153 #else  /* not HAVE_SCANDIR */
154
155 DIR *dirp;
156
157 char *
158 next_file (char *dirname)
159 {
160   struct dirent *dirent;
161
162   if (dir_index == 0)
163     dirp = opendir (dirname);
164   while ((dirent = readdir (dirp))
165          && (strcmp (dirent->d_name, ".") == 0
166              || strcmp (dirent->d_name, "..") == 0));
167   if (! dirent)
168     return NULL;
169   dir_index++;
170   return dirent->d_name;
171 }
172
173 #endif /* not HAVE_SCANDIR */
174
175 int
176 main (int argc, char **argv)
177
178   FT_Library ft_library;
179   FT_Face face;
180   char *filename;
181   int long_format = 0;
182   int n;
183   int i, j;
184
185   if (FT_Init_FreeType (&ft_library))
186     FATAL_ERROR ("%s\n", "!! Freetype initialization failed.");
187
188   if (argc > 1)
189     {
190       if (! strcmp (argv[1], "-h") || ! strcmp (argv[1], "--help"))
191         help_and_exit (argv[0]);
192       if (! strcmp (argv[1], "-l"))
193         long_format = 1, argc--, argv++;
194     }
195   if (argc == 2)
196     {
197       if (chdir (argv[1]) < 0)
198         FATAL_ERROR ("Can't change directory to %s\n", argv[1]);
199     }
200
201   while ((filename = next_file (".")) != NULL)
202     {
203       if (! FT_New_Face (ft_library, filename, 0, &face))
204         {
205           OTF *otf = OTF_open (filename);
206           char *name, *family = NULL, *style = NULL;
207
208           if (otf)
209             {
210               OTF_get_table (otf, "name");
211
212               if (! (family = otf->name->name[16]))
213                 family = otf->name->name[1];
214               if (! (style = otf->name->name[17]))
215                 style = otf->name->name[2];
216             }
217           if (! family)
218             family = face->family_name;
219           if (! style)
220             style = face->style_name;
221
222           name = alloca (strlen (filename)
223                          + strlen (family)
224                          + 4);
225           sprintf (name, "%s (%s)", filename, family);
226           printf ("%-40s %s", name, style);
227           for (j = 0; j < face->num_charmaps; j++)
228             printf (" %d-%d", face->charmaps[j]->platform_id,
229                     face->charmaps[j]->encoding_id);
230           printf ("\n");
231           if (otf && long_format)
232             {
233               print_gsub_gpos_info (otf, "GSUB");
234               print_gsub_gpos_info (otf, "GPOS");
235             }
236           if (otf)
237             OTF_close (otf);
238         }
239       else
240         {
241           printf ("%s fail to open\n", filename);
242         }
243     }
244   exit (0);
245 }