ac72b7a73f7647f7b7404fce834996c123f27b3e
[platform/upstream/fontconfig.git] / src / fcdir.c
1 /*
2  * $XFree86: xc/lib/fontconfig/src/fcdir.c,v 1.2 2002/02/15 06:01:28 keithp Exp $
3  *
4  * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
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 static 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 FcFileScan (FcFontSet       *set,
40             FcStrSet        *dirs,
41             FcFileCache     *cache,
42             FcBlanks        *blanks,
43             const FcChar8   *file,
44             FcBool          force)
45 {
46     int             id;
47     FcChar8         *name;
48     FcPattern       *font;
49     FcBool          ret = FcTrue;
50     FcBool          isDir;
51     int             count;
52     
53     id = 0;
54     do
55     {
56         if (!force && cache)
57             name = FcFileCacheFind (cache, file, id, &count);
58         else
59             name = 0;
60         if (name)
61         {
62             /* "." means the file doesn't contain a font */
63             if (FcStrCmp (name, FC_FONT_FILE_INVALID) == 0)
64                 font = 0;
65             else if (FcStrCmp (name, FC_FONT_FILE_DIR) == 0)
66             {
67                 ret = FcStrSetAdd (dirs, file);
68                 font = 0;
69             }
70             else
71             {
72                 font = FcNameParse (name);
73                 if (font)
74                     FcPatternAddString (font, FC_FILE, file);
75             }
76         }
77         else
78         {
79             if (FcDebug () & FC_DBG_SCAN)
80             {
81                 printf ("\tScanning file %s...", file);
82                 fflush (stdout);
83             }
84             font = FcFreeTypeQuery (file, id, blanks, &count);
85             if (FcDebug () & FC_DBG_SCAN)
86                 printf ("done\n");
87             isDir = FcFalse;
88             if (!font && FcFileIsDir (file))
89             {
90                 isDir = FcTrue;
91                 ret = FcStrSetAdd (dirs, file);
92             }
93             if (!force && cache)
94             {
95                 if (font)
96                 {
97                     FcChar8     *unparse;
98
99                     unparse = FcNameUnparse (font);
100                     if (unparse)
101                     {
102                         (void) FcFileCacheUpdate (cache, file, id, unparse);
103                         free (unparse);
104                     }
105                 }
106                 else
107                 {
108                     if (isDir)
109                     {
110                         FcFileCacheUpdate (cache, file, id, (FcChar8 *) 
111                                            FC_FONT_FILE_DIR);
112                     }
113                     else
114                     {
115                         /* negative cache files not containing fonts */
116                         FcFileCacheUpdate (cache, file, id, (FcChar8 *) 
117                                            FC_FONT_FILE_INVALID);
118                     }
119                 }
120             }
121         }
122         if (font)
123         {
124             if (!FcFontSetAdd (set, font))
125             {
126                 FcPatternDestroy (font);
127                 font = 0;
128                 ret = FcFalse;
129             }
130         }
131         id++;
132     } while (font && ret && id < count);
133     return ret;
134 }
135
136 FcBool
137 FcDirCacheValid (const FcChar8 *dir)
138 {
139     FcChar8 *path;
140     FcBool  ret;
141
142     path = (FcChar8 *) malloc (strlen ((const char *) dir) + 1 + 
143                                strlen ((const char *) FC_DIR_CACHE_FILE) + 1);
144     if (!path)
145         return FcFalse;
146     strcpy ((char *) path, (const char *) dir);
147     strcat ((char *) path, (const char *) "/");
148     strcat ((char *) path, (const char *) FC_DIR_CACHE_FILE);
149     ret = FcFileCacheValid (path);
150     free (path);
151     return ret;
152 }
153
154 #define FC_MAX_FILE_LEN     4096
155
156 FcBool
157 FcDirScan (FcFontSet        *set,
158            FcStrSet         *dirs,
159            FcFileCache      *cache,
160            FcBlanks         *blanks,
161            const FcChar8    *dir,
162            FcBool           force)
163 {
164     DIR             *d;
165     struct dirent   *e;
166     FcChar8         *file;
167     FcChar8         *base;
168     FcBool          ret = FcTrue;
169
170     file = (FcChar8 *) malloc (strlen ((char *) dir) + 1 + FC_MAX_FILE_LEN + 1);
171     if (!file)
172         return FcFalse;
173
174     strcpy ((char *) file, (char *) dir);
175     strcat ((char *) file, "/");
176     base = file + strlen ((char *) file);
177     if (!force)
178     {
179         strcpy ((char *) base, FC_DIR_CACHE_FILE);
180         
181         if (FcFileCacheReadDir (set, dirs, file))
182         {
183             free (file);
184             return FcTrue;
185         }
186     }
187     
188     d = opendir ((char *) dir);
189     if (!d)
190     {
191         free (file);
192         /* Don't complain about missing directories */
193         if (errno == ENOENT)
194             return FcTrue;
195         return FcFalse;
196     }
197     while (ret && (e = readdir (d)))
198     {
199         if (e->d_name[0] != '.' && strlen (e->d_name) < FC_MAX_FILE_LEN)
200         {
201             strcpy ((char *) base, (char *) e->d_name);
202             ret = FcFileScan (set, dirs, cache, blanks, file, force);
203         }
204     }
205     free (file);
206     closedir (d);
207     return ret;
208 }
209
210 FcBool
211 FcDirSave (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
212 {
213     FcChar8         *file;
214     FcChar8         *base;
215     FcBool          ret;
216     
217     file = (FcChar8 *) malloc (strlen ((char *) dir) + 1 + 256 + 1);
218     if (!file)
219         return FcFalse;
220
221     strcpy ((char *) file, (char *) dir);
222     strcat ((char *) file, "/");
223     base = file + strlen ((char *) file);
224     strcpy ((char *) base, FC_DIR_CACHE_FILE);
225     ret = FcFileCacheWriteDir (set, dirs, file);
226     free (file);
227     return ret;
228 }