]> git.wh0rd.org - 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 }