]> git.wh0rd.org Git - fontconfig.git/blob - src/fcdir.c
Change default set of fonts to include all of /usr/X11R6/lib/X11/fonts (or
[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 FcBool
39 FcFileScanConfig (FcFontSet     *set,
40                   FcStrSet      *dirs,
41                   FcGlobalCache *cache,
42                   FcBlanks      *blanks,
43                   const FcChar8 *file,
44                   FcBool        force,
45                   FcConfig      *config)
46 {
47     int                 id;
48     FcChar8             *name;
49     FcPattern           *font;
50     FcBool              ret = FcTrue;
51     FcBool              isDir;
52     int                 count = 0;
53     FcGlobalCacheFile   *cache_file;
54     FcGlobalCacheDir    *cache_dir;
55     FcBool              need_scan;
56     
57     if (config && !FcConfigAcceptFilename (config, file))
58         return FcTrue;
59
60     if (force)
61         cache = 0;
62     id = 0;
63     do
64     {
65         need_scan = FcTrue;
66         font = 0;
67         /*
68          * Check the cache
69          */
70         if (cache)
71         {
72             if ((cache_file = FcGlobalCacheFileGet (cache, file, id, &count)))
73             {
74                 /*
75                  * Found a cache entry for the file
76                  */
77                 if (FcGlobalCacheCheckTime (file, &cache_file->info))
78                 {
79                     name = cache_file->name;
80                     need_scan = FcFalse;
81                     FcGlobalCacheReferenced (cache, &cache_file->info);
82                     /* "." means the file doesn't contain a font */
83                     if (FcStrCmp (name, FC_FONT_FILE_INVALID) != 0)
84                     {
85                         font = FcNameParse (name);
86                         if (font)
87                             if (!FcPatternAddString (font, FC_FILE, file))
88                                 ret = FcFalse;
89                     }
90                 }
91             }
92             else if ((cache_dir = FcGlobalCacheDirGet (cache, file,
93                                                        strlen ((const char *) file),
94                                                        FcFalse)))
95             {
96                 if (FcGlobalCacheCheckTime (cache_dir->info.file, 
97                                             &cache_dir->info))
98                 {
99                     font = 0;
100                     need_scan = FcFalse;
101                     FcGlobalCacheReferenced (cache, &cache_dir->info);
102                     if (!FcStrSetAdd (dirs, file))
103                         ret = FcFalse;
104                 }
105             }
106         }
107         /*
108          * Nothing in the cache, scan the file
109          */
110         if (need_scan)
111         {
112             if (FcDebug () & FC_DBG_SCAN)
113             {
114                 printf ("\tScanning file %s...", file);
115                 fflush (stdout);
116             }
117             font = FcFreeTypeQuery (file, id, blanks, &count);
118             if (FcDebug () & FC_DBG_SCAN)
119                 printf ("done\n");
120             isDir = FcFalse;
121             if (!font && FcFileIsDir (file))
122             {
123                 isDir = FcTrue;
124                 ret = FcStrSetAdd (dirs, file);
125             }
126             /*
127              * Update the cache
128              */
129             if (cache && font)
130             {
131                 FcChar8 *unparse;
132
133                 unparse = FcNameUnparse (font);
134                 if (unparse)
135                 {
136                     (void) FcGlobalCacheUpdate (cache, file, id, unparse);
137                     FcStrFree (unparse);
138                 }
139             }
140         }
141         /*
142          * Add the font
143          */
144         if (font && (!config || FcConfigAcceptFont (config, font)))
145         {
146             if (!FcFontSetAdd (set, font))
147             {
148                 FcPatternDestroy (font);
149                 font = 0;
150                 ret = FcFalse;
151             }
152         }
153         id++;
154     } while (font && ret && id < count);
155     return ret;
156 }
157
158 FcBool
159 FcFileScan (FcFontSet       *set,
160             FcStrSet        *dirs,
161             FcGlobalCache   *cache,
162             FcBlanks        *blanks,
163             const FcChar8   *file,
164             FcBool          force)
165 {
166     return FcFileScanConfig (set, dirs, cache, blanks, file, force, 0);
167 }
168
169 /*
170  * Scan 'dir', adding font files to 'set' and
171  * subdirectories to 'dirs'
172  */
173
174 FcBool
175 FcDirScanConfig (FcFontSet      *set,
176                  FcStrSet       *dirs,
177                  FcGlobalCache  *cache,
178                  FcBlanks       *blanks,
179                  const FcChar8  *dir,
180                  FcBool         force,
181                  FcConfig       *config)
182 {
183     DIR                 *d;
184     struct dirent       *e;
185     FcChar8             *file;
186     FcChar8             *base;
187     FcBool              ret = FcTrue;
188
189     if (config && !FcConfigAcceptFilename (config, dir))
190         return FcTrue;
191
192     if (!force)
193     {
194         /*
195          * Check fonts.cache-<version> file
196          */
197         if (FcDirCacheReadDir (set, dirs, dir, config))
198         {
199             if (cache)
200                 FcGlobalCacheReferenceSubdir (cache, dir);
201             return FcTrue;
202         }
203     
204         /*
205          * Check ~/.fonts.cache-<version> file
206          */
207         if (cache && FcGlobalCacheScanDir (set, dirs, cache, dir, config))
208             return FcTrue;
209     }
210     
211     /* freed below */
212     file = (FcChar8 *) malloc (strlen ((char *) dir) + 1 + FC_MAX_FILE_LEN + 1);
213     if (!file)
214         return FcFalse;
215
216     strcpy ((char *) file, (char *) dir);
217     strcat ((char *) file, "/");
218     base = file + strlen ((char *) file);
219     
220     if (FcDebug () & FC_DBG_SCAN)
221         printf ("\tScanning dir %s\n", dir);
222         
223     d = opendir ((char *) dir);
224     
225     if (!d)
226     {
227         free (file);
228         /* Don't complain about missing directories */
229         if (errno == ENOENT)
230             return FcTrue;
231         return FcFalse;
232     }
233     while (ret && (e = readdir (d)))
234     {
235         if (e->d_name[0] != '.' && strlen (e->d_name) < FC_MAX_FILE_LEN)
236         {
237             strcpy ((char *) base, (char *) e->d_name);
238             ret = FcFileScanConfig (set, dirs, cache, blanks, file, force, config);
239         }
240     }
241     free (file);
242     closedir (d);
243     /*
244      * Now that the directory has been scanned,
245      * add the cache entry 
246      */
247     if (ret && cache)
248         FcGlobalCacheUpdate (cache, dir, 0, 0);
249         
250     return ret;
251 }
252
253 FcBool
254 FcDirScan (FcFontSet        *set,
255            FcStrSet         *dirs,
256            FcGlobalCache    *cache,
257            FcBlanks         *blanks,
258            const FcChar8    *dir,
259            FcBool           force)
260 {
261     return FcDirScanConfig (set, dirs, cache, blanks, dir, force, 0);
262 }
263
264 FcBool
265 FcDirSave (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
266 {
267     return FcDirCacheWriteDir (set, dirs, dir);
268 }