]> git.wh0rd.org Git - fontconfig.git/blob - src/fcdir.c
Skip broken caches. Cache files are auto-written, don't rewrite in fc-cache.
[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                   FcBool        force,
89                   FcConfig      *config)
90 {
91     if (config && !FcConfigAcceptFilename (config, file))
92         return FcTrue;
93
94     if (FcFileIsDir (file))
95         return FcStrSetAdd (dirs, file);
96     else
97         return FcFileScanFontConfig (set, blanks, file, config);
98 }
99
100 FcBool
101 FcFileScan (FcFontSet       *set,
102             FcStrSet        *dirs,
103             FcFileCache     *cache, /* XXX unused */
104             FcBlanks        *blanks,
105             const FcChar8   *file,
106             FcBool          force)
107 {
108     return FcFileScanConfig (set, dirs, blanks, file, force, 0);
109 }
110
111 /*
112  * Strcmp helper that takes pointers to pointers, copied from qsort(3) manpage
113  */
114
115 static int
116 cmpstringp(const void *p1, const void *p2)
117 {
118     return strcmp(* (char **) p1, * (char **) p2);
119 }
120
121 /*
122  * Scan 'dir', adding font files to 'set' and
123  * subdirectories to 'dirs'
124  */
125
126 FcBool
127 FcDirScanConfig (FcFontSet      *set,
128                  FcStrSet       *dirs,
129                  FcBlanks       *blanks,
130                  const FcChar8  *dir,
131                  FcBool         force,
132                  FcConfig       *config)
133 {
134     DIR                 *d;
135     FcChar8             *canon_dir;
136     struct dirent       *e;
137     FcStrSet            *dirlist, *filelist;
138     FcChar8             *file;
139     FcChar8             *base;
140     FcBool              ret = FcTrue;
141     FcFontSet           *tmpSet;
142     int                 i;
143
144     canon_dir = FcStrCanonFilename (dir);
145     if (!canon_dir) canon_dir = (FcChar8 *) dir;
146     
147     if (config && !FcConfigAcceptFilename (config, canon_dir)) {
148         ret = FcTrue;
149         goto bail;
150     }
151
152     if (!force)
153     {
154         if (FcDirCacheRead (set, dirs, canon_dir, config)) {
155             ret = FcTrue;
156             goto bail;
157         }
158     }
159     
160     if (FcDebug () & FC_DBG_FONTSET)
161         printf ("cache scan dir %s\n", canon_dir);
162
163     /* freed below */
164     file = (FcChar8 *) malloc (strlen ((char *) canon_dir) + 1 + FC_MAX_FILE_LEN + 1);
165     if (!file) {
166         ret = FcFalse;
167         goto bail;
168     }
169
170     strcpy ((char *) file, (char *) canon_dir);
171     strcat ((char *) file, "/");
172     base = file + strlen ((char *) file);
173     
174     if (FcDebug () & FC_DBG_SCAN)
175         printf ("\tScanning dir %s\n", canon_dir);
176         
177     d = opendir ((char *) canon_dir);
178     if (!d)
179     {
180         /* Don't complain about missing directories */
181         if (errno == ENOENT)
182             ret = FcTrue;
183         else
184             ret = FcFalse;
185         goto bail_1;
186     }
187
188     tmpSet = FcFontSetCreate();
189     if (!tmpSet) 
190     {
191         ret = FcFalse;
192         goto bail0;
193     }
194
195     dirlist = FcStrSetCreate ();
196     if (!dirlist) 
197     {
198         ret = FcFalse;
199         goto bail1;
200     }
201     filelist = FcStrSetCreate ();
202     if (!filelist)
203     {
204         ret = FcFalse;
205         goto bail2;
206     }
207     while ((e = readdir (d)))
208     {
209         if (e->d_name[0] != '.' && strlen (e->d_name) < FC_MAX_FILE_LEN)
210         {
211             strcpy ((char *) base, (char *) e->d_name);
212             if (FcFileIsDir (file)) {
213                 if (!FcStrSetAdd (dirlist, file)) {
214                     ret = FcFalse;
215                     goto bail3;
216                 }
217             } else {
218                 if (!FcStrSetAdd (filelist, file)) {
219                     ret = FcFalse;
220                     goto bail3;
221                 }
222             }
223         }
224     }
225     /*
226      * Sort files and dirs to make things prettier
227      */
228     qsort(dirlist->strs, dirlist->num, sizeof(FcChar8 *), cmpstringp);
229     qsort(filelist->strs, filelist->num, sizeof(FcChar8 *), cmpstringp);
230     
231     for (i = 0; i < filelist->num; i++)
232         FcFileScanFontConfig (tmpSet, blanks, filelist->strs[i], config);
233     
234     /*
235      * Now that the directory has been scanned,
236      * write out the cache file
237      */
238     FcDirCacheWrite (tmpSet, dirlist, canon_dir, config);
239
240     /*
241      * Add the discovered fonts to our internal non-cache list
242      */
243     for (i = 0; i < tmpSet->nfont; i++)
244         FcFontSetAdd (set, tmpSet->fonts[i]);
245
246     /*
247      * the patterns in tmpset now belong to set; don't free them 
248      */
249     tmpSet->nfont = 0;
250
251     /*
252      * Add the discovered directories to the list to be scanned
253      */
254     for (i = 0; i < dirlist->num; i++)
255         if (!FcStrSetAdd (dirs, dirlist->strs[i])) {
256             ret = FcFalse;
257             goto bail3;
258         }
259     
260  bail3:
261     FcStrSetDestroy (filelist);
262  bail2:
263     FcStrSetDestroy (dirlist);
264  bail1:
265     FcFontSetDestroy (tmpSet);
266     
267  bail0:
268     closedir (d);
269     
270  bail_1:
271     free (file);
272  bail:
273     if (canon_dir != dir) free (canon_dir);
274     return ret;
275 }
276
277 FcBool
278 FcDirScan (FcFontSet        *set,
279            FcStrSet         *dirs,
280            FcFileCache      *cache, /* XXX unused */
281            FcBlanks         *blanks,
282            const FcChar8    *dir,
283            FcBool           force)
284 {
285     return FcDirScanConfig (set, dirs, blanks, dir, force, 0);
286 }
287
288 FcBool
289 FcDirSave (FcFontSet *set, FcStrSet * dirs, const FcChar8 *dir)
290 {
291     return FcFalse;
292 }