]> git.wh0rd.org - fontconfig.git/blob - src/fcdir.c
Add ref counting to font config patterns so that FcFontSort return values
[fontconfig.git] / src / fcdir.c
1 /*
2 * $XFree86: xc/lib/fontconfig/src/fcdir.c,v 1.5 2002/05/21 17:06:22 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 if (!FcPatternAddString (font, FC_FILE, file))
75 ret = FcFalse;
76 }
77 }
78 else
79 {
80 if (FcDebug () & FC_DBG_SCAN)
81 {
82 printf ("\tScanning file %s...", file);
83 fflush (stdout);
84 }
85 font = FcFreeTypeQuery (file, id, blanks, &count);
86 if (FcDebug () & FC_DBG_SCAN)
87 printf ("done\n");
88 isDir = FcFalse;
89 if (!font && FcFileIsDir (file))
90 {
91 isDir = FcTrue;
92 ret = FcStrSetAdd (dirs, file);
93 }
94 if (!force && cache)
95 {
96 if (font)
97 {
98 FcChar8 *unparse;
99
100 unparse = FcNameUnparse (font);
101 if (unparse)
102 {
103 (void) FcFileCacheUpdate (cache, file, id, unparse);
104 free (unparse);
105 }
106 }
107 else
108 {
109 if (isDir)
110 {
111 FcFileCacheUpdate (cache, file, id, (FcChar8 *)
112 FC_FONT_FILE_DIR);
113 }
114 else
115 {
116 /* negative cache files not containing fonts */
117 FcFileCacheUpdate (cache, file, id, (FcChar8 *)
118 FC_FONT_FILE_INVALID);
119 }
120 }
121 }
122 }
123 if (font)
124 {
125 if (!FcFontSetAdd (set, font))
126 {
127 FcPatternDestroy (font);
128 font = 0;
129 ret = FcFalse;
130 }
131 }
132 id++;
133 } while (font && ret && id < count);
134 return ret;
135 }
136
137 FcBool
138 FcDirCacheValid (const FcChar8 *dir)
139 {
140 FcChar8 *path;
141 FcBool ret;
142
143 path = (FcChar8 *) malloc (strlen ((const char *) dir) + 1 +
144 strlen ((const char *) FC_DIR_CACHE_FILE) + 1);
145 if (!path)
146 return FcFalse;
147 strcpy ((char *) path, (const char *) dir);
148 strcat ((char *) path, (const char *) "/");
149 strcat ((char *) path, (const char *) FC_DIR_CACHE_FILE);
150 ret = FcFileCacheValid (path);
151 free (path);
152 return ret;
153 }
154
155 #define FC_MAX_FILE_LEN 4096
156
157 FcBool
158 FcDirScan (FcFontSet *set,
159 FcStrSet *dirs,
160 FcFileCache *cache,
161 FcBlanks *blanks,
162 const FcChar8 *dir,
163 FcBool force)
164 {
165 DIR *d;
166 struct dirent *e;
167 FcChar8 *file;
168 FcChar8 *base;
169 FcBool ret = FcTrue;
170
171 file = (FcChar8 *) malloc (strlen ((char *) dir) + 1 + FC_MAX_FILE_LEN + 1);
172 if (!file)
173 return FcFalse;
174
175 strcpy ((char *) file, (char *) dir);
176 strcat ((char *) file, "/");
177 base = file + strlen ((char *) file);
178 if (!force)
179 {
180 strcpy ((char *) base, FC_DIR_CACHE_FILE);
181
182 if (FcFileCacheReadDir (set, dirs, file))
183 {
184 free (file);
185 return FcTrue;
186 }
187 }
188
189 d = opendir ((char *) dir);
190 if (!d)
191 {
192 free (file);
193 /* Don't complain about missing directories */
194 if (errno == ENOENT)
195 return FcTrue;
196 return FcFalse;
197 }
198 while (ret && (e = readdir (d)))
199 {
200 if (e->d_name[0] != '.' && strlen (e->d_name) < FC_MAX_FILE_LEN)
201 {
202 strcpy ((char *) base, (char *) e->d_name);
203 ret = FcFileScan (set, dirs, cache, blanks, file, force);
204 }
205 }
206 free (file);
207 closedir (d);
208 return ret;
209 }
210
211 FcBool
212 FcDirSave (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
213 {
214 FcChar8 *file;
215 FcChar8 *base;
216 FcBool ret;
217
218 file = (FcChar8 *) malloc (strlen ((char *) dir) + 1 + 256 + 1);
219 if (!file)
220 return FcFalse;
221
222 strcpy ((char *) file, (char *) dir);
223 strcat ((char *) file, "/");
224 base = file + strlen ((char *) file);
225 strcpy ((char *) base, FC_DIR_CACHE_FILE);
226 ret = FcFileCacheWriteDir (set, dirs, file);
227 free (file);
228 return ret;
229 }