]> git.wh0rd.org Git - fontconfig.git/blob - src/fcdir.c
Pass directory information around in FcCache structure. Freeze charsets.
[fontconfig.git] / src / fcdir.c
1 /*
2  * $RCSId: xc/lib/fontconfig/src/fcdir.c,v 1.9 2002/08/31 22:17:32 keithp Exp $
3  *
4  * Copyright © 2000 Keith Packard
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that
9  * copyright notice and this permission notice appear in supporting
10  * documentation, and that the name of Keith Packard not be used in
11  * advertising or publicity pertaining to distribution of the software without
12  * specific, written prior permission.  Keith Packard makes no
13  * representations about the suitability of this software for any purpose.  It
14  * is provided "as is" without express or implied warranty.
15  *
16  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22  * PERFORMANCE OF THIS SOFTWARE.
23  */
24
25 #include "fcint.h"
26 #include <dirent.h>
27
28 FcBool
29 FcFileIsDir (const FcChar8 *file)
30 {
31     struct stat     statb;
32
33     if (stat ((const char *) file, &statb) != 0)
34         return FcFalse;
35     return S_ISDIR(statb.st_mode);
36 }
37
38 static FcBool
39 FcFileScanFontConfig (FcFontSet         *set,
40                       FcBlanks          *blanks,
41                       const FcChar8     *file,
42                       FcConfig          *config)
43 {
44     FcPattern   *font;
45     FcBool      ret = FcTrue;
46     int         id;
47     int         count = 0;
48     
49     id = 0;
50     do
51     {
52         font = 0;
53         /*
54          * Nothing in the cache, scan the file
55          */
56         if (FcDebug () & FC_DBG_SCAN)
57         {
58             printf ("\tScanning file %s...", file);
59             fflush (stdout);
60         }
61         font = FcFreeTypeQuery (file, id, blanks, &count);
62         if (FcDebug () & FC_DBG_SCAN)
63             printf ("done\n");
64         /*
65          * Add the font
66          */
67         if (font && (!config || FcConfigAcceptFont (config, font)))
68         {
69             if (!FcFontSetAdd (set, font))
70             {
71                 FcPatternDestroy (font);
72                 font = 0;
73                 ret = FcFalse;
74             }
75         }
76         else if (font)
77             FcPatternDestroy (font);
78         id++;
79     } while (font && ret && id < count);
80     return ret;
81 }
82
83 FcBool
84 FcFileScanConfig (FcFontSet     *set,
85                   FcStrSet      *dirs,
86                   FcBlanks      *blanks,
87                   const FcChar8 *file,
88                   FcConfig      *config)
89 {
90     if (FcFileIsDir (file))
91         return FcStrSetAdd (dirs, file);
92     else
93         return FcFileScanFontConfig (set, blanks, file, config);
94 }
95
96 FcBool
97 FcFileScan (FcFontSet       *set,
98             FcStrSet        *dirs,
99             FcFileCache     *cache, /* XXX unused */
100             FcBlanks        *blanks,
101             const FcChar8   *file,
102             FcBool          force)
103 {
104     return FcFileScanConfig (set, dirs, blanks, file, NULL);
105 }
106
107 /*
108  * Strcmp helper that takes pointers to pointers, copied from qsort(3) manpage
109  */
110 static int
111 cmpstringp(const void *p1, const void *p2)
112 {
113     return strcmp(* (char **) p1, * (char **) p2);
114 }
115
116 /*
117  * Scan the specified directory and construct a cache of its contents
118  */
119 FcCache *
120 FcDirCacheScan (const FcChar8 *dir, FcConfig *config)
121 {
122     DIR                 *d;
123     struct dirent       *e;
124     FcStrSet            *files;
125     FcStrSet            *dirs;
126     FcChar8             *file;
127     FcChar8             *base;
128     FcBool              ret = FcTrue;
129     FcFontSet           *set;
130     int                 i;
131     FcBlanks            *blanks = FcConfigGetBlanks (config);
132     FcCache             *cache = NULL;
133
134     if (FcDebug () & FC_DBG_FONTSET)
135         printf ("cache scan dir %s\n", dir);
136
137     /* freed below */
138     file = (FcChar8 *) malloc (strlen ((char *) dir) + 1 + FC_MAX_FILE_LEN + 1);
139     if (!file) {
140         ret = FcFalse;
141         goto bail;
142     }
143
144     strcpy ((char *) file, (char *) dir);
145     strcat ((char *) file, "/");
146     base = file + strlen ((char *) file);
147     
148     if (FcDebug () & FC_DBG_SCAN)
149         printf ("\tScanning dir %s\n", dir);
150         
151     d = opendir ((char *) dir);
152     if (!d)
153     {
154         /* Don't complain about missing directories */
155         if (errno == ENOENT)
156             ret = FcTrue;
157         else
158             ret = FcFalse;
159         goto bail_1;
160     }
161
162     set = FcFontSetCreate();
163     if (!set) 
164     {
165         ret = FcFalse;
166         goto bail0;
167     }
168
169     files = FcStrSetCreate ();
170     if (!files)
171     {
172         ret = FcFalse;
173         goto bail1;
174     }
175     while ((e = readdir (d)))
176     {
177         if (e->d_name[0] != '.' && strlen (e->d_name) < FC_MAX_FILE_LEN)
178         {
179             strcpy ((char *) base, (char *) e->d_name);
180             if (!FcStrSetAdd (files, file)) {
181                 ret = FcFalse;
182                 goto bail2;
183             }
184         }
185     }
186
187     /*
188      * Sort files to make things prettier
189      */
190     qsort(files->strs, files->num, sizeof(FcChar8 *), cmpstringp);
191     
192     dirs = FcStrSetCreate ();
193     if (!dirs)
194         goto bail2;
195     
196     /*
197      * Scan file files to build font patterns
198      */
199     for (i = 0; i < files->num; i++)
200         FcFileScanConfig (set, dirs, blanks, files->strs[i], config);
201     
202     /*
203      * Build the cache object
204      */
205     cache = FcDirCacheBuild (set, dir, dirs);
206     if (!cache)
207         goto bail3;
208     
209     /*
210      * Write out the cache file, ignoring any troubles
211      */
212     FcDirCacheWrite (cache, config);
213     
214  bail3:
215     FcStrSetDestroy (dirs);
216  bail2:
217     FcStrSetDestroy (files);
218  bail1:
219     FcFontSetDestroy (set);
220     
221  bail0:
222     closedir (d);
223     
224  bail_1:
225     free (file);
226  bail:
227     return cache;
228 }
229
230 /*
231  * Read (or construct) the cache for a directory
232  */
233 FcCache *
234 FcDirCacheRead (const FcChar8 *dir, FcBool force, FcConfig *config)
235 {
236     FcCache             *cache = NULL;
237     FcChar8             *canon_dir;
238
239     canon_dir = FcStrCanonFilename (dir);
240     if (!canon_dir) canon_dir = (FcChar8 *) dir;
241     
242     if (config && !FcConfigAcceptFilename (config, canon_dir)) {
243         goto bail;
244     }
245
246     /* Try to use existing cache file */
247     if (!force)
248         cache = FcDirCacheLoad (canon_dir, config, NULL);
249     
250     /* Not using existing cache file, construct new cache */
251     if (!cache)
252         cache = FcDirCacheScan (canon_dir, config);
253     
254 bail:
255     if (canon_dir != dir) 
256         free (canon_dir);
257     
258     return cache;
259 }
260
261 FcBool
262 FcDirScanConfig (FcFontSet      *set,
263                  FcStrSet       *dirs,
264                  FcBlanks       *blanks,
265                  const FcChar8  *dir,
266                  FcBool         force,
267                  FcConfig       *config)
268 {
269     return FcFalse; /* XXX fixme */
270 }
271
272 FcBool
273 FcDirScan (FcFontSet        *set,
274            FcStrSet         *dirs,
275            FcFileCache      *cache, /* XXX unused */
276            FcBlanks         *blanks,
277            const FcChar8    *dir,
278            FcBool           force)
279 {
280     return FcDirScanConfig (set, dirs, blanks, dir, force, NULL);
281 }
282
283 FcBool
284 FcDirSave (FcFontSet *set, FcStrSet * dirs, const FcChar8 *dir)
285 {
286     return FcFalse; /* XXX deprecated */
287 }