]> git.wh0rd.org - fontconfig.git/blob - src/fcdir.c
Fix up fc-cache and fc-cat for no global cache changes.
[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 struct dirent *e;
136 FcStrSet *dirlist, *filelist;
137 FcChar8 *file;
138 FcChar8 *base;
139 FcBool ret = FcTrue;
140 FcFontSet *tmpSet;
141 int i;
142
143 if (config && !FcConfigAcceptFilename (config, dir))
144 return FcTrue;
145
146 if (!force)
147 {
148 if (FcDirCacheRead (set, dirs, dir, config))
149 return FcTrue;
150 }
151
152 if (FcDebug () & FC_DBG_FONTSET)
153 printf ("cache scan dir %s\n", dir);
154
155 /* freed below */
156 file = (FcChar8 *) malloc (strlen ((char *) dir) + 1 + FC_MAX_FILE_LEN + 1);
157 if (!file)
158 return FcFalse;
159
160 strcpy ((char *) file, (char *) dir);
161 strcat ((char *) file, "/");
162 base = file + strlen ((char *) file);
163
164 if (FcDebug () & FC_DBG_SCAN)
165 printf ("\tScanning dir %s\n", dir);
166
167 d = opendir ((char *) dir);
168 if (!d)
169 {
170 free (file);
171 /* Don't complain about missing directories */
172 if (errno == ENOENT)
173 return FcTrue;
174 return FcFalse;
175 }
176
177 tmpSet = FcFontSetCreate();
178 if (!tmpSet)
179 {
180 ret = FcFalse;
181 goto bail0;
182 }
183
184 dirlist = FcStrSetCreate ();
185 if (!dirlist)
186 {
187 ret = FcFalse;
188 goto bail1;
189 }
190 filelist = FcStrSetCreate ();
191 if (!filelist)
192 {
193 ret = FcFalse;
194 goto bail2;
195 }
196 while ((e = readdir (d)))
197 {
198 if (e->d_name[0] != '.' && strlen (e->d_name) < FC_MAX_FILE_LEN)
199 {
200 strcpy ((char *) base, (char *) e->d_name);
201 if (FcFileIsDir (file)) {
202 if (!FcStrSetAdd (dirlist, file)) {
203 ret = FcFalse;
204 goto bail3;
205 }
206 } else {
207 if (!FcStrSetAdd (filelist, file)) {
208 ret = FcFalse;
209 goto bail3;
210 }
211 }
212 }
213 }
214 /*
215 * Sort files and dirs to make things prettier
216 */
217 qsort(dirlist->strs, dirlist->num, sizeof(FcChar8 *), cmpstringp);
218 qsort(filelist->strs, filelist->num, sizeof(FcChar8 *), cmpstringp);
219
220 for (i = 0; i < filelist->num; i++)
221 FcFileScanFontConfig (tmpSet, blanks, filelist->strs[i], config);
222
223 /*
224 * Now that the directory has been scanned,
225 * write out the cache file
226 */
227 FcDirCacheWrite (tmpSet, dirlist, dir, config);
228
229 /*
230 * Add the discovered fonts to our internal non-cache list
231 */
232 for (i = 0; i < tmpSet->nfont; i++)
233 FcFontSetAdd (set, tmpSet->fonts[i]);
234
235 /*
236 * the patterns in tmpset now belong to set; don't free them
237 */
238 tmpSet->nfont = 0;
239
240 /*
241 * Add the discovered directories to the list to be scanned
242 */
243 for (i = 0; i < dirlist->num; i++)
244 if (!FcStrSetAdd (dirs, dirlist->strs[i])) {
245 ret = FcFalse;
246 goto bail3;
247 }
248
249 bail3:
250 FcStrSetDestroy (filelist);
251 bail2:
252 FcStrSetDestroy (dirlist);
253 bail1:
254 FcFontSetDestroy (tmpSet);
255
256 bail0:
257 closedir (d);
258
259 free (file);
260 return ret;
261 }
262
263 FcBool
264 FcDirScan (FcFontSet *set,
265 FcStrSet *dirs,
266 FcFileCache *cache, /* XXX unused */
267 FcBlanks *blanks,
268 const FcChar8 *dir,
269 FcBool force)
270 {
271 return FcDirScanConfig (set, dirs, blanks, dir, force, 0);
272 }
273
274 FcBool
275 FcDirSave (FcFontSet *set, FcStrSet * dirs, const FcChar8 *dir)
276 {
277 return FcDirCacheWrite (set, dirs, dir, FcConfigGetCurrent ());
278 }