4 * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
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.
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.
28 FcFileCacheHash (const FcChar8 *string)
33 while ((c = *string++))
39 FcFileCacheFind (FcFileCache *cache,
46 FcFileCacheEnt *c, *name;
52 hash = FcFileCacheHash (match);
55 for (c = cache->ents[hash % FC_FILE_CACHE_HASH_SIZE]; c; c = c->next)
57 if (c->hash == hash && !strcmp (match, c->file))
63 if (stat ((char *) file, &statb) < 0)
65 if (FcDebug () & FC_DBG_CACHE)
66 printf (" file missing\n");
69 if (statb.st_mtime != c->time)
71 if (FcDebug () & FC_DBG_CACHE)
72 printf (" timestamp mismatch (was %d is %d)\n",
73 (int) c->time, (int) statb.st_mtime);
79 c->referenced = FcTrue;
92 * Cache file syntax is quite simple:
94 * "file_name" id time "font_name" \n
98 FcFileCacheReadString (FILE *f, FcChar8 *dest, int len)
106 while ((c = getc (f)) != EOF)
118 while ((c = getc (f)) != EOF)
133 FcChar8 *new = malloc (size * 2);
136 memcpy (new, d, size);
153 FcFileCacheReadUlong (FILE *f, unsigned long *dest)
158 while ((c = getc (f)) != EOF)
168 if (c == EOF || isspace (c))
172 t = t * 10 + (c - '0');
180 FcFileCacheReadInt (FILE *f, int *dest)
185 ret = FcFileCacheReadUlong (f, &t);
192 FcFileCacheReadTime (FILE *f, time_t *dest)
197 ret = FcFileCacheReadUlong (f, &t);
204 FcFileCacheAdd (FcFileCache *cache,
212 FcFileCacheEnt **prev, *old;
215 if (FcDebug () & FC_DBG_CACHE)
217 printf ("%s face %s/%d as %s\n", replace ? "Replace" : "Add",
220 hash = FcFileCacheHash (file);
221 for (prev = &cache->ents[hash % FC_FILE_CACHE_HASH_SIZE];
223 prev = &(*prev)->next)
225 if (old->hash == hash && old->id == id && !strcmp (old->file, file))
241 c = malloc (sizeof (FcFileCacheEnt) +
242 strlen ((char *) file) + 1 +
243 strlen ((char *) name) + 1);
249 c->file = (FcChar8 *) (c + 1);
251 c->name = c->file + strlen ((char *) file) + 1;
252 strcpy (c->file, file);
254 c->referenced = replace;
255 strcpy (c->name, name);
261 FcFileCacheCreate (void)
266 cache = malloc (sizeof (FcFileCache));
269 for (h = 0; h < FC_FILE_CACHE_HASH_SIZE; h++)
272 cache->referenced = 0;
273 cache->updated = FcFalse;
278 FcFileCacheDestroy (FcFileCache *cache)
280 FcFileCacheEnt *c, *next;
283 for (h = 0; h < FC_FILE_CACHE_HASH_SIZE; h++)
285 for (c = cache->ents[h]; c; c = next)
295 FcFileCacheLoad (FcFileCache *cache,
296 const FcChar8 *cache_file)
299 FcChar8 file_buf[8192], *file;
302 FcChar8 name_buf[8192], *name;
304 f = fopen ((char *) cache_file, "r");
308 cache->updated = FcFalse;
311 while ((file = FcFileCacheReadString (f, file_buf, sizeof (file_buf))) &&
312 FcFileCacheReadInt (f, &id) &&
313 FcFileCacheReadTime (f, &time) &&
314 (name = FcFileCacheReadString (f, name_buf, sizeof (name_buf))))
316 (void) FcFileCacheAdd (cache, file, id, time, name, FcFalse);
317 if (file != file_buf)
319 if (name != name_buf)
324 if (file && file != file_buf)
326 if (name && name != name_buf)
332 FcFileCacheUpdate (FcFileCache *cache,
337 const FcChar8 *match;
343 if (stat ((char *) file, &statb) < 0)
345 ret = FcFileCacheAdd (cache, match, id,
346 statb.st_mtime, name, FcTrue);
348 cache->updated = FcTrue;
353 FcFileCacheWriteString (FILE *f, const FcChar8 *string)
357 if (putc ('"', f) == EOF)
359 while ((c = *string++))
364 if (putc ('\\', f) == EOF)
368 if (putc (c, f) == EOF)
372 if (putc ('"', f) == EOF)
378 FcFileCacheWriteUlong (FILE *f, unsigned long t)
381 unsigned long temp, digit;
394 if (putc ((char) digit + '0', f) == EOF)
396 temp = temp - pow * digit;
403 FcFileCacheWriteInt (FILE *f, int i)
405 return FcFileCacheWriteUlong (f, (unsigned long) i);
409 FcFileCacheWriteTime (FILE *f, time_t t)
411 return FcFileCacheWriteUlong (f, (unsigned long) t);
415 FcFileCacheSave (FcFileCache *cache,
416 const FcChar8 *cache_file)
424 if (!cache->updated && cache->referenced == cache->entries)
427 lck = malloc (strlen ((char *) cache_file)*2 + 4);
430 tmp = lck + strlen ((char *) cache_file) + 2;
431 strcpy ((char *) lck, (char *) cache_file);
432 strcat ((char *) lck, "L");
433 strcpy ((char *) tmp, (char *) cache_file);
434 strcat ((char *) tmp, "T");
435 if (link ((char *) lck, (char *) cache_file) < 0 && errno != ENOENT)
437 if (access ((char *) tmp, F_OK) == 0)
439 f = fopen ((char *) tmp, "w");
443 for (h = 0; h < FC_FILE_CACHE_HASH_SIZE; h++)
445 for (c = cache->ents[h]; c; c = c->next)
449 if (!FcFileCacheWriteString (f, c->file))
451 if (putc (' ', f) == EOF)
453 if (!FcFileCacheWriteInt (f, c->id))
455 if (putc (' ', f) == EOF)
457 if (!FcFileCacheWriteTime (f, c->time))
459 if (putc (' ', f) == EOF)
461 if (!FcFileCacheWriteString (f, c->name))
463 if (putc ('\n', f) == EOF)
468 if (fclose (f) == EOF)
471 if (rename ((char *) tmp, (char *) cache_file) < 0)
474 unlink ((char *) lck);
475 cache->updated = FcFalse;
481 unlink ((char *) tmp);
483 unlink ((char *) lck);
491 FcFileCacheReadDir (FcFontSet *set, const FcChar8 *cache_file)
497 FcChar8 file_buf[8192], *file;
499 FcChar8 name_buf[8192], *name;
500 FcBool ret = FcFalse;
502 if (FcDebug () & FC_DBG_CACHE)
504 printf ("FcFileCacheReadDir cache_file \"%s\"\n", cache_file);
507 f = fopen ((char *) cache_file, "r");
510 if (FcDebug () & FC_DBG_CACHE)
512 printf (" no cache file\n");
517 base = (FcChar8 *) strrchr ((char *) cache_file, '/');
521 path = malloc (base - cache_file + 8192 + 1);
524 memcpy (path, cache_file, base - cache_file);
525 base = path + (base - cache_file);
529 while ((file = FcFileCacheReadString (f, file_buf, sizeof (file_buf))) &&
530 FcFileCacheReadInt (f, &id) &&
531 (name = FcFileCacheReadString (f, name_buf, sizeof (name_buf))))
533 font = FcNameParse (name);
537 if (FcDebug () & FC_DBG_CACHEV)
539 printf (" dir cache file \"%s\"\n", file);
541 FcPatternAddString (font, FC_FILE, path);
542 if (!FcFontSetAdd (set, font))
545 if (file != file_buf)
547 if (name != name_buf)
551 if (FcDebug () & FC_DBG_CACHE)
553 printf (" cache loaded\n");
559 if (file && file != file_buf)
561 if (name && name != name_buf)
570 FcFileCacheWriteDir (FcFontSet *set, const FcChar8 *cache_file)
575 const FcChar8 *file, *base;
580 if (FcDebug () & FC_DBG_CACHE)
581 printf ("FcFileCacheWriteDir cache_file \"%s\"\n", cache_file);
583 f = fopen ((char *) cache_file, "w");
586 if (FcDebug () & FC_DBG_CACHE)
587 printf (" can't create \"%s\"\n", cache_file);
590 for (n = 0; n < set->nfont; n++)
592 font = set->fonts[n];
593 if (FcPatternGetString (font, FC_FILE, 0, &file) != FcResultMatch)
595 base = (FcChar8 *) strrchr ((char *) file, '/');
600 if (FcPatternGetInteger (font, FC_INDEX, 0, &id) != FcResultMatch)
602 if (FcDebug () & FC_DBG_CACHEV)
603 printf (" write file \"%s\"\n", base);
604 if (!FcFileCacheWriteString (f, base))
606 if (putc (' ', f) == EOF)
608 if (!FcFileCacheWriteInt (f, id))
610 if (putc (' ', f) == EOF)
612 name = FcNameUnparse (font);
615 ret = FcFileCacheWriteString (f, name);
619 if (putc ('\n', f) == EOF)
622 if (fclose (f) == EOF)
625 if (FcDebug () & FC_DBG_CACHE)
626 printf (" cache written\n");
632 unlink ((char *) cache_file);