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