5452b60ca6f91daf2c6da51610faac751e7fbb29
[platform/upstream/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     FcPattern           *font;
49     FcBool              ret = FcTrue;
50     FcBool              isDir;
51     int                 count = 0;
52     
53     if (config && !FcConfigAcceptFilename (config, file))
54         return FcTrue;
55
56     if (force)
57         cache = 0;
58     id = 0;
59     do
60     {
61         font = 0;
62         /*
63          * Nothing in the cache, scan the file
64          */
65         if (FcDebug () & FC_DBG_SCAN)
66         {
67             printf ("\tScanning file %s...", file);
68             fflush (stdout);
69         }
70         font = FcFreeTypeQuery (file, id, blanks, &count);
71         if (FcDebug () & FC_DBG_SCAN)
72             printf ("done\n");
73         isDir = FcFalse;
74         if (!font && FcFileIsDir (file))
75         {
76             isDir = FcTrue;
77             ret = FcStrSetAdd (dirs, file);
78         }
79         /*
80          * Add the font
81          */
82         if (font && (!config || FcConfigAcceptFont (config, font)))
83         {
84             if (!FcFontSetAdd (set, font))
85             {
86                 FcPatternDestroy (font);
87                 font = 0;
88                 ret = FcFalse;
89             }
90         }
91         else if (font)
92             FcPatternDestroy (font);
93         id++;
94     } while (font && ret && id < count);
95     return ret;
96 }
97
98 FcBool
99 FcFileScan (FcFontSet       *set,
100             FcStrSet        *dirs,
101             FcGlobalCache   *cache,
102             FcBlanks        *blanks,
103             const FcChar8   *file,
104             FcBool          force)
105 {
106     return FcFileScanConfig (set, dirs, cache, blanks, file, force, 0);
107 }
108
109 /*
110  * Scan 'dir', adding font files to 'set' and
111  * subdirectories to 'dirs'
112  */
113
114 FcBool
115 FcDirScanConfig (FcFontSet      *set,
116                  FcStrSet       *dirs,
117                  FcGlobalCache  *cache,
118                  FcBlanks       *blanks,
119                  const FcChar8  *dir,
120                  FcBool         force,
121                  FcConfig       *config)
122 {
123     DIR                 *d;
124     struct dirent       *e;
125     FcChar8             *file;
126     FcChar8             *base;
127     FcBool              ret = FcTrue;
128     FcFontSet           *tmpSet;
129     int                 i;
130
131     if (config && !FcConfigAcceptFilename (config, dir))
132         return FcTrue;
133
134     if (!force)
135     {
136         /*
137          * Check ~/.fonts.cache-<version> file
138          */
139         if (cache && FcGlobalCacheReadDir (set, dirs, cache, (char *)dir, config))
140             return FcTrue;
141
142         if (FcDirCacheValid (dir) && FcDirCacheRead (set, dirs, dir))
143             return FcTrue;
144     }
145     
146     /* freed below */
147     file = (FcChar8 *) malloc (strlen ((char *) dir) + 1 + FC_MAX_FILE_LEN + 1);
148     if (!file)
149         return FcFalse;
150
151     strcpy ((char *) file, (char *) dir);
152     strcat ((char *) file, "/");
153     base = file + strlen ((char *) file);
154     
155     if (FcDebug () & FC_DBG_SCAN)
156         printf ("\tScanning dir %s\n", dir);
157         
158     d = opendir ((char *) dir);
159     if (!d)
160     {
161         free (file);
162         /* Don't complain about missing directories */
163         if (errno == ENOENT)
164             return FcTrue;
165         return FcFalse;
166     }
167
168     tmpSet = FcFontSetCreate();
169     if (!tmpSet)
170     {   
171         free (file);
172         return FcFalse;
173     }
174
175     while (ret && (e = readdir (d)))
176     {
177         if (e->d_name[0] != '.' && strlen (e->d_name) < FC_MAX_FILE_LEN)
178         {
179             strcpy ((char *) base, (char *) e->d_name);
180             ret = FcFileScanConfig (tmpSet, dirs, cache, blanks, file, force, config);
181         }
182     }
183     free (file);
184     closedir (d);
185     /*
186      * Now that the directory has been scanned,
187      * add the cache entry 
188      */
189     if (ret && cache)
190         FcGlobalCacheUpdate (cache, (char *)dir, tmpSet);
191
192     for (i = 0; i < tmpSet->nfont; i++)
193         FcFontSetAdd (set, tmpSet->fonts[i]);
194
195     if (tmpSet->fonts)
196     {
197         FcMemFree (FC_MEM_FONTPTR, tmpSet->sfont * sizeof (FcPattern *));
198         free (tmpSet->fonts);
199     }
200     FcMemFree (FC_MEM_FONTSET, sizeof (FcFontSet));
201     free (tmpSet);
202         
203     return ret;
204 }
205
206 FcBool
207 FcDirScan (FcFontSet        *set,
208            FcStrSet         *dirs,
209            FcGlobalCache    *cache,
210            FcBlanks         *blanks,
211            const FcChar8    *dir,
212            FcBool           force)
213 {
214     return FcDirScanConfig (set, dirs, cache, blanks, dir, force, 0);
215 }
216
217 FcBool
218 FcDirSave (FcFontSet *set, FcStrSet * dirs, const FcChar8 *dir)
219 {
220     return FcDirCacheWrite (set, dirs, dir);
221 }