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