home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / extensions / server / PEX / ospex / osPexFont.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-04  |  15.3 KB  |  579 lines

  1. /* $XConsortium: osPexFont.c,v 5.6 91/06/04 16:35:40 hersh Exp $ */
  2.  
  3. /***********************************************************
  4. Copyright 1989, 1990, 1991 by Sun Microsystems, Inc. and the X Consortium.
  5.  
  6.                         All Rights Reserved
  7.  
  8. Permission to use, copy, modify, and distribute this software and its 
  9. documentation for any purpose and without fee is hereby granted, 
  10. provided that the above copyright notice appear in all copies and that
  11. both that copyright notice and this permission notice appear in 
  12. supporting documentation, and that the names of Sun Microsystems,
  13. the X Consortium, and MIT not be used in advertising or publicity 
  14. pertaining to distribution of the software without specific, written 
  15. prior permission.  
  16.  
  17. SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 
  18. INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT 
  19. SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 
  20. DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  21. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  22. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  23. SOFTWARE.
  24.  
  25. ******************************************************************/
  26.  
  27. #include <X11/Xos.h>
  28. #ifndef X_NOT_STDC_ENV
  29. #include <stdlib.h>
  30. #else
  31. extern char *getenv();
  32. #endif
  33.  
  34. #include <stdio.h>
  35. #include "mipex.h"
  36. #include "miFont.h"
  37. #include "PEXErr.h"
  38. #define XK_LATIN1
  39. #include "keysymdef.h"
  40.  
  41. #ifndef PEX_DEFAULT_FONTPATH
  42. #define PEX_DEFAULT_FONTPATH "/usr/lib/X11/fonts/PEX"
  43. #endif
  44.  
  45. #ifndef X_NOT_POSIX
  46. #include <dirent.h>
  47. #else
  48. #ifdef SYSV
  49. #include <dirent.h>
  50. #else
  51. #ifdef USG
  52. #include <dirent.h>
  53. #else
  54. #include <sys/dir.h>
  55. #ifndef dirent
  56. #define dirent direct
  57. #endif
  58. #endif
  59. #endif
  60. #endif
  61.  
  62.  
  63. /* A convenient shorthand. */
  64. typedef struct dirent     ENTRY;
  65.  
  66. extern void CopyISOLatin1Lowered();
  67. extern int get_lowered_truncated_entry();
  68.  
  69. void ClosePEXFontFile();
  70. void SetPEXFontFilePtr();
  71.  
  72. extern  diFontHandle defaultPEXFont;
  73.  
  74. /*
  75.  * Unless an environment variable named PEX_FONTPATH is set before the
  76.  * server is started up, PEX will look in the path defined in the
  77.  * PEX_DEFAULT_FONTPATH compiler constant defined in miFont.h for PEX fonts.
  78.  * If environment variable PEX_FONTPATH is defined, then this will
  79.  * be used as the path to the fonts .
  80.  */
  81.  
  82. static char *
  83. pex_get_font_directory_path()
  84. {
  85.     static int     already_determined = 0;
  86.     static char *font_dir_path = NULL;
  87.     
  88.     if (!already_determined) {
  89.     if (getenv("PEX_FONTPATH")) {
  90.         font_dir_path = 
  91.            (char *)Xalloc((unsigned long)(1+strlen(getenv("PEX_FONTPATH"))));
  92.         strcpy(font_dir_path, getenv("PEX_FONTPATH"));
  93.     } else {
  94.         font_dir_path =
  95.         (char *)Xalloc((unsigned long)(1+strlen(PEX_DEFAULT_FONTPATH)));
  96.         strcpy(font_dir_path, PEX_DEFAULT_FONTPATH);
  97.     }
  98.     already_determined = 1;
  99.     }
  100.     
  101.     return (font_dir_path);
  102. }
  103.  
  104.  
  105. /*
  106.  * The next two functions (pex_setup_wild_match() and pex_is_matching()) are 
  107.  * stolen (and slightly modified) from MIT X11R4 fonts/mkfontdir/fontdir.c.
  108.  * pex_setup_wild_match() sets up some state about the pattern to match, which
  109.  * pex_is_matching() then uses.
  110.  */
  111.  
  112.  
  113. /* results of this function are used by pex_is_matching() */
  114.  
  115. static void
  116. pex_setup_wild_match(pat, phead, ptail, plen)
  117. char    *pat;            /* in */
  118. int    *phead, *ptail, *plen;    /* out */
  119. {
  120.     register int head, tail;
  121.     register char c, *firstWild;
  122.  
  123.     *plen = tail = strlen(pat);
  124.     for (   firstWild = pat; 
  125.         ((c = *firstWild) && !((c == XK_asterisk) || (c == XK_question)));
  126.             firstWild++)
  127.     ;
  128.         
  129.     head = firstWild - pat;
  130.  
  131.     while ((c = pat[head]) && (c != XK_asterisk))
  132.         head++;
  133.     if (head < tail)
  134.     {
  135.         while (pat[tail-1] != XK_asterisk)
  136.             tail--;
  137.     }
  138.     *phead = head;
  139.     *ptail = tail;
  140. }
  141.  
  142. /* returns value greater than 0 if successful.  head, tail, and plen
  143.  * come from a previous call to pex_setup_wild_match 
  144.  */
  145. static int 
  146. pex_is_matching(string, pat, head, tail, plen)
  147. register char       *string;        /* in */
  148. register char       *pat;        /* in */
  149. int                 head, tail, plen;    /* in */
  150. {
  151.     register int i, l;
  152.     int j, m, res;
  153.     register char cp, cs;
  154.  
  155.     res = -1;
  156.     for (i = 0; i < head; i++)
  157.     {
  158.         cp = pat[i];
  159.         if (cp == XK_question)
  160.         {
  161.             if (!string[i])
  162.                 return res;
  163.             res = 0;
  164.         }
  165.         else if (cp != string[i])
  166.             return res;
  167.     }
  168.     if (head == plen)
  169.         return (string[head] ? res : 1);
  170.     l = head;
  171.     while (++i < tail)
  172.     {
  173.         /* we just skipped an asterisk */
  174.         j = i;
  175.         m = l;
  176.         while ((cp = pat[i]) != XK_asterisk)
  177.         {
  178.             if (!(cs = string[l]))
  179.                 return 0;
  180.             if ((cp != cs) && (cp != XK_question))
  181.             {
  182.                 m++;
  183.                 cp = pat[j];
  184.                 if (cp == XK_asterisk)
  185.                 {
  186.                     if (!string[m])
  187.                         return 0;
  188.                 }
  189.                 else
  190.                 {
  191.                     while ((cs = string[m]) != cp)
  192.                     {
  193.                         if (!cs)
  194.                             return 0;
  195.                         m++;
  196.                     }
  197.                 }
  198.                 l = m;
  199.                 i = j;
  200.             }
  201.             l++;
  202.             i++;
  203.         }
  204.     }
  205.     m = strlen(&string[l]);
  206.     j = plen - tail;
  207.     if (m < j)
  208.         return 0;
  209.     l = (l + m) - j;
  210.     while (cp = pat[i])
  211.     {
  212.         if ((cp != string[l]) && (cp != XK_question))
  213.             return 0;
  214.         l++;
  215.         i++;
  216.     }
  217.     return 1;
  218. }
  219.  
  220. /*
  221.  * Caller is responsible for freeing contents of buffer and buffer when
  222.  * done with it.
  223.  */
  224. #define ABSOLUTE_MAX_NAMES 200
  225.  
  226. int
  227. pex_get_matching_names(patLen, pPattern, maxNames, numNames, names)
  228. ddUSHORT   patLen;        /* in */
  229. ddUCHAR      *pPattern;        /* in */
  230. ddUSHORT   maxNames;        /* in */
  231. ddULONG   *numNames;        /* out - number of names found */
  232. char    ***names;        /* out - pointer to list of strings */
  233. {
  234.     DIR            *fontdir;
  235.     ENTRY           *dir_entry;
  236.     char         pattern[100];
  237.     char         entry[100];
  238.     int             i, head, tail, len, total = 0;
  239.     
  240.     CopyISOLatin1Lowered(pattern, pPattern, patLen);
  241.     
  242.     if (!(*names = (char **)Xalloc((unsigned long)(ABSOLUTE_MAX_NAMES * sizeof(char *)))))
  243.     return 0;
  244.     
  245.     if (!(fontdir = opendir(pex_get_font_directory_path())))
  246.     return 0;
  247.  
  248.     pex_setup_wild_match(pattern, &head, &tail, &len);
  249.     
  250.     do {
  251.     dir_entry = readdir(fontdir);
  252.     if (dir_entry) {
  253.     
  254.         if (!get_lowered_truncated_entry(dir_entry->d_name, entry))
  255.         continue;
  256.  
  257.         if (pex_is_matching(entry, pattern, head, tail, len) > 0) {
  258.         
  259.         if (!( (*names)[total] = (char *)Xalloc((unsigned long)(1 + strlen(entry))))) {
  260.             for (i = 0; i < total; i++)
  261.             Xfree((*names)[i]);
  262.             Xfree(*names);
  263.             return 0;
  264.         }
  265.         
  266.         strcpy((*names)[total], entry);
  267.         total++;
  268.         }
  269.     }
  270.     } while (dir_entry && total < maxNames);
  271.  
  272.     closedir(fontdir);
  273.     
  274.     *numNames = total;
  275.     
  276.     return 1;
  277. }
  278.  
  279. /*
  280.  * get_stroke(stroke, fp) extracts the definition of characters
  281.  * from the font file.  It return -1 if anything goes wrong, 0 if
  282.  * everything is OK.  
  283.  */
  284.  
  285. static int
  286. get_stroke(stroke, fp)
  287.     Ch_stroke_data     *stroke;
  288.     FILE               *fp;
  289. {
  290.     listofddPoint       *spath;
  291.     register int        i;
  292.     unsigned long        closed;    /* placeholder, really unused */
  293.     register ddULONG        npath;
  294.     register miListHeader  *hdr = &(stroke->strokes);
  295.  
  296.     stroke->n_vertices = 0;
  297.     npath = hdr->maxLists = hdr->numLists;
  298.     hdr->type = DD_2D_POINT;
  299.     hdr->ddList = spath = (listofddPoint *)
  300.     Xalloc((unsigned long)(sizeof(listofddPoint) * npath));
  301.     
  302.     if (spath == NULL)
  303.     return -1;
  304.  
  305.     for (i = 0; i < npath; i++, spath++)
  306.     spath->pts.p2Dpt = NULL;
  307.  
  308.     for (i = 0, spath = hdr->ddList; i < npath; i++, spath++) {
  309.     
  310.     /* for each subpath of the character definition ... */
  311.     
  312.     if (fread((char *) &spath->numPoints,
  313.           sizeof(spath->numPoints), 1, fp) != 1 ||
  314.         fread((char *) &closed, sizeof(closed), 1, fp) != 1)
  315.         return -1;
  316.  
  317.     if (spath->numPoints <= 0)
  318.         continue;
  319.  
  320.     spath->maxData = sizeof(ddCoord2D) * spath->numPoints;
  321.     
  322.     if (!(spath->pts.p2Dpt = (ddCoord2D *) Xalloc((unsigned long)(spath->maxData))))
  323.         return -1;
  324.         
  325.     if (fread((char *)spath->pts.p2Dpt, sizeof(ddCoord2D), 
  326.           spath->numPoints, fp) != spath->numPoints)
  327.         return -1;
  328.         
  329.     stroke->n_vertices += spath->numPoints;
  330.     }
  331.     return 0;
  332. }
  333.  
  334.  
  335.  
  336. /*
  337.     read in the pex font
  338.  */
  339. ErrorCode
  340. LoadPEXFontFile(length, fontname, pFont)
  341.     unsigned        length;
  342.     char *        fontname;
  343.     diFontHandle    pFont;
  344. {
  345.     char                fname[100];
  346.     FILE               *fp;
  347.     Font_file_header    header;
  348.     Property           *properties = 0;
  349.     Dispatch           *table = 0;
  350.     miFontHeader       *font = (miFontHeader *)(pFont->deviceData);
  351.     int                 found_first, found_it = 0, err = Success, numChars, np;
  352.     char        name_to_match[100];
  353.     char        lowered_entry[100];
  354.     DIR               *fontdir;
  355.     ENTRY              *dir_entry;
  356.     register int        i;
  357.     register Ch_stroke_data **ch_font, *ch_stroke = 0;
  358.     register Dispatch  *tblptr = 0;
  359.     register Property  *propptr = 0;
  360.     register pexFontProp *fpptr = 0;
  361.  
  362.     CopyISOLatin1Lowered(name_to_match, fontname, length);
  363.  
  364.     /* open up the font directory and look for matching file names */
  365.     if (!(fontdir = opendir(pex_get_font_directory_path())))
  366.     return (PEXERR(PEXFontError));
  367.  
  368.     do {
  369.     dir_entry = readdir(fontdir);
  370.     if (dir_entry) {
  371.         /* strip off .phont and make all lower case */
  372.         if (!get_lowered_truncated_entry(dir_entry->d_name, lowered_entry))
  373.         continue;
  374.         
  375.         /* does this match what got passed in? */
  376.         if (strcmp(lowered_entry, name_to_match) == 0)
  377.         found_it = 1;
  378.     }
  379.     } while (dir_entry && !found_it);
  380.     
  381.     if (!found_it)
  382.     return (PEXERR(PEXFontError));
  383.     
  384.     (void) strcpy(fname, pex_get_font_directory_path());
  385.     (void) strcat(fname, "/");
  386.     (void) strcat(fname, dir_entry->d_name);
  387.     
  388.     closedir(fontdir);
  389.  
  390.     if ((fp = fopen(fname, "r")) == NULL)
  391.     return (PEXERR(PEXFontError));
  392.  
  393.     /*
  394.      * read in the file header.  The file header has fields containing the
  395.      * num of characters in the font, the extreme values, and number of font
  396.      * properties defined, if any.
  397.      */
  398.  
  399.     tblptr = 0;
  400.     if (fread((char *) &header, sizeof(header), 1, fp) != 1) {
  401.     (void) ClosePEXFontFile(fp);
  402.     return (PEXERR(PEXFontError)); }
  403.     
  404.     /* Initialize font structure */
  405.     (void) strcpy(font->name, header.name);
  406.     font->font_type = FONT_POLYLINES;
  407.     font->top = header.top;
  408.     font->bottom = header.bottom;
  409.     font->num_ch = header.num_ch;
  410.     font->font_info.numProps = (CARD32)header.num_props;
  411.     font->max_width = header.max_width;
  412.  
  413.     /* read in the font properties, if any, into font data area */
  414.     if (header.num_props > 0) {
  415.  
  416.     (void) SetPEXFontFilePtr(fp, START_PROPS);   /* Get to props position */
  417.     properties = (Property *) Xalloc(header.num_props * sizeof(Property));
  418.     if (properties == NULL) {
  419.         (void) ClosePEXFontFile(fp);
  420.         return (BadAlloc); }
  421.  
  422.     if (fread((char *) properties, sizeof(Property), 
  423.           header.num_props, fp) != header.num_props) {
  424.         Xfree((char *) properties);
  425.         (void) ClosePEXFontFile(fp);
  426.         return (PEXERR(PEXFontError)); }
  427.     
  428.     /* Create space for font properties in the font data area */
  429.  
  430.     font->properties =
  431.         (pexFontProp *) Xalloc( (unsigned long)(header.num_props
  432.                     * sizeof(pexFontProp)));
  433.     if (font->properties == NULL) {
  434.         Xfree((char *) properties);
  435.         (void) ClosePEXFontFile(fp);
  436.         return (BadAlloc); }
  437.  
  438.     np = header.num_props;
  439.     for (    i=0, propptr = properties, fpptr = font->properties;
  440.         i < np;
  441.         i++, propptr++, fpptr++) {
  442.  
  443.         if (propptr->propname == NULL) {
  444.         (header.num_props)--;
  445.         continue; }
  446.  
  447.         fpptr->name = MakeAtom( (char *)propptr->propname,
  448.                     strlen(propptr->propname), 1);
  449.  
  450.         if (propptr->propvalue != NULL)
  451.         fpptr->value = MakeAtom((char *)propptr->propvalue,
  452.                     strlen(propptr->propvalue), 1);
  453.         else fpptr->value = 0;
  454.     }
  455.  
  456.     /* free up local storage allocated for properties */
  457.      Xfree((char *) properties);
  458.     }
  459.  
  460.     /* position file pointer to dispatch data */
  461.     (void) SetPEXFontFilePtr(fp, (long) START_DISPATCH(header.num_props));
  462.  
  463.     /*
  464.      * read in the distable font, use the offset to see if the
  465.      * character is defined or not.  The strokes are defined in Phigs style.
  466.      * The "center" of the character is not the physical center. It is the
  467.      * center defined by the font designer.  The actual center is half the
  468.      * "right" value.
  469.      */
  470.  
  471.     table = (Dispatch *)Xalloc((unsigned long)(sizeof(Dispatch) *font->num_ch));
  472.     
  473.     if (table == NULL) {
  474.     (void) ClosePEXFontFile(fp);
  475.     return (BadAlloc); }
  476.     
  477.     if (fread((char *) table, sizeof(Dispatch), font->num_ch, fp)
  478.         != font->num_ch) {
  479.     Xfree((char *) table);
  480.     (void) ClosePEXFontFile(fp);
  481.     return (PEXERR(PEXFontError)); }
  482.     
  483.     font->ch_data =
  484.     (Ch_stroke_data **) Xalloc((unsigned long)(sizeof(Ch_stroke_data *) * 
  485.                             font->num_ch));
  486.     if (font->ch_data == NULL) {
  487.     Xfree((char *) table);
  488.     (void) ClosePEXFontFile(fp);
  489.     return (BadAlloc); }
  490.     
  491.     /* The next loop initializes all ch_data pointers to null; essential
  492.     for non-crashing during font clean-up in case of failed font file
  493.     read.  Also count the number of non-blank chars.
  494.      */
  495.     for (   i = 0, ch_font = font->ch_data, tblptr = table, numChars = 0;
  496.         i < font->num_ch;
  497.         i++, ch_font++, tblptr++) {
  498.     *ch_font = NULL;
  499.     if (tblptr->offset != 0) numChars++; }
  500.  
  501.     ch_stroke = (Ch_stroke_data *)Xalloc((unsigned long)(numChars *
  502.                             sizeof(Ch_stroke_data)));
  503.     if (!ch_stroke) {
  504.     err = BadAlloc;
  505.     goto disaster;
  506.     }
  507.  
  508.     /* read in the char data  (the font file format should be changed
  509.     so that the allocation can be done outside this loop--this
  510.     method is inefficient)
  511.      */
  512.     for (   i = 0, ch_font = font->ch_data, tblptr = table, found_first = 0;
  513.         i < font->num_ch;
  514.         i++, ch_font++, tblptr++) {
  515.     if (tblptr->offset != 0) {
  516.         (*ch_font) = ch_stroke++;
  517.         (*ch_font)->strokes.ddList = NULL;
  518.         (*ch_font)->center = table[i].center;
  519.         (*ch_font)->right = table[i].right;
  520.         
  521.         (void) SetPEXFontFilePtr(fp, tblptr->offset);
  522.  
  523.         /* read in the type, number of subpaths, and n_vertices fields */
  524.         if (    (fread(&((*ch_font)->type),
  525.                sizeof(Font_path_type), 1, fp) != 1) 
  526.         ||  (fread(&((*ch_font)->strokes.numLists),
  527.                sizeof(ddULONG),1,fp) != 1)
  528.         ||  (fread(&((*ch_font)->n_vertices),
  529.                sizeof(ddULONG), 1, fp) != 1) )
  530.         {          
  531.             err = PEXERR(PEXFontError);
  532.             goto disaster;
  533.         }
  534.         
  535.         (*ch_font)->strokes.maxLists = (*ch_font)->strokes.numLists;
  536.         if ((*ch_font)->strokes.numLists > 0) {
  537.         
  538.         if (get_stroke(*ch_font, fp)) {
  539.             err = BadAlloc;
  540.             goto disaster; }
  541.         
  542.         if (!found_first) {
  543.             font->font_info.firstGlyph = i;
  544.             found_first = 1; }
  545.  
  546.         font->font_info.lastGlyph = i; }
  547.         }
  548.     }
  549.  
  550.     Xfree((char *)table);
  551.  
  552.     (void) ClosePEXFontFile(fp);
  553.     
  554.     return (Success);
  555.  
  556. disaster:
  557.     (void) ClosePEXFontFile(fp);
  558.     if (table) Xfree(table);
  559.     if (pFont == defaultPEXFont) defaultPEXFont = 0;    /* force free */
  560.     FreePEXFont((diFontHandle) pFont, pFont->id);
  561.     return (err);
  562.     
  563. }
  564. void
  565. ClosePEXFontFile(fp)
  566.     FILE *fp;
  567. {
  568.     fclose (fp);
  569. }
  570.  
  571. void
  572. SetPEXFontFilePtr(fp,where)
  573.     FILE *fp;
  574.     long where;
  575. {
  576.     (void) fseek(fp, where, SEEK_SET);        /* set pointer at "where" bytes
  577.                         from the beginning of the file */
  578. }
  579.