fontfile.c revision c7b4381a
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#ifdef WIN32
38a96d7823Smrg#include <ctype.h>
39a96d7823Smrg#endif
40c7b4381aSmrg#include "src/util/replace.h"
41a96d7823Smrg
42a96d7823Smrgstatic unsigned char
43a96d7823SmrgISOLatin1ToLower(unsigned char source)
44a96d7823Smrg{
45a96d7823Smrg    if (source >= XK_A && source <= XK_Z)
46a96d7823Smrg	return source + (XK_a - XK_A);
47a96d7823Smrg    if (source >= XK_Agrave && source <= XK_Odiaeresis)
48a96d7823Smrg	return source + (XK_agrave - XK_Agrave);
49a96d7823Smrg    if (source >= XK_Ooblique && source <= XK_Thorn)
50a96d7823Smrg	return source + (XK_oslash - XK_Ooblique);
51a96d7823Smrg    return source;
52a96d7823Smrg}
53a96d7823Smrg
54a96d7823Smrg_X_HIDDEN void
55a96d7823SmrgCopyISOLatin1Lowered(char *dest, const char *source, int length)
56a96d7823Smrg{
57a96d7823Smrg    int i;
58a96d7823Smrg    for (i = 0; i < length; i++, source++, dest++)
59a96d7823Smrg	*dest = ISOLatin1ToLower(*source);
60a96d7823Smrg    *dest = '\0';
61a96d7823Smrg}
62a96d7823Smrg
63a96d7823Smrg/*
64a96d7823Smrg * Map FPE functions to renderer functions
65a96d7823Smrg */
66a96d7823Smrg
67a96d7823Smrgstatic int FontFileOpenBitmapNCF (FontPathElementPtr fpe, FontPtr *pFont,
68a96d7823Smrg				  int flags, FontEntryPtr entry,
69a96d7823Smrg				  fsBitmapFormat format,
70a96d7823Smrg				  fsBitmapFormatMask fmask,
71a96d7823Smrg				  FontPtr non_cachable_font);
72a96d7823Smrg
73a96d7823Smrgint
74a96d7823SmrgFontFileNameCheck (const char *name)
75a96d7823Smrg{
76a96d7823Smrg#ifndef NCD
77a96d7823Smrg#if defined(WIN32)
78a96d7823Smrg    /* OS/2 uses D:/... as a path name for fonts, so accept this as a valid
79a96d7823Smrg     * path if it starts with a letter and a colon. Same applies for WIN32
80a96d7823Smrg     */
81a96d7823Smrg    if (isalpha(*name) && name[1]==':')
82a96d7823Smrg        return TRUE;
83a96d7823Smrg#endif
84a96d7823Smrg    return *name == '/';
85a96d7823Smrg#else
86a96d7823Smrg    return ((strcmp(name, "built-ins") == 0) || (*name == '/'));
87a96d7823Smrg#endif
88a96d7823Smrg}
89a96d7823Smrg
90a96d7823Smrgint
91a96d7823SmrgFontFileInitFPE (FontPathElementPtr fpe)
92a96d7823Smrg{
93a96d7823Smrg    int			status;
94a96d7823Smrg    FontDirectoryPtr	dir;
95a96d7823Smrg
96a96d7823Smrg    status = FontFileReadDirectory (fpe->name, &dir);
97a96d7823Smrg    if (status == Successful)
98a96d7823Smrg    {
99a96d7823Smrg	if (dir->nonScalable.used > 0)
100a96d7823Smrg	    if (!FontFileRegisterBitmapSource (fpe))
101a96d7823Smrg	    {
102a96d7823Smrg		FontFileFreeFPE (fpe);
103a96d7823Smrg		return AllocError;
104a96d7823Smrg	    }
105a96d7823Smrg	fpe->private = (pointer) dir;
106a96d7823Smrg    }
107a96d7823Smrg    return status;
108a96d7823Smrg}
109a96d7823Smrg
110a96d7823Smrg/* ARGSUSED */
111a96d7823Smrgint
112a96d7823SmrgFontFileResetFPE (FontPathElementPtr fpe)
113a96d7823Smrg{
114a96d7823Smrg    FontDirectoryPtr	dir;
115a96d7823Smrg
116a96d7823Smrg    dir = (FontDirectoryPtr) fpe->private;
117a96d7823Smrg    /*
118a96d7823Smrg     * The reset must fail for bitmap fonts because they get cleared when
119a96d7823Smrg     * the path is set.
120a96d7823Smrg     */
121a96d7823Smrg    if (FontFileDirectoryChanged (dir))
122a96d7823Smrg    {
123a96d7823Smrg	/* can't do it, so tell the caller to close and re-open */
124a96d7823Smrg	return FPEResetFailed;
125a96d7823Smrg    }
126a96d7823Smrg    else
127a96d7823Smrg    {
128a96d7823Smrg	if (dir->nonScalable.used > 0)
129a96d7823Smrg	    if (!FontFileRegisterBitmapSource (fpe))
130a96d7823Smrg	    {
131a96d7823Smrg	        return FPEResetFailed;
132a96d7823Smrg	    }
133a96d7823Smrg        return Successful;
134a96d7823Smrg    }
135a96d7823Smrg}
136a96d7823Smrg
137a96d7823Smrgint
138a96d7823SmrgFontFileFreeFPE (FontPathElementPtr fpe)
139a96d7823Smrg{
140a96d7823Smrg    FontFileUnregisterBitmapSource (fpe);
141a96d7823Smrg    FontFileFreeDir ((FontDirectoryPtr) fpe->private);
142a96d7823Smrg    return Successful;
143a96d7823Smrg}
144a96d7823Smrg
145a96d7823Smrgstatic int
146a96d7823Smrgtransfer_values_to_alias(char *entryname, int entrynamelength,
147a96d7823Smrg			 char *resolvedname,
148a96d7823Smrg			 char **aliasName, FontScalablePtr vals)
149a96d7823Smrg{
150a96d7823Smrg    static char		aliasname[MAXFONTNAMELEN];
151a96d7823Smrg    int			nameok = 1, len;
152a96d7823Smrg    char		lowerName[MAXFONTNAMELEN];
153a96d7823Smrg
154a96d7823Smrg    *aliasName = resolvedname;
155a96d7823Smrg    if ((len = strlen(*aliasName)) <= MAXFONTNAMELEN &&
156a96d7823Smrg	(entrynamelength < MAXFONTNAMELEN) &&
157a96d7823Smrg	FontFileCountDashes (*aliasName, len) == 14)
158a96d7823Smrg    {
159a96d7823Smrg	FontScalableRec tmpVals;
160a96d7823Smrg	FontScalableRec tmpVals2;
161a96d7823Smrg
162a96d7823Smrg	tmpVals2 = *vals;
163a96d7823Smrg
164a96d7823Smrg	/* If we're aliasing a scalable name, transfer values
165a96d7823Smrg	   from the name into the destination alias, multiplying
166a96d7823Smrg	   by matrices that appear in the alias. */
167a96d7823Smrg
168a96d7823Smrg	CopyISOLatin1Lowered (lowerName, entryname,
169a96d7823Smrg			      entrynamelength);
170a96d7823Smrg	lowerName[entrynamelength] = '\0';
171a96d7823Smrg
172a96d7823Smrg	if (FontParseXLFDName(lowerName, &tmpVals,
173a96d7823Smrg			      FONT_XLFD_REPLACE_NONE) &&
174a96d7823Smrg	    !tmpVals.values_supplied &&
175a96d7823Smrg	    FontParseXLFDName(*aliasName, &tmpVals,
176a96d7823Smrg			      FONT_XLFD_REPLACE_NONE))
177a96d7823Smrg	{
178a96d7823Smrg	    double *matrix = 0, tempmatrix[4];
179a96d7823Smrg
180a96d7823Smrg	    /* Use a matrix iff exactly one is defined */
181a96d7823Smrg	    if ((tmpVals.values_supplied & PIXELSIZE_MASK) ==
182a96d7823Smrg		PIXELSIZE_ARRAY &&
183a96d7823Smrg		!(tmpVals.values_supplied & POINTSIZE_MASK))
184a96d7823Smrg		matrix = tmpVals.pixel_matrix;
185a96d7823Smrg	    else if ((tmpVals.values_supplied & POINTSIZE_MASK) ==
186a96d7823Smrg		     POINTSIZE_ARRAY &&
187a96d7823Smrg		     !(tmpVals.values_supplied & PIXELSIZE_MASK))
188a96d7823Smrg		matrix = tmpVals.point_matrix;
189a96d7823Smrg
190a96d7823Smrg	    /* If matrix given in the alias, compute new point
191a96d7823Smrg	       and/or pixel matrices */
192a96d7823Smrg	    if (matrix)
193a96d7823Smrg	    {
194a96d7823Smrg		/* Complete the XLFD name to avoid potential
195a96d7823Smrg		   gotchas */
196a96d7823Smrg		if (FontFileCompleteXLFD(&tmpVals2, &tmpVals2))
197a96d7823Smrg		{
198a96d7823Smrg		    tempmatrix[0] =
199a96d7823Smrg			matrix[0] * tmpVals2.point_matrix[0] +
200a96d7823Smrg			matrix[1] * tmpVals2.point_matrix[2];
201a96d7823Smrg		    tempmatrix[1] =
202a96d7823Smrg			matrix[0] * tmpVals2.point_matrix[1] +
203a96d7823Smrg			matrix[1] * tmpVals2.point_matrix[3];
204a96d7823Smrg		    tempmatrix[2] =
205a96d7823Smrg			matrix[2] * tmpVals2.point_matrix[0] +
206a96d7823Smrg			matrix[3] * tmpVals2.point_matrix[2];
207a96d7823Smrg		    tempmatrix[3] =
208a96d7823Smrg			matrix[2] * tmpVals2.point_matrix[1] +
209a96d7823Smrg			matrix[3] * tmpVals2.point_matrix[3];
210a96d7823Smrg		    tmpVals2.point_matrix[0] = tempmatrix[0];
211a96d7823Smrg		    tmpVals2.point_matrix[1] = tempmatrix[1];
212a96d7823Smrg		    tmpVals2.point_matrix[2] = tempmatrix[2];
213a96d7823Smrg		    tmpVals2.point_matrix[3] = tempmatrix[3];
214a96d7823Smrg
215a96d7823Smrg		    tempmatrix[0] =
216a96d7823Smrg			matrix[0] * tmpVals2.pixel_matrix[0] +
217a96d7823Smrg			matrix[1] * tmpVals2.pixel_matrix[2];
218a96d7823Smrg		    tempmatrix[1] =
219a96d7823Smrg			matrix[0] * tmpVals2.pixel_matrix[1] +
220a96d7823Smrg			matrix[1] * tmpVals2.pixel_matrix[3];
221a96d7823Smrg		    tempmatrix[2] =
222a96d7823Smrg			matrix[2] * tmpVals2.pixel_matrix[0] +
223a96d7823Smrg			matrix[3] * tmpVals2.pixel_matrix[2];
224a96d7823Smrg		    tempmatrix[3] =
225a96d7823Smrg			matrix[2] * tmpVals2.pixel_matrix[1] +
226a96d7823Smrg			matrix[3] * tmpVals2.pixel_matrix[3];
227a96d7823Smrg		    tmpVals2.pixel_matrix[0] = tempmatrix[0];
228a96d7823Smrg		    tmpVals2.pixel_matrix[1] = tempmatrix[1];
229a96d7823Smrg		    tmpVals2.pixel_matrix[2] = tempmatrix[2];
230a96d7823Smrg		    tmpVals2.pixel_matrix[3] = tempmatrix[3];
231a96d7823Smrg
232a96d7823Smrg		    tmpVals2.values_supplied =
233a96d7823Smrg			(tmpVals2.values_supplied &
234a96d7823Smrg			 ~(PIXELSIZE_MASK | POINTSIZE_MASK)) |
235a96d7823Smrg			PIXELSIZE_ARRAY | POINTSIZE_ARRAY;
236a96d7823Smrg		}
237a96d7823Smrg		else
238a96d7823Smrg		    nameok = 0;
239a96d7823Smrg	    }
240a96d7823Smrg
241a96d7823Smrg	    CopyISOLatin1Lowered (aliasname, *aliasName, len + 1);
242a96d7823Smrg	    if (nameok && FontParseXLFDName(aliasname, &tmpVals2,
243a96d7823Smrg				  FONT_XLFD_REPLACE_VALUE))
244a96d7823Smrg		/* Return a version of the aliasname that has
245a96d7823Smrg		   had the vals stuffed into it.  To avoid
246a96d7823Smrg		   memory leak, this alias name lives in a
247a96d7823Smrg		   static buffer.  The caller needs to be done
248a96d7823Smrg		   with this buffer before this procedure is
249a96d7823Smrg		   called again to avoid reentrancy problems. */
250a96d7823Smrg		    *aliasName = aliasname;
251a96d7823Smrg	}
252a96d7823Smrg    }
253a96d7823Smrg    return nameok;
254a96d7823Smrg}
255a96d7823Smrg
256a96d7823Smrg/* ARGSUSED */
257a96d7823Smrgint
258a96d7823SmrgFontFileOpenFont (pointer client, FontPathElementPtr fpe, Mask flags,
259a96d7823Smrg		  const char *name, int namelen,
260a96d7823Smrg		  fsBitmapFormat format, fsBitmapFormatMask fmask,
261a96d7823Smrg		  XID id, FontPtr *pFont, char **aliasName,
262a96d7823Smrg		  FontPtr non_cachable_font)
263a96d7823Smrg{
264a96d7823Smrg    FontDirectoryPtr	dir;
265a96d7823Smrg    char		lowerName[MAXFONTNAMELEN];
266a96d7823Smrg    char		fileName[MAXFONTFILENAMELEN*2 + 1];
267a96d7823Smrg    FontNameRec		tmpName;
268a96d7823Smrg    FontEntryPtr	entry;
269a96d7823Smrg    FontScalableRec	vals;
270a96d7823Smrg    FontScalableEntryPtr   scalable;
271a96d7823Smrg    FontScaledPtr	scaled;
272a96d7823Smrg    FontBitmapEntryPtr	bitmap;
273a96d7823Smrg    int			ret;
274a96d7823Smrg    Bool		noSpecificSize;
275a96d7823Smrg    int			nranges;
276a96d7823Smrg    fsRange		*ranges;
277a96d7823Smrg
278a96d7823Smrg    if (namelen >= MAXFONTNAMELEN)
279a96d7823Smrg	return AllocError;
280a96d7823Smrg    dir = (FontDirectoryPtr) fpe->private;
281a96d7823Smrg
282a96d7823Smrg    /* Match non-scalable pattern */
283a96d7823Smrg    CopyISOLatin1Lowered (lowerName, name, namelen);
284a96d7823Smrg    lowerName[namelen] = '\0';
285a96d7823Smrg    ranges = FontParseRanges(lowerName, &nranges);
286a96d7823Smrg    tmpName.name = lowerName;
287a96d7823Smrg    tmpName.length = namelen;
288a96d7823Smrg    tmpName.ndashes = FontFileCountDashes (lowerName, namelen);
289a96d7823Smrg    if (!FontParseXLFDName(lowerName, &vals, FONT_XLFD_REPLACE_NONE))
290a96d7823Smrg	bzero(&vals, sizeof(vals));
291a96d7823Smrg    if (!(entry = FontFileFindNameInDir (&dir->nonScalable, &tmpName)) &&
292a96d7823Smrg	tmpName.ndashes == 14 &&
293a96d7823Smrg	FontParseXLFDName (lowerName, &vals, FONT_XLFD_REPLACE_ZERO))
294a96d7823Smrg    {
295a96d7823Smrg        tmpName.length = strlen(lowerName);
296a96d7823Smrg	entry = FontFileFindNameInDir (&dir->nonScalable, &tmpName);
297a96d7823Smrg    }
298a96d7823Smrg
299a96d7823Smrg    if (entry)
300a96d7823Smrg    {
301a96d7823Smrg	switch (entry->type) {
302a96d7823Smrg	case FONT_ENTRY_BITMAP:
303a96d7823Smrg	    bitmap = &entry->u.bitmap;
304a96d7823Smrg	    if (bitmap->pFont)
305a96d7823Smrg	    {
306a96d7823Smrg	    	*pFont = bitmap->pFont;
307a96d7823Smrg		(*pFont)->fpe = fpe;
308a96d7823Smrg	    	ret = Successful;
309a96d7823Smrg	    }
310a96d7823Smrg	    else
311a96d7823Smrg	    {
312a96d7823Smrg		ret = FontFileOpenBitmapNCF (fpe, pFont, flags, entry, format,
313a96d7823Smrg					     fmask, non_cachable_font);
314a96d7823Smrg		if (ret == Successful && *pFont)
315a96d7823Smrg		    (*pFont)->fpe = fpe;
316a96d7823Smrg	    }
317a96d7823Smrg	    break;
318a96d7823Smrg	case FONT_ENTRY_ALIAS:
319a96d7823Smrg	    vals.nranges = nranges;
320a96d7823Smrg	    vals.ranges = ranges;
321a96d7823Smrg	    transfer_values_to_alias(entry->name.name, entry->name.length,
322a96d7823Smrg				     entry->u.alias.resolved, aliasName, &vals);
323a96d7823Smrg	    ret = FontNameAlias;
324a96d7823Smrg	    break;
325a96d7823Smrg	default:
326a96d7823Smrg	    ret = BadFontName;
327a96d7823Smrg	}
328a96d7823Smrg    }
329a96d7823Smrg    else
330a96d7823Smrg    {
331a96d7823Smrg	ret = BadFontName;
332a96d7823Smrg    }
333a96d7823Smrg
334a96d7823Smrg    if (ret != BadFontName)
335a96d7823Smrg    {
336a96d7823Smrg	if (ranges) free(ranges);
337a96d7823Smrg	return ret;
338a96d7823Smrg    }
339a96d7823Smrg
340a96d7823Smrg    /* Match XLFD patterns */
341a96d7823Smrg    CopyISOLatin1Lowered (lowerName, name, namelen);
342a96d7823Smrg    lowerName[namelen] = '\0';
343a96d7823Smrg    tmpName.name = lowerName;
344a96d7823Smrg    tmpName.length = namelen;
345a96d7823Smrg    tmpName.ndashes = FontFileCountDashes (lowerName, namelen);
346a96d7823Smrg    if (!FontParseXLFDName (lowerName, &vals, FONT_XLFD_REPLACE_ZERO) ||
347a96d7823Smrg	!(tmpName.length = strlen (lowerName),
348a96d7823Smrg	  entry = FontFileFindNameInScalableDir (&dir->scalable, &tmpName,
349a96d7823Smrg						 &vals))) {
350a96d7823Smrg	CopyISOLatin1Lowered (lowerName, name, namelen);
351a96d7823Smrg	lowerName[namelen] = '\0';
352a96d7823Smrg	tmpName.name = lowerName;
353a96d7823Smrg	tmpName.length = namelen;
354a96d7823Smrg	tmpName.ndashes = FontFileCountDashes (lowerName, namelen);
355a96d7823Smrg	entry = FontFileFindNameInScalableDir (&dir->scalable, &tmpName, &vals);
356a96d7823Smrg	if (entry)
357a96d7823Smrg	{
358c7b4381aSmrg	    strlcpy(lowerName, entry->name.name, sizeof(lowerName));
359a96d7823Smrg	    tmpName.name = lowerName;
360a96d7823Smrg	    tmpName.length = entry->name.length;
361a96d7823Smrg	    tmpName.ndashes = entry->name.ndashes;
362a96d7823Smrg	}
363a96d7823Smrg    }
364a96d7823Smrg
365a96d7823Smrg    if (entry)
366a96d7823Smrg    {
367a96d7823Smrg	noSpecificSize = FALSE;	/* TRUE breaks XLFD enhancements */
368a96d7823Smrg    	if (entry->type == FONT_ENTRY_SCALABLE &&
369a96d7823Smrg	    FontFileCompleteXLFD (&vals, &entry->u.scalable.extra->defaults))
370a96d7823Smrg	{
371a96d7823Smrg	    scalable = &entry->u.scalable;
372a96d7823Smrg	    if ((vals.values_supplied & PIXELSIZE_MASK) == PIXELSIZE_ARRAY ||
373a96d7823Smrg		(vals.values_supplied & POINTSIZE_MASK) == POINTSIZE_ARRAY ||
374a96d7823Smrg		(vals.values_supplied &
375a96d7823Smrg		 ~SIZE_SPECIFY_MASK & ~CHARSUBSET_SPECIFIED))
376a96d7823Smrg		scaled = 0;
377a96d7823Smrg	    else
378a96d7823Smrg	        scaled = FontFileFindScaledInstance (entry, &vals,
379a96d7823Smrg						     noSpecificSize);
380a96d7823Smrg	    /*
381a96d7823Smrg	     * A scaled instance can occur one of two ways:
382a96d7823Smrg	     *
383a96d7823Smrg	     *  Either the font has been scaled to this
384a96d7823Smrg	     *   size already, in which case scaled->pFont
385a96d7823Smrg	     *   will point at that font.
386a96d7823Smrg	     *
387a96d7823Smrg	     *  Or a bitmap instance in this size exists,
388a96d7823Smrg	     *   which is handled as if we got a pattern
389a96d7823Smrg	     *   matching the bitmap font name.
390a96d7823Smrg	     */
391a96d7823Smrg	    if (scaled)
392a96d7823Smrg	    {
393a96d7823Smrg		if (scaled->pFont)
394a96d7823Smrg		{
395a96d7823Smrg		    *pFont = scaled->pFont;
396a96d7823Smrg		    (*pFont)->fpe = fpe;
397a96d7823Smrg		    ret = Successful;
398a96d7823Smrg		}
399a96d7823Smrg		else if (scaled->bitmap)
400a96d7823Smrg		{
401a96d7823Smrg		    entry = scaled->bitmap;
402a96d7823Smrg		    bitmap = &entry->u.bitmap;
403a96d7823Smrg		    if (bitmap->pFont)
404a96d7823Smrg		    {
405a96d7823Smrg			*pFont = bitmap->pFont;
406a96d7823Smrg			(*pFont)->fpe = fpe;
407a96d7823Smrg			ret = Successful;
408a96d7823Smrg		    }
409a96d7823Smrg		    else
410a96d7823Smrg		    {
411a96d7823Smrg			ret = FontFileOpenBitmapNCF (fpe, pFont, flags, entry,
412a96d7823Smrg						     format, fmask,
413a96d7823Smrg						     non_cachable_font);
414a96d7823Smrg			if (ret == Successful && *pFont)
415a96d7823Smrg			    (*pFont)->fpe = fpe;
416a96d7823Smrg		    }
417a96d7823Smrg		}
418a96d7823Smrg		else /* "cannot" happen */
419a96d7823Smrg		{
420a96d7823Smrg		    ret = BadFontName;
421a96d7823Smrg		}
422a96d7823Smrg	    }
423a96d7823Smrg	    else
424a96d7823Smrg	    {
425a96d7823Smrg		ret = FontFileMatchBitmapSource (fpe, pFont, flags, entry, &tmpName, &vals, format, fmask, noSpecificSize);
426a96d7823Smrg		if (ret != Successful)
427a96d7823Smrg		{
428a96d7823Smrg		    char origName[MAXFONTNAMELEN];
429a96d7823Smrg
430a96d7823Smrg		    CopyISOLatin1Lowered (origName, name, namelen);
431a96d7823Smrg		    origName[namelen] = '\0';
432a96d7823Smrg
433a96d7823Smrg		    /* Pass the original XLFD name in the vals
434a96d7823Smrg		       structure; the rasterizer is free to examine it
435a96d7823Smrg		       for hidden meanings.  This information will not
436a96d7823Smrg		       be saved in the scaled-instances table.  */
437a96d7823Smrg
438a96d7823Smrg		    vals.xlfdName = origName;
439a96d7823Smrg		    vals.ranges = ranges;
440a96d7823Smrg		    vals.nranges = nranges;
441a96d7823Smrg
442a96d7823Smrg		    if (strlen(dir->directory) + strlen(scalable->fileName) >=
443a96d7823Smrg			sizeof(fileName)) {
444a96d7823Smrg			ret = BadFontName;
445a96d7823Smrg		    } else {
446c7b4381aSmrg			strlcpy (fileName, dir->directory, sizeof(fileName));
447c7b4381aSmrg			strlcat (fileName, scalable->fileName, sizeof(fileName));
448a96d7823Smrg                        if (scalable->renderer->OpenScalable) {
449a96d7823Smrg			    ret = (*scalable->renderer->OpenScalable) (fpe, pFont,
450a96d7823Smrg			       flags, entry, fileName, &vals, format, fmask,
451a96d7823Smrg			       non_cachable_font);
452a96d7823Smrg                        }
453a96d7823Smrg                        else if (scalable->renderer->OpenBitmap) {
454a96d7823Smrg                            ret = (*scalable->renderer->OpenBitmap) (fpe, pFont,
455a96d7823Smrg                               flags, entry, fileName, format, fmask,
456a96d7823Smrg                               non_cachable_font);
457a96d7823Smrg                        }
458a96d7823Smrg		    }
459a96d7823Smrg
460a96d7823Smrg		    /* In case rasterizer does something bad because of
461a96d7823Smrg		       charset subsetting... */
462a96d7823Smrg		    if (ret == Successful &&
463a96d7823Smrg			((*pFont)->info.firstCol > (*pFont)->info.lastCol ||
464a96d7823Smrg			 (*pFont)->info.firstRow > (*pFont)->info.lastRow))
465a96d7823Smrg		    {
466a96d7823Smrg			(*(*pFont)->unload_font)(*pFont);
467a96d7823Smrg			ret = BadFontName;
468a96d7823Smrg		    }
469a96d7823Smrg		    /* Save the instance */
470a96d7823Smrg		    if (ret == Successful)
471a96d7823Smrg		    {
472a96d7823Smrg		    	if (FontFileAddScaledInstance (entry, &vals,
473a96d7823Smrg						    *pFont, (char *) 0))
474a96d7823Smrg			    ranges = 0;
475a96d7823Smrg			else
476a96d7823Smrg			    (*pFont)->fpePrivate = (pointer) 0;
477a96d7823Smrg			(*pFont)->fpe = fpe;
478a96d7823Smrg		    }
479a96d7823Smrg		}
480a96d7823Smrg	    }
481a96d7823Smrg	}
482a96d7823Smrg    }
483a96d7823Smrg    else
484a96d7823Smrg	ret = BadFontName;
485a96d7823Smrg
486a96d7823Smrg    if (ranges)
487a96d7823Smrg	free(ranges);
488a96d7823Smrg    return ret;
489a96d7823Smrg}
490a96d7823Smrg
491a96d7823Smrg/* ARGSUSED */
492a96d7823Smrgvoid
493a96d7823SmrgFontFileCloseFont (FontPathElementPtr fpe, FontPtr pFont)
494a96d7823Smrg{
495a96d7823Smrg    FontEntryPtr    entry;
496a96d7823Smrg
497a96d7823Smrg    if ((entry = (FontEntryPtr) pFont->fpePrivate)) {
498a96d7823Smrg	switch (entry->type) {
499a96d7823Smrg	case FONT_ENTRY_SCALABLE:
500a96d7823Smrg	    FontFileRemoveScaledInstance (entry, pFont);
501a96d7823Smrg	    break;
502a96d7823Smrg	case FONT_ENTRY_BITMAP:
503a96d7823Smrg	    entry->u.bitmap.pFont = 0;
504a96d7823Smrg	    break;
505a96d7823Smrg	default:
506a96d7823Smrg	    /* "cannot" happen */
507a96d7823Smrg	    break;
508a96d7823Smrg	}
509a96d7823Smrg	pFont->fpePrivate = 0;
510a96d7823Smrg    }
511a96d7823Smrg    (*pFont->unload_font) (pFont);
512a96d7823Smrg}
513a96d7823Smrg
514a96d7823Smrgstatic int
515a96d7823SmrgFontFileOpenBitmapNCF (FontPathElementPtr fpe, FontPtr *pFont,
516a96d7823Smrg		       int flags, FontEntryPtr entry,
517a96d7823Smrg		       fsBitmapFormat format, fsBitmapFormatMask fmask,
518a96d7823Smrg		       FontPtr non_cachable_font)
519a96d7823Smrg{
520a96d7823Smrg    FontBitmapEntryPtr	bitmap;
521a96d7823Smrg    char		fileName[MAXFONTFILENAMELEN*2+1];
522a96d7823Smrg    int			ret;
523a96d7823Smrg    FontDirectoryPtr	dir;
524a96d7823Smrg
525a96d7823Smrg    dir = (FontDirectoryPtr) fpe->private;
526a96d7823Smrg    bitmap = &entry->u.bitmap;
527a96d7823Smrg    if(!bitmap || !bitmap->renderer->OpenBitmap)
528a96d7823Smrg        return BadFontName;
529a96d7823Smrg    if (strlen(dir->directory) + strlen(bitmap->fileName) >= sizeof(fileName))
530a96d7823Smrg	return BadFontName;
531c7b4381aSmrg    strlcpy (fileName, dir->directory, sizeof(fileName));
532c7b4381aSmrg    strlcat (fileName, bitmap->fileName, sizeof(fileName));
533a96d7823Smrg    ret = (*bitmap->renderer->OpenBitmap)
534a96d7823Smrg			(fpe, pFont, flags, entry, fileName, format, fmask,
535a96d7823Smrg			 non_cachable_font);
536a96d7823Smrg    if (ret == Successful)
537a96d7823Smrg    {
538a96d7823Smrg	bitmap->pFont = *pFont;
539a96d7823Smrg	(*pFont)->fpePrivate = (pointer) entry;
540a96d7823Smrg    }
541a96d7823Smrg    return ret;
542a96d7823Smrg}
543a96d7823Smrg
544a96d7823Smrgint
545a96d7823SmrgFontFileOpenBitmap (FontPathElementPtr fpe, FontPtr *pFont,
546a96d7823Smrg		    int flags, FontEntryPtr entry,
547a96d7823Smrg		    fsBitmapFormat format, fsBitmapFormatMask fmask)
548a96d7823Smrg{
549a96d7823Smrg    return FontFileOpenBitmapNCF (fpe, pFont, flags, entry, format, fmask,
550a96d7823Smrg				  (FontPtr)0);
551a96d7823Smrg}
552a96d7823Smrg
553a96d7823Smrgstatic int
554a96d7823SmrgFontFileGetInfoBitmap (FontPathElementPtr fpe, FontInfoPtr pFontInfo,
555a96d7823Smrg		       FontEntryPtr entry)
556a96d7823Smrg{
557a96d7823Smrg    FontBitmapEntryPtr	bitmap;
558a96d7823Smrg    char		fileName[MAXFONTFILENAMELEN*2+1];
559a96d7823Smrg    int			ret;
560a96d7823Smrg    FontDirectoryPtr	dir;
561a96d7823Smrg
562a96d7823Smrg    dir = (FontDirectoryPtr) fpe->private;
563a96d7823Smrg    bitmap = &entry->u.bitmap;
564a96d7823Smrg    if (!bitmap || !bitmap->renderer->GetInfoBitmap)
565a96d7823Smrg	return BadFontName;
566a96d7823Smrg    if (strlen(dir->directory) + strlen(bitmap->fileName) >= sizeof(fileName))
567a96d7823Smrg	return BadFontName;
568c7b4381aSmrg    strlcpy (fileName, dir->directory, sizeof(fileName));
569c7b4381aSmrg    strlcat (fileName, bitmap->fileName, sizeof(fileName));
570a96d7823Smrg    ret = (*bitmap->renderer->GetInfoBitmap) (fpe, pFontInfo, entry, fileName);
571a96d7823Smrg    return ret;
572a96d7823Smrg}
573a96d7823Smrg
574a96d7823Smrgstatic void
575a96d7823Smrg_FontFileAddScalableNames(FontNamesPtr names, FontNamesPtr scaleNames,
576a96d7823Smrg			  FontNamePtr nameptr, char *zeroChars,
577a96d7823Smrg			  FontScalablePtr vals, fsRange *ranges,
578a96d7823Smrg			  int nranges, int *max)
579a96d7823Smrg{
580a96d7823Smrg    int i;
581a96d7823Smrg    FontScalableRec	zeroVals, tmpVals;
582a96d7823Smrg    for (i = 0; i < scaleNames->nnames; i++)
583a96d7823Smrg    {
584a96d7823Smrg	char nameChars[MAXFONTNAMELEN];
585a96d7823Smrg	if (!*max)
586a96d7823Smrg	    return;
587a96d7823Smrg	FontParseXLFDName (scaleNames->names[i], &zeroVals,
588a96d7823Smrg			   FONT_XLFD_REPLACE_NONE);
589a96d7823Smrg	tmpVals = *vals;
590a96d7823Smrg	if (FontFileCompleteXLFD (&tmpVals, &zeroVals))
591a96d7823Smrg	{
592a96d7823Smrg	    --*max;
593a96d7823Smrg
594c7b4381aSmrg	    strlcpy (nameChars, scaleNames->names[i], sizeof(nameChars));
595a96d7823Smrg	    if ((vals->values_supplied & PIXELSIZE_MASK) ||
596a96d7823Smrg		!(vals->values_supplied & PIXELSIZE_WILDCARD) ||
597a96d7823Smrg		vals->y == 0)
598a96d7823Smrg	    {
599a96d7823Smrg		tmpVals.values_supplied =
600a96d7823Smrg		    (tmpVals.values_supplied & ~PIXELSIZE_MASK) |
601a96d7823Smrg		    (vals->values_supplied & PIXELSIZE_MASK);
602a96d7823Smrg		tmpVals.pixel_matrix[0] = vals->pixel_matrix[0];
603a96d7823Smrg		tmpVals.pixel_matrix[1] = vals->pixel_matrix[1];
604a96d7823Smrg		tmpVals.pixel_matrix[2] = vals->pixel_matrix[2];
605a96d7823Smrg		tmpVals.pixel_matrix[3] = vals->pixel_matrix[3];
606a96d7823Smrg	    }
607a96d7823Smrg	    if ((vals->values_supplied & POINTSIZE_MASK) ||
608a96d7823Smrg		!(vals->values_supplied & POINTSIZE_WILDCARD) ||
609a96d7823Smrg		vals->y == 0)
610a96d7823Smrg	    {
611a96d7823Smrg		tmpVals.values_supplied =
612a96d7823Smrg		    (tmpVals.values_supplied & ~POINTSIZE_MASK) |
613a96d7823Smrg		    (vals->values_supplied & POINTSIZE_MASK);
614a96d7823Smrg		tmpVals.point_matrix[0] = vals->point_matrix[0];
615a96d7823Smrg		tmpVals.point_matrix[1] = vals->point_matrix[1];
616a96d7823Smrg		tmpVals.point_matrix[2] = vals->point_matrix[2];
617a96d7823Smrg		tmpVals.point_matrix[3] = vals->point_matrix[3];
618a96d7823Smrg	    }
619a96d7823Smrg	    if (vals->width <= 0)
620a96d7823Smrg		tmpVals.width = 0;
621a96d7823Smrg	    if (vals->x == 0)
622a96d7823Smrg		tmpVals.x = 0;
623a96d7823Smrg	    if (vals->y == 0)
624a96d7823Smrg		tmpVals.y = 0;
625a96d7823Smrg	    tmpVals.ranges = ranges;
626a96d7823Smrg	    tmpVals.nranges = nranges;
627a96d7823Smrg	    FontParseXLFDName (nameChars, &tmpVals,
628a96d7823Smrg			       FONT_XLFD_REPLACE_VALUE);
629a96d7823Smrg	    /* If we're marking aliases with negative lengths, we
630a96d7823Smrg	       need to concoct a valid target name to follow it.
631a96d7823Smrg	       Otherwise we're done.  */
632a96d7823Smrg	    if (scaleNames->length[i] >= 0)
633a96d7823Smrg	    {
634a96d7823Smrg		(void) xfont2_add_font_names_name (names, nameChars,
635a96d7823Smrg					 strlen (nameChars));
636a96d7823Smrg		/* If our original pattern matches the name from
637a96d7823Smrg		   the table and that name doesn't duplicate what
638a96d7823Smrg		   we just added, add the name from the table */
639a96d7823Smrg		if (strcmp(nameChars, scaleNames->names[i]) &&
640a96d7823Smrg		    FontFileMatchName(scaleNames->names[i],
641a96d7823Smrg				      scaleNames->length[i],
642a96d7823Smrg				      nameptr) &&
643a96d7823Smrg		    *max)
644a96d7823Smrg		{
645a96d7823Smrg		    --*max;
646a96d7823Smrg		    (void) xfont2_add_font_names_name (names, scaleNames->names[i],
647a96d7823Smrg					     scaleNames->length[i]);
648a96d7823Smrg		}
649a96d7823Smrg	    }
650a96d7823Smrg	    else
651a96d7823Smrg	    {
652a96d7823Smrg		char *aliasName;
653a96d7823Smrg		vals->ranges = ranges;
654a96d7823Smrg		vals->nranges = nranges;
655a96d7823Smrg		if (transfer_values_to_alias(zeroChars,
656a96d7823Smrg					     strlen(zeroChars),
657a96d7823Smrg					     scaleNames->names[++i],
658a96d7823Smrg					     &aliasName, vals))
659a96d7823Smrg		{
660a96d7823Smrg		    (void) xfont2_add_font_names_name (names, nameChars,
661a96d7823Smrg					     strlen (nameChars));
662a96d7823Smrg		    names->length[names->nnames - 1] =
663a96d7823Smrg			-names->length[names->nnames - 1];
664a96d7823Smrg		    (void) xfont2_add_font_names_name (names, aliasName,
665a96d7823Smrg					     strlen (aliasName));
666a96d7823Smrg		    /* If our original pattern matches the name from
667a96d7823Smrg		       the table and that name doesn't duplicate what
668a96d7823Smrg		       we just added, add the name from the table */
669a96d7823Smrg		    if (strcmp(nameChars, scaleNames->names[i - 1]) &&
670a96d7823Smrg			FontFileMatchName(scaleNames->names[i - 1],
671a96d7823Smrg					  -scaleNames->length[i - 1],
672a96d7823Smrg					  nameptr) &&
673a96d7823Smrg			*max)
674a96d7823Smrg		    {
675a96d7823Smrg			--*max;
676a96d7823Smrg			(void) xfont2_add_font_names_name (names,
677a96d7823Smrg						 scaleNames->names[i - 1],
678a96d7823Smrg						 -scaleNames->length[i - 1]);
679a96d7823Smrg			names->length[names->nnames - 1] =
680a96d7823Smrg			    -names->length[names->nnames - 1];
681a96d7823Smrg			(void) xfont2_add_font_names_name (names, aliasName,
682a96d7823Smrg						 strlen (aliasName));
683a96d7823Smrg		    }
684a96d7823Smrg		}
685a96d7823Smrg	    }
686a96d7823Smrg	}
687a96d7823Smrg    }
688a96d7823Smrg}
689a96d7823Smrg
690a96d7823Smrg/* ARGSUSED */
691a96d7823Smrgstatic int
692a96d7823Smrg_FontFileListFonts (pointer client, FontPathElementPtr fpe,
693a96d7823Smrg		    const char *pat, int len, int max, FontNamesPtr names,
694a96d7823Smrg		    int mark_aliases)
695a96d7823Smrg{
696a96d7823Smrg    FontDirectoryPtr	dir;
697a96d7823Smrg    char		lowerChars[MAXFONTNAMELEN], zeroChars[MAXFONTNAMELEN];
698a96d7823Smrg    FontNameRec		lowerName;
699a96d7823Smrg    FontNameRec		zeroName;
700a96d7823Smrg    FontNamesPtr	scaleNames;
701a96d7823Smrg    FontScalableRec	vals;
702a96d7823Smrg    fsRange		*ranges;
703a96d7823Smrg    int			nranges;
704a96d7823Smrg    int			result = BadFontName;
705a96d7823Smrg
706a96d7823Smrg    if (len >= MAXFONTNAMELEN)
707a96d7823Smrg	return AllocError;
708a96d7823Smrg    dir = (FontDirectoryPtr) fpe->private;
709a96d7823Smrg    CopyISOLatin1Lowered (lowerChars, pat, len);
710a96d7823Smrg    lowerChars[len] = '\0';
711a96d7823Smrg    lowerName.name = lowerChars;
712a96d7823Smrg    lowerName.length = len;
713a96d7823Smrg    lowerName.ndashes = FontFileCountDashes (lowerChars, len);
714a96d7823Smrg
715a96d7823Smrg    /* Match XLFD patterns */
716a96d7823Smrg
717c7b4381aSmrg    strlcpy (zeroChars, lowerChars, sizeof(zeroChars));
718a96d7823Smrg    if (lowerName.ndashes == 14 &&
719a96d7823Smrg	FontParseXLFDName (zeroChars, &vals, FONT_XLFD_REPLACE_ZERO))
720a96d7823Smrg    {
721a96d7823Smrg	ranges = FontParseRanges(lowerChars, &nranges);
722a96d7823Smrg        result = FontFileFindNamesInScalableDir (&dir->nonScalable,
723a96d7823Smrg				&lowerName, max, names,
724a96d7823Smrg				(FontScalablePtr)0,
725a96d7823Smrg				(mark_aliases ?
726a96d7823Smrg				 LIST_ALIASES_AND_TARGET_NAMES :
727a96d7823Smrg				 NORMAL_ALIAS_BEHAVIOR) |
728a96d7823Smrg				IGNORE_SCALABLE_ALIASES,
729a96d7823Smrg				&max);
730a96d7823Smrg	zeroName.name = zeroChars;
731a96d7823Smrg	zeroName.length = strlen (zeroChars);
732a96d7823Smrg	zeroName.ndashes = lowerName.ndashes;
733a96d7823Smrg
734a96d7823Smrg	/* Look for scalable names and aliases, adding scaled instances of
735a96d7823Smrg	   them to the output */
736a96d7823Smrg
737a96d7823Smrg	/* Scalable names... */
738a96d7823Smrg	scaleNames = xfont2_make_font_names_record (0);
739a96d7823Smrg	if (!scaleNames)
740a96d7823Smrg	{
741a96d7823Smrg	    if (ranges) free(ranges);
742a96d7823Smrg	    return AllocError;
743a96d7823Smrg	}
744a96d7823Smrg	FontFileFindNamesInScalableDir (&dir->scalable, &zeroName, max,
745a96d7823Smrg					scaleNames, &vals,
746a96d7823Smrg					mark_aliases ?
747a96d7823Smrg					LIST_ALIASES_AND_TARGET_NAMES :
748a96d7823Smrg					NORMAL_ALIAS_BEHAVIOR, (int *)0);
749a96d7823Smrg	_FontFileAddScalableNames(names, scaleNames, &lowerName,
750a96d7823Smrg				  zeroChars, &vals, ranges, nranges,
751a96d7823Smrg				  &max);
752a96d7823Smrg	xfont2_free_font_names (scaleNames);
753a96d7823Smrg
754a96d7823Smrg	/* Scalable aliases... */
755a96d7823Smrg	scaleNames = xfont2_make_font_names_record (0);
756a96d7823Smrg	if (!scaleNames)
757a96d7823Smrg	{
758a96d7823Smrg	    if (ranges) free(ranges);
759a96d7823Smrg	    return AllocError;
760a96d7823Smrg	}
761a96d7823Smrg	FontFileFindNamesInScalableDir (&dir->nonScalable, &zeroName,
762a96d7823Smrg					max, scaleNames, &vals,
763a96d7823Smrg					mark_aliases ?
764a96d7823Smrg					LIST_ALIASES_AND_TARGET_NAMES :
765a96d7823Smrg					NORMAL_ALIAS_BEHAVIOR, (int *)0);
766a96d7823Smrg	_FontFileAddScalableNames(names, scaleNames, &lowerName,
767a96d7823Smrg				  zeroChars, &vals, ranges, nranges,
768a96d7823Smrg				  &max);
769a96d7823Smrg	xfont2_free_font_names (scaleNames);
770a96d7823Smrg
771a96d7823Smrg	if (ranges) free(ranges);
772a96d7823Smrg    }
773a96d7823Smrg    else
774a96d7823Smrg    {
775a96d7823Smrg        result = FontFileFindNamesInScalableDir (&dir->nonScalable,
776a96d7823Smrg				&lowerName, max, names,
777a96d7823Smrg				(FontScalablePtr)0,
778a96d7823Smrg				mark_aliases ?
779a96d7823Smrg				LIST_ALIASES_AND_TARGET_NAMES :
780a96d7823Smrg				NORMAL_ALIAS_BEHAVIOR,
781a96d7823Smrg				&max);
782a96d7823Smrg	if (result == Successful)
783a96d7823Smrg    	    result = FontFileFindNamesInScalableDir (&dir->scalable,
784a96d7823Smrg				&lowerName, max, names,
785a96d7823Smrg				(FontScalablePtr)0,
786a96d7823Smrg				mark_aliases ?
787a96d7823Smrg				LIST_ALIASES_AND_TARGET_NAMES :
788a96d7823Smrg				NORMAL_ALIAS_BEHAVIOR, (int *)0);
789a96d7823Smrg    }
790a96d7823Smrg    return result;
791a96d7823Smrg}
792a96d7823Smrg
793a96d7823Smrgtypedef struct _LFWIData {
794a96d7823Smrg    FontNamesPtr    names;
795a96d7823Smrg    int                   current;
796a96d7823Smrg} LFWIDataRec, *LFWIDataPtr;
797a96d7823Smrg
798a96d7823Smrgint
799a96d7823SmrgFontFileListFonts (pointer client, FontPathElementPtr fpe, const char *pat,
800a96d7823Smrg		   int len, int max, FontNamesPtr names)
801a96d7823Smrg{
802a96d7823Smrg    return _FontFileListFonts (client, fpe, pat, len, max, names, 0);
803a96d7823Smrg}
804a96d7823Smrg
805a96d7823Smrgint
806a96d7823SmrgFontFileStartListFonts(pointer client, FontPathElementPtr fpe,
807a96d7823Smrg		       const char *pat, int len, int max,
808a96d7823Smrg		       pointer *privatep, int mark_aliases)
809a96d7823Smrg{
810a96d7823Smrg    LFWIDataPtr	data;
811a96d7823Smrg    int		ret;
812a96d7823Smrg
813a96d7823Smrg    data = malloc (sizeof *data);
814a96d7823Smrg    if (!data)
815a96d7823Smrg	return AllocError;
816a96d7823Smrg    data->names = xfont2_make_font_names_record (0);
817a96d7823Smrg    if (!data->names)
818a96d7823Smrg    {
819a96d7823Smrg	free (data);
820a96d7823Smrg	return AllocError;
821a96d7823Smrg    }
822a96d7823Smrg    ret = _FontFileListFonts (client, fpe, pat, len,
823a96d7823Smrg			      max, data->names, mark_aliases);
824a96d7823Smrg    if (ret != Successful)
825a96d7823Smrg    {
826a96d7823Smrg	xfont2_free_font_names (data->names);
827a96d7823Smrg	free (data);
828a96d7823Smrg	return ret;
829a96d7823Smrg    }
830a96d7823Smrg    data->current = 0;
831a96d7823Smrg    *privatep = (pointer) data;
832a96d7823Smrg    return Successful;
833a96d7823Smrg}
834a96d7823Smrg
835a96d7823Smrg
836a96d7823Smrgint
837a96d7823SmrgFontFileStartListFontsWithInfo(pointer client, FontPathElementPtr fpe,
838a96d7823Smrg			       const char *pat, int len, int max,
839a96d7823Smrg			       pointer *privatep)
840a96d7823Smrg{
841a96d7823Smrg    return FontFileStartListFonts(client, fpe, pat, len, max, privatep, 0);
842a96d7823Smrg}
843a96d7823Smrg
844a96d7823Smrg/* ARGSUSED */
845a96d7823Smrgstatic int
846a96d7823SmrgFontFileListOneFontWithInfo (pointer client, FontPathElementPtr fpe,
847a96d7823Smrg			     char **namep, int *namelenp,
848a96d7823Smrg			     FontInfoPtr *pFontInfo)
849a96d7823Smrg{
850a96d7823Smrg    FontDirectoryPtr	dir;
851a96d7823Smrg    char		lowerName[MAXFONTNAMELEN];
852a96d7823Smrg    char		fileName[MAXFONTFILENAMELEN*2 + 1];
853a96d7823Smrg    FontNameRec		tmpName;
854a96d7823Smrg    FontEntryPtr	entry;
855a96d7823Smrg    FontScalableRec	vals;
856a96d7823Smrg    FontScalableEntryPtr   scalable;
857a96d7823Smrg    FontScaledPtr	scaled;
858a96d7823Smrg    FontBitmapEntryPtr	bitmap;
859a96d7823Smrg    int			ret;
860a96d7823Smrg    Bool		noSpecificSize;
861a96d7823Smrg    int			nranges;
862a96d7823Smrg    fsRange		*ranges;
863a96d7823Smrg
864a96d7823Smrg    char		*name = *namep;
865a96d7823Smrg    int			namelen = *namelenp;
866a96d7823Smrg
867a96d7823Smrg    if (namelen >= MAXFONTNAMELEN)
868a96d7823Smrg	return AllocError;
869a96d7823Smrg    dir = (FontDirectoryPtr) fpe->private;
870a96d7823Smrg
871a96d7823Smrg    /* Match non-scalable pattern */
872a96d7823Smrg    CopyISOLatin1Lowered (lowerName, name, namelen);
873a96d7823Smrg    lowerName[namelen] = '\0';
874a96d7823Smrg    ranges = FontParseRanges(lowerName, &nranges);
875a96d7823Smrg    tmpName.name = lowerName;
876a96d7823Smrg    tmpName.length = namelen;
877a96d7823Smrg    tmpName.ndashes = FontFileCountDashes (lowerName, namelen);
878a96d7823Smrg    if (!FontParseXLFDName(lowerName, &vals, FONT_XLFD_REPLACE_NONE))
879a96d7823Smrg	bzero(&vals, sizeof(vals));
880a96d7823Smrg    if (!(entry = FontFileFindNameInDir (&dir->nonScalable, &tmpName)) &&
881a96d7823Smrg	tmpName.ndashes == 14 &&
882a96d7823Smrg	FontParseXLFDName (lowerName, &vals, FONT_XLFD_REPLACE_ZERO))
883a96d7823Smrg    {
884a96d7823Smrg        tmpName.length = strlen(lowerName);
885a96d7823Smrg	entry = FontFileFindNameInDir (&dir->nonScalable, &tmpName);
886a96d7823Smrg    }
887a96d7823Smrg
888a96d7823Smrg    if (entry)
889a96d7823Smrg    {
890a96d7823Smrg	switch (entry->type) {
891a96d7823Smrg	case FONT_ENTRY_BITMAP:
892a96d7823Smrg	    bitmap = &entry->u.bitmap;
893a96d7823Smrg	    if (bitmap->pFont)
894a96d7823Smrg	    {
895a96d7823Smrg	    	*pFontInfo = &bitmap->pFont->info;
896a96d7823Smrg	    	ret = Successful;
897a96d7823Smrg	    }
898a96d7823Smrg	    else
899a96d7823Smrg	    {
900a96d7823Smrg		ret = FontFileGetInfoBitmap (fpe, *pFontInfo, entry);
901a96d7823Smrg	    }
902a96d7823Smrg	    break;
903a96d7823Smrg	case FONT_ENTRY_ALIAS:
904a96d7823Smrg	    vals.nranges = nranges;
905a96d7823Smrg	    vals.ranges = ranges;
906a96d7823Smrg	    transfer_values_to_alias(entry->name.name, entry->name.length,
907a96d7823Smrg				     entry->u.alias.resolved, namep, &vals);
908a96d7823Smrg	    *namelenp = strlen (*namep);
909a96d7823Smrg	    ret = FontNameAlias;
910a96d7823Smrg	    break;
911a96d7823Smrg	default:
912a96d7823Smrg	    ret = BadFontName;
913a96d7823Smrg	}
914a96d7823Smrg    }
915a96d7823Smrg    else
916a96d7823Smrg    {
917a96d7823Smrg      ret = BadFontName;
918a96d7823Smrg    }
919a96d7823Smrg
920a96d7823Smrg    if (ret != BadFontName)
921a96d7823Smrg    {
922a96d7823Smrg	if (ranges) free(ranges);
923a96d7823Smrg	return ret;
924a96d7823Smrg    }
925a96d7823Smrg
926a96d7823Smrg    /* Match XLFD patterns */
927a96d7823Smrg    CopyISOLatin1Lowered (lowerName, name, namelen);
928a96d7823Smrg    lowerName[namelen] = '\0';
929a96d7823Smrg    tmpName.name = lowerName;
930a96d7823Smrg    tmpName.length = namelen;
931a96d7823Smrg    tmpName.ndashes = FontFileCountDashes (lowerName, namelen);
932a96d7823Smrg    if (!FontParseXLFDName (lowerName, &vals, FONT_XLFD_REPLACE_ZERO) ||
933a96d7823Smrg	!(tmpName.length = strlen (lowerName),
934a96d7823Smrg	  entry = FontFileFindNameInScalableDir (&dir->scalable, &tmpName,
935a96d7823Smrg						 &vals))) {
936a96d7823Smrg	CopyISOLatin1Lowered (lowerName, name, namelen);
937a96d7823Smrg	lowerName[namelen] = '\0';
938a96d7823Smrg	tmpName.name = lowerName;
939a96d7823Smrg	tmpName.length = namelen;
940a96d7823Smrg	tmpName.ndashes = FontFileCountDashes (lowerName, namelen);
941a96d7823Smrg	entry = FontFileFindNameInScalableDir (&dir->scalable, &tmpName, &vals);
942a96d7823Smrg	if (entry)
943a96d7823Smrg	{
944c7b4381aSmrg	    strlcpy(lowerName, entry->name.name, sizeof(lowerName));
945a96d7823Smrg	    tmpName.name = lowerName;
946a96d7823Smrg	    tmpName.length = entry->name.length;
947a96d7823Smrg	    tmpName.ndashes = entry->name.ndashes;
948a96d7823Smrg	}
949a96d7823Smrg    }
950a96d7823Smrg
951a96d7823Smrg    if (entry)
952a96d7823Smrg    {
953a96d7823Smrg	noSpecificSize = FALSE;	/* TRUE breaks XLFD enhancements */
954a96d7823Smrg    	if (entry && entry->type == FONT_ENTRY_SCALABLE &&
955a96d7823Smrg	    FontFileCompleteXLFD (&vals, &entry->u.scalable.extra->defaults))
956a96d7823Smrg	{
957a96d7823Smrg	    scalable = &entry->u.scalable;
958a96d7823Smrg	    scaled = FontFileFindScaledInstance (entry, &vals, noSpecificSize);
959a96d7823Smrg	    /*
960a96d7823Smrg	     * A scaled instance can occur one of two ways:
961a96d7823Smrg	     *
962a96d7823Smrg	     *  Either the font has been scaled to this
963a96d7823Smrg	     *   size already, in which case scaled->pFont
964a96d7823Smrg	     *   will point at that font.
965a96d7823Smrg	     *
966a96d7823Smrg	     *  Or a bitmap instance in this size exists,
967a96d7823Smrg	     *   which is handled as if we got a pattern
968a96d7823Smrg	     *   matching the bitmap font name.
969a96d7823Smrg	     */
970a96d7823Smrg	    if (scaled)
971a96d7823Smrg	    {
972a96d7823Smrg		if (scaled->pFont)
973a96d7823Smrg		{
974a96d7823Smrg		    *pFontInfo = &scaled->pFont->info;
975a96d7823Smrg		    ret = Successful;
976a96d7823Smrg		}
977a96d7823Smrg		else if (scaled->bitmap)
978a96d7823Smrg		{
979a96d7823Smrg		    entry = scaled->bitmap;
980a96d7823Smrg		    bitmap = &entry->u.bitmap;
981a96d7823Smrg		    if (bitmap->pFont)
982a96d7823Smrg		    {
983a96d7823Smrg			*pFontInfo = &bitmap->pFont->info;
984a96d7823Smrg			ret = Successful;
985a96d7823Smrg		    }
986a96d7823Smrg		    else
987a96d7823Smrg		    {
988a96d7823Smrg			ret = FontFileGetInfoBitmap (fpe, *pFontInfo, entry);
989a96d7823Smrg		    }
990a96d7823Smrg		}
991a96d7823Smrg		else /* "cannot" happen */
992a96d7823Smrg		{
993a96d7823Smrg		    ret = BadFontName;
994a96d7823Smrg		}
995a96d7823Smrg	    }
996a96d7823Smrg	    else
997a96d7823Smrg	    {
998a96d7823Smrg		{
999a96d7823Smrg		    char origName[MAXFONTNAMELEN];
1000a96d7823Smrg
1001a96d7823Smrg		    CopyISOLatin1Lowered (origName, name, namelen);
1002a96d7823Smrg		    origName[namelen] = '\0';
1003a96d7823Smrg		    vals.xlfdName = origName;
1004a96d7823Smrg		    vals.ranges = ranges;
1005a96d7823Smrg		    vals.nranges = nranges;
1006a96d7823Smrg
1007a96d7823Smrg		    /* Make a new scaled instance */
1008a96d7823Smrg		    if (strlen(dir->directory) + strlen(scalable->fileName) >=
1009a96d7823Smrg			sizeof(fileName)) {
1010a96d7823Smrg			ret = BadFontName;
1011a96d7823Smrg		    } else {
1012c7b4381aSmrg			strlcpy (fileName, dir->directory, sizeof(fileName));
1013c7b4381aSmrg			strlcat (fileName, scalable->fileName, sizeof(fileName));
1014a96d7823Smrg                        if (scalable->renderer->GetInfoScalable)
1015a96d7823Smrg			    ret = (*scalable->renderer->GetInfoScalable)
1016a96d7823Smrg			        (fpe, *pFontInfo, entry, &tmpName, fileName,
1017a96d7823Smrg                                 &vals);
1018a96d7823Smrg                        else if (scalable->renderer->GetInfoBitmap)
1019a96d7823Smrg                            ret = (*scalable->renderer->GetInfoBitmap)
1020a96d7823Smrg                                (fpe, *pFontInfo, entry, fileName);
1021a96d7823Smrg		    }
1022a96d7823Smrg		    if (ranges) {
1023a96d7823Smrg			free(ranges);
1024a96d7823Smrg			ranges = NULL;
1025a96d7823Smrg		    }
1026a96d7823Smrg		}
1027a96d7823Smrg	    }
1028a96d7823Smrg	    if (ret == Successful) return ret;
1029a96d7823Smrg	}
1030a96d7823Smrg	CopyISOLatin1Lowered (lowerName, name, namelen);
1031a96d7823Smrg	tmpName.length = namelen;
1032a96d7823Smrg    }
1033a96d7823Smrg    else
1034a96d7823Smrg	ret = BadFontName;
1035a96d7823Smrg
1036a96d7823Smrg    if (ranges)
1037a96d7823Smrg	free(ranges);
1038a96d7823Smrg    return ret;
1039a96d7823Smrg}
1040a96d7823Smrg
1041a96d7823Smrgint
1042a96d7823SmrgFontFileListNextFontWithInfo(pointer client, FontPathElementPtr fpe,
1043a96d7823Smrg			     char **namep, int *namelenp,
1044a96d7823Smrg			     FontInfoPtr *pFontInfo,
1045a96d7823Smrg			     int *numFonts, pointer private)
1046a96d7823Smrg{
1047a96d7823Smrg    LFWIDataPtr	data = (LFWIDataPtr) private;
1048a96d7823Smrg    int		ret;
1049a96d7823Smrg    char	*name;
1050a96d7823Smrg    int		namelen;
1051a96d7823Smrg
1052a96d7823Smrg    if (data->current == data->names->nnames)
1053a96d7823Smrg    {
1054a96d7823Smrg	xfont2_free_font_names (data->names);
1055a96d7823Smrg	free (data);
1056a96d7823Smrg	return BadFontName;
1057a96d7823Smrg    }
1058a96d7823Smrg    name = data->names->names[data->current];
1059a96d7823Smrg    namelen = data->names->length[data->current];
1060a96d7823Smrg    ret = FontFileListOneFontWithInfo (client, fpe, &name, &namelen, pFontInfo);
1061a96d7823Smrg    if (ret == BadFontName)
1062a96d7823Smrg	ret = AllocError;
1063a96d7823Smrg    *namep = name;
1064a96d7823Smrg    *namelenp = namelen;
1065a96d7823Smrg    ++data->current;
1066a96d7823Smrg    *numFonts = data->names->nnames - data->current;
1067a96d7823Smrg    return ret;
1068a96d7823Smrg}
1069a96d7823Smrg
1070a96d7823Smrgint
1071a96d7823SmrgFontFileStartListFontsAndAliases(pointer client, FontPathElementPtr fpe,
1072a96d7823Smrg				 const char *pat, int len, int max,
1073a96d7823Smrg				 pointer *privatep)
1074a96d7823Smrg{
1075a96d7823Smrg    return FontFileStartListFonts(client, fpe, pat, len, max, privatep, 1);
1076a96d7823Smrg}
1077a96d7823Smrg
1078a96d7823Smrgint
1079a96d7823SmrgFontFileListNextFontOrAlias(pointer client, FontPathElementPtr fpe,
1080a96d7823Smrg			    char **namep, int *namelenp, char **resolvedp,
1081a96d7823Smrg			    int *resolvedlenp, pointer private)
1082a96d7823Smrg{
1083a96d7823Smrg    LFWIDataPtr	data = (LFWIDataPtr) private;
1084a96d7823Smrg    int		ret;
1085a96d7823Smrg    char	*name;
1086a96d7823Smrg    int		namelen;
1087a96d7823Smrg
1088a96d7823Smrg    if (data->current == data->names->nnames)
1089a96d7823Smrg    {
1090a96d7823Smrg	xfont2_free_font_names (data->names);
1091a96d7823Smrg	free (data);
1092a96d7823Smrg	return BadFontName;
1093a96d7823Smrg    }
1094a96d7823Smrg    name = data->names->names[data->current];
1095a96d7823Smrg    namelen = data->names->length[data->current];
1096a96d7823Smrg
1097a96d7823Smrg    /* If this is a real font name... */
1098a96d7823Smrg    if (namelen >= 0)
1099a96d7823Smrg    {
1100a96d7823Smrg	*namep = name;
1101a96d7823Smrg	*namelenp = namelen;
1102a96d7823Smrg	ret = Successful;
1103a96d7823Smrg    }
1104a96d7823Smrg    /* Else if an alias */
1105a96d7823Smrg    else
1106a96d7823Smrg    {
1107a96d7823Smrg	/* Tell the caller that this is an alias... let him resolve it to
1108a96d7823Smrg	   see if it's valid */
1109a96d7823Smrg	*namep = name;
1110a96d7823Smrg	*namelenp = -namelen;
1111a96d7823Smrg	*resolvedp = data->names->names[++data->current];
1112a96d7823Smrg	*resolvedlenp = data->names->length[data->current];
1113a96d7823Smrg	ret = FontNameAlias;
1114a96d7823Smrg    }
1115a96d7823Smrg
1116a96d7823Smrg    ++data->current;
1117a96d7823Smrg    return ret;
1118a96d7823Smrg}
1119a96d7823Smrg
1120a96d7823Smrgstatic const xfont2_fpe_funcs_rec fontfile_fpe_funcs = {
1121a96d7823Smrg	.version = XFONT2_FPE_FUNCS_VERSION,
1122a96d7823Smrg	.name_check = FontFileNameCheck,
1123a96d7823Smrg	.init_fpe = FontFileInitFPE,
1124a96d7823Smrg	.free_fpe = FontFileFreeFPE,
1125a96d7823Smrg	.reset_fpe = FontFileResetFPE,
1126a96d7823Smrg	.open_font = FontFileOpenFont,
1127a96d7823Smrg	.close_font = FontFileCloseFont,
1128a96d7823Smrg	.list_fonts = FontFileListFonts,
1129a96d7823Smrg	.start_list_fonts_with_info = FontFileStartListFontsWithInfo,
1130a96d7823Smrg	.list_next_font_with_info = FontFileListNextFontWithInfo,
1131a96d7823Smrg	.wakeup_fpe = 0,
1132a96d7823Smrg	.client_died = 0,
1133a96d7823Smrg	.load_glyphs = 0,
1134a96d7823Smrg	.start_list_fonts_and_aliases = FontFileStartListFontsAndAliases,
1135a96d7823Smrg	.list_next_font_or_alias = FontFileListNextFontOrAlias,
1136a96d7823Smrg	.set_path_hook = FontFileEmptyBitmapSource,
1137a96d7823Smrg};
1138a96d7823Smrg
1139a96d7823Smrgvoid
1140a96d7823SmrgFontFileRegisterLocalFpeFunctions (void)
1141a96d7823Smrg{
1142a96d7823Smrg    register_fpe_funcs(&fontfile_fpe_funcs);
1143a96d7823Smrg}
1144