2 * Copyright © 2007 Red Hat, Inc
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
24 * Kristian Høgsberg <krh@redhat.com>
30 #include <X11/fonts/fntfilst.h>
31 #include <sys/types.h>
36 static const char CataloguePrefix[] = "catalogue:";
38 static int CatalogueFreeFPE (FontPathElementPtr fpe);
41 CatalogueNameCheck (char *name)
43 return strncmp(name, CataloguePrefix, sizeof(CataloguePrefix) - 1) == 0;
46 typedef struct _CatalogueRec {
48 int fpeCount, fpeAlloc;
49 FontPathElementPtr *fpeList;
50 } CatalogueRec, *CataloguePtr;
53 CatalogueAddFPE (CataloguePtr cat, FontPathElementPtr fpe)
55 FontPathElementPtr *new;
57 if (cat->fpeCount >= cat->fpeAlloc)
59 if (cat->fpeAlloc == 0)
64 new = realloc(cat->fpeList, cat->fpeAlloc * sizeof(FontPathElementPtr));
71 cat->fpeList[cat->fpeCount++] = fpe;
76 static const char PriorityAttribute[] = "pri=";
79 ComparePriority(const void *p1, const void *p2)
81 FontDirectoryPtr dir1 = (*(FontPathElementPtr*) p1)->private;
82 FontDirectoryPtr dir2 = (*(FontPathElementPtr*) p2)->private;
83 const char *pri1 = NULL;
84 const char *pri2 = NULL;
86 if (dir1->attributes != NULL)
87 pri1 = strstr(dir1->attributes, PriorityAttribute);
88 if (dir2->attributes != NULL)
89 pri2 = strstr(dir2->attributes, PriorityAttribute);
91 if (pri1 == NULL && pri2 == NULL)
93 else if (pri1 == NULL)
95 else if (pri2 == NULL)
99 atoi(pri1 + strlen(PriorityAttribute)) -
100 atoi(pri2 + strlen(PriorityAttribute));
104 CatalogueUnrefFPEs (FontPathElementPtr fpe)
106 CataloguePtr cat = fpe->private;
107 FontPathElementPtr subfpe;
110 for (i = 0; i < cat->fpeCount; i++)
112 subfpe = cat->fpeList[i];
114 if (subfpe->refcount == 0)
116 FontFileFreeFPE (subfpe);
125 /* Rescan catalogue directory if modified timestamp has changed or
126 * the forceScan argument says to do it anyway (like on first load). */
128 CatalogueRescan (FontPathElementPtr fpe, Bool forceScan)
130 CataloguePtr cat = fpe->private;
131 char link[MAXFONTFILENAMELEN];
132 char dest[MAXFONTFILENAMELEN];
134 FontPathElementPtr subfpe;
138 struct dirent *entry;
142 path = fpe->name + strlen(CataloguePrefix);
143 if (stat(path, &statbuf) < 0 || !S_ISDIR(statbuf.st_mode))
146 if ((forceScan == FALSE) && (statbuf.st_mtime <= cat->mtime))
156 CatalogueUnrefFPEs (fpe);
157 while (entry = readdir(dir), entry != NULL)
159 snprintf(link, sizeof link, "%s/%s", path, entry->d_name);
160 len = readlink(link, dest, sizeof dest - 1);
168 pathlen = strlen(path);
169 memmove(dest + pathlen + 1, dest, sizeof dest - pathlen - 1);
170 memcpy(dest, path, pathlen);
171 memcpy(dest + pathlen, "/", 1);
175 attrib = strchr(link, ':');
176 if (attrib && len + strlen(attrib) < sizeof dest)
178 memcpy(dest + len, attrib, strlen(attrib));
179 len += strlen(attrib);
182 subfpe = malloc(sizeof *subfpe);
186 /* The fonts returned by OpenFont will point back to the
187 * subfpe they come from. So set the type of the subfpe to
188 * what the catalogue fpe was assigned, so calls to CloseFont
189 * (which uses font->fpe->type) goes to CatalogueCloseFont. */
190 subfpe->type = fpe->type;
191 subfpe->name_length = len;
192 subfpe->name = malloc (len + 1);
199 memcpy(subfpe->name, dest, len);
200 subfpe->name[len] = '\0';
202 /* The X server will manipulate the subfpe ref counts
203 * associated with the font in OpenFont and CloseFont, so we
204 * have to make sure it's valid. */
205 subfpe->refcount = 1;
207 if (FontFileInitFPE (subfpe) != Successful)
214 if (CatalogueAddFPE(cat, subfpe) != Successful)
216 FontFileFreeFPE (subfpe);
225 cat->fpeCount, sizeof cat->fpeList[0], ComparePriority);
227 cat->mtime = statbuf.st_mtime;
233 CatalogueInitFPE (FontPathElementPtr fpe)
237 cat = malloc(sizeof *cat);
241 fpe->private = (pointer) cat;
247 return CatalogueRescan (fpe, TRUE);
251 CatalogueResetFPE (FontPathElementPtr fpe)
253 /* Always just tell the caller to close and re-open */
254 return FPEResetFailed;
258 CatalogueFreeFPE (FontPathElementPtr fpe)
260 CataloguePtr cat = fpe->private;
262 /* If the catalogue is modified while the xserver has fonts open
263 * from the previous subfpes, we'll unref the old subfpes when we
264 * reload the catalogue, and the xserver will the call FreeFPE on
265 * them once it drops its last reference. Thus, the FreeFPE call
266 * for the subfpe ends up here and we just forward it to
267 * FontFileFreeFPE. */
269 if (!CatalogueNameCheck (fpe->name))
270 return FontFileFreeFPE (fpe);
272 CatalogueUnrefFPEs (fpe);
280 CatalogueOpenFont (pointer client, FontPathElementPtr fpe, Mask flags,
281 char *name, int namelen,
282 fsBitmapFormat format, fsBitmapFormatMask fmask,
283 XID id, FontPtr *pFont, char **aliasName,
284 FontPtr non_cachable_font)
286 CataloguePtr cat = fpe->private;
287 FontPathElementPtr subfpe;
288 FontDirectoryPtr dir;
291 CatalogueRescan (fpe, FALSE);
293 for (i = 0; i < cat->fpeCount; i++)
295 subfpe = cat->fpeList[i];
296 dir = subfpe->private;
297 status = FontFileOpenFont(client, subfpe, flags,
298 name, namelen, format, fmask, id,
299 pFont, aliasName, non_cachable_font);
300 if (status == Successful || status == FontNameAlias)
308 CatalogueCloseFont (FontPathElementPtr fpe, FontPtr pFont)
310 /* Note: this gets called with the actual subfpe where we found
311 * the font, not the catalogue fpe. */
313 FontFileCloseFont(fpe, pFont);
317 CatalogueListFonts (pointer client, FontPathElementPtr fpe, char *pat,
318 int len, int max, FontNamesPtr names)
320 CataloguePtr cat = fpe->private;
321 FontPathElementPtr subfpe;
322 FontDirectoryPtr dir;
325 CatalogueRescan (fpe, FALSE);
327 for (i = 0; i < cat->fpeCount; i++)
329 subfpe = cat->fpeList[i];
330 dir = subfpe->private;
331 FontFileListFonts(client, subfpe, pat, len, max, names);
338 FontFileStartListFonts(pointer client, FontPathElementPtr fpe,
339 char *pat, int len, int max,
340 pointer *privatep, int mark_aliases);
342 typedef struct _LFWIData {
345 } LFWIDataRec, *LFWIDataPtr;
348 CatalogueStartListFonts(pointer client, FontPathElementPtr fpe,
349 char *pat, int len, int max, pointer *privatep,
352 CataloguePtr cat = fpe->private;
356 CatalogueRescan (fpe, FALSE);
358 data = malloc (sizeof *data + sizeof data->privates[0] * cat->fpeCount);
361 data->privates = (pointer *) (data + 1);
363 for (i = 0; i < cat->fpeCount; i++)
365 ret = FontFileStartListFonts(client, cat->fpeList[i], pat, len,
366 max, &data->privates[i], mark_aliases);
367 if (ret != Successful)
372 *privatep = (pointer) data;
376 for (j = 0; j < i; j++)
377 /* FIXME: we have no way to free the per-fpe privates. */;
384 CatalogueStartListFontsWithInfo(pointer client, FontPathElementPtr fpe,
385 char *pat, int len, int max,
388 return CatalogueStartListFonts(client, fpe, pat, len, max, privatep, 0);
392 CatalogueListNextFontWithInfo(pointer client, FontPathElementPtr fpe,
393 char **namep, int *namelenp,
394 FontInfoPtr *pFontInfo,
395 int *numFonts, pointer private)
397 LFWIDataPtr data = private;
398 CataloguePtr cat = fpe->private;
401 if (data->current == cat->fpeCount)
407 ret = FontFileListNextFontWithInfo(client, cat->fpeList[data->current],
410 data->privates[data->current]);
411 if (ret == BadFontName)
414 return CatalogueListNextFontWithInfo(client, fpe, namep, namelenp,
415 pFontInfo, numFonts, private);
422 CatalogueStartListFontsAndAliases(pointer client, FontPathElementPtr fpe,
423 char *pat, int len, int max,
426 return CatalogueStartListFonts(client, fpe, pat, len, max, privatep, 1);
430 CatalogueListNextFontOrAlias(pointer client, FontPathElementPtr fpe,
431 char **namep, int *namelenp, char **resolvedp,
432 int *resolvedlenp, pointer private)
434 LFWIDataPtr data = private;
435 CataloguePtr cat = fpe->private;
438 if (data->current == cat->fpeCount)
444 ret = FontFileListNextFontOrAlias(client, cat->fpeList[data->current],
446 resolvedp, resolvedlenp,
447 data->privates[data->current]);
448 if (ret == BadFontName)
451 return CatalogueListNextFontOrAlias(client, fpe, namep, namelenp,
452 resolvedp, resolvedlenp, private);
459 CatalogueRegisterLocalFpeFunctions (void)
461 RegisterFPEFunctions(CatalogueNameCheck,
468 CatalogueStartListFontsWithInfo,
469 CatalogueListNextFontWithInfo,
473 CatalogueStartListFontsAndAliases,
474 CatalogueListNextFontOrAlias,
475 FontFileEmptyBitmapSource);