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