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