]> git.wh0rd.org - fontconfig.git/blame - src/fcdir.c
Eliminate ./ and ../ elements from font directory names when scanning.
[fontconfig.git] / src / fcdir.c
CommitLineData
24330d27 1/*
4bd4418a 2 * $RCSId: xc/lib/fontconfig/src/fcdir.c,v 1.9 2002/08/31 22:17:32 keithp Exp $
24330d27 3 *
46b51147 4 * Copyright © 2000 Keith Packard
24330d27
KP
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
24330d27 25#include "fcint.h"
179c3995
KP
26#include <dirent.h>
27
2d9c79c0 28FcBool
179c3995
KP
29FcFileIsDir (const FcChar8 *file)
30{
31 struct stat statb;
24330d27 32
179c3995
KP
33 if (stat ((const char *) file, &statb) != 0)
34 return FcFalse;
35 return S_ISDIR(statb.st_mode);
36}
24330d27 37
00f059e9
KP
38static FcBool
39FcFileScanFontConfig (FcFontSet *set,
40 FcBlanks *blanks,
41 const FcChar8 *file,
42 FcConfig *config)
24330d27 43{
00f059e9
KP
44 FcPattern *font;
45 FcBool ret = FcTrue;
46 int id;
47 int count = 0;
24330d27
KP
48
49 id = 0;
50 do
51 {
327a7fd4
KP
52 font = 0;
53 /*
eb0cf671 54 * Nothing in the cache, scan the file
327a7fd4 55 */
eb0cf671 56 if (FcDebug () & FC_DBG_SCAN)
24330d27 57 {
eb0cf671
PL
58 printf ("\tScanning file %s...", file);
59 fflush (stdout);
24330d27 60 }
eb0cf671
PL
61 font = FcFreeTypeQuery (file, id, blanks, &count);
62 if (FcDebug () & FC_DBG_SCAN)
63 printf ("done\n");
327a7fd4
KP
64 /*
65 * Add the font
66 */
4f27c1c0 67 if (font && (!config || FcConfigAcceptFont (config, font)))
24330d27
KP
68 {
69 if (!FcFontSetAdd (set, font))
70 {
71 FcPatternDestroy (font);
72 font = 0;
73 ret = FcFalse;
74 }
75 }
47b49bf1
KP
76 else if (font)
77 FcPatternDestroy (font);
24330d27
KP
78 id++;
79 } while (font && ret && id < count);
80 return ret;
81}
82
00f059e9
KP
83FcBool
84FcFileScanConfig (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
d47c9d6e
KP
100FcBool
101FcFileScan (FcFontSet *set,
102 FcStrSet *dirs,
00f059e9 103 FcFileCache *cache, /* XXX unused */
d47c9d6e
KP
104 FcBlanks *blanks,
105 const FcChar8 *file,
106 FcBool force)
107{
00f059e9 108 return FcFileScanConfig (set, dirs, blanks, file, force, 0);
d47c9d6e
KP
109}
110
e3c6d336
PL
111/*
112 * Strcmp helper that takes pointers to pointers, copied from qsort(3) manpage
113 */
114
115static int
116cmpstringp(const void *p1, const void *p2)
117{
118 return strcmp(* (char **) p1, * (char **) p2);
119}
120
c8d5753c
KP
121/*
122 * Scan 'dir', adding font files to 'set' and
123 * subdirectories to 'dirs'
124 */
125
24330d27 126FcBool
d47c9d6e
KP
127FcDirScanConfig (FcFontSet *set,
128 FcStrSet *dirs,
d47c9d6e
KP
129 FcBlanks *blanks,
130 const FcChar8 *dir,
131 FcBool force,
132 FcConfig *config)
24330d27 133{
327a7fd4 134 DIR *d;
0d9e31c8 135 FcChar8 *canon_dir;
327a7fd4 136 struct dirent *e;
00f059e9 137 FcStrSet *dirlist, *filelist;
327a7fd4
KP
138 FcChar8 *file;
139 FcChar8 *base;
140 FcBool ret = FcTrue;
eb0cf671
PL
141 FcFontSet *tmpSet;
142 int i;
24330d27 143
0d9e31c8
KP
144 canon_dir = FcStrCanonFilename (dir);
145 if (!canon_dir) canon_dir = (FcChar8 *) dir;
146 printf ("dir %s canon %s\n", dir, canon_dir);
147
148 if (config && !FcConfigAcceptFilename (config, canon_dir)) {
149 ret = FcTrue;
150 goto bail;
151 }
d47c9d6e 152
327a7fd4
KP
153 if (!force)
154 {
0d9e31c8
KP
155 if (FcDirCacheRead (set, dirs, canon_dir, config)) {
156 ret = FcTrue;
157 goto bail;
158 }
327a7fd4
KP
159 }
160
00f059e9 161 if (FcDebug () & FC_DBG_FONTSET)
0d9e31c8 162 printf ("cache scan dir %s\n", canon_dir);
00f059e9 163
9dac3c59 164 /* freed below */
0d9e31c8
KP
165 file = (FcChar8 *) malloc (strlen ((char *) canon_dir) + 1 + FC_MAX_FILE_LEN + 1);
166 if (!file) {
167 ret = FcFalse;
168 goto bail;
169 }
24330d27 170
0d9e31c8 171 strcpy ((char *) file, (char *) canon_dir);
ccb3e93b
KP
172 strcat ((char *) file, "/");
173 base = file + strlen ((char *) file);
24330d27 174
a8386abc 175 if (FcDebug () & FC_DBG_SCAN)
0d9e31c8 176 printf ("\tScanning dir %s\n", canon_dir);
a8386abc 177
0d9e31c8 178 d = opendir ((char *) canon_dir);
24330d27
KP
179 if (!d)
180 {
179c3995
KP
181 /* Don't complain about missing directories */
182 if (errno == ENOENT)
0d9e31c8
KP
183 ret = FcTrue;
184 else
185 ret = FcFalse;
186 goto bail_1;
24330d27 187 }
eb0cf671
PL
188
189 tmpSet = FcFontSetCreate();
65448e8b
PL
190 if (!tmpSet)
191 {
192 ret = FcFalse;
193 goto bail0;
eb0cf671
PL
194 }
195
00f059e9 196 dirlist = FcStrSetCreate ();
65448e8b
PL
197 if (!dirlist)
198 {
199 ret = FcFalse;
200 goto bail1;
201 }
00f059e9
KP
202 filelist = FcStrSetCreate ();
203 if (!filelist)
204 {
205 ret = FcFalse;
206 goto bail2;
207 }
e3c6d336 208 while ((e = readdir (d)))
24330d27 209 {
179c3995 210 if (e->d_name[0] != '.' && strlen (e->d_name) < FC_MAX_FILE_LEN)
24330d27 211 {
00f059e9
KP
212 strcpy ((char *) base, (char *) e->d_name);
213 if (FcFileIsDir (file)) {
214 if (!FcStrSetAdd (dirlist, file)) {
65448e8b 215 ret = FcFalse;
00f059e9
KP
216 goto bail3;
217 }
218 } else {
219 if (!FcStrSetAdd (filelist, file)) {
220 ret = FcFalse;
221 goto bail3;
65448e8b 222 }
65448e8b 223 }
24330d27
KP
224 }
225 }
00f059e9
KP
226 /*
227 * Sort files and dirs to make things prettier
228 */
229 qsort(dirlist->strs, dirlist->num, sizeof(FcChar8 *), cmpstringp);
230 qsort(filelist->strs, filelist->num, sizeof(FcChar8 *), cmpstringp);
231
232 for (i = 0; i < filelist->num; i++)
233 FcFileScanFontConfig (tmpSet, blanks, filelist->strs[i], config);
234
af180c40
KP
235 /*
236 * Now that the directory has been scanned,
237 * write out the cache file
238 */
0d9e31c8 239 FcDirCacheWrite (tmpSet, dirlist, canon_dir, config);
00f059e9 240
c8d5753c 241 /*
00f059e9 242 * Add the discovered fonts to our internal non-cache list
c8d5753c 243 */
eb0cf671
PL
244 for (i = 0; i < tmpSet->nfont; i++)
245 FcFontSetAdd (set, tmpSet->fonts[i]);
246
00f059e9
KP
247 /*
248 * the patterns in tmpset now belong to set; don't free them
249 */
250 tmpSet->nfont = 0;
65448e8b 251
00f059e9
KP
252 /*
253 * Add the discovered directories to the list to be scanned
254 */
255 for (i = 0; i < dirlist->num; i++)
256 if (!FcStrSetAdd (dirs, dirlist->strs[i])) {
257 ret = FcFalse;
258 goto bail3;
259 }
260
261 bail3:
262 FcStrSetDestroy (filelist);
65448e8b 263 bail2:
00f059e9 264 FcStrSetDestroy (dirlist);
65448e8b 265 bail1:
00f059e9 266 FcFontSetDestroy (tmpSet);
65448e8b
PL
267
268 bail0:
269 closedir (d);
270
0d9e31c8 271 bail_1:
65448e8b 272 free (file);
0d9e31c8
KP
273 bail:
274 if (canon_dir != dir) free (canon_dir);
24330d27
KP
275 return ret;
276}
277
d47c9d6e
KP
278FcBool
279FcDirScan (FcFontSet *set,
280 FcStrSet *dirs,
00f059e9 281 FcFileCache *cache, /* XXX unused */
d47c9d6e
KP
282 FcBlanks *blanks,
283 const FcChar8 *dir,
284 FcBool force)
285{
00f059e9 286 return FcDirScanConfig (set, dirs, blanks, dir, force, 0);
d47c9d6e
KP
287}
288
24330d27 289FcBool
2304e38f 290FcDirSave (FcFontSet *set, FcStrSet * dirs, const FcChar8 *dir)
24330d27 291{
7410e40b 292 return FcDirCacheWrite (set, dirs, dir, FcConfigGetCurrent ());
24330d27 293}