home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / server / os / osfonts.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-01  |  23.6 KB  |  1,042 lines

  1. /************************************************************************
  2. Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
  3. and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its 
  8. documentation for any purpose and without fee is hereby granted, 
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in 
  11. supporting documentation, and that the names of Digital or MIT not be
  12. used in advertising or publicity pertaining to distribution of the
  13. software without specific, written prior permission.  
  14.  
  15. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  16. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  17. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  18. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  19. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  20. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  21. SOFTWARE.
  22.  
  23. ************************************************************************/
  24.  
  25. /* $XConsortium: osfonts.c,v 1.37 91/07/02 09:14:47 rws Exp $ */
  26.  
  27. #include <stdio.h>
  28. #include "Xos.h"
  29. #include <sys/dir.h>
  30. #include <sys/param.h>
  31. #include <sys/stat.h>
  32. #include <errno.h>
  33.  
  34. #include "X.h"
  35. #include "Xmd.h"
  36. #include "Xproto.h"
  37. #include "dixfontstr.h"
  38. #include "fontstruct.h"
  39. #include "osstruct.h"
  40. #include "misc.h"
  41. #include "opaque.h"
  42. #include "dixstruct.h"
  43.  
  44. #include "fonttype.h"
  45. #include "fontdir.h"
  46.  
  47. #ifndef X_NOT_POSIX
  48. #ifdef _POSIX_SOURCE
  49. #include <limits.h>
  50. #else
  51. #define _POSIX_SOURCE
  52. #include <limits.h>
  53. #undef _POSIX_SOURCE
  54. #endif
  55. #endif
  56. #ifndef PATH_MAX
  57. #ifdef MAXPATHLEN
  58. #define PATH_MAX MAXPATHLEN
  59. #else
  60. #define PATH_MAX 1024
  61. #endif
  62. #endif
  63.  
  64. #define MAXFNAMELEN 1024
  65.  
  66. extern int errno;
  67.  
  68. extern void CopyISOLatin1Lowered();
  69. extern Atom    MakeAtom();
  70. extern char *defaultFontPath;
  71.  
  72. static int    ReadFontAlias ();
  73. FontFile    FindFontFile ();
  74. static int    ReadFontDir ();
  75.  
  76. FontPathPtr        GetFontPath ();
  77.  
  78. static FontPathPtr searchList = (FontPathPtr)NULL;
  79.  
  80. extern void FreeScaledFonts();
  81. extern FontFile FindScaledFont();
  82.  
  83. void
  84. FreeFontRecord(pFP)
  85.     FontPathPtr pFP;
  86. {
  87.     int i;
  88.     for (i=0; i<pFP->npaths; i++) {
  89.         xfree(pFP->paths[i]);
  90.     }
  91.     xfree(pFP->paths);
  92.     xfree(pFP->length);
  93.     xfree(pFP->osPrivate);
  94.     xfree(pFP);
  95. }
  96.  
  97. static FontPathPtr
  98. MakeFontPathRecord(size)
  99.     unsigned    size;
  100. {
  101.     FontPathPtr fp;    
  102.  
  103.     fp = (FontPathPtr)xalloc(sizeof(FontPathRec));
  104.     if (fp) {
  105.     fp->npaths = 0;
  106.     fp->size = size;
  107.     fp->length = (int *)xalloc(size * sizeof(int));
  108.     fp->paths = (char **)xalloc(size * sizeof(char *));
  109.     fp->osPrivate = (pointer *)xalloc(size * sizeof(pointer));
  110.     if (!fp->length || !fp->paths || !fp->osPrivate) {
  111.         xfree(fp->length);
  112.         xfree(fp->paths);
  113.         xfree(fp->osPrivate);
  114.         xfree(fp);
  115.         fp = (FontPathPtr)NULL;
  116.     }
  117.     }
  118.     return fp;
  119. }
  120.  
  121. static int
  122. AddFontPathElement(path, element, length, fontDir)
  123.     FontPathPtr path;
  124.     char *element;
  125.     int  length;
  126.     Bool fontDir;
  127. {
  128.     int index = path->npaths;
  129.     FontTable table;
  130.     char *nelt;
  131.     int status;
  132.  
  133.     if (fontDir)
  134.     {
  135.     status = ReadFontDir(element, &table, path);
  136.     if (status != Success)
  137.         return status;
  138.     }
  139.     nelt = (char *)xalloc(length + 1);
  140.     if (!nelt)
  141.     return BadAlloc;
  142.     if (index >= path->size)
  143.     {
  144.     int size = path->size << 1;
  145.     int *nlength;
  146.     char **npaths;
  147.     pointer *npriv;
  148.  
  149.     nlength = (int *)xrealloc(path->length, size*sizeof(int));
  150.     npaths = (char **)xrealloc(path->paths, size*sizeof(char *));
  151.     npriv = (pointer *)xrealloc(path->osPrivate, size * sizeof(pointer));
  152.     if (nlength && npaths && npriv)
  153.     {
  154.         path->size = size;
  155.         path->length = nlength;
  156.         path->paths = npaths;
  157.         path->osPrivate = npriv;
  158.     }
  159.     else
  160.     {
  161.         xfree(nelt);
  162.         xfree(nlength);
  163.         xfree(npaths);
  164.         xfree(npriv);
  165.         return BadAlloc;
  166.     }
  167.     }
  168.     path->length[index] = length;
  169.     path->paths[index] = nelt;
  170.     strncpy(nelt, element, length);
  171.     nelt[length] = '\0';
  172.     path->osPrivate[index] = (pointer)table;
  173.     path->npaths++;
  174.     return Success;
  175. }
  176.  
  177. static void
  178. FreeFontPath(path)
  179.     FontPathPtr path;
  180. {
  181.     int     i, j;
  182.     FontPtr font;
  183.     FontTable table;
  184.  
  185.     /* 
  186.      * First all the back pointers for the outstanding fonts must be smashed
  187.      * to NULL so that when the font is freed, the removal from the (now
  188.      * freed) previous table can be skipped.
  189.      */
  190.     if (path) {
  191.     for (i = 0; i < path->npaths; i++) {
  192.         table = (FontTable) path->osPrivate[i];
  193.         for (j = 0; j < table->file.used; j++) {
  194.         if (!table->file.ff[j].alias &&
  195.             (font = (FontPtr) table->file.ff[j].private))
  196.             font->osPrivate = NULL;
  197.         }
  198.         FreeFontTable (table);
  199.     }
  200.     FreeFontRecord (path);
  201.     }
  202. }
  203.  
  204. /*
  205.  * Font paths are not smashed to lower case. (Note "/usr/lib/X11/fonts")
  206.  *
  207.  * Allow initial font path to have names separated by spaces tabs or commas
  208.  */
  209. int
  210. SetDefaultFontPath(name)
  211.     char *    name;
  212. {
  213.     register char *start, *end;
  214.     char dirName[PATH_MAX];
  215.     FontPathPtr path;
  216.     int status;
  217.  
  218.     path = MakeFontPathRecord(3);
  219.     if (!path)
  220.     return BadAlloc;
  221.     end = name;
  222.     for (;;) {
  223.     start = end;
  224.     while ((*start == ' ') || (*start == '\t') || (*start == ','))
  225.         start++;
  226.     if (*start == '\0')
  227.         break;
  228.     end = start;
  229.     while ((*end != ' ') && (*end != '\t') && (*end != ',') &&
  230.         (*end != '\0'))
  231.        end++;
  232.     strncpy(dirName, start, end - start);
  233.     dirName[end - start] = '\0';
  234.     if (dirName[strlen(dirName) - 1] != '/')
  235.         strcat(dirName, "/");
  236.     status = AddFontPathElement(path, dirName, strlen (dirName), True);
  237.     if (status != Success)
  238.     {
  239.         FreeFontPath(path);
  240.         return status;
  241.     }
  242.     }
  243.     FreeFontPath(searchList);
  244.     searchList = path;
  245.     FreeScaledFonts();
  246.     return Success;
  247. }
  248.  
  249. int
  250. SetFontPath(client, npaths, countedStrings)
  251.     ClientPtr    client;
  252.     unsigned    npaths;
  253.     char *    countedStrings;
  254. {
  255.     int i;
  256.     unsigned char * bufPtr = (unsigned char *)countedStrings;
  257.     char dirName[PATH_MAX];
  258.     unsigned int n;
  259.     FontPathPtr path;
  260.     int status;
  261.  
  262.     if (npaths == 0)
  263.     return SetDefaultFontPath(defaultFontPath); /* this frees old paths */
  264.  
  265.     path = MakeFontPathRecord(npaths);
  266.     if (!path)
  267.     return BadAlloc;
  268.     for (i=0; i<npaths; i++) {
  269.     n = (unsigned int)(*bufPtr++);
  270.     strncpy(dirName, (char *) bufPtr, (int) n);
  271.     dirName[n] = '\0';
  272.     if (dirName[n - 1] != '/')
  273.         strcat(dirName, "/");
  274.     status = AddFontPathElement(path, dirName, strlen (dirName), True);
  275.     if (status != Success)
  276.     {
  277.         FreeFontPath(path);
  278.         client->errorValue = i;
  279.         return status;
  280.     }
  281.     bufPtr += n;
  282.     }
  283.     FreeFontPath(searchList);
  284.     searchList = path;
  285.     FreeScaledFonts();
  286.     return Success;
  287. }
  288.  
  289. FontPathPtr
  290. GetFontPath()
  291. {
  292.     return(searchList);
  293. }
  294.  
  295. static int
  296. FindFileType(name)
  297.     char *name;
  298. {
  299.     register int i, j, k;
  300.     char *ext;
  301.  
  302.     k = strlen(name);
  303.     for (i = 0; fontFileReaders[i].extension; i++) {
  304.     ext = fontFileReaders[i].extension;
  305.     j = strlen(ext);
  306.     if ((k > j) && (strcmp(ext, name + k - j) == 0))
  307.         return i;
  308.     }
  309.     return -1;
  310. }
  311.  
  312. static int
  313. ReadFontDir(directory, ptable, path)
  314.     char    *directory;
  315.     FontTable    *ptable;
  316.     FontPathPtr path;
  317. {
  318.     char file_name[PATH_MAX];
  319.     char font_name[MAXFNAMELEN];
  320.     char dir_file[PATH_MAX];
  321.     char BUF[BUFSIZ];
  322.     FILE *file;
  323.     int count, i, status;
  324.     FontTable matchTable;
  325.     FontTable table = NullTable;
  326.  
  327.     strcpy(dir_file, directory);
  328.     if (directory[strlen(directory) - 1] != '/')
  329.      strcat(dir_file, "/");
  330.     strcat(dir_file, FontDirFile);
  331.     file = fopen(dir_file, "r");
  332.     if (file)
  333.     {
  334.     setbuf (file, BUF);
  335.     count = fscanf(file, "%d\n", &i);
  336.     if ((count == EOF) || (count != 1)) {
  337.         fclose(file);
  338.         return BadValue;
  339.     }
  340.     table = MakeFontTable(directory, i);
  341.     for (;;) {
  342.         count = fscanf(file, "%s %[^\n]\n", file_name, font_name);
  343.         if (count == EOF)
  344.         break;
  345.         if (count != 2) {
  346.             fclose(file);
  347.         return BadValue;
  348.         }
  349.         if (!FindFontFile (path, font_name, 0, FALSE, &matchTable) &&
  350.         (FindFileType (file_name) >= 0)) {
  351.         i = AddFileEntry(table, file_name, False);
  352.         if (i < 0) {
  353.             fclose(file);
  354.             return BadAlloc;
  355.         }
  356.         i = AddNameEntry(table, font_name, i);
  357.         if (i <= 0) {
  358.             fclose(file);
  359.             return (i ? BadAlloc : BadValue);
  360.         }
  361.         }
  362.     }
  363.     fclose(file);
  364.     }
  365.     else if (errno != ENOENT)
  366.     {
  367.     return BadValue;
  368.     }
  369.     status = ReadFontAlias(directory, FALSE, &table, path);
  370.     if (status != Success)
  371.     {
  372.     FreeFontTable(table);
  373.     return status;
  374.     }
  375.     if (!table)
  376.     return BadValue;
  377.     /*
  378.      * At this point, no more entries will be made in file table. This means
  379.      * that it will not be realloced and we can put pointers (rather than
  380.      * indices into the table.
  381.      */
  382.     for (i = 0; i < table->name.used; i++)
  383.     table->name.fn[i].u.ff = &table->file.ff[table->name.fn[i].u.index];
  384.  
  385.     *ptable = table;
  386.     return Success;
  387. }
  388.  
  389. /* 
  390.  * Make each of the file names an automatic alias for each of the files.
  391.  * This assumes that all file names are of the form <root>.<extension>.
  392.  */
  393.  
  394. static Bool
  395. AddFileNameAliases(table, path)
  396.     FontTable table;
  397.     FontPathPtr path;
  398. {
  399.     int i, typeIndex;
  400.     Boolean found;
  401.     FontTable    matchTable;
  402.  
  403.     char copy[PATH_MAX];
  404.  
  405.     for (i = 0; i < table->file.used; i++) {
  406.     if (table->file.ff[i].alias)
  407.         continue;
  408.     strcpy(copy, table->file.ff[i].name);
  409.     typeIndex = FindFileType(copy);
  410.     copy[strlen(copy) - strlen(fontFileReaders[typeIndex].extension)] = NUL;
  411.     CopyISOLatin1Lowered ((unsigned char *)copy, (unsigned char *)copy,
  412.                   strlen (copy));
  413.     (void)  FindNameInFontTable(table, copy, &found);
  414.     if (!found && !FindFontFile (path, copy, 0, FALSE, &matchTable)) {
  415.         if (AddNameEntry(table, copy, i) < 0)
  416.         return FALSE;
  417.     }
  418.     }
  419.     return TRUE;
  420. }
  421.  
  422. /*
  423.  * parse the font.aliases file.  Format is:
  424.  *
  425.  * alias font-name
  426.  *
  427.  * To imbed white-space in an alias name, enclose it like "font name" 
  428.  * in double quotes.  \ escapes and character, so
  429.  * "font name \"With Double Quotes\" \\ and \\ back-slashes"
  430.  * works just fine.
  431.  */
  432.  
  433. /*
  434.  * token types
  435.  */
  436.  
  437. static int    lexAlias (), lexc ();
  438.  
  439. # define NAME        0
  440. # define NEWLINE    1
  441. # define DONE        2
  442. # define EALLOC        3
  443.  
  444. static int
  445. ReadFontAlias(directory, isFile, ptable, path)
  446.     char      *directory;
  447.     Bool      isFile;
  448.     FontTable *ptable;
  449.     FontPathPtr path;
  450. {
  451.     char alias[MAXFNAMELEN];
  452.     char font_name[MAXFNAMELEN];
  453.     char alias_file[PATH_MAX];
  454.     char buf[BUFSIZ];
  455.     FILE *file;
  456.     int i;
  457.     FontTable matchTable;
  458.     FontTable table;
  459.     int    token;
  460.     Bool found;
  461.     char *lexToken;
  462.     int status = Success;
  463.  
  464.     table = *ptable;
  465.     strcpy(alias_file, directory);
  466.     if (!isFile)
  467.     {
  468.     if (directory[strlen(directory) - 1] != '/')
  469.         strcat(alias_file, "/");
  470.     strcat(alias_file, AliasFile);
  471.     }
  472.     file = fopen(alias_file, "r");
  473.     if (!file)
  474.     return ((errno == ENOENT) ? Success : BadValue);
  475.     setbuf (file, buf);
  476.     if (!table)
  477.     *ptable = table = MakeFontTable (directory, 10);
  478.     if (!table)
  479.     return BadAlloc;
  480.     while (status == Success) {
  481.     token = lexAlias (file, &lexToken);
  482.     switch (token) {
  483.     case NEWLINE:
  484.         break;
  485.     case DONE:
  486.         fclose (file);
  487.         return Success;
  488.     case EALLOC:
  489.         status = BadAlloc;
  490.         break;
  491.     case NAME:
  492.         strcpy (alias, lexToken);
  493.         token = lexAlias (file, &lexToken);
  494.         switch (token) {
  495.         case NEWLINE:
  496.         if (strcmp (alias, "FILE_NAMES_ALIASES"))
  497.             status = BadValue;
  498.         else if (!AddFileNameAliases (table, path))
  499.             status = BadAlloc;
  500.         break;
  501.         case DONE:
  502.         status = BadValue;
  503.         break;
  504.         case EALLOC:
  505.         status = BadAlloc;
  506.         break;
  507.         case NAME:
  508.         CopyISOLatin1Lowered ((unsigned char *)alias,
  509.                       (unsigned char *)alias,
  510.                       strlen (alias));
  511.         CopyISOLatin1Lowered ((unsigned char *)font_name,
  512.                       (unsigned char *)lexToken,
  513.                       strlen (lexToken));
  514.         (void) FindNameInFontTable (table, alias, &found);
  515.         if (!found &&
  516.             !FindFontFile (path, alias, 0, FALSE, &matchTable)) {
  517.             i = AddFileEntry(table, font_name, True);
  518.             if (i < 0) {
  519.             status = BadAlloc;
  520.             } else {
  521.             i = AddNameEntry(table, alias, i);
  522.             if (i <= 0)
  523.                 status = (i ? BadAlloc : BadValue);
  524.             }
  525.         }
  526.         break;
  527.         }
  528.     }
  529.     }
  530.     fclose(file);
  531.     return status;
  532. }
  533.  
  534. # define QUOTE        0
  535. # define WHITE        1
  536. # define NORMAL        2
  537. # define END        3
  538. # define NL        4
  539.  
  540. static int    charClass;
  541.  
  542. static int
  543. lexAlias (file, lexToken)
  544. FILE    *file;
  545. char    **lexToken;
  546. {
  547.     int        c;
  548.     char        *t;
  549.     enum state { Begin, Normal, Quoted } state;
  550.     int        count;
  551.  
  552.     static char    *tokenBuf = (char *)NULL;
  553.     static int    tokenSize = 0;
  554.  
  555.     t = tokenBuf;
  556.     count = 0;
  557.     state = Begin;
  558.     for (;;) {
  559.         if (count == tokenSize) {
  560.             int nsize;
  561.             char *nbuf;
  562.  
  563.             nsize = tokenSize ? (tokenSize << 1) : 64;
  564.             nbuf = (char *)xrealloc(tokenBuf, nsize);
  565.             if (!nbuf)
  566.             return EALLOC;
  567.             tokenBuf = nbuf;
  568.             tokenSize = nsize;
  569.             t = tokenBuf + count;
  570.         }
  571.         c = lexc (file);
  572.         switch (charClass) {
  573.         case QUOTE:
  574.             switch (state) {
  575.             case Begin:
  576.             case Normal:
  577.                 state = Quoted;
  578.                 break;
  579.             case Quoted:
  580.                 state = Normal;
  581.                 break;
  582.             }
  583.             break;
  584.         case WHITE:
  585.             switch (state) {
  586.             case Begin:
  587.                 continue;
  588.             case Normal:
  589.                 *t = '\0';
  590.                 *lexToken = tokenBuf;
  591.                 return NAME;
  592.             case Quoted:
  593.                 break;
  594.             }
  595.             /* fall through */
  596.         case NORMAL:
  597.             switch (state) {
  598.             case Begin:
  599.                 state = Normal;
  600.             }
  601.             *t++ = c;
  602.             ++count;
  603.             break;
  604.         case END:
  605.         case NL:
  606.             switch (state) {
  607.             case Begin:
  608.                 *lexToken = (char *)NULL;
  609.                 return charClass == END ? DONE : NEWLINE;
  610.             default:
  611.                 *t = '\0';
  612.                 *lexToken = tokenBuf;
  613.                 ungetc (c, file);
  614.                 return NAME;
  615.             }
  616.         }
  617.     }
  618. }
  619.  
  620. static int
  621. lexc (file)
  622. FILE    *file;
  623. {
  624.     int    c;
  625.     c = getc (file);
  626.     switch (c) {
  627.     case EOF:
  628.         charClass = END;
  629.         break;
  630.     case '\\':
  631.         c = getc (file);
  632.         if (c == EOF)
  633.             charClass = END;
  634.         else
  635.             charClass = NORMAL;
  636.         break;
  637.     case '"':
  638.         charClass = QUOTE;
  639.         break;
  640.     case ' ':
  641.     case '\t':
  642.         charClass = WHITE;
  643.         break;
  644.     case '\n':
  645.         charClass = NL;
  646.         break;
  647.     default:
  648.         charClass = NORMAL;
  649.         break;
  650.     }
  651.     return c;
  652. }
  653.  
  654. static Bool
  655. SearchDirectory(index, pat, fontList, limit)
  656.     int index;
  657.     char *pat;
  658.     FontPathPtr fontList;
  659.     unsigned limit;
  660. {
  661.     int i, res, len, head, tail;
  662.     FontTable table;
  663.  
  664.     if (!searchList)
  665.     return TRUE;
  666.     table = (FontTable)searchList->osPrivate[index];
  667.     i = SetupWildMatch(table, pat, (char *)NULL, &head, &tail, &len);
  668.     while (i < table->name.used)
  669.     {
  670.     res = Match(table->name.fn[i].name, pat, head, tail, len);
  671.     if (res > 0)
  672.     {
  673.         if (AddFontPathElement(fontList, table->name.fn[i].name,
  674.                    strlen(table->name.fn[i].name), False))
  675.         return FALSE;
  676.         if (fontList->npaths >= limit)
  677.         break;
  678.     }
  679.     else if (res < 0)
  680.         break;
  681.     i++;
  682.     }
  683.     return TRUE;
  684. }
  685.  
  686. /*******************************************************************
  687.  *  ExpandFontNamePattern
  688.  *
  689.  *    Returns a FontPathPtr with at most max-names, of names of fonts
  690.  *      matching
  691.  *    the pattern.  The pattern should use the ASCII encoding, and
  692.  *      upper/lower case does not matter.  In the pattern, the '?' character
  693.  *    (octal value 77) will match any single character, and the character '*'
  694.  *    (octal value 52) will match any number of characters.  The return
  695.  *    names are in lower case.
  696.  *
  697.  *      Used only by protocol request ListFonts & ListFontsWithInfo
  698.  *******************************************************************/
  699.  
  700. FontPathPtr
  701. ExpandFontNamePattern(lenpat, countedPattern, maxNames)
  702.     unsigned    lenpat;
  703.     char    *countedPattern;
  704.     unsigned    maxNames;
  705. {
  706.     char    *pattern;
  707.     int        i;
  708.     FontPathPtr    fpr;
  709.  
  710.     if (!searchList)
  711.     return (FontPathPtr)NULL;
  712.     /* random number, this is a guess, but it hardly matters. */
  713.     fpr = MakeFontPathRecord ((unsigned) 100);
  714.     if (!fpr)
  715.     return (FontPathPtr)NULL;
  716.     pattern = (char *)ALLOCATE_LOCAL (lenpat + 1);
  717.     if (!pattern)
  718.     {
  719.     FreeFontRecord(fpr);
  720.     return (FontPathPtr)NULL;
  721.     }
  722.     /*
  723.      * make a pattern which is guaranteed NULL-terminated
  724.      */
  725.     CopyISOLatin1Lowered((unsigned char *)pattern,
  726.              (unsigned char *)countedPattern,
  727.              (int) lenpat);
  728.  
  729.     for ( i=0; i<searchList->npaths; i++)
  730.     {
  731.     if (!SearchDirectory(i, pattern, fpr, maxNames))
  732.     {
  733.         DEALLOCATE_LOCAL(pattern);
  734.         FreeFontRecord(fpr);
  735.         return (FontPathPtr)NULL;
  736.     }
  737.     if (fpr->npaths >= maxNames)
  738.         break;
  739.     }
  740.     DEALLOCATE_LOCAL(pattern);
  741.     return fpr;
  742. }
  743.  
  744. /*
  745.  * OS interface to reading font files. This is not called by the dix routines
  746.  * but rather by any of the pseudo-os-independent font internalization
  747.  * routines.
  748.  */
  749.  
  750. int
  751. FontFileRead(buf, itemsize, nitems, fid)
  752.     char    *buf;
  753.     unsigned    itemsize;
  754.     unsigned    nitems;
  755.     FID        fid;
  756. {
  757.     FontFileReadFunc    reader;
  758.  
  759.     if (reader = fontFileReaders[((FontFIDPtr) fid)->type].read)
  760.     return reader ( buf, (int) itemsize, (int) nitems, ((FontFIDPtr)fid)->fid);
  761.     return (int) fread ( buf, (int) itemsize, (int) nitems, ((FontFIDPtr)fid)->fid);
  762. }
  763.  
  764. int
  765. FontFileSkip(bytes, fid)
  766.     unsigned    bytes;
  767.     FID        fid;
  768. {
  769.     struct stat    stats;
  770.     int c;
  771.     FontFileSkipFunc    skipper;
  772.  
  773.     if ((skipper = fontFileReaders[((FontFIDPtr) fid)->type].skip))
  774.     return skipper ( bytes, ((FontFIDPtr)fid)->fid);
  775.  
  776.     fid = ((FontFIDPtr)fid)->fid;
  777.     fstat(fileno((FILE *)fid), &stats);
  778.     if ((stats.st_mode & S_IFMT) == S_IFREG)
  779.     c = fseek((FILE *) fid, (long) bytes, 1);
  780.     else
  781.     while (bytes-- && ((c = getc((FILE *)fid)) != EOF))
  782.         ;
  783.     return c;
  784. }
  785.  
  786. /*
  787.  * When a font is unloaded (destroyed) it is necessary to remove the pointer
  788.  * in the font table since it is no longer valid. This means that the
  789.  * "obvious" technique of putting the FontPtr into the table when an aliased
  790.  * font is loaded would mean that the table would have to be searched for
  791.  * any matching entry. To avoid scanning all the tables when a font is FontPtr
  792.  * destroyed, the Font has a back pointer to the FontFile (in the table) where
  793.  * it was entered.
  794.  *
  795.  * So that aliases will not also keep a copy of the FontPtr in their FontTable
  796.  * entries, a pointer to the "resolved" FontTable is actually kept and the
  797.  * indirection is taken.
  798.  *
  799.  * A slight non-conformance to the protocol is possible here. If any
  800.  * FontTable is for a file that does not load (i.e. was changed since the
  801.  * font.dirs was created), then that font name will not work even though it
  802.  * should because of wild carding or the use of a search path. The moral is
  803.  * is that the font.dirs should be correct.
  804.  *
  805.  * To prevent circular aliases from crashing the server (due to the recursive
  806.  * nature of FindFontFile) a limit of MAX_LINKS is put on the length of a
  807.  * chain that will be followed.
  808.  */
  809.  
  810. #define MAX_LINKS 20
  811.  
  812. FontFile 
  813. FindFontFile(path, fontname, depth, followAliases, table)
  814.     FontPathPtr path;
  815.     char *    fontname;
  816.     int        depth;
  817.     Bool    followAliases;    
  818.     FontTable    *table;     /* returned */
  819. {
  820.     int     nameIndex, i;
  821.     Bool found;
  822.     FontFile ff, resolved;
  823.  
  824.     if (!path || (depth >= MAX_LINKS))
  825.     return NullFontFile;
  826.     for (i = 0; i < path->npaths; i++)
  827.     {
  828.     *table = (FontTable) path->osPrivate[i];
  829.     nameIndex = FindNameInFontTable (*table, fontname, &found);
  830.     if (!found)
  831.         continue;
  832.     ff = (*table)->name.fn[nameIndex].u.ff;
  833.     if (!ff->alias || !followAliases)
  834.         return ff;
  835.     /* since the cached FontFile might be from a different table, ensure
  836.      * that the font is still loaded, otherwise OpenFontFile will fail */
  837.     if (ff->private && ((FontFile)ff->private)->private)
  838.         return (FontFile) ff->private;
  839.     if (resolved = FindFontFile (path, ff->name, depth + 1, TRUE, table))
  840.     {
  841.         if (!resolved->alias) /* alias here means a scaled font */
  842.         ff->private = (Opaque) resolved;
  843.         return resolved;
  844.     }
  845.     }
  846.     if (followAliases)
  847.     return FindScaledFont(path, fontname, table);
  848.     return NullFontFile;
  849. }
  850.  
  851. #if defined(SYSV) && !defined(hpux)        /* hpux does have vfork */
  852. #define vfork() fork()
  853. #endif
  854.  
  855. #ifdef apollo               /* Domain/OS has vfork but it breaks the graphics layer */
  856. #define vfork() fork()
  857. #endif
  858.  
  859. static int
  860. FontFilter(fp, filter)
  861.     FILE *fp;
  862.     char **filter;
  863. {
  864.     int pfd[2];
  865.     int pid;
  866.  
  867.     if (pipe(pfd) < 0) {
  868.     fclose(fp);
  869.     return (-1);
  870.     }
  871.     switch(pid = vfork()) {
  872.     case 0:
  873.     dup2(fileno(fp), 0);
  874.     close(fileno(fp));
  875.     dup2(pfd[1], 1);
  876.     close(pfd[0]);
  877.     close(pfd[1]);
  878.     execvp(filter[0], filter);
  879.     _exit(127);
  880.     case -1:
  881.     close(pfd[0]);
  882.     close(pfd[1]);
  883.     fclose(fp);
  884.     return(-1);
  885.     default:
  886.     dup2(pfd[0], fileno(fp));
  887.     close(pfd[0]);
  888.     close(pfd[1]);
  889.     return(pid);
  890.     }    
  891. }
  892.  
  893. static FILE *
  894. OpenFontFile(table, name, typeIndex, pid)
  895.     FontTable table;
  896.     char     *name;
  897.     int         *typeIndex;
  898.     int      *pid;
  899. {
  900.     char    pathName[PATH_MAX];
  901.     FILE   *fp;
  902.     char **filter;
  903.  
  904.     strcpy (pathName, table->directory);
  905.     strcat (pathName, name);
  906.     if ((fp = fopen (pathName, "r")) == (FILE *)NULL)
  907.     return fp;
  908.     *pid = 0;
  909.     *typeIndex = FindFileType (name);
  910.     filter = fontFileReaders[*typeIndex].filter;
  911.     if (filter) {
  912.     *pid = FontFilter(fp, filter);
  913.     if (*pid < 0)
  914.         return (FILE *)NULL;
  915.     }
  916.     return fp;
  917. }
  918.  
  919. static void
  920. CloseFontFile(fp, pid)
  921.     FILE *fp;
  922.     int pid;
  923. {
  924.     int child;
  925.  
  926.     fclose (fp);
  927.     if (pid > 0)
  928.        do { child = wait(0); } while (child != pid && child != -1);
  929. }
  930.  
  931. FontPtr 
  932. FontFileLoad(fontname, length)
  933.     unsigned    length;
  934.     char *    fontname;
  935. {
  936.     FontPtr    font;
  937.     char    fName[MAXFNAMELEN];
  938.     char    buf[BUFSIZ];
  939.     FILE    * fp;
  940.     FontTable    table;
  941.     FontFile    ff;
  942.     int        typeIndex;
  943.     int        cookie;
  944.     FontFIDRec    fid;
  945.  
  946.     CopyISOLatin1Lowered((unsigned char *)fName, (unsigned char *)fontname,
  947.              (int) length);
  948.     ff = FindFontFile (searchList, fName, 1, TRUE, &table);
  949.     if (!ff)
  950.     return NullFont;
  951.     if (ff->private != NULL)
  952.     return (FontPtr) ff->private;    /* already loaded */
  953.     if ((fp = OpenFontFile(table, ff->name, &typeIndex, &cookie)) == NULL)
  954.     return NullFont;
  955.     setbuf (fp, buf);
  956.     fid.type = typeIndex;
  957.     fid.fid = (FID) fp;
  958.     if (fontFileReaders[typeIndex].init)
  959.     {
  960.     fid.fid = (FID) (*fontFileReaders[typeIndex].init) (fp);
  961.     if (!fid.fid)
  962.     {
  963.         fclose (fp);
  964.         return NullFont;
  965.     }
  966.     }
  967.     font = (fontFileReaders[typeIndex].loadFont) (&fid);
  968.     if (fontFileReaders[typeIndex].done)
  969.     (*fontFileReaders[typeIndex].done) (fid.fid);
  970.     CloseFontFile(fp, cookie);
  971.     if (font == NullFont)
  972.     return NullFont;
  973.     ff->private = (Opaque) font;
  974.     font->refcnt = 0;
  975.     font->fileType = typeIndex;
  976.     font->osPrivate = (pointer) ff;
  977.     return font;
  978. }
  979.  
  980. /*
  981.  * This either returns an existing font, or if that can't be found,
  982.  * then fills in the FontInfo and FontProp by reading from the disk.
  983.  */
  984.  
  985. Bool
  986. FontFilePropLoad(fontname, length, font, fi, props)
  987.     char    *fontname;
  988.     unsigned int length;
  989.     FontInfoPtr fi;
  990.     DIXFontPropPtr *props;    /* return */
  991.     FontPtr    *font;        /* return */
  992. {
  993.     char    fName[MAXFNAMELEN];
  994.     FILE *    fp;
  995.     FontTable    table;
  996.     FontFile    ff;
  997.     Bool    found;
  998.     int        typeIndex;
  999.     char    buf[BUFSIZ];
  1000.     int        cookie;
  1001.     FontFIDRec    fid;
  1002.  
  1003.     CopyISOLatin1Lowered((unsigned char *)fName, (unsigned char *)fontname,
  1004.              (int) length);
  1005.     ff = FindFontFile (searchList, fName, 1, TRUE, &table);
  1006.     if (!ff)
  1007.     return FALSE;
  1008.     if (ff->private != NULL) {
  1009.     *font = (FontPtr) ff->private;
  1010.     return TRUE;
  1011.     }
  1012.     *font = NullFont;
  1013.     if ((fp = OpenFontFile(table, ff->name, &typeIndex, &cookie)) == NULL)
  1014.     return FALSE;
  1015.     setbuf (fp, buf);
  1016.     fid.type = typeIndex;
  1017.     fid.fid = (FID) fp;
  1018.     if (fontFileReaders[typeIndex].init)
  1019.     {
  1020.     fid.fid = (FID) (*fontFileReaders[typeIndex].init) (fp);
  1021.     if (!fid.fid)
  1022.     {
  1023.         fclose (fp);
  1024.         return FALSE;
  1025.     }
  1026.     }
  1027.     found = (*fontFileReaders[typeIndex].loadProperties) (&fid, fi, props);
  1028.     if (fontFileReaders[typeIndex].done)
  1029.     (*fontFileReaders[typeIndex].done) (fid.fid);
  1030.     CloseFontFile(fp, cookie);
  1031.     return found;
  1032. }
  1033.  
  1034. void FontUnload(font)
  1035.     FontPtr font;
  1036. {
  1037.     FontFile ff;
  1038.     if ((ff = (FontFile)font->osPrivate) != NULL)
  1039.     ff->private = NULL;
  1040.     (*fontFileReaders[font->fileType].freeFont)(font);
  1041. }
  1042.