fontdir.c revision fd60135f
1a96d7823Smrg/*
2a96d7823Smrg
3a96d7823SmrgCopyright 1991, 1998  The Open Group
4a96d7823Smrg
5a96d7823SmrgPermission to use, copy, modify, distribute, and sell this software and its
6a96d7823Smrgdocumentation for any purpose is hereby granted without fee, provided that
7a96d7823Smrgthe above copyright notice appear in all copies and that both that
8a96d7823Smrgcopyright notice and this permission notice appear in supporting
9a96d7823Smrgdocumentation.
10a96d7823Smrg
11a96d7823SmrgThe above copyright notice and this permission notice shall be included in
12a96d7823Smrgall copies or substantial portions of the Software.
13a96d7823Smrg
14a96d7823SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15a96d7823SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16a96d7823SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17a96d7823SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18a96d7823SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19a96d7823SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20a96d7823Smrg
21a96d7823SmrgExcept as contained in this notice, the name of The Open Group shall not be
22a96d7823Smrgused in advertising or otherwise to promote the sale, use or other dealings
23a96d7823Smrgin this Software without prior written authorization from The Open Group.
24a96d7823Smrg
25a96d7823Smrg*/
26a96d7823Smrg
27a96d7823Smrg/*
28a96d7823Smrg * Author:  Keith Packard, MIT X Consortium
29a96d7823Smrg */
30a96d7823Smrg
31a96d7823Smrg#ifdef HAVE_CONFIG_H
32a96d7823Smrg#include <config.h>
33a96d7823Smrg#endif
34a96d7823Smrg#include "libxfontint.h"
35a96d7823Smrg#include    <X11/fonts/fntfilst.h>
36a96d7823Smrg#include    <X11/keysym.h>
37a96d7823Smrg
38a96d7823Smrg#if HAVE_STDINT_H
39a96d7823Smrg#include <stdint.h>
40a96d7823Smrg#elif !defined(INT32_MAX)
41a96d7823Smrg#define INT32_MAX 0x7fffffff
42a96d7823Smrg#endif
43a96d7823Smrg
44a96d7823SmrgBool
45a96d7823SmrgFontFileInitTable (FontTablePtr table, int size)
46a96d7823Smrg{
47a96d7823Smrg    if (size < 0 || (size > INT32_MAX/sizeof(FontEntryRec)))
48a96d7823Smrg	return FALSE;
49a96d7823Smrg    if (size)
50a96d7823Smrg    {
51a96d7823Smrg	table->entries = malloc(sizeof(FontEntryRec) * size);
52a96d7823Smrg	if (!table->entries)
53a96d7823Smrg	    return FALSE;
54a96d7823Smrg    }
55a96d7823Smrg    else
56a96d7823Smrg	table->entries = 0;
57a96d7823Smrg    table->used = 0;
58a96d7823Smrg    table->size = size;
59a96d7823Smrg    table->sorted = FALSE;
60a96d7823Smrg    return TRUE;
61a96d7823Smrg}
62a96d7823Smrg
63a96d7823Smrgvoid
64a96d7823SmrgFontFileFreeEntry (FontEntryPtr entry)
65a96d7823Smrg{
66a96d7823Smrg    FontScalableExtraPtr   extra;
67a96d7823Smrg    int i;
68a96d7823Smrg
69a96d7823Smrg    if (entry->name.name)
70a96d7823Smrg	free(entry->name.name);
71a96d7823Smrg    entry->name.name = NULL;
72a96d7823Smrg
73a96d7823Smrg    switch (entry->type)
74a96d7823Smrg    {
75a96d7823Smrg    case FONT_ENTRY_SCALABLE:
76a96d7823Smrg	free (entry->u.scalable.fileName);
77a96d7823Smrg	extra = entry->u.scalable.extra;
78a96d7823Smrg	for (i = 0; i < extra->numScaled; i++)
79a96d7823Smrg	    if (extra->scaled[i].vals.ranges)
80a96d7823Smrg		free (extra->scaled[i].vals.ranges);
81a96d7823Smrg	free (extra->scaled);
82a96d7823Smrg	free (extra);
83a96d7823Smrg	break;
84a96d7823Smrg    case FONT_ENTRY_BITMAP:
85a96d7823Smrg	free (entry->u.bitmap.fileName);
86a96d7823Smrg	entry->u.bitmap.fileName = NULL;
87a96d7823Smrg	break;
88a96d7823Smrg    case FONT_ENTRY_ALIAS:
89a96d7823Smrg	free (entry->u.alias.resolved);
90a96d7823Smrg	entry->u.alias.resolved = NULL;
91a96d7823Smrg	break;
92a96d7823Smrg    }
93a96d7823Smrg}
94a96d7823Smrg
95a96d7823Smrgvoid
96a96d7823SmrgFontFileFreeTable (FontTablePtr table)
97a96d7823Smrg{
98a96d7823Smrg    int	i;
99a96d7823Smrg
100a96d7823Smrg    for (i = 0; i < table->used; i++)
101a96d7823Smrg	FontFileFreeEntry (&table->entries[i]);
102a96d7823Smrg    free (table->entries);
103a96d7823Smrg}
104a96d7823Smrg
105a96d7823SmrgFontDirectoryPtr
106a96d7823SmrgFontFileMakeDir(const char *dirName, int size)
107a96d7823Smrg{
108a96d7823Smrg    FontDirectoryPtr	dir;
109a96d7823Smrg    int			dirlen;
110a96d7823Smrg    int			needslash = 0;
111a96d7823Smrg    const char		*attrib;
112a96d7823Smrg    int			attriblen;
113a96d7823Smrg
114a96d7823Smrg#if !defined(WIN32)
115a96d7823Smrg    attrib = strchr(dirName, ':');
116a96d7823Smrg#else
117a96d7823Smrg    /* OS/2 uses the colon in the drive letter descriptor, skip this */
118a96d7823Smrg    attrib = strchr(dirName+2, ':');
119a96d7823Smrg#endif
120a96d7823Smrg    if (attrib) {
121a96d7823Smrg	dirlen = attrib - dirName;
122a96d7823Smrg	attriblen = strlen(attrib);
123a96d7823Smrg    } else {
124a96d7823Smrg	dirlen = strlen(dirName);
125a96d7823Smrg	attriblen = 0;
126a96d7823Smrg    }
127a96d7823Smrg    if (dirName[dirlen - 1] != '/')
128a96d7823Smrg#ifdef NCD
129a96d7823Smrg    if (dirlen)     /* leave out slash for builtins */
130a96d7823Smrg#endif
131a96d7823Smrg	needslash = 1;
132a96d7823Smrg    dir = malloc(sizeof *dir + dirlen + needslash + 1 +
133a96d7823Smrg		 (attriblen ? attriblen + 1 : 0));
134a96d7823Smrg    if (!dir)
135a96d7823Smrg	return (FontDirectoryPtr)0;
136a96d7823Smrg    if (!FontFileInitTable (&dir->scalable, 0))
137a96d7823Smrg    {
138a96d7823Smrg	free (dir);
139a96d7823Smrg	return (FontDirectoryPtr)0;
140a96d7823Smrg    }
141a96d7823Smrg    if (!FontFileInitTable (&dir->nonScalable, size))
142a96d7823Smrg    {
143a96d7823Smrg	FontFileFreeTable (&dir->scalable);
144a96d7823Smrg	free (dir);
145a96d7823Smrg	return (FontDirectoryPtr)0;
146a96d7823Smrg    }
147a96d7823Smrg    dir->directory = (char *) (dir + 1);
148a96d7823Smrg    dir->dir_mtime = 0;
149a96d7823Smrg    dir->alias_mtime = 0;
150a96d7823Smrg    if (attriblen)
151a96d7823Smrg	dir->attributes = dir->directory + dirlen + needslash + 1;
152a96d7823Smrg    else
153a96d7823Smrg	dir->attributes = NULL;
154a96d7823Smrg    strncpy(dir->directory, dirName, dirlen);
155a96d7823Smrg    dir->directory[dirlen] = '\0';
156a96d7823Smrg    if (dir->attributes)
157a96d7823Smrg	strcpy(dir->attributes, attrib);
158a96d7823Smrg    if (needslash)
159a96d7823Smrg	strcat(dir->directory, "/");
160a96d7823Smrg    return dir;
161a96d7823Smrg}
162a96d7823Smrg
163a96d7823Smrgvoid
164a96d7823SmrgFontFileFreeDir (FontDirectoryPtr dir)
165a96d7823Smrg{
166a96d7823Smrg    FontFileFreeTable (&dir->scalable);
167a96d7823Smrg    FontFileFreeTable (&dir->nonScalable);
168a96d7823Smrg    free(dir);
169a96d7823Smrg}
170a96d7823Smrg
171a96d7823SmrgFontEntryPtr
172a96d7823SmrgFontFileAddEntry(FontTablePtr table, FontEntryPtr prototype)
173a96d7823Smrg{
174a96d7823Smrg    FontEntryPtr    entry;
175a96d7823Smrg    int		    newsize;
176a96d7823Smrg
177a96d7823Smrg    /* can't add entries to a sorted table, pointers get broken! */
178a96d7823Smrg    if (table->sorted)
179a96d7823Smrg	return (FontEntryPtr) 0;    /* "cannot" happen */
180a96d7823Smrg    if (table->used == table->size) {
181a96d7823Smrg	if (table->size >= ((INT32_MAX / sizeof(FontEntryRec)) - 100))
182a96d7823Smrg	    /* If we've read so many entries we're going to ask for 2gb
183a96d7823Smrg	       or more of memory, something is so wrong with this font
184a96d7823Smrg	       directory that we should just give up before we overflow. */
185a96d7823Smrg	    return NULL;
186a96d7823Smrg	newsize = table->size + 100;
187a96d7823Smrg	entry = realloc(table->entries, newsize * sizeof(FontEntryRec));
188a96d7823Smrg	if (!entry)
189a96d7823Smrg	    return (FontEntryPtr)0;
190a96d7823Smrg	table->size = newsize;
191a96d7823Smrg	table->entries = entry;
192a96d7823Smrg    }
193a96d7823Smrg    entry = &table->entries[table->used];
194a96d7823Smrg    *entry = *prototype;
195a96d7823Smrg    entry->name.name = malloc(prototype->name.length + 1);
196a96d7823Smrg    if (!entry->name.name)
197a96d7823Smrg	return (FontEntryPtr)0;
198a96d7823Smrg    memcpy (entry->name.name, prototype->name.name, prototype->name.length);
199a96d7823Smrg    entry->name.name[entry->name.length] = '\0';
200a96d7823Smrg    table->used++;
201a96d7823Smrg    return entry;
202a96d7823Smrg}
203a96d7823Smrg
204a96d7823Smrg/*
205a96d7823Smrg * Compare two strings just like strcmp, but preserve decimal integer
206a96d7823Smrg * sorting order, i.e. "2" < "10" or "iso8859-2" < "iso8859-10" <
207a96d7823Smrg * "iso10646-1". Strings are sorted as if sequences of digits were
208a96d7823Smrg * prefixed by a length indicator (i.e., does not ignore leading zeroes).
209a96d7823Smrg *
210a96d7823Smrg * Markus Kuhn <Markus.Kuhn@cl.cam.ac.uk>
211a96d7823Smrg */
212a96d7823Smrg#define Xisdigit(c) ('\060' <= (c) && (c) <= '\071')
213a96d7823Smrg
214a96d7823Smrgstatic int strcmpn(const char *s1, const char *s2)
215a96d7823Smrg{
216a96d7823Smrg    int digits, predigits = 0;
217a96d7823Smrg    const char *ss1, *ss2;
218a96d7823Smrg
219a96d7823Smrg    while (1) {
220a96d7823Smrg	if (*s1 == 0 && *s2 == 0)
221a96d7823Smrg	    return 0;
222a96d7823Smrg	digits = Xisdigit(*s1) && Xisdigit(*s2);
223a96d7823Smrg	if (digits && !predigits) {
224a96d7823Smrg	    ss1 = s1;
225a96d7823Smrg	    ss2 = s2;
226a96d7823Smrg	    while (Xisdigit(*ss1) && Xisdigit(*ss2))
227a96d7823Smrg		ss1++, ss2++;
228a96d7823Smrg	    if (!Xisdigit(*ss1) && Xisdigit(*ss2))
229a96d7823Smrg		return -1;
230a96d7823Smrg	    if (Xisdigit(*ss1) && !Xisdigit(*ss2))
231a96d7823Smrg		return 1;
232a96d7823Smrg	}
233a96d7823Smrg	if ((unsigned char)*s1 < (unsigned char)*s2)
234a96d7823Smrg	    return -1;
235a96d7823Smrg	if ((unsigned char)*s1 > (unsigned char)*s2)
236a96d7823Smrg	    return 1;
237a96d7823Smrg	predigits = digits;
238a96d7823Smrg	s1++, s2++;
239a96d7823Smrg    }
240a96d7823Smrg}
241a96d7823Smrg
242a96d7823Smrg
243a96d7823Smrgstatic int
244a96d7823SmrgFontFileNameCompare(const void* a, const void* b)
245a96d7823Smrg{
246a96d7823Smrg    FontEntryPtr    a_name = (FontEntryPtr) a,
247a96d7823Smrg		    b_name = (FontEntryPtr) b;
248a96d7823Smrg
249a96d7823Smrg    return strcmpn(a_name->name.name, b_name->name.name);
250a96d7823Smrg}
251a96d7823Smrg
252a96d7823Smrgvoid
253a96d7823SmrgFontFileSortTable (FontTablePtr table)
254a96d7823Smrg{
255a96d7823Smrg    if (!table->sorted) {
256a96d7823Smrg	qsort((char *) table->entries, table->used, sizeof(FontEntryRec),
257a96d7823Smrg	      FontFileNameCompare);
258a96d7823Smrg	table->sorted = TRUE;
259a96d7823Smrg    }
260a96d7823Smrg}
261a96d7823Smrg
262a96d7823Smrgvoid
263a96d7823SmrgFontFileSortDir(FontDirectoryPtr dir)
264a96d7823Smrg{
265a96d7823Smrg    FontFileSortTable (&dir->scalable);
266a96d7823Smrg    FontFileSortTable (&dir->nonScalable);
267a96d7823Smrg    /* now that the table is fixed in size, swizzle the pointers */
268a96d7823Smrg    FontFileSwitchStringsToBitmapPointers (dir);
269a96d7823Smrg}
270a96d7823Smrg
271a96d7823Smrg/*
272a96d7823Smrg  Given a Font Table, SetupWildMatch() sets up various pointers and state
273a96d7823Smrg  information so the table can be searched for name(s) that match a given
274a96d7823Smrg  fontname pattern -- which may contain wildcards.  Under certain
275a96d7823Smrg  circumstances, SetupWildMatch() will find the one table entry that
276a96d7823Smrg  matches the pattern.  If those circumstances do not pertain,
277a96d7823Smrg  SetupWildMatch() returns a range within the the table that should be
278a96d7823Smrg  searched for matching name(s).  With the information established by
279a96d7823Smrg  SetupWildMatch(), including state information in "private", the
280a96d7823Smrg  PatternMatch() procedure is then used to test names in the range for a
281a96d7823Smrg  match.
282a96d7823Smrg*/
283a96d7823Smrg
284a96d7823Smrg#define isWild(c)   ((c) == XK_asterisk || (c) == XK_question)
285a96d7823Smrg#define isDigit(c)  (XK_0 <= (c) && (c) <= XK_9)
286a96d7823Smrg
287a96d7823Smrgstatic int
288a96d7823SmrgSetupWildMatch(FontTablePtr table, FontNamePtr pat,
289a96d7823Smrg	       int *leftp, int *rightp, int *privatep)
290a96d7823Smrg{
291a96d7823Smrg    int         nDashes;
292a96d7823Smrg    char        c;
293a96d7823Smrg    char       *t;
294a96d7823Smrg    char       *firstWild;
295a96d7823Smrg    char       *firstDigit;
296a96d7823Smrg    int         first;
297a96d7823Smrg    int         center,
298a96d7823Smrg                left,
299a96d7823Smrg                right;
300a96d7823Smrg    int         result;
301a96d7823Smrg    char	*name;
302a96d7823Smrg
303a96d7823Smrg    name = pat->name;
304a96d7823Smrg    nDashes = pat->ndashes;
305a96d7823Smrg    firstWild = 0;
306a96d7823Smrg    firstDigit = 0;
307a96d7823Smrg    t = name;
308a96d7823Smrg    while ((c = *t++)) {
309a96d7823Smrg	if (isWild(c)) {
310a96d7823Smrg	    if (!firstWild)
311a96d7823Smrg		firstWild = t - 1;
312a96d7823Smrg	}
313a96d7823Smrg	if (isDigit(c)) {
314a96d7823Smrg	    if (!firstDigit)
315a96d7823Smrg		firstDigit = t - 1;
316a96d7823Smrg	}
317a96d7823Smrg    }
318a96d7823Smrg    left = 0;
319a96d7823Smrg    right = table->used;
320a96d7823Smrg    if (firstWild)
321a96d7823Smrg	*privatep = nDashes;
322a96d7823Smrg    else
323a96d7823Smrg	*privatep = -1;
324a96d7823Smrg    if (!table->sorted) {
325a96d7823Smrg	*leftp = left;
326a96d7823Smrg	*rightp = right;
327a96d7823Smrg	return -1;
328a96d7823Smrg    } else if (firstWild) {
329a96d7823Smrg	if (firstDigit && firstDigit < firstWild)
330a96d7823Smrg	    first = firstDigit - name;
331a96d7823Smrg	else
332a96d7823Smrg	    first = firstWild - name;
333a96d7823Smrg	while (left < right) {
334a96d7823Smrg	    center = (left + right) / 2;
335a96d7823Smrg	    result = strncmp(name, table->entries[center].name.name, first);
336a96d7823Smrg	    if (result == 0)
337a96d7823Smrg		break;
338a96d7823Smrg	    if (result < 0)
339a96d7823Smrg		right = center;
340a96d7823Smrg	    else
341a96d7823Smrg		left = center + 1;
342a96d7823Smrg	}
343a96d7823Smrg	*leftp = left;
344a96d7823Smrg	*rightp = right;
345a96d7823Smrg	return -1;
346a96d7823Smrg    } else {
347a96d7823Smrg	while (left < right) {
348a96d7823Smrg	    center = (left + right) / 2;
349a96d7823Smrg	    result = strcmpn(name, table->entries[center].name.name);
350a96d7823Smrg	    if (result == 0)
351a96d7823Smrg		return center;
352a96d7823Smrg	    if (result < 0)
353a96d7823Smrg		right = center;
354a96d7823Smrg	    else
355a96d7823Smrg		left = center + 1;
356a96d7823Smrg	}
357a96d7823Smrg	*leftp = 1;
358a96d7823Smrg	*rightp = 0;
359a96d7823Smrg	return -1;
360a96d7823Smrg    }
361a96d7823Smrg}
362a96d7823Smrg
363a96d7823Smrgstatic int
364a96d7823SmrgPatternMatch(char *pat, int patdashes, char *string, int stringdashes)
365a96d7823Smrg{
366a96d7823Smrg    char        c,
367a96d7823Smrg                t;
368a96d7823Smrg
369a96d7823Smrg    if (stringdashes < patdashes)
370a96d7823Smrg	return 0;
371a96d7823Smrg    for (;;) {
372a96d7823Smrg	switch (c = *pat++) {
373a96d7823Smrg	case '*':
374a96d7823Smrg	    if (!(c = *pat++))
375a96d7823Smrg		return 1;
376a96d7823Smrg	    if (c == XK_minus) {
377a96d7823Smrg		patdashes--;
378a96d7823Smrg		for (;;) {
379a96d7823Smrg		    while ((t = *string++) != XK_minus)
380a96d7823Smrg			if (!t)
381a96d7823Smrg			    return 0;
382a96d7823Smrg		    stringdashes--;
383a96d7823Smrg		    if (PatternMatch(pat, patdashes, string, stringdashes))
384a96d7823Smrg			return 1;
385a96d7823Smrg		    if (stringdashes == patdashes)
386a96d7823Smrg			return 0;
387a96d7823Smrg		}
388a96d7823Smrg	    } else {
389a96d7823Smrg		for (;;) {
390a96d7823Smrg		    while ((t = *string++) != c) {
391a96d7823Smrg			if (!t)
392a96d7823Smrg			    return 0;
393a96d7823Smrg			if (t == XK_minus) {
394a96d7823Smrg			    if (stringdashes-- < patdashes)
395a96d7823Smrg				return 0;
396a96d7823Smrg			}
397a96d7823Smrg		    }
398a96d7823Smrg		    if (PatternMatch(pat, patdashes, string, stringdashes))
399a96d7823Smrg			return 1;
400a96d7823Smrg		}
401a96d7823Smrg	    }
402a96d7823Smrg	case '?':
403fd60135fSmrg	    if ((t = *string++) == XK_minus)
404a96d7823Smrg		stringdashes--;
405fd60135fSmrg	    if (!t)
406fd60135fSmrg		return 0;
407a96d7823Smrg	    break;
408a96d7823Smrg	case '\0':
409a96d7823Smrg	    return (*string == '\0');
410a96d7823Smrg	case XK_minus:
411a96d7823Smrg	    if (*string++ == XK_minus) {
412a96d7823Smrg		patdashes--;
413a96d7823Smrg		stringdashes--;
414a96d7823Smrg		break;
415a96d7823Smrg	    }
416a96d7823Smrg	    return 0;
417a96d7823Smrg	default:
418a96d7823Smrg	    if (c == *string++)
419a96d7823Smrg		break;
420a96d7823Smrg	    return 0;
421a96d7823Smrg	}
422a96d7823Smrg    }
423a96d7823Smrg}
424a96d7823Smrg
425a96d7823Smrgint
426a96d7823SmrgFontFileCountDashes (char *name, int namelen)
427a96d7823Smrg{
428a96d7823Smrg    int	ndashes = 0;
429a96d7823Smrg
430a96d7823Smrg    while (namelen--)
431a96d7823Smrg	if (*name++ == '\055')	/* avoid non ascii systems */
432a96d7823Smrg	    ++ndashes;
433a96d7823Smrg    return ndashes;
434a96d7823Smrg}
435a96d7823Smrg
436a96d7823Smrg/* exported in public API in <X11/fonts/fntfil.h> */
437a96d7823Smrgchar *
438a96d7823SmrgFontFileSaveString (char *s)
439a96d7823Smrg{
440a96d7823Smrg    return strdup(s);
441a96d7823Smrg}
442a96d7823Smrg#define FontFileSaveString(s) strdup(s)
443a96d7823Smrg
444a96d7823SmrgFontEntryPtr
445a96d7823SmrgFontFileFindNameInScalableDir(FontTablePtr table, FontNamePtr pat,
446a96d7823Smrg			      FontScalablePtr vals)
447a96d7823Smrg{
448a96d7823Smrg    int         i,
449a96d7823Smrg                start,
450a96d7823Smrg                stop,
451a96d7823Smrg                res,
452a96d7823Smrg                private;
453a96d7823Smrg    FontNamePtr	name;
454a96d7823Smrg
455a96d7823Smrg    if (!table->entries)
456a96d7823Smrg	return NULL;
457a96d7823Smrg    if ((i = SetupWildMatch(table, pat, &start, &stop, &private)) >= 0)
458a96d7823Smrg	return &table->entries[i];
459a96d7823Smrg    for (i = start; i < stop; i++) {
460a96d7823Smrg	name = &table->entries[i].name;
461a96d7823Smrg	res = PatternMatch(pat->name, private, name->name, name->ndashes);
462a96d7823Smrg	if (res > 0)
463a96d7823Smrg	{
464a96d7823Smrg	    /* Check to see if enhancements requested are available */
465a96d7823Smrg	    if (vals)
466a96d7823Smrg	    {
467a96d7823Smrg		int vs = vals->values_supplied;
468a96d7823Smrg		int cap;
469a96d7823Smrg
470a96d7823Smrg		if (table->entries[i].type == FONT_ENTRY_SCALABLE)
471a96d7823Smrg		    cap = table->entries[i].u.scalable.renderer->capabilities;
472a96d7823Smrg		else if (table->entries[i].type == FONT_ENTRY_ALIAS)
473a96d7823Smrg		    cap = ~0;	/* Calling code will have to see if true */
474a96d7823Smrg		else
475a96d7823Smrg		    cap = 0;
476a96d7823Smrg		if ((((vs & PIXELSIZE_MASK) == PIXELSIZE_ARRAY ||
477a96d7823Smrg		      (vs & POINTSIZE_MASK) == POINTSIZE_ARRAY) &&
478a96d7823Smrg		     !(cap & CAP_MATRIX)) ||
479a96d7823Smrg		    ((vs & CHARSUBSET_SPECIFIED) &&
480a96d7823Smrg		     !(cap & CAP_CHARSUBSETTING)))
481a96d7823Smrg		    continue;
482a96d7823Smrg	    }
483a96d7823Smrg	    return &table->entries[i];
484a96d7823Smrg	}
485a96d7823Smrg	if (res < 0)
486a96d7823Smrg	    break;
487a96d7823Smrg    }
488a96d7823Smrg    return (FontEntryPtr)0;
489a96d7823Smrg}
490a96d7823Smrg
491a96d7823SmrgFontEntryPtr
492a96d7823SmrgFontFileFindNameInDir(FontTablePtr table, FontNamePtr pat)
493a96d7823Smrg{
494a96d7823Smrg    return FontFileFindNameInScalableDir(table, pat, (FontScalablePtr)0);
495a96d7823Smrg}
496a96d7823Smrg
497a96d7823Smrgint
498a96d7823SmrgFontFileFindNamesInScalableDir(FontTablePtr table, FontNamePtr pat, int max,
499a96d7823Smrg			       FontNamesPtr names, FontScalablePtr vals,
500a96d7823Smrg			       int alias_behavior, int *newmax)
501a96d7823Smrg{
502a96d7823Smrg    int		    i,
503a96d7823Smrg		    start,
504a96d7823Smrg		    stop,
505a96d7823Smrg		    res,
506a96d7823Smrg		    private;
507a96d7823Smrg    int		    ret = Successful;
508a96d7823Smrg    FontEntryPtr    fname;
509a96d7823Smrg    FontNamePtr	    name;
510a96d7823Smrg
511a96d7823Smrg    if (max <= 0)
512a96d7823Smrg	return Successful;
513a96d7823Smrg    if ((i = SetupWildMatch(table, pat, &start, &stop, &private)) >= 0) {
514a96d7823Smrg	if (alias_behavior == NORMAL_ALIAS_BEHAVIOR ||
515a96d7823Smrg	    table->entries[i].type != FONT_ENTRY_ALIAS)
516a96d7823Smrg	{
517a96d7823Smrg	    name = &table->entries[i].name;
518a96d7823Smrg	    if (newmax) *newmax = max - 1;
519a96d7823Smrg	    return xfont2_add_font_names_name(names, name->name, name->length);
520a96d7823Smrg	}
521a96d7823Smrg	start = i;
522a96d7823Smrg	stop = i + 1;
523a96d7823Smrg    }
524a96d7823Smrg    for (i = start, fname = &table->entries[start]; i < stop; i++, fname++) {
525a96d7823Smrg	res = PatternMatch(pat->name, private, fname->name.name, fname->name.ndashes);
526a96d7823Smrg	if (res > 0) {
527a96d7823Smrg	    if (vals)
528a96d7823Smrg	    {
529a96d7823Smrg		int vs = vals->values_supplied;
530a96d7823Smrg		int cap;
531a96d7823Smrg
532a96d7823Smrg		if (fname->type == FONT_ENTRY_SCALABLE)
533a96d7823Smrg		    cap = fname->u.scalable.renderer->capabilities;
534a96d7823Smrg		else if (fname->type == FONT_ENTRY_ALIAS)
535a96d7823Smrg		    cap = ~0;	/* Calling code will have to see if true */
536a96d7823Smrg		else
537a96d7823Smrg		    cap = 0;
538a96d7823Smrg		if ((((vs & PIXELSIZE_MASK) == PIXELSIZE_ARRAY ||
539a96d7823Smrg		     (vs & POINTSIZE_MASK) == POINTSIZE_ARRAY) &&
540a96d7823Smrg		    !(cap & CAP_MATRIX)) ||
541a96d7823Smrg		    ((vs & CHARSUBSET_SPECIFIED) &&
542a96d7823Smrg		    !(cap & CAP_CHARSUBSETTING)))
543a96d7823Smrg		    continue;
544a96d7823Smrg	    }
545a96d7823Smrg
546a96d7823Smrg	    if ((alias_behavior & IGNORE_SCALABLE_ALIASES) &&
547a96d7823Smrg		fname->type == FONT_ENTRY_ALIAS)
548a96d7823Smrg	    {
549a96d7823Smrg		FontScalableRec	tmpvals;
550a96d7823Smrg		if (FontParseXLFDName (fname->name.name, &tmpvals,
551a96d7823Smrg				       FONT_XLFD_REPLACE_NONE) &&
552a96d7823Smrg		    !(tmpvals.values_supplied & SIZE_SPECIFY_MASK))
553a96d7823Smrg		    continue;
554a96d7823Smrg	    }
555a96d7823Smrg
556a96d7823Smrg	    ret = xfont2_add_font_names_name(names, fname->name.name, fname->name.length);
557a96d7823Smrg	    if (ret != Successful)
558a96d7823Smrg		goto bail;
559a96d7823Smrg
560a96d7823Smrg	    /* If alias_behavior is LIST_ALIASES_AND_TARGET_NAMES, mark
561a96d7823Smrg	       this entry as an alias by negating its length and follow
562a96d7823Smrg	       it by the resolved name */
563a96d7823Smrg	    if ((alias_behavior & LIST_ALIASES_AND_TARGET_NAMES) &&
564a96d7823Smrg		fname->type == FONT_ENTRY_ALIAS)
565a96d7823Smrg	    {
566a96d7823Smrg		names->length[names->nnames - 1] =
567a96d7823Smrg		    -names->length[names->nnames - 1];
568a96d7823Smrg		ret = xfont2_add_font_names_name(names, fname->u.alias.resolved,
569a96d7823Smrg				       strlen(fname->u.alias.resolved));
570a96d7823Smrg		if (ret != Successful)
571a96d7823Smrg		    goto bail;
572a96d7823Smrg	    }
573a96d7823Smrg
574a96d7823Smrg	    if (--max <= 0)
575a96d7823Smrg		break;
576a96d7823Smrg	} else if (res < 0)
577a96d7823Smrg	    break;
578a96d7823Smrg    }
579a96d7823Smrg  bail: ;
580a96d7823Smrg    if (newmax) *newmax = max;
581a96d7823Smrg    return ret;
582a96d7823Smrg}
583a96d7823Smrg
584a96d7823Smrgint
585a96d7823SmrgFontFileFindNamesInDir(FontTablePtr table, FontNamePtr pat,
586a96d7823Smrg		       int max, FontNamesPtr names)
587a96d7823Smrg{
588a96d7823Smrg    return FontFileFindNamesInScalableDir(table, pat, max, names,
589a96d7823Smrg					  (FontScalablePtr)0,
590a96d7823Smrg					  NORMAL_ALIAS_BEHAVIOR, (int *)0);
591a96d7823Smrg}
592a96d7823Smrg
593a96d7823SmrgBool
594a96d7823SmrgFontFileMatchName(char *name, int length, FontNamePtr pat)
595a96d7823Smrg{
596a96d7823Smrg    /* Perform a fontfile-type name match on a single name */
597a96d7823Smrg    FontTableRec table;
598a96d7823Smrg    FontEntryRec entries[1];
599a96d7823Smrg
600a96d7823Smrg    /* Dummy up a table */
601a96d7823Smrg    table.used = 1;
602a96d7823Smrg    table.size = 1;
603a96d7823Smrg    table.sorted = TRUE;
604a96d7823Smrg    table.entries = entries;
605a96d7823Smrg    entries[0].name.name = name;
606a96d7823Smrg    entries[0].name.length = length;
607a96d7823Smrg    entries[0].name.ndashes = FontFileCountDashes(name, length);
608a96d7823Smrg
609a96d7823Smrg    return FontFileFindNameInDir(&table, pat) != (FontEntryPtr)0;
610a96d7823Smrg}
611a96d7823Smrg
612a96d7823Smrg/*
613a96d7823Smrg * Add a font file to a directory.  This handles bitmap and
614a96d7823Smrg * scalable names both
615a96d7823Smrg */
616a96d7823Smrg
617a96d7823SmrgBool
618a96d7823SmrgFontFileAddFontFile (FontDirectoryPtr dir, char *fontName, char *fileName)
619a96d7823Smrg{
620a96d7823Smrg    FontEntryRec	    entry;
621a96d7823Smrg    FontScalableRec	    vals, zeroVals;
622a96d7823Smrg    FontRendererPtr	    renderer;
623a96d7823Smrg    FontEntryPtr	    existing;
624a96d7823Smrg    FontScalableExtraPtr    extra;
625a96d7823Smrg    FontEntryPtr	    bitmap = 0, scalable;
626a96d7823Smrg    Bool		    isscale;
627a96d7823Smrg    Bool		    scalable_xlfd;
628a96d7823Smrg
629a96d7823Smrg    renderer = FontFileMatchRenderer (fileName);
630a96d7823Smrg    if (!renderer)
631a96d7823Smrg	return FALSE;
632a96d7823Smrg    entry.name.length = strlen (fontName);
633a96d7823Smrg    if (entry.name.length > MAXFONTNAMELEN)
634a96d7823Smrg	entry.name.length = MAXFONTNAMELEN;
635a96d7823Smrg    entry.name.name = fontName;
636a96d7823Smrg    CopyISOLatin1Lowered (entry.name.name, fontName, entry.name.length);
637a96d7823Smrg    entry.name.ndashes = FontFileCountDashes (entry.name.name, entry.name.length);
638a96d7823Smrg    entry.name.name[entry.name.length] = '\0';
639a96d7823Smrg    /*
640a96d7823Smrg     * Add a bitmap name if the incoming name isn't an XLFD name, or
641a96d7823Smrg     * if it isn't a scalable name (i.e. non-zero scalable fields)
642a96d7823Smrg     *
643a96d7823Smrg     * If name of bitmapped font contains XLFD enhancements, do not add
644a96d7823Smrg     * a scalable version of the name... this can lead to confusion and
645a96d7823Smrg     * ambiguity between the font name and the field enhancements.
646a96d7823Smrg     */
647a96d7823Smrg    isscale = entry.name.ndashes == 14 &&
648a96d7823Smrg	      FontParseXLFDName(entry.name.name,
649a96d7823Smrg				&vals, FONT_XLFD_REPLACE_NONE) &&
650a96d7823Smrg	      (vals.values_supplied & PIXELSIZE_MASK) != PIXELSIZE_ARRAY &&
651a96d7823Smrg	      (vals.values_supplied & POINTSIZE_MASK) != POINTSIZE_ARRAY &&
652a96d7823Smrg	      !(vals.values_supplied & ENHANCEMENT_SPECIFY_MASK);
653a96d7823Smrg#define UNSCALED_ATTRIB "unscaled"
654a96d7823Smrg    scalable_xlfd = (isscale &&
655a96d7823Smrg		(((vals.values_supplied & PIXELSIZE_MASK) == 0) ||
656a96d7823Smrg		 ((vals.values_supplied & POINTSIZE_MASK) == 0)));
657a96d7823Smrg    /*
658a96d7823Smrg     * For scalable fonts without a scalable XFLD, check if the "unscaled"
659a96d7823Smrg     * attribute is present.
660a96d7823Smrg     */
661a96d7823Smrg    if (isscale && !scalable_xlfd &&
662a96d7823Smrg	    dir->attributes && dir->attributes[0] == ':') {
663a96d7823Smrg	char *ptr1 = dir->attributes + 1;
664a96d7823Smrg	char *ptr2;
665a96d7823Smrg	int length;
666a96d7823Smrg	int uslength = strlen(UNSCALED_ATTRIB);
667a96d7823Smrg
668a96d7823Smrg	do {
669a96d7823Smrg	    ptr2 = strchr(ptr1, ':');
670a96d7823Smrg	    if (ptr2)
671a96d7823Smrg		length = ptr2 - ptr1;
672a96d7823Smrg	    else
673a96d7823Smrg		length = dir->attributes + strlen(dir->attributes) - ptr1;
674a96d7823Smrg	    if (length == uslength && !strncmp(ptr1, UNSCALED_ATTRIB, uslength))
675a96d7823Smrg		isscale = FALSE;
676a96d7823Smrg	    if (ptr2)
677a96d7823Smrg		ptr1 = ptr2 + 1;
678a96d7823Smrg	} while (ptr2);
679a96d7823Smrg    }
680a96d7823Smrg    if (!isscale || (vals.values_supplied & SIZE_SPECIFY_MASK))
681a96d7823Smrg    {
682a96d7823Smrg      /*
683a96d7823Smrg       * If the renderer doesn't support OpenBitmap, FontFileOpenFont
684a96d7823Smrg       * will still do the right thing.
685a96d7823Smrg       */
686a96d7823Smrg	entry.type = FONT_ENTRY_BITMAP;
687a96d7823Smrg	entry.u.bitmap.renderer = renderer;
688a96d7823Smrg	entry.u.bitmap.pFont = NullFont;
689a96d7823Smrg	if (!(entry.u.bitmap.fileName = FontFileSaveString (fileName)))
690a96d7823Smrg	    return FALSE;
691a96d7823Smrg	if (!(bitmap = FontFileAddEntry (&dir->nonScalable, &entry)))
692a96d7823Smrg	{
693a96d7823Smrg	    free (entry.u.bitmap.fileName);
694a96d7823Smrg	    return FALSE;
695a96d7823Smrg	}
696a96d7823Smrg    }
697a96d7823Smrg    /*
698a96d7823Smrg     * Parse out scalable fields from XLFD names - a scalable name
699a96d7823Smrg     * just gets inserted, a scaled name has more things to do.
700a96d7823Smrg     */
701a96d7823Smrg    if (isscale)
702a96d7823Smrg    {
703a96d7823Smrg	if (vals.values_supplied & SIZE_SPECIFY_MASK)
704a96d7823Smrg	{
705a96d7823Smrg	    bzero((char *)&zeroVals, sizeof(zeroVals));
706a96d7823Smrg	    zeroVals.x = vals.x;
707a96d7823Smrg	    zeroVals.y = vals.y;
708a96d7823Smrg	    zeroVals.values_supplied = PIXELSIZE_SCALAR | POINTSIZE_SCALAR;
709a96d7823Smrg	    FontParseXLFDName (entry.name.name, &zeroVals,
710a96d7823Smrg			       FONT_XLFD_REPLACE_VALUE);
711a96d7823Smrg	    entry.name.length = strlen (entry.name.name);
712a96d7823Smrg	    existing = FontFileFindNameInDir (&dir->scalable, &entry.name);
713a96d7823Smrg	    if (existing)
714a96d7823Smrg	    {
715a96d7823Smrg		if ((vals.values_supplied & POINTSIZE_MASK) ==
716a96d7823Smrg			POINTSIZE_SCALAR &&
717a96d7823Smrg		    (int)(vals.point_matrix[3] * 10) == GetDefaultPointSize())
718a96d7823Smrg		{
719a96d7823Smrg		    existing->u.scalable.extra->defaults = vals;
720a96d7823Smrg
721a96d7823Smrg		    free (existing->u.scalable.fileName);
722a96d7823Smrg		    if (!(existing->u.scalable.fileName = FontFileSaveString (fileName)))
723a96d7823Smrg			return FALSE;
724a96d7823Smrg		}
725a96d7823Smrg                if(bitmap)
726a96d7823Smrg                {
727a96d7823Smrg                    FontFileCompleteXLFD(&vals, &vals);
728a96d7823Smrg                    FontFileAddScaledInstance (existing, &vals, NullFont,
729a96d7823Smrg                                               bitmap->name.name);
730a96d7823Smrg                    return TRUE;
731a96d7823Smrg                }
732a96d7823Smrg	    }
733a96d7823Smrg	}
734a96d7823Smrg	if (!(entry.u.scalable.fileName = FontFileSaveString (fileName)))
735a96d7823Smrg	    return FALSE;
736a96d7823Smrg	extra = malloc (sizeof (FontScalableExtraRec));
737a96d7823Smrg	if (!extra)
738a96d7823Smrg	{
739a96d7823Smrg	    free (entry.u.scalable.fileName);
740a96d7823Smrg	    return FALSE;
741a96d7823Smrg	}
742a96d7823Smrg	bzero((char *)&extra->defaults, sizeof(extra->defaults));
743a96d7823Smrg	if ((vals.values_supplied & POINTSIZE_MASK) == POINTSIZE_SCALAR &&
744a96d7823Smrg	    (int)(vals.point_matrix[3] * 10) == GetDefaultPointSize())
745a96d7823Smrg	    extra->defaults = vals;
746a96d7823Smrg	else
747a96d7823Smrg	{
748a96d7823Smrg	    FontResolutionPtr resolution;
749a96d7823Smrg	    int num;
750a96d7823Smrg	    int default_point_size = GetDefaultPointSize();
751a96d7823Smrg
752a96d7823Smrg	    extra->defaults.point_matrix[0] =
753a96d7823Smrg		extra->defaults.point_matrix[3] =
754a96d7823Smrg	            (double)default_point_size / 10.0;
755a96d7823Smrg	    extra->defaults.point_matrix[1] =
756a96d7823Smrg		extra->defaults.point_matrix[2] = 0.0;
757a96d7823Smrg	    extra->defaults.values_supplied =
758a96d7823Smrg		POINTSIZE_SCALAR | PIXELSIZE_UNDEFINED;
759a96d7823Smrg	    extra->defaults.width = -1;
760a96d7823Smrg	    if (vals.x <= 0 || vals.y <= 0)
761a96d7823Smrg	    {
762a96d7823Smrg	        resolution = GetClientResolutions (&num);
763a96d7823Smrg	        if (resolution && num > 0)
764a96d7823Smrg	        {
765a96d7823Smrg	    	    extra->defaults.x = resolution->x_resolution;
766a96d7823Smrg	    	    extra->defaults.y = resolution->y_resolution;
767a96d7823Smrg	        }
768a96d7823Smrg	        else
769a96d7823Smrg	        {
770a96d7823Smrg		    extra->defaults.x = 75;
771a96d7823Smrg		    extra->defaults.y = 75;
772a96d7823Smrg	        }
773a96d7823Smrg	     }
774a96d7823Smrg	     else
775a96d7823Smrg	     {
776a96d7823Smrg		extra->defaults.x = vals.x;
777a96d7823Smrg		extra->defaults.y = vals.y;
778a96d7823Smrg	     }
779a96d7823Smrg	     FontFileCompleteXLFD (&extra->defaults, &extra->defaults);
780a96d7823Smrg	}
781a96d7823Smrg	extra->numScaled = 0;
782a96d7823Smrg	extra->sizeScaled = 0;
783a96d7823Smrg	extra->scaled = 0;
784a96d7823Smrg	extra->private = 0;
785a96d7823Smrg	entry.type = FONT_ENTRY_SCALABLE;
786a96d7823Smrg	entry.u.scalable.renderer = renderer;
787a96d7823Smrg	entry.u.scalable.extra = extra;
788a96d7823Smrg	if (!(scalable = FontFileAddEntry (&dir->scalable, &entry)))
789a96d7823Smrg	{
790a96d7823Smrg	    free (extra);
791a96d7823Smrg	    free (entry.u.scalable.fileName);
792a96d7823Smrg	    return FALSE;
793a96d7823Smrg	}
794a96d7823Smrg	if (vals.values_supplied & SIZE_SPECIFY_MASK)
795a96d7823Smrg	{
796a96d7823Smrg            if(bitmap)
797a96d7823Smrg            {
798a96d7823Smrg                FontFileCompleteXLFD(&vals, &vals);
799a96d7823Smrg                FontFileAddScaledInstance (scalable, &vals, NullFont,
800a96d7823Smrg                                           bitmap->name.name);
801a96d7823Smrg            }
802a96d7823Smrg	}
803a96d7823Smrg    }
804a96d7823Smrg    return TRUE;
805a96d7823Smrg}
806a96d7823Smrg
807a96d7823SmrgBool
808a96d7823SmrgFontFileAddFontAlias (FontDirectoryPtr dir, char *aliasName, char *fontName)
809a96d7823Smrg{
810a96d7823Smrg    FontEntryRec	entry;
811a96d7823Smrg
812a96d7823Smrg    if (strcmp(aliasName,fontName) == 0) {
813a96d7823Smrg        /* Don't allow an alias to point to itself and create a loop */
814a96d7823Smrg        return FALSE;
815a96d7823Smrg    }
816a96d7823Smrg    entry.name.length = strlen (aliasName);
817a96d7823Smrg    CopyISOLatin1Lowered (aliasName, aliasName, entry.name.length);
818a96d7823Smrg    entry.name.name = aliasName;
819a96d7823Smrg    entry.name.ndashes = FontFileCountDashes (entry.name.name, entry.name.length);
820a96d7823Smrg    entry.type = FONT_ENTRY_ALIAS;
821a96d7823Smrg    if (!(entry.u.alias.resolved = FontFileSaveString (fontName)))
822a96d7823Smrg	return FALSE;
823a96d7823Smrg    if (!FontFileAddEntry (&dir->nonScalable, &entry))
824a96d7823Smrg    {
825a96d7823Smrg	free (entry.u.alias.resolved);
826a96d7823Smrg	return FALSE;
827a96d7823Smrg    }
828a96d7823Smrg    return TRUE;
829a96d7823Smrg}
830